Add ZendFramework, PHPLine and Basic CLI classes
authorTim Düsterhus <duesterhus@woltlab.com>
Thu, 1 Nov 2012 22:20:50 +0000 (23:20 +0100)
committerTim Düsterhus <duesterhus@woltlab.com>
Mon, 5 Nov 2012 14:31:52 +0000 (15:31 +0100)
71 files changed:
wcfsetup/install/files/cli.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/CLIWCF.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/phpline/LICENSE.txt [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/phpline/phpline.phar [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/phpline/version [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/Adapter/AbstractAdapter.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/Adapter/AdapterInterface.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/Adapter/Posix.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/Adapter/Virtual.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/Adapter/Windows.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/Adapter/WindowsAnsicon.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/Charset/Ascii.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/Charset/AsciiExtended.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/Charset/CharsetInterface.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/Charset/DECSG.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/Charset/Utf8.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/Charset/Utf8Heavy.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/ColorInterface.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/Console.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/Exception/BadMethodCallException.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/Exception/ExceptionInterface.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/Exception/InvalidArgumentException.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/Exception/RuntimeException.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/Getopt.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/Prompt/AbstractPrompt.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/Prompt/Char.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/Prompt/Confirm.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/Prompt/Line.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/Prompt/Number.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/Prompt/PromptInterface.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/Prompt/Select.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/Request.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/Response.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Console/composer.json [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/LICENSE.txt [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Loader/AutoloaderFactory.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Loader/ClassMapAutoloader.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Loader/Exception/BadMethodCallException.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Loader/Exception/DomainException.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Loader/Exception/ExceptionInterface.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Loader/Exception/InvalidArgumentException.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Loader/Exception/InvalidPathException.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Loader/Exception/MissingResourceNamespaceException.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Loader/Exception/PluginLoaderException.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Loader/Exception/RuntimeException.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Loader/Exception/SecurityException.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Loader/ModuleAutoloader.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Loader/PluginClassLoader.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Loader/PluginClassLocator.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Loader/ShortNameLocator.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Loader/SplAutoloader.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Loader/StandardAutoloader.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/Loader/composer.json [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/ProgressBar/Adapter/AbstractAdapter.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/ProgressBar/Adapter/Console.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/ProgressBar/Adapter/Exception/ExceptionInterface.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/ProgressBar/Adapter/Exception/InvalidArgumentException.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/ProgressBar/Adapter/Exception/RuntimeException.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/ProgressBar/Adapter/JsPull.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/ProgressBar/Adapter/JsPush.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/ProgressBar/Exception/ExceptionInterface.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/ProgressBar/Exception/InvalidArgumentException.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/ProgressBar/Exception/OutOfRangeException.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/ProgressBar/Exception/RuntimeException.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/ProgressBar/ProgressBar.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/ProgressBar/composer.json [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/README-GIT.md [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/README.md [new file with mode: 0644]
wcfsetup/install/files/lib/system/api/zend/version [new file with mode: 0644]
wcfsetup/install/files/lib/system/cli/DatabaseCommandHistory.class.php [new file with mode: 0644]
wcfsetup/setup/db/install.sql

diff --git a/wcfsetup/install/files/cli.php b/wcfsetup/install/files/cli.php
new file mode 100644 (file)
index 0000000..894a392
--- /dev/null
@@ -0,0 +1,14 @@
+<?php
+/**
+ * @author     Tim Düsterhus
+ * @copyright  2001-2011 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @category   Community Framework
+ */
+// define the wcf-root-dir
+define('WCF_DIR', dirname(__FILE__).'/');
+
+// initiate wcf core
+require_once(WCF_DIR.'lib/system/CLIWCF.class.php');
+new wcf\system\CLIWCF();
diff --git a/wcfsetup/install/files/lib/system/CLIWCF.class.php b/wcfsetup/install/files/lib/system/CLIWCF.class.php
new file mode 100644 (file)
index 0000000..1773473
--- /dev/null
@@ -0,0 +1,114 @@
+<?php
+namespace wcf\system;
+require_once('WCF.class.php');
+use phpline\console\ConsoleReader;
+use phpline\TerminalFactory;
+use wcf\system\cli\DatabaseCommandHistory;
+use wcf\system\exception\UserInputException;
+use wcf\system\user\authentication\UserAuthenticationFactory;
+use wcf\util\StringUtil;
+use Zend\Loader\StandardAutoloader as ZendLoader;
+
+/**
+ * Extends WCF class with functions for CLI.
+ *
+ * @author     Tim Düsterhus
+ * @copyright  2001-2012 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system
+ * @category   Community Framework
+ */
+class CLIWCF extends WCF {
+       /**
+        * instance of ConsoleReader
+        * @var phpline\console\ConsoleReader
+        */
+       protected static $consoleReader = null;
+       
+       /**
+        * Calls all init functions of the WCF class.
+        */
+       public function __construct() {
+               parent::__construct();
+               
+               // register additional autoloaders
+               require_once(WCF_DIR.'lib/system/api/phpline/phpline.phar');
+               require_once(WCF_DIR.'lib/system/api/zend/Loader/StandardAutoloader.php');
+               $zendLoader = new ZendLoader(array(ZendLoader::AUTOREGISTER_ZF => true));
+               $zendLoader->register();
+               
+               $this->initPHPLine();
+               $this->initAuth();
+       }
+       
+       /**
+        * Initializes PHPLine.
+        */
+       protected function initPHPLine() {
+               $terminal = TerminalFactory::get();
+               self::$consoleReader = new ConsoleReader("WoltLab Community Framework", null, null, $terminal);
+               self::getReader()->setExpandEvents(false);
+               
+               $headline = str_pad("WoltLab (r) Community Framework (tm) ".WCF_VERSION, self::getTerminal()->getWidth(), " ", STR_PAD_BOTH);
+               self::getReader()->println($headline);
+       }
+       
+       /**
+        * Returns ConsoleReader.
+        * 
+        * @return phpline\console\ConsoleReader
+        */
+       public function getReader() {
+               return self::$consoleReader;
+       }
+       
+       /**
+        * Returns the terminal that is attached to ConsoleReader
+        * 
+        * @return phpline\Terminal
+        */
+       public function getTerminal() {
+               return self::getReader()->getTerminal();
+       }
+       
+       /**
+        * Converts certain HTML entities to a proper CLI counterpart.
+        * 
+        * @param       string  $string
+        * @return      string
+        */
+       public function convertEntities($string) {
+               return Regex::compile('&[lrb]dquo;')->replace($string, '"');
+       }
+       
+       /**
+        * Does the user authentification.
+        */
+       protected function initAuth() {
+               do {
+                       $username = StringUtil::trim(self::getReader()->readLine(WCF::getLanguage()->get('wcf.user.username').'> '));
+               }
+               while ($username === '');
+               do {
+                       $password = StringUtil::trim(self::getReader()->readLine(WCF::getLanguage()->get('wcf.user.password').'> ', '*'));
+               }
+               while ($password === '');
+               
+               try {
+                       $user = UserAuthenticationFactory::getUserAuthentication()->loginManually($username, $password);
+                       WCF::getSession()->changeUser($user);
+               }
+               catch (UserInputException $e) {
+                       $message = WCF::getLanguage()->getDynamicVariable('wcf.user.'.$e->getField().'.error.'.$e->getType(), array('username' => $username));
+                       self::getReader()->println(self::convertEntities($message));
+                       exit;
+               }
+               
+               $history = new DatabaseCommandHistory();
+               $history->load();
+               self::getReader()->setHistory($history);
+               
+               while ('exit' !== StringUtil::trim(self::getReader()->readLine('>')));
+       }
+}
diff --git a/wcfsetup/install/files/lib/system/api/phpline/LICENSE.txt b/wcfsetup/install/files/lib/system/api/phpline/LICENSE.txt
new file mode 100644 (file)
index 0000000..4ac9522
--- /dev/null
@@ -0,0 +1,35 @@
+Copyright (c) 2002-2012, the original author or authors.
+All rights reserved.
+
+http://www.opensource.org/licenses/bsd-license.php
+
+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 JLine 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.
+
diff --git a/wcfsetup/install/files/lib/system/api/phpline/phpline.phar b/wcfsetup/install/files/lib/system/api/phpline/phpline.phar
new file mode 100644 (file)
index 0000000..c76252a
Binary files /dev/null and b/wcfsetup/install/files/lib/system/api/phpline/phpline.phar differ
diff --git a/wcfsetup/install/files/lib/system/api/phpline/version b/wcfsetup/install/files/lib/system/api/phpline/version
new file mode 100644 (file)
index 0000000..9137731
--- /dev/null
@@ -0,0 +1 @@
+Version of PHPLine is f3dce6b625ddd50ef42deec5fd198c8b124fb740
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/Adapter/AbstractAdapter.php b/wcfsetup/install/files/lib/system/api/zend/Console/Adapter/AbstractAdapter.php
new file mode 100644 (file)
index 0000000..174eded
--- /dev/null
@@ -0,0 +1,616 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console\Adapter;
+
+use Zend\Console\Charset;
+use Zend\Console\Exception;
+
+/**
+ * @category   Zend
+ * @package    Zend_Console
+ * @subpackage Adapter
+ */
+abstract class AbstractAdapter implements AdapterInterface
+{
+    /**
+     * Whether or not mbstring is enabled
+     *
+     * @var null|bool
+     */
+    protected static $hasMBString;
+
+    /**
+     * @var Charset\CharsetInterface
+     */
+    protected $charset;
+
+    /**
+     * Current cursor X position
+     *
+     * @var int
+     */
+    protected $posX;
+
+    /**
+     * Current cursor Y position
+     *
+     * @var int
+     */
+    protected $posY;
+
+    /**
+     * Write a chunk of text to console.
+     *
+     * @param string   $text
+     * @param null|int $color
+     * @param null|int $bgColor
+     */
+    public function write($text, $color = null, $bgColor = null)
+    {
+        if ($color !== null || $bgColor !== null) {
+            echo $this->colorize($text, $color, $bgColor);
+        } else {
+            echo $text;
+        }
+    }
+
+    /**
+     * Alias for write()
+     *
+     * @param string   $text
+     * @param null|int $color
+     * @param null|int $bgColor
+     */
+    public function writeText($text, $color = null, $bgColor = null)
+    {
+        return $this->write($text, $color, $bgColor);
+    }
+
+    /**
+     * Write a single line of text to console and advance cursor to the next line.
+     * If the text is longer than console width it will be truncated.
+     *
+     *
+     * @param string   $text
+     * @param null|int $color
+     * @param null|int $bgColor
+     */
+    public function writeLine($text = "", $color = null, $bgColor = null)
+    {
+        $width = $this->getStringWidth($text);
+
+        // Remove newline characters from the end of string
+        $text = trim($text, "\r\n");
+
+        // Replace newline characters with spaces
+        $test = str_replace("\n", " ", $text);
+
+        // Trim the line if it's too long and output text
+        $consoleWidth = $this->getWidth();
+        if ($width > $consoleWidth) {
+            $text = $this->stringTrim($text, $consoleWidth);
+            $this->write($text, $color, $bgColor);
+        } elseif ($width == $consoleWidth) {
+            $this->write($text, $color, $bgColor);
+        } else {
+            $this->write($text . "\n", $color, $bgColor);
+        }
+    }
+
+    /**
+     * Write a piece of text at the coordinates of $x and $y
+     *
+     *
+     * @param string   $text    Text to write
+     * @param int      $x       Console X coordinate (column)
+     * @param int      $y       Console Y coordinate (row)
+     * @param null|int $color
+     * @param null|int $bgColor
+     */
+    public function writeAt($text, $x, $y, $color = null, $bgColor = null)
+    {
+        $this->setPos( $x, $y );
+        $this->write( $text, $color, $bgColor );
+    }
+
+    /**
+     * Write a box at the specified coordinates.
+     * If X or Y coordinate value is negative, it will be calculated as the distance from far right or bottom edge
+     * of the console (respectively).
+     *
+     * @param int      $x1           Top-left corner X coordinate (column)
+     * @param int      $y1           Top-left corner Y coordinate (row)
+     * @param int      $x2           Bottom-right corner X coordinate (column)
+     * @param int      $y2           Bottom-right corner Y coordinate (row)
+     * @param int      $lineStyle    (optional) Box border style.
+     * @param int      $fillStyle    (optional) Box fill style or a single character to fill it with.
+     * @param int      $color        (optional) Foreground color
+     * @param int      $bgColor      (optional) Background color
+     * @param null|int $fillColor    (optional) Foreground color of box fill
+     * @param null|int $fillBgColor  (optional) Background color of box fill
+     * @throws Exception\BadMethodCallException if coordinates are invalid
+     */
+    public function writeBox(
+        $x1,
+        $y1,
+        $x2,
+        $y2,
+        $lineStyle = self::LINE_SINGLE,
+        $fillStyle = self::FILL_NONE,
+        $color = null,
+        $bgColor = null,
+        $fillColor = null,
+        $fillBgColor = null
+    ) {
+        // Sanitize coordinates
+        $x1 = (int) $x1;
+        $y1 = (int) $y1;
+        $x2 = (int) $x2;
+        $y2 = (int) $y2;
+
+        // Translate negative coordinates
+        if ($x2 < 0) {
+            $x2 = $this->getWidth() - $x2;
+        }
+
+        if ($y2 < 0) {
+            $y2 = $this->getHeight() - $y2;
+        }
+
+        // Validate coordinates
+        if ($x1 < 0
+            || $y1 < 0
+            || $x2 < $x1
+            || $y2 < $y1
+       ) {
+            throw new Exception\BadMethodCallException('Supplied X,Y coordinates are invalid.');
+        }
+
+        // Determine charset and dimensions
+        $charset = $this->getCharset();
+        $width   = $x2 - $x1 + 1;
+        $height  = $y2 - $y1 + 1;
+
+        if ($width <= 2) {
+            $lineStyle = static::LINE_NONE;
+        }
+
+        // Activate line drawing
+        $this->write($charset::ACTIVATE);
+
+        // Draw horizontal lines
+        if ($lineStyle !== static::LINE_NONE) {
+            switch ($lineStyle) {
+                case static::LINE_SINGLE:
+                    $lineChar = $charset::LINE_SINGLE_EW;
+                    break;
+
+                case static::LINE_DOUBLE:
+                    $lineChar = $charset::LINE_DOUBLE_EW;
+                    break;
+
+                case static::LINE_BLOCK:
+                default:
+                    $lineChar = $charset::LINE_BLOCK_EW;
+                    break;
+            }
+
+            $this->setPos($x1 + 1, $y1);
+            $this->write(str_repeat($lineChar, $width - 2), $color, $bgColor);
+            $this->setPos($x1 + 1, $y2);
+            $this->write(str_repeat($lineChar, $width - 2), $color, $bgColor);
+        }
+
+        // Draw vertical lines and fill
+        if (is_numeric($fillStyle)
+            && $fillStyle !== static::FILL_NONE) {
+
+            switch ($fillStyle) {
+                case static::FILL_SHADE_LIGHT:
+                    $fillChar = $charset::SHADE_LIGHT;
+                    break;
+                case static::FILL_SHADE_MEDIUM:
+                    $fillChar = $charset::SHADE_MEDIUM;
+                    break;
+                case static::FILL_SHADE_DARK:
+                    $fillChar = $charset::SHADE_DARK;
+                    break;
+                case static::FILL_SHADE_LIGHT:
+                    $fillChar = $charset::SHADE_LIGHT;
+                    break;
+                case static::FILL_BLOCK:
+                default:
+                    $fillChar = $charset::BLOCK;
+                    break;
+            }
+
+        } elseif ($fillStyle) {
+            $fillChar = $this->stringTrim($fillStyle, 1);
+        } else {
+            $fillChar = ' ';
+        }
+
+        if ($lineStyle === static::LINE_NONE) {
+            for ($y = $y1; $y <= $y2; $y++) {
+                $this->setPos($x1, $y);
+                $this->write(str_repeat($fillChar, $width), $fillColor, $fillBgColor);
+            }
+        } else {
+            switch ($lineStyle) {
+                case static::LINE_DOUBLE:
+                    $lineChar = $charset::LINE_DOUBLE_NS;
+                    break;
+                case static::LINE_BLOCK:
+                    $lineChar = $charset::LINE_BLOCK_NS;
+                    break;
+                case static::LINE_SINGLE:
+                default:
+                    $lineChar = $charset::LINE_SINGLE_NS;
+                    break;
+            }
+
+            for ($y = $y1 + 1; $y < $y2; $y++) {
+                $this->setPos($x1, $y);
+                $this->write($lineChar, $color, $bgColor);
+                $this->write(str_repeat($fillChar, $width - 2), $fillColor, $fillBgColor);
+                $this->write($lineChar, $color, $bgColor);
+            }
+        }
+
+
+        // Draw corners
+        if ($lineStyle !== static::LINE_NONE) {
+            if ($color !== null) {
+                $this->setColor($color);
+            }
+            if ($bgColor !== null) {
+                $this->setBgColor($bgColor);
+            }
+            if ($lineStyle === static::LINE_SINGLE) {
+                $this->writeAt($charset::LINE_SINGLE_NW, $x1, $y1);
+                $this->writeAt($charset::LINE_SINGLE_NE, $x2, $y1);
+                $this->writeAt($charset::LINE_SINGLE_SE, $x2, $y2);
+                $this->writeAt($charset::LINE_SINGLE_SW, $x1, $y2);
+            } elseif ($lineStyle === static::LINE_DOUBLE) {
+                $this->writeAt($charset::LINE_DOUBLE_NW, $x1, $y1);
+                $this->writeAt($charset::LINE_DOUBLE_NE, $x2, $y1);
+                $this->writeAt($charset::LINE_DOUBLE_SE, $x2, $y2);
+                $this->writeAt($charset::LINE_DOUBLE_SW, $x1, $y2);
+            } elseif ($lineStyle === static::LINE_BLOCK) {
+                $this->writeAt($charset::LINE_BLOCK_NW, $x1, $y1);
+                $this->writeAt($charset::LINE_BLOCK_NE, $x2, $y1);
+                $this->writeAt($charset::LINE_BLOCK_SE, $x2, $y2);
+                $this->writeAt($charset::LINE_BLOCK_SW, $x1, $y2);
+            }
+        }
+
+        // Deactivate line drawing and reset colors
+        $this->write($charset::DEACTIVATE);
+        $this->resetColor();
+    }
+
+    /**
+     * Write a block of text at the given coordinates, matching the supplied width and height.
+     * In case a line of text does not fit desired width, it will be wrapped to the next line.
+     * In case the whole text does not fit in desired height, it will be truncated.
+     *
+     * @param string   $text    Text to write
+     * @param int      $width   Maximum block width. Negative value means distance from right edge.
+     * @param int|null $height  Maximum block height. Negative value means distance from bottom edge.
+     * @param int      $x       Block X coordinate (column)
+     * @param int      $y       Block Y coordinate (row)
+     * @param null|int $color   (optional) Text color
+     * @param null|int $bgColor (optional) Text background color
+     */
+    public function writeTextBlock(
+        $text,
+        $width,
+        $height = null,
+        $x = 0,
+        $y = 0,
+        $color = null,
+        $bgColor = null
+    ) {
+    }
+
+    /**
+     * Determine and return current console width.
+     *
+     * @return int
+     */
+    public function getWidth()
+    {
+        return 80;
+    }
+
+    /**
+     * Determine and return current console height.
+     *
+     * @return int
+     */
+    public function getHeight()
+    {
+        return 25;
+    }
+
+    /**
+     * Determine and return current console width and height.
+     *
+     * @return array array($width, $height)
+     */
+    public function getSize()
+    {
+        return array(
+            $this->getWidth(),
+            $this->getHeight(),
+        );
+    }
+
+    /**
+     * Check if console is UTF-8 compatible
+     *
+     * @return bool
+     */
+    public function isUtf8()
+    {
+        return true;
+    }
+
+    /**
+     * Return current cursor position - array($x, $y)
+     *
+     *
+     * @return array array($x, $y);
+     */
+    public function getPos()
+    {
+    }
+
+//    /**
+//     * Return current cursor X coordinate (column)
+//     *
+//     *
+//     * @return  false|int       Integer or false if failed to determine.
+//     */
+//    public function getX();
+//
+//    /**
+//     * Return current cursor Y coordinate (row)
+//     *
+//     *
+//     * @return  false|int       Integer or false if failed to determine.
+//     */
+//    public function getY();
+
+    /**
+     * Set cursor position
+     *
+     * @param int $x
+     * @param int $y
+     */
+    public function setPos($x, $y)
+    {
+    }
+
+    /**
+     * Show console cursor
+     */
+    public function showCursor()
+    {
+    }
+
+    /**
+     * Hide console cursor
+     */
+    public function hideCursor()
+    {
+    }
+
+    /**
+     * Return current console window title.
+     *
+     * @return string
+     */
+    public function getTitle()
+    {
+        return '';
+    }
+
+    /**
+     * Set console window title
+     *
+     * @param $title
+     */
+    public function setTitle($title)
+    {
+    }
+
+    /**
+     * Reset console window title to previous value.
+     */
+    public function resetTitle()
+    {
+    }
+
+    /**
+     * Prepare a string that will be rendered in color.
+     *
+     * @param  string   $string
+     * @param  int      $color
+     * @param  null|int $bgColor
+     * @return string
+     */
+    public function colorize($string, $color = null, $bgColor = null)
+    {
+        return $string;
+    }
+
+    /**
+     * Change current drawing color.
+     *
+     * @param int $color
+     */
+    public function setColor($color)
+    {
+    }
+
+    /**
+     * Change current drawing background color
+     *
+     * @param int $color
+     */
+    public function setBgColor($color)
+    {
+    }
+
+    /**
+     * Reset color to console default.
+     */
+    public function resetColor()
+    {
+    }
+
+    /**
+     * Set Console charset to use.
+     *
+     * @param Charset\CharsetInterface $charset
+     */
+    public function setCharset(Charset\CharsetInterface $charset)
+    {
+        $this->charset = $charset;
+    }
+
+    /**
+     * Get charset currently in use by this adapter.
+     *
+     * @return Charset\CharsetInterface $charset
+     */
+    public function getCharset()
+    {
+        if ($this->charset === null) {
+            $this->charset = $this->getDefaultCharset();
+        }
+
+        return $this->charset;
+    }
+
+    /**
+     * @return Charset\Utf8
+     */
+    public function getDefaultCharset()
+    {
+        return new Charset\Utf8;
+    }
+
+    /**
+     * Clear console screen
+     */
+    public function clear()
+    {
+        echo "\f";
+    }
+
+    /**
+     * Clear line at cursor position
+     */
+    public function clearLine()
+    {
+        echo "\r" . str_repeat( " ", $this->getWidth() ) . "\r";
+    }
+
+    /**
+     * Clear console screen
+     */
+    public function clearScreen()
+    {
+        return $this->clear();
+    }
+
+    /**
+     * Helper function that return string length as rendered in console.
+     *
+     * @static
+     * @param $string
+     * @return int
+     */
+    protected function getStringWidth($string)
+    {
+        $width = strlen($string);
+
+        if (!$this->isUtf8()) {
+            return $width;
+        }
+
+        if (static::$hasMBString === null) {
+            static::$hasMBString = extension_loaded( 'mbstring' );
+        }
+
+        $width = (static::$hasMBString)
+               ? mb_strlen($string, 'UTF-8' )
+               : strlen(utf8_decode($string));
+
+        return $width;
+    }
+
+    /**
+     * Trim a string in an encoding-safe way
+     *
+     * @param  mixed $string
+     * @param  mixed $length
+     * @return int
+     */
+    protected function stringTrim($string, $length)
+    {
+        if ($this->isUtf8()) {
+            if (static::$hasMBString === null) {
+                static::$hasMBString = extension_loaded('mbstring');
+            }
+
+            if (static::$hasMBString) {
+                return mb_strlen($string, 'UTF-8');
+            }
+
+            return strlen(utf8_decode($string));
+        }
+
+        return strlen($string);
+    }
+
+    /**
+     * Read a single line from the console input
+     *
+     * @param int $maxLength        Maximum response length
+     * @return string
+     */
+    public function readLine($maxLength = 2048)
+    {
+        $f    = fopen('php://stdin','r');
+        $line = stream_get_line($f, $maxLength, PHP_EOL);
+        fclose($f);
+        return rtrim($line,"\n\r");
+    }
+
+    /**
+     * Read a single character from the console input
+     *
+     * @param string|null   $mask   A list of allowed chars
+     * @return string
+     */
+    public function readChar($mask = null)
+    {
+        $f = fopen('php://stdin','r');
+        do {
+            $char = fread($f,1);
+        } while ($mask === null || stristr($mask, $char));
+        fclose($f);
+        return $char;
+    }
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/Adapter/AdapterInterface.php b/wcfsetup/install/files/lib/system/api/zend/Console/Adapter/AdapterInterface.php
new file mode 100644 (file)
index 0000000..676db68
--- /dev/null
@@ -0,0 +1,289 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console\Adapter;
+
+use Zend\Console\Charset\CharsetInterface;
+
+/**
+ * @category   Zend
+ * @package    Zend_Console
+ */
+interface AdapterInterface
+{
+    const LINE_NONE = 1;
+    const LINE_SINGLE = 2;
+    const LINE_DOUBLE = 3;
+    const LINE_BLOCK = 4;
+    const FILL_NONE = 0;
+    const FILL_SHADE_LIGHT = 1;
+    const FILL_SHADE_MEDIUM = 2;
+    const FILL_SHADE_DARK = 3;
+    const FILL_BLOCK = 10;
+
+    /**
+     * Write a chunk of text to console.
+     *
+     * @param string                   $text
+     * @param null|int $color
+     * @param null|int $bgColor
+     */
+    public function write($text, $color = null, $bgColor = null);
+
+    /**
+     * Alias for write()
+     *
+     * @param string                   $text
+     * @param null|int $color
+     * @param null|int $bgColor
+     */
+    public function writeText($text, $color = null, $bgColor = null);
+
+    /**
+     * Write a single line of text to console and advance cursor to the next line.
+     * If the text is longer than console width it will be truncated.
+     *
+     * @param string                   $text
+     * @param null|int $color
+     * @param null|int $bgColor
+     */
+    public function writeLine($text = "", $color = null, $bgColor = null);
+
+    /**
+     * Write a piece of text at the coordinates of $x and $y
+     *
+     * @param string                   $text     Text to write
+     * @param int                      $x        Console X coordinate (column)
+     * @param int                      $y        Console Y coordinate (row)
+     * @param null|int $color
+     * @param null|int $bgColor
+     */
+    public function writeAt($text, $x, $y, $color = null, $bgColor = null);
+
+    /**
+     * Write a box at the specified coordinates.
+     * If X or Y coordinate value is negative, it will be calculated as the distance from far right or bottom edge
+     * of the console (respectively).
+     *
+     * @param int                      $x1           Top-left corner X coordinate (column)
+     * @param int                      $y1           Top-left corner Y coordinate (row)
+     * @param int                      $x2           Bottom-right corner X coordinate (column)
+     * @param int                      $y2           Bottom-right corner Y coordinate (row)
+     * @param int                      $lineStyle    (optional) Box border style.
+     * @param int                      $fillStyle    (optional) Box fill style or a single character to fill it with.
+     * @param int      $color        (optional) Foreground color
+     * @param int      $bgColor      (optional) Background color
+     * @param null|int $fillColor    (optional) Foreground color of box fill
+     * @param null|int $fillBgColor  (optional) Background color of box fill
+     */
+    public function writeBox(
+        $x1,
+        $y1,
+        $x2,
+        $y2,
+        $lineStyle = self::LINE_SINGLE,
+        $fillStyle = self::FILL_NONE,
+        $color = null,
+        $bgColor = null,
+        $fillColor = null,
+        $fillBgColor = null
+    );
+
+    /**
+     * Write a block of text at the given coordinates, matching the supplied width and height.
+     * In case a line of text does not fit desired width, it will be wrapped to the next line.
+     * In case the whole text does not fit in desired height, it will be truncated.
+     *
+     * @param string                   $text     Text to write
+     * @param int                      $width    Maximum block width. Negative value means distance from right edge.
+     * @param int|null                 $height   Maximum block height. Negative value means distance from bottom edge.
+     * @param int                      $x        Block X coordinate (column)
+     * @param int                      $y        Block Y coordinate (row)
+     * @param null|int                 $color    (optional) Text color
+     * @param null|int $bgColor  (optional) Text background color
+     */
+    public function writeTextBlock(
+        $text,
+        $width,
+        $height = null,
+        $x = 0,
+        $y = 0,
+        $color = null,
+        $bgColor = null
+    );
+
+
+    /**
+     * Determine and return current console width.
+     *
+     * @return int
+     */
+    public function getWidth();
+
+    /**
+     * Determine and return current console height.
+     *
+     * @return int
+     */
+    public function getHeight();
+
+    /**
+     * Determine and return current console width and height.
+     *
+     * @return array        array($width, $height)
+     */
+    public function getSize();
+
+    /**
+     * Check if console is UTF-8 compatible
+     *
+     * @return bool
+     */
+    public function isUtf8();
+
+
+//    /**
+//     * Return current cursor position - array($x, $y)
+//     *
+//     * @return array        array($x, $y);
+//     */
+//    public function getPos();
+//
+//    /**
+//     * Return current cursor X coordinate (column)
+//     *
+//     * @return  false|int       Integer or false if failed to determine.
+//     */
+//    public function getX();
+//
+//    /**
+//     * Return current cursor Y coordinate (row)
+//     *
+//     * @return  false|int       Integer or false if failed to determine.
+//     */
+//    public function getY();
+
+    /**
+     * Set cursor position
+     *
+     * @param int   $x
+     * @param int   $y
+     */
+    public function setPos($x, $y);
+
+    /**
+     * Hide console cursor
+     */
+    public function hideCursor();
+
+    /**
+     * Show console cursor
+     */
+    public function showCursor();
+
+    /**
+     * Return current console window title.
+     *
+     * @return string
+     */
+    public function getTitle();
+
+    /**
+     * Set console window title
+     *
+     * @param $title
+     */
+    public function setTitle($title);
+
+    /**
+     * Reset console window title to previous value.
+     */
+    public function resetTitle();
+
+
+    /**
+     * Prepare a string that will be rendered in color.
+     *
+     * @param string                     $string
+     * @param null|int   $color    Foreground color
+     * @param null|int   $bgColor  Background color
+     */
+    public function colorize($string, $color = null, $bgColor = null);
+
+    /**
+     * Change current drawing color.
+     *
+     * @param int $color
+     */
+    public function setColor($color);
+
+    /**
+     * Change current drawing background color
+     *
+     * @param int $color
+     */
+    public function setBgColor($color);
+
+    /**
+     * Reset color to console default.
+     */
+    public function resetColor();
+
+
+    /**
+     * Set Console charset to use.
+     *
+     * @param CharsetInterface $charset
+     */
+    public function setCharset(CharsetInterface $charset);
+
+    /**
+     * Get charset currently in use by this adapter.
+     *
+     * @return CharsetInterface $charset
+     */
+    public function getCharset();
+
+    /**
+     * @return CharsetInterface
+     */
+    public function getDefaultCharset();
+
+    /**
+     * Clear console screen
+     */
+    public function clear();
+
+    /**
+     * Clear line at cursor position
+     */
+    public function clearLine();
+
+    /**
+     * Clear console screen
+     */
+    public function clearScreen();
+
+    /**
+     * Read a single line from the console input
+     *
+     * @param int $maxLength        Maximum response length
+     * @return string
+     */
+    public function readLine($maxLength = 2048);
+
+    /**
+     * Read a single character from the console input
+     *
+     * @param string|null   $mask   A list of allowed chars
+     * @return string
+     */
+    public function readChar($mask = null);
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/Adapter/Posix.php b/wcfsetup/install/files/lib/system/api/zend/Console/Adapter/Posix.php
new file mode 100644 (file)
index 0000000..c432754
--- /dev/null
@@ -0,0 +1,405 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console\Adapter;
+
+use Zend\Console\Charset;
+use Zend\Console\Exception;
+use Zend\Console\ColorInterface as Color;
+
+/**
+ * @todo Add GNU readline support
+ * @category   Zend
+ * @package    Zend_Console
+ * @subpackage Adapter
+ * @link http://en.wikipedia.org/wiki/ANSI_escape_code
+ */
+class Posix extends AbstractAdapter
+{
+    /**
+     * Whether or not mbstring is enabled
+     *
+     * @var null|bool
+     */
+    protected static $hasMBString;
+
+    /**
+     * @var Charset\CharsetInterface
+     */
+    protected $charset;
+
+    /**
+     * Map of colors to ANSI codes
+     *
+     * @todo implement Xterm 256 colors (http://www.frexx.de/xterm-256-notes/)
+     * @var array
+     */
+    protected static $ansiColorMap = array(
+        'fg' => array(
+            Color::NORMAL        => '22;39m',
+            Color::RESET         => '22;39m',
+
+            Color::BLACK         => '0;30',
+            Color::RED           => '0;31',
+            Color::GREEN         => '0;32',
+            Color::YELLOW        => '0;33',
+            Color::BLUE          => '0;34',
+            Color::MAGENTA       => '0;35',
+            Color::CYAN          => '0;36',
+            Color::WHITE         => '0;37',
+
+            Color::GRAY          => '1;30',
+            Color::LIGHT_RED     => '1;31',
+            Color::LIGHT_GREEN   => '1;32',
+            Color::LIGHT_YELLOW  => '1;33',
+            Color::LIGHT_BLUE    => '1;34',
+            Color::LIGHT_MAGENTA => '1;35',
+            Color::LIGHT_CYAN    => '1;36',
+            Color::LIGHT_WHITE   => '1;37',
+        ),
+        'bg' => array(
+            Color::NORMAL        => '0;49m',
+            Color::RESET         => '0;49m',
+
+            Color::BLACK         => '40',
+            Color::RED           => '41',
+            Color::GREEN         => '42',
+            Color::YELLOW        => '43',
+            Color::BLUE          => '44',
+            Color::MAGENTA       => '45',
+            Color::CYAN          => '46',
+            Color::WHITE         => '47',
+
+            Color::GRAY          => '40',
+            Color::LIGHT_RED     => '41',
+            Color::LIGHT_GREEN   => '42',
+            Color::LIGHT_YELLOW  => '43',
+            Color::LIGHT_BLUE    => '44',
+            Color::LIGHT_MAGENTA => '45',
+            Color::LIGHT_CYAN    => '46',
+            Color::LIGHT_WHITE   => '47',
+        ),
+    );
+
+    /**
+     * Last fetched TTY mode
+     *
+     * @var string|null
+     */
+    protected $lastTTYMode = null;
+
+    /**
+     * Determine and return current console width.
+     *
+     * @return int
+     */
+    public function getWidth()
+    {
+        static $width;
+        if ($width > 0) {
+            return $width;
+        }
+
+        /**
+         * Try to read env variable
+         */
+        if (($result = getenv('COLUMNS')) !== false) {
+            return $width = (int) $result;
+        }
+
+        /**
+         * Try to read console size from "tput" command
+         */
+        $result = exec('tput cols', $output, $return);
+        if (!$return && is_numeric($result)) {
+            return $width = (int) $result;
+        }
+
+        return $width = parent::getWidth();
+    }
+
+    /**
+     * Determine and return current console height.
+     *
+     * @return false|int
+     */
+    public function getHeight()
+    {
+        static $height;
+        if ($height > 0) {
+            return $height;
+        }
+
+        // Try to read env variable
+        if (($result = getenv('LINES')) !== false) {
+            return $height = (int) $result;
+        }
+
+        // Try to read console size from "tput" command
+        $result = exec('tput lines', $output, $return);
+        if (!$return && is_numeric($result)) {
+            return $height = (int) $result;
+        }
+
+        return $height = parent::getHeight();
+    }
+
+    /**
+     * Run a mode command and store results
+     *
+     * @return void
+     */
+    protected function runModeCommand()
+    {
+        exec('mode', $output, $return);
+        if ($return || !count($output)) {
+            $this->modeResult = '';
+        } else {
+            $this->modeResult = trim(implode('', $output));
+        }
+    }
+
+    /**
+     * Check if console is UTF-8 compatible
+     *
+     * @return bool
+     */
+    public function isUtf8()
+    {
+        // Try to retrieve it from LANG env variable
+        if (($lang = getenv('LANG')) !== false) {
+            return stristr($lang, 'utf-8') || stristr($lang, 'utf8');
+        }
+
+        return false;
+    }
+
+    /**
+     * Show console cursor
+     */
+    public function showCursor()
+    {
+        echo "\x1b[?25h";
+    }
+
+    /**
+     * Hide console cursor
+     */
+    public function hideCursor()
+    {
+        echo "\x1b[?25l";
+    }
+
+    /**
+     * Set cursor position
+     * @param int $x
+     * @param int $y
+     */
+    public function setPos($x, $y)
+    {
+        echo "\x1b[" . $y . ';' . $x . 'f';
+    }
+
+    /**
+     * Prepare a string that will be rendered in color.
+     *
+     * @param  string   $string
+     * @param  int      $color
+     * @param  null|int $bgColor
+     * @throws Exception\BadMethodCallException
+     * @return string
+     */
+    public function colorize($string, $color = null, $bgColor = null)
+    {
+        // Retrieve ansi color codes
+        if ($color !== null) {
+            if (!isset(static::$ansiColorMap['fg'][$color])) {
+                throw new Exception\BadMethodCallException(sprintf(
+                    'Unknown color "%s". Please use one of the Zend\Console\ColorInterface constants',
+                    $color
+                ));
+            }
+            $color = static::$ansiColorMap['fg'][$color];
+        }
+
+        if ($bgColor !== null) {
+            if (!isset(static::$ansiColorMap['bg'][$bgColor])) {
+                throw new Exception\BadMethodCallException(sprintf(
+                    'Unknown color "%s". Please use one of the Zend\Console\ColorInterface constants',
+                    $bgColor
+                ));
+            }
+            $bgColor = static::$ansiColorMap['bg'][$bgColor];
+        }
+
+        return ($color   !== null ? "\x1b[" . $color   . 'm' : '')
+            . ($bgColor !== null ? "\x1b[" . $bgColor . 'm' : '')
+            . $string
+            . "\x1b[22;39m\x1b[0;49m";
+    }
+
+    /**
+     * Change current drawing color.
+     *
+     * @param int $color
+     * @throws Exception\BadMethodCallException
+     */
+    public function setColor($color)
+    {
+        // Retrieve ansi color code
+        if ($color !== null) {
+            if (!isset(static::$ansiColorMap['fg'][$color])) {
+                throw new Exception\BadMethodCallException(sprintf(
+                    'Unknown color "%s". Please use one of the Zend\Console\ColorInterface constants',
+                    $color
+                ));
+            }
+            $color = static::$ansiColorMap['fg'][$color];
+        }
+
+        echo "\x1b[" . $color . 'm';
+    }
+
+    /**
+     * Change current drawing background color
+     *
+     * @param int $bgColor
+     * @throws Exception\BadMethodCallException
+     */
+    public function setBgColor($bgColor)
+    {
+        // Retrieve ansi color code
+        if ($bgColor !== null) {
+            if (!isset(static::$ansiColorMap['bg'][$bgColor])) {
+                throw new Exception\BadMethodCallException(sprintf(
+                    'Unknown color "%s". Please use one of the Zend\Console\ColorInterface constants',
+                    $bgColor
+                ));
+            }
+
+            $bgColor = static::$ansiColorMap['bg'][$bgColor];
+        }
+
+        echo "\x1b[" . ($bgColor) . 'm';
+    }
+
+    /**
+     * Reset color to console default.
+     */
+    public function resetColor()
+    {
+        echo "\x1b[0;49m";  // reset bg color
+        echo "\x1b[22;39m"; // reset fg bold, bright and faint
+        echo "\x1b[25;39m"; // reset fg blink
+        echo "\x1b[24;39m"; // reset fg underline
+    }
+
+    /**
+     * Return current console window title.
+     *
+     * @return string
+     */
+    public function getTitle()
+    {
+    }
+
+    /**
+     * Set Console charset to use.
+     *
+     * @param Charset\CharsetInterface $charset
+     */
+    public function setCharset(Charset\CharsetInterface $charset)
+    {
+        $this->charset = $charset;
+    }
+
+    /**
+     * Get charset currently in use by this adapter.
+     *
+     * @return Charset\CharsetInterface $charset
+     */
+    public function getCharset()
+    {
+        if ($this->charset === null) {
+            $this->charset = $this->getDefaultCharset();
+        }
+
+        return $this->charset;
+    }
+
+    /**
+     * @return Charset\CharsetInterface
+     */
+    public function getDefaultCharset()
+    {
+        if ($this->isUtf8()) {
+            return new Charset\Utf8;
+        }
+        return new Charset\DECSG();
+    }
+
+    /**
+     * Read a single character from the console input
+     *
+     * @param  string|null $mask   A list of allowed chars
+     * @return string
+     */
+    public function readChar($mask = null)
+    {
+        $this->setTTYMode('-icanon -echo');
+
+        $stream = fopen('php://stdin', 'rb');
+        do {
+            $char = fgetc($stream);
+        } while (strlen($char) !== 1 || ($mask !== null && stristr($mask, $char) === false));
+        fclose($stream);
+
+        $this->restoreTTYMode();
+        return $char;
+    }
+
+    /**
+     * Reset color to console default.
+     */
+    public function clear()
+    {
+        echo "\x1b[2J";      // reset bg color
+        $this->setPos(1, 1); // reset cursor position
+    }
+
+    /**
+     * Restore TTY (Console) mode to previous value.
+     *
+     * @return void
+     */
+    protected function restoreTTYMode()
+    {
+        if ($this->lastTTYMode === null) {
+            return;
+        }
+
+        shell_exec('stty ' . escapeshellarg($this->lastTTYMode));
+    }
+
+    /**
+     * Change TTY (Console) mode
+     *
+     * @link  http://en.wikipedia.org/wiki/Stty
+     * @param $mode
+     */
+    protected function setTTYMode($mode)
+    {
+        // Store last mode
+        $this->lastTTYMode = trim(`stty -g`);
+
+        // Set new mode
+        shell_exec('stty '.escapeshellcmd($mode));
+    }
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/Adapter/Virtual.php b/wcfsetup/install/files/lib/system/api/zend/Console/Adapter/Virtual.php
new file mode 100644 (file)
index 0000000..f96f541
--- /dev/null
@@ -0,0 +1,191 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console\Adapter;
+
+use Zend\Console\Charset;
+
+/**
+ * Virtual buffer adapter
+ *
+ * @category   Zend
+ * @package    Zend_Console
+ * @subpackage Adapter
+ */
+class Virtual extends AbstractAdapter
+{
+    /**
+     * Whether or not mbstring is enabled
+     *
+     * @var null|bool
+     */
+    protected static $hasMBString;
+
+    /**
+     * Results of mode system command
+     *
+     * @var mixed
+     */
+    protected $modeResult;
+
+    /**
+     * Determine and return current console width.
+     *
+     * @return int
+     */
+    public function getWidth()
+    {
+        static $width;
+        if ($width > 0) {
+            return $width;
+        }
+
+        // Try to read console size from "mode" command
+        if ($this->modeResult === null) {
+            $this->runProbeCommand();
+        }
+
+        if (preg_match('/Columns\:\s+(\d+)/', $this->modeResult, $matches)) {
+            $width = $matches[1];
+        } else {
+            $width = parent::getWidth();
+        }
+
+        return $width;
+    }
+
+    /**
+     * Determine and return current console height.
+     *
+     * @return false|int
+     */
+    public function getHeight()
+    {
+        static $height;
+        if ($height > 0) {
+            return $height;
+        }
+
+        // Try to read console size from "mode" command
+        if ($this->modeResult === null) {
+            $this->runProbeCommand();
+        }
+
+        if (preg_match('/Rows\:\s+(\d+)/', $this->modeResult, $matches)) {
+            $height = $matches[1];
+        } else {
+            $height = parent::getHeight();
+        }
+
+        return $height;
+    }
+
+    /**
+     * Run and store the results of mode command
+     *
+     * @return void
+     */
+    protected function runProbeCommand()
+    {
+        exec('mode', $output, $return);
+        if ($return || !count($output)) {
+            $this->modeResult = '';
+        } else {
+            $this->modeResult = trim(implode('', $output));
+        }
+    }
+
+    /**
+     * Check if console is UTF-8 compatible
+     *
+     * @return bool
+     */
+    public function isUtf8()
+    {
+        // Try to read code page info from "mode" command
+        if ($this->modeResult === null) {
+            $this->runProbeCommand();
+        }
+
+        if (preg_match('/Code page\:\s+(\d+)/', $this->modeResult, $matches)) {
+            return (int) $matches[1] == 65001;
+        }
+
+        return false;
+    }
+
+    /**
+     * Set cursor position
+     *
+     * @param int $x
+     * @param int $y
+     */
+    public function setPos($x, $y)
+    {
+    }
+
+    /**
+     * Return current console window title.
+     *
+     * @return string
+     */
+    public function getTitle()
+    {
+        // Try to use powershell to retrieve console window title
+        exec('powershell -command "write $Host.UI.RawUI.WindowTitle"', $output, $result);
+        if ($result || !$output) {
+            return '';
+        }
+
+        return trim($output, "\r\n");
+    }
+
+    /**
+     * Set Console charset to use.
+     *
+     * @param Charset\CharsetInterface $charset
+     */
+    public function setCharset(Charset\CharsetInterface $charset)
+    {
+        $this->charset = $charset;
+    }
+
+    /**
+     * Get charset currently in use by this adapter.
+     *
+     * @return Charset\CharsetInterface $charset
+     */
+    public function getCharset()
+    {
+        if ($this->charset === null) {
+            $this->charset = $this->getDefaultCharset();
+        }
+
+        return $this->charset;
+    }
+
+    /**
+     * @return Charset\AsciiExtended
+     */
+    public function getDefaultCharset()
+    {
+        return new Charset\AsciiExtended;
+    }
+
+    /**
+     * Switch to UTF mode
+     *
+     * @return void
+     */
+    protected function switchToUtf8()
+    {
+        shell_exec('mode con cp select=65001');
+    }
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/Adapter/Windows.php b/wcfsetup/install/files/lib/system/api/zend/Console/Adapter/Windows.php
new file mode 100644 (file)
index 0000000..e35984c
--- /dev/null
@@ -0,0 +1,371 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console\Adapter;
+
+use Zend\Console\Charset;
+use Zend\Console\Exception;
+
+/**
+ * @category   Zend
+ * @package    Zend_Console
+ * @subpackage Adapter
+ */
+class Windows extends Virtual
+{
+    /**
+     * Whether or not mbstring is enabled
+     *
+     * @var null|bool
+     */
+    protected static $hasMBString;
+
+    /**
+     * Results of probing system capabilities
+     *
+     * @var mixed
+     */
+    protected $probeResult;
+
+    /**
+     * Results of mode command
+     *
+     * @var mixed
+     */
+    protected $modeResult;
+
+    /**
+     * Determine and return current console width.
+     *
+     * @return int
+     */
+    public function getWidth()
+    {
+        static $width;
+        if ($width > 0) {
+            return $width;
+        }
+
+        // Try to read console size from "mode" command
+        if ($this->probeResult === null) {
+            $this->runProbeCommand();
+        }
+
+        if (count($this->probeResult) && (int) $this->probeResult[0]) {
+            $width = (int)$this->probeResult[0];
+        } else {
+            $width = parent::getWidth();
+        }
+
+        return $width;
+    }
+
+    /**
+     * Determine and return current console height.
+     *
+     * @return false|int
+     */
+    public function getHeight()
+    {
+        static $height;
+        if ($height > 0) {
+            return $height;
+        }
+
+        // Try to read console size from "mode" command
+        if ($this->probeResult === null) {
+            $this->runProbeCommand();
+        }
+
+        if (count($this->probeResult) && (int) $this->probeResult[1]) {
+            $height = (int) $this->probeResult[1];
+        } else {
+            $height = parent::getheight();
+        }
+
+        return $height;
+    }
+
+    /**
+     * Probe for system capabilities and cache results
+     *
+     * Run a Windows Powershell command that determines parameters of console window. The command is fed through
+     * standard input (with echo) to prevent Powershell from creating a sub-thread and hanging PHP when run through
+     * a debugger/IDE.
+     *
+     * @return void
+     */
+    protected function runProbeCommand()
+    {
+        exec(
+            'echo $size = $Host.ui.rawui.windowsize; write $($size.width) $($size.height) | powershell -NonInteractive -NoProfile -NoLogo -OutputFormat Text -Command -',
+            $output,
+            $return
+        );
+        if ($return || empty($output)) {
+            $this->probeResult = '';
+        } else {
+            $this->probeResult = $output;
+        }
+    }
+
+    /**
+     * Run and cache results of mode command
+     *
+     * @return void
+     */
+    protected function runModeCommand()
+    {
+        exec('mode', $output, $return);
+        if ($return || !count($output)) {
+            $this->modeResult = '';
+        } else {
+            $this->modeResult = trim(implode('', $output));
+        }
+    }
+
+    /**
+     * Check if console is UTF-8 compatible
+     *
+     * @return bool
+     */
+    public function isUtf8()
+    {
+        // Try to read code page info from "mode" command
+        if ($this->modeResult === null) {
+            $this->runModeCommand();
+        }
+
+        if (preg_match('/Code page\:\s+(\d+)/', $this->modeResult, $matches)) {
+            return (int) $matches[1] == 65001;
+        }
+
+        return false;
+    }
+
+    /**
+     * Set cursor position
+     * @param int $x
+     * @param int $y
+     */
+    public function setPos($x, $y)
+    {
+    }
+
+    /**
+     * Return current console window title.
+     *
+     * @return string
+     */
+    public function getTitle()
+    {
+        // Try to use powershell to retrieve console window title
+        exec('powershell -command "write $Host.UI.RawUI.WindowTitle"', $output, $result);
+        if ($result || !$output) {
+            return '';
+        }
+
+        return trim($output, "\r\n");
+    }
+
+    /**
+     * Set Console charset to use.
+     *
+     * @param Charset\CharsetInterface $charset
+     */
+    public function setCharset(Charset\CharsetInterface $charset)
+    {
+        $this->charset = $charset;
+    }
+
+    /**
+     * Get charset currently in use by this adapter.
+     *
+     * @return Charset\CharsetInterface $charset
+     */
+    public function getCharset()
+    {
+        if ($this->charset === null) {
+            $this->charset = $this->getDefaultCharset();
+        }
+
+        return $this->charset;
+    }
+
+    /**
+     * @return Charset\AsciiExtended
+     */
+    public function getDefaultCharset()
+    {
+        return new Charset\AsciiExtended;
+    }
+
+    /**
+     * Switch to utf-8 encoding
+     *
+     * @return void
+     */
+    protected function switchToUtf8()
+    {
+        shell_exec('mode con cp select=65001');
+    }
+
+    /**
+     * Clear console screen
+     */
+    public function clear()
+    {
+        // Attempt to clear the screen using PowerShell command
+        exec("powershell -NonInteractive -NoProfile -NoLogo -OutputFormat Text -Command Clear-Host", $output, $return);
+
+        if ($return) {
+            // Could not run powershell... fall back to filling the buffer with newlines
+            echo str_repeat("\r\n", $this->getHeight());
+        }
+    }
+
+    /**
+     * Clear line at cursor position
+     */
+    public function clearLine()
+    {
+        echo "\r" . str_repeat(' ', $this->getWidth()) . "\r";
+    }
+
+    /**
+     * Read a single character from the console input
+     *
+     * @param  string|null $mask A list of allowed chars
+     * @throws Exception\RuntimeException
+     * @return string
+     */
+    public function readChar($mask = null)
+    {
+        // Decide if we can use `choice` tool
+        $useChoice = $mask !== null && preg_match('/^[a-zA-Z0-9]+$/D', $mask);
+
+        if ($useChoice) {
+            // Use Windows 95+ "choice" command, which allows for reading a
+            // single character matching a mask, but is limited to lower ASCII
+            // range.
+            do {
+                exec('choice /n /cs /c:' . $mask, $output, $return);
+                if ($return == 255 || $return < 1 || $return > strlen($mask)) {
+                    throw new Exception\RuntimeException('"choice" command failed to run. Are you using Windows XP or newer?');
+                }
+
+                // Fetch the char from mask
+                $char = substr($mask, $return - 1, 1);
+            } while (!$char || ($mask !== null && !stristr($mask, $char)));
+
+            return $char;
+        }
+
+        // Try to use PowerShell, giving it console access. Because PowersShell
+        // interpreter can take a short while to load, we are emptying the
+        // whole keyboard buffer and picking the last key that has been pressed
+        // before or after PowerShell command has started. The ASCII code for
+        // that key is then converted to a character.
+        if ($mask === null) {
+            exec(
+                'powershell -NonInteractive -NoProfile -NoLogo -OutputFormat Text -Command "'
+                    . 'while ($Host.UI.RawUI.KeyAvailable) {$key = $Host.UI.RawUI.ReadKey(\'NoEcho,IncludeKeyDown\');}'
+                    . 'write $key.VirtualKeyCode;'
+                    . '"',
+                $result,
+                $return
+            );
+
+            // Retrieve char from the result.
+            $char = !empty($result) ? implode('', $result) : null;
+
+            if (!empty($char) && !$return) {
+                // We have obtained an ASCII code, convert back to a char ...
+                $char = chr($char);
+
+                // ... and return it...
+                return $char;
+            }
+        } else {
+            // Windows and DOS will return carriage-return char (ASCII 13) when
+            // the user presses [ENTER] key, but Console Adapter user might
+            // have provided a \n Newline (ASCII 10) in the mask, to allow [ENTER].
+            // We are going to replace all CR with NL to conform.
+            $mask = strtr($mask, "\n", "\r");
+
+            // Prepare a list of ASCII codes from mask chars
+            $asciiMask = array_map(function ($char) {
+                return ord($char);
+            }, str_split($mask));
+            $asciiMask = array_unique($asciiMask);
+
+            // Char mask filtering is now handled by the PowerShell itself,
+            // because it's a much faster method than invoking PS interpreter
+            // after each mismatch. The command should return ASCII code of a
+            // matching key.
+            $result = $return = null;
+
+            exec(
+                'powershell -NonInteractive -NoProfile -NoLogo -OutputFormat Text -Command "'
+                    . '[int[]] $mask = ' . join(',', $asciiMask) . ';'
+                    . 'do {'
+                        . '$key = $Host.UI.RawUI.ReadKey(\'NoEcho,IncludeKeyDown\').VirtualKeyCode;'
+                    . '} while( !($mask -contains $key) );'
+                    . 'write $key;'
+                    . '"',
+                $result,
+                $return
+            );
+
+            $char = !empty($result) ? trim(implode('', $result)) : null;
+
+            if (!$return && $char && ($mask === null || in_array($char, $asciiMask))) {
+                // Normalize CR to LF
+                if ($char == 13) {
+                    $char = 10;
+                }
+
+                // Convert to a char
+                $char = chr($char);
+
+                // ... and return it...
+                return $char;
+            }
+        }
+
+        // Fall back to standard input, which on Windows does not allow reading
+        // a single character. This is a limitation of Windows streams
+        // implementation (not PHP) and this behavior cannot be changed with a
+        // command like "stty", known to POSIX systems.
+        $stream = fopen('php://stdin', 'rb');
+        do {
+            $char = fgetc($stream);
+            $char = substr(trim($char), 0, 1);
+        } while (!$char || ($mask !== null && !stristr($mask, $char)));
+        fclose($stream);
+
+        return $char;
+    }
+
+    /**
+     * Read a single line from the console input.
+     *
+     * @param  int $maxLength Maximum response length
+     * @return string
+     */
+    public function readLine($maxLength = 2048)
+    {
+        $f    = fopen('php://stdin','r');
+        $line = rtrim(fread($f, $maxLength),"\r\n");
+        fclose($f);
+
+        return $line;
+    }
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/Adapter/WindowsAnsicon.php b/wcfsetup/install/files/lib/system/api/zend/Console/Adapter/WindowsAnsicon.php
new file mode 100644 (file)
index 0000000..247bb81
--- /dev/null
@@ -0,0 +1,307 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console\Adapter;
+
+use Zend\Console\Charset\CharsetInterface;
+use Zend\Console\Exception;
+use Zend\Console\Charset;
+
+/**
+ * MS Windows with ANSICON console adapter
+ *
+ * This adapter requires ANSICON extension to be installed. It can be obtained from:
+ *      https://github.com/adoxa/ansicon
+ *
+ * ANSICON has to be loaded and enabled before using this adapter. It's best to install
+ * it using following command:
+ *      ansicon -I
+ *
+ * Console should not run in UTF8 code page (65001), because ANSICON does not behave well with it.
+ * It's best to use non-unicode code page 437, 850, 851, 852 or similar. Run "help mode" for more
+ * information on how to change Windows console code page.
+ *
+ * @category   Zend
+ * @package    Zend_Console
+ * @subpackage Adapter
+ */
+class WindowsAnsicon extends Posix
+{
+    /**
+     * Whether or not mbstring is enabled
+     *
+     * @var null|bool
+     */
+    protected static $hasMBString;
+
+    /**
+     * Results of mode command
+     *
+     * @var mixed
+     */
+    protected $modeResult;
+
+    /**
+     * Determine and return current console width.
+     *
+     * @return int
+     */
+    public function getWidth()
+    {
+        static $width;
+        if ($width > 0) {
+            return $width;
+        }
+
+        // Try to read console size from ANSICON env var
+        if (preg_match('/\((\d+)x/', getenv('ANSICON'), $matches)) {
+            $width = $matches[1];
+        } else {
+            $width = AbstractAdapter::getWidth();
+        }
+
+        return $width;
+    }
+
+    /**
+     * Determine and return current console height.
+     *
+     * @return false|int
+     */
+    public function getHeight()
+    {
+        static $height;
+        if ($height > 0) {
+            return $height;
+        }
+
+        // Try to read console size from ANSICON env var
+        if (preg_match('/\(\d+x(\d+)/', getenv('ANSICON'), $matches)) {
+            $height = $matches[1];
+        } else {
+            $height = AbstractAdapter::getHeight();
+        }
+        return $height;
+    }
+
+    /**
+     * Run and cache results of mode command
+     *
+     * @return void
+     */
+    protected function runModeCommand()
+    {
+        exec('mode', $output, $return);
+        if ($return || !count($output)) {
+            $this->modeResult = '';
+        } else {
+            $this->modeResult = trim(implode('', $output));
+        }
+    }
+
+    /**
+     * Check if console is UTF-8 compatible
+     *
+     * @return bool
+     */
+    public function isUtf8()
+    {
+        // Try to read code page info from "mode" command
+        if ($this->modeResult === null) {
+            $this->runModeCommand();
+        }
+
+        if (preg_match('/Code page\:\s+(\d+)/', $this->modeResult, $matches)) {
+            return (int) $matches[1] == 65001;
+        }
+
+        return false;
+    }
+
+    /**
+     * Return current console window title.
+     *
+     * @return string
+     */
+    public function getTitle()
+    {
+        // Try to use powershell to retrieve console window title
+        exec('powershell -command "write $Host.UI.RawUI.WindowTitle"', $output, $result);
+        if ($result || !$output) {
+            return '';
+        }
+
+        return trim($output, "\r\n");
+    }
+
+    /**
+     * Clear console screen
+     */
+    public function clear()
+    {
+        echo chr(27) . '[1J' . chr(27) . '[u';
+    }
+
+    /**
+     * Clear line at cursor position
+     */
+    public function clearLine()
+    {
+        echo chr(27) . '[1K';
+    }
+
+    /**
+     * Set Console charset to use.
+     *
+     * @param CharsetInterface $charset
+     */
+    public function setCharset(CharsetInterface $charset)
+    {
+        $this->charset = $charset;
+    }
+
+    /**
+     * Get charset currently in use by this adapter.
+     *
+
+     * @return CharsetInterface $charset
+     */
+    public function getCharset()
+    {
+        if ($this->charset === null) {
+            $this->charset = $this->getDefaultCharset();
+        }
+
+        return $this->charset;
+    }
+
+    /**
+     * @return Charset\AsciiExtended
+     */
+    public function getDefaultCharset()
+    {
+        return new Charset\AsciiExtended();
+    }
+
+    /**
+     * Read a single character from the console input
+     *
+     * @param  string|null $mask A list of allowed chars
+     * @return string
+     * @throws Exception\RuntimeException
+     */
+    public function readChar($mask = null)
+    {
+        // Decide if we can use `choice` tool
+        $useChoice = $mask !== null && preg_match('/^[a-zA-Z0-9]+$/D', $mask);
+
+        if ($useChoice) {
+            // Use Windows 98+ "choice" command, which allows for reading a
+            // single character matching a mask, but is limited to lower ASCII
+            // range.
+            do {
+                exec('choice /n /cs /c:' . $mask, $output, $return);
+                if ($return == 255 || $return < 1 || $return > strlen($mask)) {
+                    throw new Exception\RuntimeException('"choice" command failed to run. Are you using Windows XP or newer?');
+                }
+
+                // Fetch the char from mask
+                $char = substr($mask, $return - 1, 1);
+            } while (!$char || ($mask !== null && !stristr($mask, $char)));
+
+            return $char;
+        }
+
+        // Try to use PowerShell, giving it console access. Because PowersShell
+        // interpreter can take a short while to load, we are emptying the
+        // whole keyboard buffer and picking the last key that has been pressed
+        // before or after PowerShell command has started. The ASCII code for
+        // that key is then converted to a character.
+        if ($mask === null) {
+            exec(
+                'powershell -NonInteractive -NoProfile -NoLogo -OutputFormat Text -Command "'
+                    . 'while ($Host.UI.RawUI.KeyAvailable) {$key = $Host.UI.RawUI.ReadKey(\'NoEcho,IncludeKeyDown\');}'
+                    . 'write $key.VirtualKeyCode;'
+                    . '"',
+                $result,
+                $return
+            );
+
+            // Retrieve char from the result.
+            $char = !empty($result) ? implode('', $result) : null;
+
+            if (!empty($char) && !$return) {
+                // We have obtained an ASCII code, convert back to a char ...
+                $char = chr($char);
+
+                // ... and return it...
+                return $char;
+            }
+        } else {
+            // Windows and DOS will return carriage-return char (ASCII 13) when
+            // the user presses [ENTER] key, but Console Adapter user might
+            // have provided a \n Newline (ASCII 10) in the mask, to allow
+            // [ENTER].  We are going to replace all CR with NL to conform.
+            $mask = strtr($mask, "\n", "\r");
+
+            // Prepare a list of ASCII codes from mask chars
+            $asciiMask = array_map(function ($char) {
+                return ord($char);
+            }, str_split($mask));
+            $asciiMask = array_unique($asciiMask);
+
+            // Char mask filtering is now handled by the PowerShell itself,
+            // because it's a much faster method than invoking PS interpreter
+            // after each mismatch. The command should return ASCII code of a
+            // matching key.
+            $result = $return = null;
+            exec(
+                'powershell -NonInteractive -NoProfile -NoLogo -OutputFormat Text -Command "'
+                    . '[int[]] $mask = '.join(',', $asciiMask).';'
+                    . 'do {'
+                        . '$key = $Host.UI.RawUI.ReadKey(\'NoEcho,IncludeKeyDown\').VirtualKeyCode;'
+                    . '} while( !($mask -contains $key) );'
+                    . 'write $key;'
+                    . '"',
+                $result,
+                $return
+            );
+
+            $char = !empty($result) ? trim(implode('', $result)) : null;
+
+            if (!$return && $char && ($mask === null || in_array($char, $asciiMask))) {
+                // We have obtained an ASCII code, check if it is a carriage
+                // return and normalize it as needed
+                if ($char == 13) {
+                    $char = 10;
+                }
+
+                // Convert to a character
+                $char = chr($char);
+
+                // ... and return it...
+                return $char;
+            }
+        }
+
+        // Fall back to standard input, which on Windows does not allow reading
+        // a single character. This is a limitation of Windows streams
+        // implementation (not PHP) and this behavior cannot be changed with a
+        // command like "stty", known to POSIX systems.
+        $stream = fopen('php://stdin', 'rb');
+        do {
+            $char = fgetc($stream);
+            $char = substr(trim($char), 0, 1);
+        } while (!$char || ($mask !== null && !stristr($mask, $char)));
+        fclose($stream);
+
+        return $char;
+    }
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/Charset/Ascii.php b/wcfsetup/install/files/lib/system/api/zend/Console/Charset/Ascii.php
new file mode 100644 (file)
index 0000000..5614127
--- /dev/null
@@ -0,0 +1,55 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console\Charset;
+
+/**
+ * Basic (low) ASCII line drawing characters.
+ *
+ * @category   Zend
+ * @package    Zend_Console
+ * @subpackage Charset
+ */
+class Ascii implements CharsetInterface
+{
+
+    const ACTIVATE          = "";
+    const DEACTIVATE        = "";
+
+    const BLOCK             = "#";
+    const SHADE_LIGHT       = " ";
+    const SHADE_MEDIUM      = "#";
+    const SHADE_DARK        = "#";
+
+    const LINE_SINGLE_EW    = "-";
+    const LINE_SINGLE_NS    = "|";
+    const LINE_SINGLE_NW    = "+";
+    const LINE_SINGLE_NE    = "+";
+    const LINE_SINGLE_SE    = "+";
+    const LINE_SINGLE_SW    = "+";
+    const LINE_SINGLE_CROSS = "+";
+
+    const LINE_DOUBLE_EW    = "=";
+    const LINE_DOUBLE_NS    = "|";
+    const LINE_DOUBLE_NW    = "+";
+    const LINE_DOUBLE_NE    = "+";
+    const LINE_DOUBLE_SE    = "+";
+    const LINE_DOUBLE_SW    = "+";
+    const LINE_DOUBLE_CROSS = "+";
+
+    const LINE_BLOCK_EW     = "=";
+    const LINE_BLOCK_NS     = "#";
+    const LINE_BLOCK_NW     = "+";
+    const LINE_BLOCK_NE     = "+";
+    const LINE_BLOCK_SE     = "+";
+    const LINE_BLOCK_SW     = "+";
+    const LINE_BLOCK_CROSS  = "+";
+
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/Charset/AsciiExtended.php b/wcfsetup/install/files/lib/system/api/zend/Console/Charset/AsciiExtended.php
new file mode 100644 (file)
index 0000000..b13acaf
--- /dev/null
@@ -0,0 +1,55 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console\Charset;
+
+/**
+ * Extended ASCII character set (positions 127+, MS DOS & Windows compatible)
+ *
+ * @link http://en.wikipedia.org/wiki/Box-drawing_characters
+ * @category   Zend
+ * @package    Zend_Console
+ * @subpackage Charset
+ */
+class AsciiExtended implements CharsetInterface
+{
+
+    const ACTIVATE          = "";
+    const DEACTIVATE        = "";
+
+    const BLOCK             = "\xdb";
+    const SHADE_LIGHT       = "\xb0";
+    const SHADE_MEDIUM      = "\xb1";
+    const SHADE_DARK        = "\xb2";
+
+    const LINE_SINGLE_EW    = "\xc4";
+    const LINE_SINGLE_NS    = "\xb3";
+    const LINE_SINGLE_NW    = "\xda";
+    const LINE_SINGLE_NE    = "\xbf";
+    const LINE_SINGLE_SE    = "\xd9";
+    const LINE_SINGLE_SW    = "\xc0";
+    const LINE_SINGLE_CROSS = "\xc5";
+
+    const LINE_DOUBLE_EW    = "\xcd";
+    const LINE_DOUBLE_NS    = "\xba";
+    const LINE_DOUBLE_NW    = "\xc9";
+    const LINE_DOUBLE_NE    = "\xbb";
+    const LINE_DOUBLE_SE    = "\xbc";
+    const LINE_DOUBLE_SW    = "\xc8";
+    const LINE_DOUBLE_CROSS = "\xce";
+
+    const LINE_BLOCK_EW     = "\xdb";
+    const LINE_BLOCK_NS     = "\xdb";
+    const LINE_BLOCK_NW     = "\xdb";
+    const LINE_BLOCK_NE     = "\xdb";
+    const LINE_BLOCK_SE     = "\xdb";
+    const LINE_BLOCK_SW     = "\xdb";
+    const LINE_BLOCK_CROSS  = "\xdb";
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/Charset/CharsetInterface.php b/wcfsetup/install/files/lib/system/api/zend/Console/Charset/CharsetInterface.php
new file mode 100644 (file)
index 0000000..98cd068
--- /dev/null
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console\Charset;
+
+/**
+ * @category   Zend
+ * @package    Zend_Console
+ */
+interface CharsetInterface
+{
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/Charset/DECSG.php b/wcfsetup/install/files/lib/system/api/zend/Console/Charset/DECSG.php
new file mode 100644 (file)
index 0000000..d86bd2a
--- /dev/null
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console\Charset;
+
+/**
+ * DEC Special Graphics (VT100 line drawing) character set
+ *
+ * @link http://vt100.net/docs/vt220-rm/table2-4.html
+ * @category   Zend
+ * @package    Zend_Console
+ * @subpackage Charset
+ */
+class DECSG implements CharsetInterface
+{
+
+    const ACTIVATE          = "\x1b(0";
+    const DEACTIVATE        = "\x1b(B";
+
+    const BLOCK             = "\x61";
+    const SHADE_LIGHT       = "\x61";
+    const SHADE_MEDIUM      = "\x61";
+    const SHADE_DARK        = "\x61";
+
+    const LINE_SINGLE_EW    = "\x71";
+    const LINE_SINGLE_NS    = "\x78";
+    const LINE_SINGLE_NW    = "\x6c";
+    const LINE_SINGLE_NE    = "\x6b";
+    const LINE_SINGLE_SE    = "\x6a";
+    const LINE_SINGLE_SW    = "\x6d";
+    const LINE_SINGLE_CROSS = "\x6e";
+
+    const LINE_DOUBLE_EW    = "\x73";
+    const LINE_DOUBLE_NS    = "\x78";
+    const LINE_DOUBLE_NW    = "\x6c";
+    const LINE_DOUBLE_NE    = "\x5b";
+    const LINE_DOUBLE_SE    = "\x6a";
+    const LINE_DOUBLE_SW    = "\x6d";
+    const LINE_DOUBLE_CROSS = "\x6e";
+
+    const LINE_BLOCK_EW    = "\x61";
+    const LINE_BLOCK_NS    = "\x61";
+    const LINE_BLOCK_NW    = "\x61";
+    const LINE_BLOCK_NE    = "\x61";
+    const LINE_BLOCK_SE    = "\x61";
+    const LINE_BLOCK_SW    = "\x61";
+    const LINE_BLOCK_CROSS = "\x61";
+
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/Charset/Utf8.php b/wcfsetup/install/files/lib/system/api/zend/Console/Charset/Utf8.php
new file mode 100644 (file)
index 0000000..4c1cb74
--- /dev/null
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console\Charset;
+
+/**
+ * UTF-8 box drawing
+ *
+ * @link http://en.wikipedia.org/wiki/Box-drawing_characters
+ * @category   Zend
+ * @package    Zend_Console
+ * @subpackage Charset
+ */
+class Utf8 implements CharsetInterface
+{
+
+    const ACTIVATE          = "";
+    const DEACTIVATE        = "";
+
+    const BLOCK = "█";
+    const SHADE_LIGHT = "░";
+    const SHADE_MEDIUM = "▒";
+    const SHADE_DARK = "▓";
+
+    const LINE_SINGLE_EW = "─";
+    const LINE_SINGLE_NS = "│";
+    const LINE_SINGLE_NW = "┌";
+    const LINE_SINGLE_NE = "┐";
+    const LINE_SINGLE_SE = "┘";
+    const LINE_SINGLE_SW = "└";
+    const LINE_SINGLE_CROSS = "┼";
+
+    const LINE_DOUBLE_EW = "═";
+    const LINE_DOUBLE_NS = "║";
+    const LINE_DOUBLE_NW = "╔";
+    const LINE_DOUBLE_NE = "╗";
+    const LINE_DOUBLE_SE = "╝";
+    const LINE_DOUBLE_SW = "╚";
+    const LINE_DOUBLE_CROSS = "╬";
+
+    const LINE_BLOCK_EW = "█";
+    const LINE_BLOCK_NS = "█";
+    const LINE_BLOCK_NW = "█";
+    const LINE_BLOCK_NE = "█";
+    const LINE_BLOCK_SE = "█";
+    const LINE_BLOCK_SW = "█";
+    const LINE_BLOCK_CROSS = "█";
+
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/Charset/Utf8Heavy.php b/wcfsetup/install/files/lib/system/api/zend/Console/Charset/Utf8Heavy.php
new file mode 100644 (file)
index 0000000..be50118
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console\Charset;
+
+/**
+ * UTF-8 box drawing (modified to use heavy single lines)
+ *
+ * @link http://en.wikipedia.org/wiki/Box-drawing_characters
+ * @category   Zend
+ * @package    Zend_Console
+ * @subpackage Charset
+ */
+class Utf8Heavy extends Utf8
+{
+
+    const LINE_SINGLE_EW = "━";
+    const LINE_SINGLE_NS = "┃";
+    const LINE_SINGLE_NW = "┏";
+    const LINE_SINGLE_NE = "┓";
+    const LINE_SINGLE_SE = "┛";
+    const LINE_SINGLE_SW = "┗";
+    const LINE_SINGLE_CROSS = "╋";
+
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/ColorInterface.php b/wcfsetup/install/files/lib/system/api/zend/Console/ColorInterface.php
new file mode 100644 (file)
index 0000000..7bcbb2e
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console;
+
+/**
+ * @category   Zend
+ * @package    Zend_Console
+ */
+interface ColorInterface
+{
+    const NORMAL = 0;
+    const RESET = 0;
+
+    const BLACK = 1;
+    const RED = 2;
+    const GREEN = 3;
+    const YELLOW = 4;
+    const BLUE = 5;
+    const MAGENTA = 6;
+    const CYAN = 7;
+    const WHITE = 8;
+
+    const GRAY = 9;
+    const LIGHT_RED = 10;
+    const LIGHT_GREEN = 11;
+    const LIGHT_YELLOW = 12;
+    const LIGHT_BLUE = 13;
+    const LIGHT_MAGENTA = 14;
+    const LIGHT_CYAN = 15;
+    const LIGHT_WHITE = 16;
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/Console.php b/wcfsetup/install/files/lib/system/api/zend/Console/Console.php
new file mode 100644 (file)
index 0000000..fb6a375
--- /dev/null
@@ -0,0 +1,197 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console;
+
+/**
+ * An static, utility class for interacting with Console environment.
+ * Declared abstract to prevent from instantiating.
+ *
+ * @category   Zend
+ * @package    Zend_Console
+ */
+abstract class Console
+{
+    /**
+     * @var Adapter\AdapterInterface
+     */
+    protected static $instance;
+
+    /**
+     * Allow overriding whether or not we're in a console env. If set, and
+     * boolean, returns that value from isConsole().
+     * @var bool
+     */
+    protected static $isConsole;
+
+    /**
+     * Create and return Adapter\AdapterInterface instance.
+     *
+     * @param  null|string  $forceAdapter Optional adapter class name. Ccan be absolute namespace or class name
+     *                                    relative to Zend\Console\Adapter\. If not provided, a best matching
+     *                                    adapter will be automatically selected.
+     * @param  null|string  $forceCharset optional charset name can be absolute namespace or class name relative to
+     *                                    Zend\Console\Charset\. If not provided, charset will be detected
+     *                                    automatically.
+     * @throws Exception\InvalidArgumentException
+     * @throws Exception\RuntimeException
+     * @return Adapter\AdapterInterface
+     */
+    public static function getInstance($forceAdapter = null, $forceCharset = null)
+    {
+        if (static::$instance instanceof Adapter\AdapterInterface) {
+            return static::$instance;
+        }
+
+        // Create instance
+
+        if ($forceAdapter !== null) {
+            // Use the supplied adapter class
+            if (substr($forceAdapter, 0, 1) == '\\') {
+                $className = $forceAdapter;
+            } elseif (stristr($forceAdapter, '\\')) {
+                $className = __NAMESPACE__ . '\\' . ltrim($forceAdapter, '\\');
+            } else {
+                $className = __NAMESPACE__ . '\\Adapter\\' . $forceAdapter;
+            }
+
+            if (!class_exists($className)) {
+                throw new Exception\InvalidArgumentException(sprintf(
+                    'Cannot find Console adapter class "%s"',
+                    $className
+                ));
+            }
+        } else {
+            // Try to detect best instance for console
+            $className = static::detectBestAdapter();
+
+            // Check if we were able to detect console adapter
+            if (!$className) {
+                throw new Exception\RuntimeException('Cannot create Console adapter - am I running in a console?');
+            }
+        }
+
+        // Create adapter instance
+        static::$instance = new $className();
+
+        // Try to use the supplied charset class
+        if ($forceCharset !== null) {
+            if (substr($forceCharset, 0, 1) == '\\') {
+                $className = $forceCharset;
+            } elseif (stristr($forceAdapter, '\\')) {
+                $className = __NAMESPACE__ . '\\' . ltrim($forceCharset, '\\');
+            } else {
+                $className = __NAMESPACE__ . '\\Charset\\' . $forceCharset;
+            }
+
+            if (!class_exists($className)) {
+                throw new Exception\InvalidArgumentException(sprintf(
+                    'Cannot find Charset class "%s"',
+                    $className
+                ));
+            }
+
+            // Set adapter charset
+            static::$instance->setCharset(new $className());
+        }
+
+        return static::$instance;
+    }
+
+    /**
+     * Check if currently running under MS Windows
+     *
+     * @see http://stackoverflow.com/questions/738823/possible-values-for-php-os
+     * @return bool
+     */
+    public static function isWindows()
+    {
+        return
+            ( defined('PHP_OS') && ( substr_compare(PHP_OS,'win',0,3,true) === 0) ) ||
+            (getenv('OS') != false && substr_compare(getenv('OS'),'windows',0,7,true))
+        ;
+    }
+
+    /**
+     * Check if running under MS Windows Ansicon
+     *
+     * @return bool
+     */
+    public static function isAnsicon()
+    {
+        return getenv('ANSICON') !== false;
+    }
+
+    /**
+     * Check if running in a console environment (CLI)
+     *
+     * By default, returns value of PHP_SAPI global constant. If $isConsole is
+     * set, and a boolean value, that value will be returned.
+     *
+     * @return bool
+     */
+    public static function isConsole()
+    {
+        if (null !== static::$isConsole && is_bool(static::$isConsole)) {
+            return static::$isConsole;
+        }
+        return PHP_SAPI == 'cli';
+    }
+
+    /**
+     * Override the "is console environment" flag
+     *
+     * @param  null|bool $flag
+     */
+    public static function overrideIsConsole($flag)
+    {
+        static::$isConsole = $flag;
+    }
+
+    /**
+     * Try to detect best matching adapter
+     * @return string|null
+     */
+    public static function detectBestAdapter()
+    {
+        // Check if we are in a console environment
+        if (!static::isConsole()) {
+            return null;
+        }
+
+        // Check if we're on windows
+        if (static::isWindows()) {
+            if (static::isAnsicon()) {
+                $className = __NAMESPACE__ . '\Adapter\WindowsAnsicon';
+            } else {
+                $className = __NAMESPACE__ . '\Adapter\Windows';
+            }
+
+            return $className;
+        }
+
+        // Default is a Posix console
+        $className = __NAMESPACE__ . '\Adapter\Posix';
+        return $className;
+    }
+
+    /**
+     * Pass-thru static call to current AdapterInterface instance.
+     *
+     * @param $funcName
+     * @param $arguments
+     * @return mixed
+     */
+    public static function __callStatic($funcName, $arguments)
+    {
+        $instance = static::getInstance();
+        return call_user_func_array(array($instance, $funcName), $arguments);
+    }
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/Exception/BadMethodCallException.php b/wcfsetup/install/files/lib/system/api/zend/Console/Exception/BadMethodCallException.php
new file mode 100644 (file)
index 0000000..223b812
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console\Exception;
+
+/**
+ * @category   Zend
+ * @package    Zend_Console
+ * @subpackage Exception
+ */
+class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface
+{
+
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/Exception/ExceptionInterface.php b/wcfsetup/install/files/lib/system/api/zend/Console/Exception/ExceptionInterface.php
new file mode 100644 (file)
index 0000000..1412b51
--- /dev/null
@@ -0,0 +1,20 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console\Exception;
+
+/**
+ * @category   Zend
+ * @package    Zend_Console
+ * @subpackage Exception
+ */
+interface ExceptionInterface
+{
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/Exception/InvalidArgumentException.php b/wcfsetup/install/files/lib/system/api/zend/Console/Exception/InvalidArgumentException.php
new file mode 100644 (file)
index 0000000..64fba73
--- /dev/null
@@ -0,0 +1,20 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console\Exception;
+
+/**
+ * @category   Zend
+ * @package    Zend_Console
+ * @subpackage Exception
+ */
+class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
+{
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/Exception/RuntimeException.php b/wcfsetup/install/files/lib/system/api/zend/Console/Exception/RuntimeException.php
new file mode 100644 (file)
index 0000000..fea73af
--- /dev/null
@@ -0,0 +1,48 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console\Exception;
+
+/**
+ * @category   Zend
+ * @package    Zend_Console
+ * @subpackage Exception
+ */
+class RuntimeException extends \RuntimeException implements ExceptionInterface
+{
+    /**
+     * Usage
+     *
+     * @var string
+     */
+    protected $usage = '';
+
+    /**
+     * Constructor
+     *
+     * @param string $message
+     * @param string $usage
+     */
+    public function __construct($message, $usage = '')
+    {
+        $this->usage = $usage;
+        parent::__construct($message);
+    }
+
+    /**
+     * Returns the usage
+     *
+     * @return string
+     */
+    public function getUsageMessage()
+    {
+        return $this->usage;
+    }
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/Getopt.php b/wcfsetup/install/files/lib/system/api/zend/Console/Getopt.php
new file mode 100644 (file)
index 0000000..0de0fcd
--- /dev/null
@@ -0,0 +1,1021 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console;
+
+/**
+ * Getopt is a class to parse options for command-line
+ * applications.
+ *
+ * Terminology:
+ * Argument: an element of the argv array.  This may be part of an option,
+ *   or it may be a non-option command-line argument.
+ * Flag: the letter or word set off by a '-' or '--'.  Example: in '--output filename',
+ *   '--output' is the flag.
+ * Parameter: the additional argument that is associated with the option.
+ *   Example: in '--output filename', the 'filename' is the parameter.
+ * Option: the combination of a flag and its parameter, if any.
+ *   Example: in '--output filename', the whole thing is the option.
+ *
+ * The following features are supported:
+ *
+ * - Short flags like '-a'.  Short flags are preceded by a single
+ *   dash.  Short flags may be clustered e.g. '-abc', which is the
+ *   same as '-a' '-b' '-c'.
+ * - Long flags like '--verbose'.  Long flags are preceded by a
+ *   double dash.  Long flags may not be clustered.
+ * - Options may have a parameter, e.g. '--output filename'.
+ * - Parameters for long flags may also be set off with an equals sign,
+ *   e.g. '--output=filename'.
+ * - Parameters for long flags may be checked as string, word, or integer.
+ * - Automatic generation of a helpful usage message.
+ * - Signal end of options with '--'; subsequent arguments are treated
+ *   as non-option arguments, even if they begin with '-'.
+ * - Raise exception Zend_Console_Getopt_Exception in several cases
+ *   when invalid flags or parameters are given.  Usage message is
+ *   returned in the exception object.
+ *
+ * The format for specifying options uses a PHP associative array.
+ * The key is has the format of a list of pipe-separated flag names,
+ * followed by an optional '=' to indicate a required parameter or
+ * '-' to indicate an optional parameter.  Following that, the type
+ * of parameter may be specified as 's' for string, 'w' for word,
+ * or 'i' for integer.
+ *
+ * Examples:
+ * - 'user|username|u=s'  this means '--user' or '--username' or '-u'
+ *   are synonyms, and the option requires a string parameter.
+ * - 'p=i'  this means '-p' requires an integer parameter.  No synonyms.
+ * - 'verbose|v-i'  this means '--verbose' or '-v' are synonyms, and
+ *   they take an optional integer parameter.
+ * - 'help|h'  this means '--help' or '-h' are synonyms, and
+ *   they take no parameter.
+ *
+ * The values in the associative array are strings that are used as
+ * brief descriptions of the options when printing a usage message.
+ *
+ * The simpler format for specifying options used by PHP's getopt()
+ * function is also supported.  This is similar to GNU getopt and shell
+ * getopt format.
+ *
+ * Example:  'abc:' means options '-a', '-b', and '-c'
+ * are legal, and the latter requires a string parameter.
+ *
+ * @category   Zend
+ * @package    Zend_Console_Getopt
+ * @version    Release: @package_version@
+ * @since      Class available since Release 0.6.0
+ *
+ * @todo  Handle flags that implicitly print usage message, e.g. --help
+ *
+ * @todo  Enable user to specify header and footer content in the help message.
+ *
+ * @todo  Feature request to handle option interdependencies.
+ *        e.g. if -b is specified, -a must be specified or else the
+ *        usage is invalid.
+ *
+ * @todo  Feature request to implement callbacks.
+ *        e.g. if -a is specified, run function 'handleOptionA'().
+ */
+class Getopt
+{
+
+    /**
+     * The options for a given application can be in multiple formats.
+     * modeGnu is for traditional 'ab:c:' style getopt format.
+     * modeZend is for a more structured format.
+     */
+    const MODE_ZEND                         = 'zend';
+    const MODE_GNU                          = 'gnu';
+
+    /**
+     * Constant tokens for various symbols used in the mode_zend
+     * rule format.
+     */
+    const PARAM_REQUIRED                    = '=';
+    const PARAM_OPTIONAL                    = '-';
+    const TYPE_STRING                       = 's';
+    const TYPE_WORD                         = 'w';
+    const TYPE_INTEGER                      = 'i';
+    const TYPE_NUMERIC_FLAG                 = '#';
+
+    /**
+     * These are constants for optional behavior of this class.
+     * ruleMode is either 'zend' or 'gnu' or a user-defined mode.
+     * dashDash is true if '--' signifies the end of command-line options.
+     * ignoreCase is true if '--opt' and '--OPT' are implicitly synonyms.
+     * parseAll is true if all options on the command line should be parsed, regardless of
+     * whether an argument appears before them.
+     */
+    const CONFIG_RULEMODE                   = 'ruleMode';
+    const CONFIG_DASHDASH                   = 'dashDash';
+    const CONFIG_IGNORECASE                 = 'ignoreCase';
+    const CONFIG_PARSEALL                   = 'parseAll';
+    const CONFIG_CUMULATIVE_PARAMETERS      = 'cumulativeParameters';
+    const CONFIG_CUMULATIVE_FLAGS           = 'cumulativeFlags';
+    const CONFIG_PARAMETER_SEPARATOR        = 'parameterSeparator';
+    const CONFIG_FREEFORM_FLAGS             = 'freeformFlags';
+    const CONFIG_NUMERIC_FLAGS              = 'numericFlags';
+
+    /**
+     * Defaults for getopt configuration are:
+     * ruleMode is 'zend' format,
+     * dashDash (--) token is enabled,
+     * ignoreCase is not enabled,
+     * parseAll is enabled,
+     * cumulative parameters are disabled,
+     * this means that subsequent options overwrite the parameter value,
+     * cumulative flags are disable,
+     * freeform flags are disable.
+     */
+    protected $getoptConfig = array(
+        self::CONFIG_RULEMODE                => self::MODE_ZEND,
+        self::CONFIG_DASHDASH                => true,
+        self::CONFIG_IGNORECASE              => false,
+        self::CONFIG_PARSEALL                => true,
+        self::CONFIG_CUMULATIVE_PARAMETERS   => false,
+        self::CONFIG_CUMULATIVE_FLAGS        => false,
+        self::CONFIG_PARAMETER_SEPARATOR     => null,
+        self::CONFIG_FREEFORM_FLAGS          => false,
+        self::CONFIG_NUMERIC_FLAGS           => false
+    );
+
+    /**
+     * Stores the command-line arguments for the calling application.
+     *
+     * @var array
+     */
+    protected $argv = array();
+
+    /**
+     * Stores the name of the calling application.
+     *
+     * @var string
+     */
+    protected $progname = '';
+
+    /**
+     * Stores the list of legal options for this application.
+     *
+     * @var array
+     */
+    protected $rules = array();
+
+    /**
+     * Stores alternate spellings of legal options.
+     *
+     * @var array
+     */
+    protected $ruleMap = array();
+
+    /**
+     * Stores options given by the user in the current invocation
+     * of the application, as well as parameters given in options.
+     *
+     * @var array
+     */
+    protected $options = array();
+
+    /**
+     * Stores the command-line arguments other than options.
+     *
+     * @var array
+     */
+    protected $remainingArgs = array();
+
+    /**
+     * State of the options: parsed or not yet parsed?
+     *
+     * @var boolean
+     */
+    protected $parsed = false;
+
+    /**
+     * The constructor takes one to three parameters.
+     *
+     * The first parameter is $rules, which may be a string for
+     * gnu-style format, or a structured array for Zend-style format.
+     *
+     * The second parameter is $argv, and it is optional.  If not
+     * specified, $argv is inferred from the global argv.
+     *
+     * The third parameter is an array of configuration parameters
+     * to control the behavior of this instance of Getopt; it is optional.
+     *
+     * @param  array $rules
+     * @param  array $argv
+     * @param  array $getoptConfig
+     * @throws Exception\InvalidArgumentException
+     */
+    public function __construct($rules, $argv = null, $getoptConfig = array())
+    {
+        if (!isset($_SERVER['argv'])) {
+            $errorDescription = (ini_get('register_argc_argv') == false)
+                ? "argv is not available, because ini option 'register_argc_argv' is set Off"
+                : '$_SERVER["argv"] is not set, but Zend_Console_Getopt cannot work without this information.';
+            throw new Exception\InvalidArgumentException($errorDescription);
+        }
+
+        $this->progname = $_SERVER['argv'][0];
+        $this->setOptions($getoptConfig);
+        $this->addRules($rules);
+        if (!is_array($argv)) {
+            $argv = array_slice($_SERVER['argv'], 1);
+        }
+        if (isset($argv)) {
+            $this->addArguments((array) $argv);
+        }
+    }
+
+    /**
+     * Return the state of the option seen on the command line of the
+     * current application invocation.  This function returns true, or the
+     * parameter to the option, if any.  If the option was not given,
+     * this function returns null.
+     *
+     * The magic __get method works in the context of naming the option
+     * as a virtual member of this class.
+     *
+     * @param  string $key
+     * @return string
+     */
+    public function __get($key)
+    {
+        return $this->getOption($key);
+    }
+
+    /**
+     * Test whether a given option has been seen.
+     *
+     * @param  string $key
+     * @return boolean
+     */
+    public function __isset($key)
+    {
+        $this->parse();
+        if (isset($this->ruleMap[$key])) {
+            $key = $this->ruleMap[$key];
+            return isset($this->options[$key]);
+        }
+        return false;
+    }
+
+    /**
+     * Set the value for a given option.
+     *
+     * @param  string $key
+     * @param  string $value
+     * @return void
+     */
+    public function __set($key, $value)
+    {
+        $this->parse();
+        if (isset($this->ruleMap[$key])) {
+            $key = $this->ruleMap[$key];
+            $this->options[$key] = $value;
+        }
+    }
+
+    /**
+     * Return the current set of options and parameters seen as a string.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        return $this->toString();
+    }
+
+    /**
+     * Unset an option.
+     *
+     * @param  string $key
+     * @return void
+     */
+    public function __unset($key)
+    {
+        $this->parse();
+        if (isset($this->ruleMap[$key])) {
+            $key = $this->ruleMap[$key];
+            unset($this->options[$key]);
+        }
+    }
+
+    /**
+     * Define additional command-line arguments.
+     * These are appended to those defined when the constructor was called.
+     *
+     * @param  array $argv
+     * @throws \Zend\Console\Exception\InvalidArgumentException When not given an array as parameter
+     * @return \Zend\Console\Getopt Provides a fluent interface
+     */
+    public function addArguments($argv)
+    {
+        if (!is_array($argv)) {
+            throw new Exception\InvalidArgumentException("Parameter #1 to addArguments should be an array");
+        }
+        $this->argv = array_merge($this->argv, $argv);
+        $this->parsed = false;
+        return $this;
+    }
+
+    /**
+     * Define full set of command-line arguments.
+     * These replace any currently defined.
+     *
+     * @param  array $argv
+     * @throws \Zend\Console\Exception\InvalidArgumentException When not given an array as parameter
+     * @return \Zend\Console\Getopt Provides a fluent interface
+     */
+    public function setArguments($argv)
+    {
+        if (!is_array($argv)) {
+            throw new Exception\InvalidArgumentException("Parameter #1 to setArguments should be an array");
+        }
+        $this->argv = $argv;
+        $this->parsed = false;
+        return $this;
+    }
+
+    /**
+     * Define multiple configuration options from an associative array.
+     * These are not program options, but properties to configure
+     * the behavior of Zend_Console_Getopt.
+     *
+     * @param  array $getoptConfig
+     * @return \Zend\Console\Getopt Provides a fluent interface
+     */
+    public function setOptions($getoptConfig)
+    {
+        if (isset($getoptConfig)) {
+            foreach ($getoptConfig as $key => $value) {
+                $this->setOption($key, $value);
+            }
+        }
+        return $this;
+    }
+
+    /**
+     * Define one configuration option as a key/value pair.
+     * These are not program options, but properties to configure
+     * the behavior of Zend_Console_Getopt.
+     *
+     * @param  string $configKey
+     * @param  string $configValue
+     * @return \Zend\Console\Getopt Provides a fluent interface
+     */
+    public function setOption($configKey, $configValue)
+    {
+        if ($configKey !== null) {
+            $this->getoptConfig[$configKey] = $configValue;
+        }
+        return $this;
+    }
+
+    /**
+     * Define additional option rules.
+     * These are appended to the rules defined when the constructor was called.
+     *
+     * @param  array $rules
+     * @return \Zend\Console\Getopt Provides a fluent interface
+     */
+    public function addRules($rules)
+    {
+        $ruleMode = $this->getoptConfig['ruleMode'];
+        switch ($this->getoptConfig['ruleMode']) {
+            case self::MODE_ZEND:
+                if (is_array($rules)) {
+                    $this->_addRulesModeZend($rules);
+                    break;
+                }
+                // intentional fallthrough
+            case self::MODE_GNU:
+                $this->_addRulesModeGnu($rules);
+                break;
+            default:
+                /**
+                 * Call addRulesModeFoo() for ruleMode 'foo'.
+                 * The developer should subclass Getopt and
+                 * provide this method.
+                 */
+                $method = '_addRulesMode' . ucfirst($ruleMode);
+                $this->$method($rules);
+        }
+        $this->parsed = false;
+        return $this;
+    }
+
+    /**
+     * Return the current set of options and parameters seen as a string.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        $this->parse();
+        $s = array();
+        foreach ($this->options as $flag => $value) {
+            $s[] = $flag . '=' . ($value === true ? 'true' : $value);
+        }
+        return implode(' ', $s);
+    }
+
+    /**
+     * Return the current set of options and parameters seen
+     * as an array of canonical options and parameters.
+     *
+     * Clusters have been expanded, and option aliases
+     * have been mapped to their primary option names.
+     *
+     * @return array
+     */
+    public function toArray()
+    {
+        $this->parse();
+        $s = array();
+        foreach ($this->options as $flag => $value) {
+            $s[] = $flag;
+            if ($value !== true) {
+                $s[] = $value;
+            }
+        }
+        return $s;
+    }
+
+    /**
+     * Return the current set of options and parameters seen in Json format.
+     *
+     * @return string
+     */
+    public function toJson()
+    {
+        $this->parse();
+        $j = array();
+        foreach ($this->options as $flag => $value) {
+            $j['options'][] = array(
+                'option' => array(
+                    'flag' => $flag,
+                    'parameter' => $value
+                )
+            );
+        }
+
+        $json = \Zend\Json\Json::encode($j);
+        return $json;
+    }
+
+    /**
+     * Return the current set of options and parameters seen in XML format.
+     *
+     * @return string
+     */
+    public function toXml()
+    {
+        $this->parse();
+        $doc = new \DomDocument('1.0', 'utf-8');
+        $optionsNode = $doc->createElement('options');
+        $doc->appendChild($optionsNode);
+        foreach ($this->options as $flag => $value) {
+            $optionNode = $doc->createElement('option');
+            $optionNode->setAttribute('flag', utf8_encode($flag));
+            if ($value !== true) {
+                $optionNode->setAttribute('parameter', utf8_encode($value));
+            }
+            $optionsNode->appendChild($optionNode);
+        }
+        $xml = $doc->saveXML();
+        return $xml;
+    }
+
+    /**
+     * Return a list of options that have been seen in the current argv.
+     *
+     * @return array
+     */
+    public function getOptions()
+    {
+        $this->parse();
+        return array_keys($this->options);
+    }
+
+    /**
+     * Return the state of the option seen on the command line of the
+     * current application invocation.
+     *
+     * This function returns true, or the parameter value to the option, if any.
+     * If the option was not given, this function returns false.
+     *
+     * @param  string $flag
+     * @return mixed
+     */
+    public function getOption($flag)
+    {
+        $this->parse();
+        if ($this->getoptConfig[self::CONFIG_IGNORECASE]) {
+            $flag = strtolower($flag);
+        }
+        if (isset($this->ruleMap[$flag])) {
+            $flag = $this->ruleMap[$flag];
+            if (isset($this->options[$flag])) {
+                return $this->options[$flag];
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Return the arguments from the command-line following all options found.
+     *
+     * @return array
+     */
+    public function getRemainingArgs()
+    {
+        $this->parse();
+        return $this->remainingArgs;
+    }
+
+    public function getArguments()
+    {
+        $result = $this->getRemainingArgs();
+        foreach ($this->getOptions() as $option) {
+            $result[$option] = $this->getOption($option);
+        }
+        return $result;
+    }
+
+    /**
+     * Return a useful option reference, formatted for display in an
+     * error message.
+     *
+     * Note that this usage information is provided in most Exceptions
+     * generated by this class.
+     *
+     * @return string
+     */
+    public function getUsageMessage()
+    {
+        $usage = "Usage: {$this->progname} [ options ]\n";
+        $maxLen = 20;
+        $lines = array();
+        foreach ($this->rules as $rule) {
+            $flags = array();
+            if (is_array($rule['alias'])) {
+                foreach ($rule['alias'] as $flag) {
+                    $flags[] = (strlen($flag) == 1 ? '-' : '--') . $flag;
+                }
+            }
+            $linepart['name'] = implode('|', $flags);
+            if (isset($rule['param']) && $rule['param'] != 'none') {
+                $linepart['name'] .= ' ';
+                switch ($rule['param']) {
+                    case 'optional':
+                        $linepart['name'] .= "[ <{$rule['paramType']}> ]";
+                        break;
+                    case 'required':
+                        $linepart['name'] .= "<{$rule['paramType']}>";
+                        break;
+                }
+            }
+            if (strlen($linepart['name']) > $maxLen) {
+                $maxLen = strlen($linepart['name']);
+            }
+            $linepart['help'] = '';
+            if (isset($rule['help'])) {
+                $linepart['help'] .= $rule['help'];
+            }
+            $lines[] = $linepart;
+        }
+        foreach ($lines as $linepart) {
+            $usage .= sprintf("%s %s\n",
+            str_pad($linepart['name'], $maxLen),
+            $linepart['help']);
+        }
+        return $usage;
+    }
+
+    /**
+     * Define aliases for options.
+     *
+     * The parameter $aliasMap is an associative array
+     * mapping option name (short or long) to an alias.
+     *
+     * @param  array $aliasMap
+     * @throws \Zend\Console\Exception\ExceptionInterface
+     * @return \Zend\Console\Getopt Provides a fluent interface
+     */
+    public function setAliases($aliasMap)
+    {
+        foreach ($aliasMap as $flag => $alias) {
+            if ($this->getoptConfig[self::CONFIG_IGNORECASE]) {
+                $flag = strtolower($flag);
+                $alias = strtolower($alias);
+            }
+            if (!isset($this->ruleMap[$flag])) {
+                continue;
+            }
+            $flag = $this->ruleMap[$flag];
+            if (isset($this->rules[$alias]) || isset($this->ruleMap[$alias])) {
+                $o = (strlen($alias) == 1 ? '-' : '--') . $alias;
+                throw new Exception\InvalidArgumentException("Option \"$o\" is being defined more than once.");
+            }
+            $this->rules[$flag]['alias'][] = $alias;
+            $this->ruleMap[$alias] = $flag;
+        }
+        return $this;
+    }
+
+    /**
+     * Define help messages for options.
+     *
+     * The parameter $help_map is an associative array
+     * mapping option name (short or long) to the help string.
+     *
+     * @param  array $helpMap
+     * @return \Zend\Console\Getopt Provides a fluent interface
+     */
+    public function setHelp($helpMap)
+    {
+        foreach ($helpMap as $flag => $help) {
+            if (!isset($this->ruleMap[$flag])) {
+                continue;
+            }
+            $flag = $this->ruleMap[$flag];
+            $this->rules[$flag]['help'] = $help;
+        }
+        return $this;
+    }
+
+    /**
+     * Parse command-line arguments and find both long and short
+     * options.
+     *
+     * Also find option parameters, and remaining arguments after
+     * all options have been parsed.
+     *
+     * @return \Zend\Console\Getopt|null Provides a fluent interface
+     */
+    public function parse()
+    {
+        if ($this->parsed === true) {
+            return;
+        }
+        $argv = $this->argv;
+        $this->options = array();
+        $this->remainingArgs = array();
+        while (count($argv) > 0) {
+            if ($argv[0] == '--') {
+                array_shift($argv);
+                if ($this->getoptConfig[self::CONFIG_DASHDASH]) {
+                    $this->remainingArgs = array_merge($this->remainingArgs, $argv);
+                    break;
+                }
+            }
+            if (substr($argv[0], 0, 2) == '--') {
+                $this->_parseLongOption($argv);
+            } elseif (substr($argv[0], 0, 1) == '-' && ('-' != $argv[0] || count($argv) >1))  {
+                $this->_parseShortOptionCluster($argv);
+            } elseif ($this->getoptConfig[self::CONFIG_PARSEALL]) {
+                $this->remainingArgs[] = array_shift($argv);
+            } else {
+                /*
+                 * We should put all other arguments in remainingArgs and stop parsing
+                 * since CONFIG_PARSEALL is false.
+                 */
+                $this->remainingArgs = array_merge($this->remainingArgs, $argv);
+                break;
+            }
+        }
+        $this->parsed = true;
+        return $this;
+    }
+
+    /**
+     * Parse command-line arguments for a single long option.
+     * A long option is preceded by a double '--' character.
+     * Long options may not be clustered.
+     *
+     * @param  mixed &$argv
+     * @return void
+     */
+    protected function _parseLongOption(&$argv)
+    {
+        $optionWithParam = ltrim(array_shift($argv), '-');
+        $l = explode('=', $optionWithParam, 2);
+        $flag = array_shift($l);
+        $param = array_shift($l);
+        if (isset($param)) {
+            array_unshift($argv, $param);
+        }
+        $this->_parseSingleOption($flag, $argv);
+    }
+
+    /**
+     * Parse command-line arguments for short options.
+     * Short options are those preceded by a single '-' character.
+     * Short options may be clustered.
+     *
+     * @param  mixed &$argv
+     * @return void
+     */
+    protected function _parseShortOptionCluster(&$argv)
+    {
+        $flagCluster = ltrim(array_shift($argv), '-');
+        foreach (str_split($flagCluster) as $flag) {
+            $this->_parseSingleOption($flag, $argv);
+        }
+    }
+
+    /**
+     * Parse command-line arguments for a single option.
+     *
+     * @param  string $flag
+     * @param  mixed  $argv
+     * @throws \Zend\Console\Exception\ExceptionInterface
+     * @return void
+     */
+    protected function _parseSingleOption($flag, &$argv)
+    {
+        if ($this->getoptConfig[self::CONFIG_IGNORECASE]) {
+            $flag = strtolower($flag);
+        }
+
+        // Check if this option is numeric one
+        if (preg_match('/^\d+$/', $flag)) {
+            return $this->_setNumericOptionValue($flag);
+        }
+
+        if (!isset($this->ruleMap[$flag])) {
+            // Don't throw Exception for flag-like param in case when freeform flags are allowed
+            if (!$this->getoptConfig[self::CONFIG_FREEFORM_FLAGS]) {
+                throw new Exception\RuntimeException(
+                    "Option \"$flag\" is not recognized.",
+                    $this->getUsageMessage()
+                    );
+            }
+
+            // Magic methods in future will use this mark as real flag value
+            $this->ruleMap[$flag] = $flag;
+            $realFlag = $flag;
+            $this->rules[$realFlag] = array('param' => 'optional');
+        } else {
+            $realFlag = $this->ruleMap[$flag];
+        }
+
+        switch ($this->rules[$realFlag]['param']) {
+            case 'required':
+                if (count($argv) > 0) {
+                    $param = array_shift($argv);
+                    $this->_checkParameterType($realFlag, $param);
+                } else {
+                    throw new Exception\RuntimeException(
+                        "Option \"$flag\" requires a parameter.",
+                        $this->getUsageMessage()
+                        );
+                }
+                break;
+            case 'optional':
+                if (count($argv) > 0 && substr($argv[0], 0, 1) != '-') {
+                    $param = array_shift($argv);
+                    $this->_checkParameterType($realFlag, $param);
+                } else {
+                    $param = true;
+                }
+                break;
+            default:
+                $param = true;
+        }
+
+        $this->_setSingleOptionValue($realFlag, $param);
+    }
+
+
+    /**
+     * Set given value as value of numeric option
+     *
+     * Throw runtime exception if this action is deny by configuration
+     * or no one numeric option handlers is defined
+     *
+     * @param  int $value
+     * @throws Exception\RuntimeException
+     * @return void
+     */
+    protected function _setNumericOptionValue($value)
+    {
+        if (!$this->getoptConfig[self::CONFIG_NUMERIC_FLAGS]) {
+            throw new Exception\RuntimeException("Using of numeric flags are deny by configuration");
+        }
+
+        if (empty($this->getoptConfig['numericFlagsOption'])) {
+            throw new Exception\RuntimeException("Any option for handling numeric flags are specified");
+        }
+
+        return $this->_setSingleOptionValue($this->getoptConfig['numericFlagsOption'], $value);
+    }
+
+    /**
+     * Add relative to options' flag value
+     *
+     * If options list already has current flag as key
+     * and parser should follow cumulative params by configuration,
+     * we should to add new param to array, not to overwrite
+     *
+     * @param  string $flag
+     * @param  string $value
+     * @return null
+     */
+    protected function _setSingleOptionValue($flag, $value)
+    {
+        if (true === $value && $this->getoptConfig[self::CONFIG_CUMULATIVE_FLAGS]) {
+            // For boolean values we have to create new flag, or increase number of flags' usage count
+            return $this->_setBooleanFlagValue($flag);
+        }
+
+        // Split multiple values, if necessary
+        // Filter empty values from splited array
+        $separator = $this->getoptConfig[self::CONFIG_PARAMETER_SEPARATOR];
+        if (is_string($value) && !empty($separator) && is_string($separator) && substr_count($value, $separator)) {
+            $value = array_filter(explode($separator, $value));
+        }
+
+        if (!array_key_exists($flag, $this->options)) {
+            $this->options[$flag] = $value;
+        } elseif ($this->getoptConfig[self::CONFIG_CUMULATIVE_PARAMETERS]) {
+            $this->options[$flag] = (array) $this->options[$flag];
+            array_push($this->options[$flag], $value);
+        } else {
+            $this->options[$flag] = $value;
+        }
+    }
+
+    /**
+     * Set TRUE value to given flag, if this option does not exist yet
+     * In other case increase value to show count of flags' usage
+     *
+     * @param  string $flag
+     * @return null
+     */
+    protected function _setBooleanFlagValue($flag)
+    {
+        $this->options[$flag] = array_key_exists($flag, $this->options)
+                               ? (int) $this->options[$flag] + 1
+                               : true;
+    }
+
+    /**
+     * Return true if the parameter is in a valid format for
+     * the option $flag.
+     * Throw an exception in most other cases.
+     *
+     * @param  string $flag
+     * @param  string $param
+     * @throws \Zend\Console\Exception\ExceptionInterface
+     * @return bool
+     */
+    protected function _checkParameterType($flag, $param)
+    {
+        $type = 'string';
+        if (isset($this->rules[$flag]['paramType'])) {
+            $type = $this->rules[$flag]['paramType'];
+        }
+        switch ($type) {
+            case 'word':
+                if (preg_match('/\W/', $param)) {
+                    throw new Exception\RuntimeException(
+                        "Option \"$flag\" requires a single-word parameter, but was given \"$param\".",
+                        $this->getUsageMessage());
+                }
+                break;
+            case 'integer':
+                if (preg_match('/\D/', $param)) {
+                    throw new Exception\RuntimeException(
+                        "Option \"$flag\" requires an integer parameter, but was given \"$param\".",
+                        $this->getUsageMessage());
+                }
+                break;
+            case 'string':
+            default:
+                break;
+        }
+        return true;
+    }
+
+    /**
+     * Define legal options using the gnu-style format.
+     *
+     * @param  string $rules
+     * @return void
+     */
+    protected function _addRulesModeGnu($rules)
+    {
+        $ruleArray = array();
+
+        /**
+         * Options may be single alphanumeric characters.
+         * Options may have a ':' which indicates a required string parameter.
+         * No long options or option aliases are supported in GNU style.
+         */
+        preg_match_all('/([a-zA-Z0-9]:?)/', $rules, $ruleArray);
+        foreach ($ruleArray[1] as $rule) {
+            $r = array();
+            $flag = substr($rule, 0, 1);
+            if ($this->getoptConfig[self::CONFIG_IGNORECASE]) {
+                $flag = strtolower($flag);
+            }
+            $r['alias'][] = $flag;
+            if (substr($rule, 1, 1) == ':') {
+                $r['param'] = 'required';
+                $r['paramType'] = 'string';
+            } else {
+                $r['param'] = 'none';
+            }
+            $this->rules[$flag] = $r;
+            $this->ruleMap[$flag] = $flag;
+        }
+    }
+
+    /**
+     * Define legal options using the Zend-style format.
+     *
+     * @param  array $rules
+     * @throws \Zend\Console\Exception\ExceptionInterface
+     * @return void
+     */
+    protected function _addRulesModeZend($rules)
+    {
+        foreach ($rules as $ruleCode => $helpMessage) {
+            // this may have to translate the long parm type if there
+            // are any complaints that =string will not work (even though that use
+            // case is not documented)
+            if (in_array(substr($ruleCode, -2, 1), array('-', '='))) {
+                $flagList  = substr($ruleCode, 0, -2);
+                $delimiter = substr($ruleCode, -2, 1);
+                $paramType = substr($ruleCode, -1);
+            } else {
+                $flagList = $ruleCode;
+                $delimiter = $paramType = null;
+            }
+            if ($this->getoptConfig[self::CONFIG_IGNORECASE]) {
+                $flagList = strtolower($flagList);
+            }
+            $flags = explode('|', $flagList);
+            $rule = array();
+            $mainFlag = $flags[0];
+            foreach ($flags as $flag) {
+                if (empty($flag)) {
+                    throw new Exception\InvalidArgumentException("Blank flag not allowed in rule \"$ruleCode\".");
+                }
+                if (strlen($flag) == 1) {
+                    if (isset($this->ruleMap[$flag])) {
+                        throw new Exception\InvalidArgumentException(
+                            "Option \"-$flag\" is being defined more than once.");
+                    }
+                    $this->ruleMap[$flag] = $mainFlag;
+                    $rule['alias'][] = $flag;
+                } else {
+                    if (isset($this->rules[$flag]) || isset($this->ruleMap[$flag])) {
+                        throw new Exception\InvalidArgumentException(
+                            "Option \"--$flag\" is being defined more than once.");
+                    }
+                    $this->ruleMap[$flag] = $mainFlag;
+                    $rule['alias'][] = $flag;
+                }
+            }
+            if (isset($delimiter)) {
+                switch ($delimiter) {
+                    case self::PARAM_REQUIRED:
+                        $rule['param'] = 'required';
+                        break;
+                    case self::PARAM_OPTIONAL:
+                    default:
+                        $rule['param'] = 'optional';
+                }
+                switch (substr($paramType, 0, 1)) {
+                    case self::TYPE_WORD:
+                        $rule['paramType'] = 'word';
+                        break;
+                    case self::TYPE_INTEGER:
+                        $rule['paramType'] = 'integer';
+                        break;
+                    case self::TYPE_NUMERIC_FLAG:
+                        $rule['paramType'] = 'numericFlag';
+                        $this->getoptConfig['numericFlagsOption'] = $mainFlag;
+                        break;
+                    case self::TYPE_STRING:
+                    default:
+                        $rule['paramType'] = 'string';
+                }
+            } else {
+                $rule['param'] = 'none';
+            }
+            $rule['help'] = $helpMessage;
+            $this->rules[$mainFlag] = $rule;
+        }
+    }
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/Prompt/AbstractPrompt.php b/wcfsetup/install/files/lib/system/api/zend/Console/Prompt/AbstractPrompt.php
new file mode 100644 (file)
index 0000000..c6c6641
--- /dev/null
@@ -0,0 +1,98 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console\Prompt;
+
+use ReflectionClass;
+use Zend\Console\Console;
+use Zend\Console\Adapter\AdapterInterface as ConsoleAdapter;
+use Zend\Console\Exception;
+
+/**
+ * @category   Zend
+ * @package    Zend_Console
+ * @subpackage Prompt
+ */
+abstract class AbstractPrompt implements PromptInterface
+{
+    /**
+     * @var ConsoleAdapter
+     */
+    protected $console;
+
+    /**
+     * @var mixed
+     */
+    protected $lastResponse;
+
+    /**
+     * Show a prompt
+     *
+     * @return void
+     */
+    abstract public function show();
+
+    /**
+     * Return last answer to this prompt.
+     *
+     * @return mixed
+     */
+    public function getLastResponse()
+    {
+        return $this->lastResponse;
+    }
+
+    /**
+     * Return console adapter to use when showing prompt.
+     *
+     * @return ConsoleAdapter
+     */
+    public function getConsole()
+    {
+        if (!$this->console) {
+            $this->console = Console::getInstance();
+        }
+
+        return $this->console;
+    }
+
+    /**
+     * Set console adapter to use when showing prompt.
+     *
+     * @param ConsoleAdapter $adapter
+     */
+    public function setConsole(ConsoleAdapter $adapter)
+    {
+        $this->console = $adapter;
+    }
+
+    /**
+     * Create an instance of this prompt, show it and return response.
+     *
+     * This is a convenience method for creating statically creating prompts, i.e.:
+     *
+     *      $name = Zend\Console\Prompt\Line::prompt("Enter your name: ");
+     *
+     * @return mixed
+     * @throws Exception\BadMethodCallException
+     */
+    public static function prompt()
+    {
+        if (get_called_class() === __CLASS__) {
+            throw new Exception\BadMethodCallException(
+                'Cannot call prompt() on AbstractPrompt class. Use one of the Zend\Console\Prompt\ subclasses.'
+            );
+        }
+
+        $refl     = new ReflectionClass(get_called_class());
+        $instance = $refl->newInstanceArgs(func_get_args());
+        return $instance->show();
+    }
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/Prompt/Char.php b/wcfsetup/install/files/lib/system/api/zend/Console/Prompt/Char.php
new file mode 100644 (file)
index 0000000..156f00b
--- /dev/null
@@ -0,0 +1,219 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console\Prompt;
+
+/**
+ * @category   Zend
+ * @package    Zend_Console
+ * @subpackage Prompt
+ */
+class Char extends AbstractPrompt
+{
+    /**
+     * @var string
+     */
+    protected $promptText = 'Please select one option ';
+
+    /**
+     * @var bool
+     */
+    protected $allowEmpty = false;
+
+    /**
+     * @var string
+     */
+    protected $allowedChars = 'yn';
+
+    /**
+     * @var bool
+     */
+    protected $ignoreCase = true;
+
+    /**
+     * @var bool
+     */
+    protected $echo = true;
+
+    /**
+     * Ask the user for a single key stroke
+     *
+     * @param string  $promptText     The prompt text to display in console
+     * @param string  $allowedChars   A list of allowed chars (i.e. "abc12345")
+     * @param bool    $ignoreCase     If true, case will be ignored and prompt will always return lower-cased response
+     * @param bool    $allowEmpty     Is empty response allowed?
+     * @param bool    $echo           Display the selection after user presses key
+     */
+    public function __construct(
+        $promptText = 'Please hit a key',
+        $allowedChars = 'abc',
+        $ignoreCase = true,
+        $allowEmpty = false,
+        $echo = true
+    ) {
+
+        if ($promptText !== null) {
+            $this->setPromptText($promptText);
+        }
+
+        if ($allowEmpty !== null) {
+            $this->setAllowEmpty($allowEmpty);
+        }
+
+        if ($ignoreCase !== null) {
+            $this->setIgnoreCase($ignoreCase);
+        }
+
+        if ($allowedChars !== null) {
+            if ($this->ignoreCase) {
+                $this->setAllowedChars(strtolower($allowedChars));
+            } else {
+                $this->setAllowedChars($allowedChars);
+            }
+        }
+
+        if ($echo !== null) {
+            $this->setEcho($echo);
+        }
+    }
+
+    /**
+     * Show the prompt to user and return a single char.
+     *
+     * @return string
+     */
+    public function show()
+    {
+        $this->getConsole()->write($this->promptText);
+        $mask = $this->getAllowedChars();
+
+        /**
+         * Normalize the mask if case is irrelevant
+         */
+        if ($this->ignoreCase) {
+            $mask = strtolower($mask);   // lowercase all
+            $mask .= strtoupper($mask);  // uppercase and append
+            $mask = str_split($mask);    // convert to array
+            $mask = array_unique($mask); // remove duplicates
+            $mask = implode("", $mask);   // convert back to string
+        }
+
+        do {
+            /**
+             * Read char from console
+             */
+            $char = $this->getConsole()->readChar($mask);
+
+            /**
+             * Lowercase the response if case is irrelevant
+             */
+            if ($this->ignoreCase) {
+                $char = strtolower($char);
+            }
+
+            /**
+             * Check if it is an allowed char
+             */
+            if (stristr($this->allowedChars, $char) !== false) {
+                if ($this->echo) {
+                    echo trim($char)."\n";
+                } else {
+                    if ($this->promptText) {
+                        echo "\n";  // skip to next line but only if we had any prompt text
+                    }
+                }
+                break;
+            }
+        } while (true);
+
+        return $this->lastResponse = $char;
+    }
+
+    /**
+     * @param boolean $allowEmpty
+     */
+    public function setAllowEmpty($allowEmpty)
+    {
+        $this->allowEmpty = $allowEmpty;
+    }
+
+    /**
+     * @return boolean
+     */
+    public function getAllowEmpty()
+    {
+        return $this->allowEmpty;
+    }
+
+    /**
+     * @param string $promptText
+     */
+    public function setPromptText($promptText)
+    {
+        $this->promptText = $promptText;
+    }
+
+    /**
+     * @return string
+     */
+    public function getPromptText()
+    {
+        return $this->promptText;
+    }
+
+    /**
+     * @param string $allowedChars
+     */
+    public function setAllowedChars($allowedChars)
+    {
+        $this->allowedChars = $allowedChars;
+    }
+
+    /**
+     * @return string
+     */
+    public function getAllowedChars()
+    {
+        return $this->allowedChars;
+    }
+
+    /**
+     * @param boolean $ignoreCase
+     */
+    public function setIgnoreCase($ignoreCase)
+    {
+        $this->ignoreCase = $ignoreCase;
+    }
+
+    /**
+     * @return boolean
+     */
+    public function getIgnoreCase()
+    {
+        return $this->ignoreCase;
+    }
+
+    /**
+     * @param boolean $echo
+     */
+    public function setEcho($echo)
+    {
+        $this->echo = $echo;
+    }
+
+    /**
+     * @return boolean
+     */
+    public function getEcho()
+    {
+        return $this->echo;
+    }
+
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/Prompt/Confirm.php b/wcfsetup/install/files/lib/system/api/zend/Console/Prompt/Confirm.php
new file mode 100644 (file)
index 0000000..60edc3d
--- /dev/null
@@ -0,0 +1,116 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console\Prompt;
+
+/**
+ * @category   Zend
+ * @package    Zend_Console
+ * @subpackage Prompt
+ */
+class Confirm extends Char
+{
+    /**
+     * @var string
+     */
+    protected $promptText = 'Are you sure?';
+
+    /**
+     * @var string
+     */
+    protected $allowedChars = 'yn';
+
+    /**
+     * @var string
+     */
+    protected $yesChar = 'y';
+
+    /**
+     * @var string
+     */
+    protected $noChar = 'n';
+
+    /**
+     * @var bool
+     */
+    protected $ignoreCase = true;
+
+    /**
+     * Ask the user for a single key stroke
+     *
+     * @param string    $promptText     The prompt text to display in console
+     * @param string    $yesChar        The "yes" key (defaults to Y)
+     * @param string    $noChar         The "no" key (defaults to N)
+     */
+    public function __construct(
+        $promptText = 'Are you sure?',
+        $yesChar = 'y',
+        $noChar = 'n'
+    ) {
+        if ($promptText !== null) {
+            $this->setPromptText($promptText);
+        }
+
+        if ($yesChar !== null) {
+            $this->setYesChar($yesChar);
+        }
+
+        if ($noChar !== null) {
+            $this->setNoChar($noChar);
+        }
+    }
+
+    /**
+     * Show the confirmation message and return result.
+     *
+     * @return bool
+     */
+    public function show()
+    {
+        $response = parent::show() === $this->yesChar;
+        return $this->lastResponse = $response;
+    }
+
+
+    /**
+     * @param string $noChar
+     */
+    public function setNoChar($noChar)
+    {
+        $this->noChar = $noChar;
+        $this->setAllowedChars($this->yesChar . $this->noChar);
+    }
+
+    /**
+     * @return string
+     */
+    public function getNoChar()
+    {
+        return $this->noChar;
+    }
+
+    /**
+     * @param string $yesChar
+     */
+    public function setYesChar($yesChar)
+    {
+        $this->yesChar = $yesChar;
+        $this->setAllowedChars($this->yesChar . $this->noChar);
+    }
+
+    /**
+     * @return string
+     */
+    public function getYesChar()
+    {
+        return $this->yesChar;
+    }
+
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/Prompt/Line.php b/wcfsetup/install/files/lib/system/api/zend/Console/Prompt/Line.php
new file mode 100644 (file)
index 0000000..7f5c582
--- /dev/null
@@ -0,0 +1,120 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console\Prompt;
+
+/**
+ * @category   Zend
+ * @package    Zend_Console
+ * @subpackage Prompt
+ */
+class Line extends AbstractPrompt
+{
+    /**
+     * @var string
+     */
+    protected $promptText = 'Please enter value: ';
+
+    /**
+     * @var bool
+     */
+    protected $allowEmpty = false;
+
+    /**
+     * @var int
+     */
+    protected $maxLength = 2048;
+
+    /**
+     * Ask the user for an answer (a line of text)
+     *
+     * @param string    $promptText     The prompt text to display in console
+     * @param bool      $allowEmpty     Is empty response allowed?
+     * @param int       $maxLength      Maximum response length
+     */
+    public function __construct($promptText = 'Please enter value: ', $allowEmpty = false, $maxLength = 2048)
+    {
+        if ($promptText !== null) {
+            $this->setPromptText($promptText);
+        }
+
+        if ($allowEmpty !== null) {
+            $this->setAllowEmpty($allowEmpty);
+        }
+
+        if ($maxLength !== null) {
+            $this->setMaxLength($maxLength);
+        }
+    }
+
+    /**
+     * Show the prompt to user and return the answer.
+     *
+     * @return mixed
+     */
+    public function show()
+    {
+        do {
+            $this->getConsole()->write($this->promptText);
+            $line = $this->getConsole()->readLine($this->maxLength);
+        } while (!$this->allowEmpty && !$line);
+
+        return $this->lastResponse = $line;
+    }
+
+    /**
+     * @param boolean $allowEmpty
+     */
+    public function setAllowEmpty($allowEmpty)
+    {
+        $this->allowEmpty = $allowEmpty;
+    }
+
+    /**
+     * @return boolean
+     */
+    public function getAllowEmpty()
+    {
+        return $this->allowEmpty;
+    }
+
+    /**
+     * @param int $maxLength
+     */
+    public function setMaxLength($maxLength)
+    {
+        $this->maxLength = $maxLength;
+    }
+
+    /**
+     * @return int
+     */
+    public function getMaxLength()
+    {
+        return $this->maxLength;
+    }
+
+    /**
+     * @param string $promptText
+     */
+    public function setPromptText($promptText)
+    {
+        $this->promptText = $promptText;
+    }
+
+    /**
+     * @return string
+     */
+    public function getPromptText()
+    {
+        return $this->promptText;
+    }
+
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/Prompt/Number.php b/wcfsetup/install/files/lib/system/api/zend/Console/Prompt/Number.php
new file mode 100644 (file)
index 0000000..75800cd
--- /dev/null
@@ -0,0 +1,215 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console\Prompt;
+
+/**
+ * @category   Zend
+ * @package    Zend_Console
+ * @subpackage Prompt
+ */
+class Number extends Line
+{
+    /**
+     * @var string
+     */
+    protected $promptText = 'Please enter a number: ';
+
+    /**
+     * @var bool
+     */
+    protected $allowFloat = false;
+
+    /**
+     * @var int
+     */
+    protected $min;
+
+    /**
+     * @var int
+     */
+    protected $max;
+
+    /**
+     * Ask the user for a number.
+     *
+     * @param string    $promptText     The prompt text to display in console
+     * @param bool      $allowEmpty     Is empty response allowed?
+     * @param bool      $allowFloat     Are floating (non-decimal) numbers allowed?
+     * @param integer   $min            Minimum value (inclusive)
+     * @param integer   $max            Maximum value (inclusive)
+     */
+    public function __construct(
+        $promptText = 'Please enter a number: ',
+        $allowEmpty = false,
+        $allowFloat = false,
+        $min = null,
+        $max = null
+    ) {
+        if ($promptText !== null) {
+            $this->setPromptText($promptText);
+        }
+
+        if ($allowEmpty !== null) {
+            $this->setAllowEmpty($allowEmpty);
+        }
+
+        if ($min !== null) {
+            $this->setMin($min);
+        }
+
+        if ($max !== null) {
+            $this->setMax($max);
+        }
+
+        if ($allowFloat !== null) {
+            $this->setAllowFloat($allowFloat);
+        }
+    }
+
+    /**
+     * Show the prompt to user and return the answer.
+     *
+     * @return mixed
+     */
+    public function show()
+    {
+        /**
+         * Ask for a number and validate it.
+         */
+        do {
+            $valid = true;
+            $number = parent::show();
+            if ($number === "" && !$this->allowEmpty) {
+                $valid = false;
+            } elseif ($number === "") {
+                $number = null;
+            } elseif (!is_numeric($number)) {
+                $this->getConsole()->writeLine("$number is not a number\n");
+                $valid = false;
+            } elseif (!$this->allowFloat && (round($number) != $number) ) {
+                $this->getConsole()->writeLine("Please enter a non-floating number, i.e. " . round($number) . "\n");
+                $valid = false;
+            } elseif ($this->max !== null && $number > $this->max) {
+                $this->getConsole()->writeLine("Please enter a number not greater than " . $this->max . "\n");
+                $valid = false;
+            } elseif ($this->min !== null && $number < $this->min) {
+                $this->getConsole()->writeLine("Please enter a number not smaller than " . $this->min . "\n");
+                $valid = false;
+            }
+        } while (!$valid);
+
+        /**
+         * Cast proper type
+         */
+        if ($number !== null) {
+            $number = $this->allowFloat ? (double) $number : (int) $number;
+        }
+
+        return $this->lastResponse = $number;
+    }
+
+    /**
+     * @param boolean $allowEmpty
+     */
+    public function setAllowEmpty($allowEmpty)
+    {
+        $this->allowEmpty = $allowEmpty;
+    }
+
+    /**
+     * @return boolean
+     */
+    public function getAllowEmpty()
+    {
+        return $this->allowEmpty;
+    }
+
+    /**
+     * @param int $maxLength
+     */
+    public function setMaxLength($maxLength)
+    {
+        $this->maxLength = $maxLength;
+    }
+
+    /**
+     * @return int
+     */
+    public function getMaxLength()
+    {
+        return $this->maxLength;
+    }
+
+    /**
+     * @param string $promptText
+     */
+    public function setPromptText($promptText)
+    {
+        $this->promptText = $promptText;
+    }
+
+    /**
+     * @return string
+     */
+    public function getPromptText()
+    {
+        return $this->promptText;
+    }
+
+    /**
+     * @param int $max
+     */
+    public function setMax($max)
+    {
+        $this->max = $max;
+    }
+
+    /**
+     * @return int
+     */
+    public function getMax()
+    {
+        return $this->max;
+    }
+
+    /**
+     * @param int $min
+     */
+    public function setMin($min)
+    {
+        $this->min = $min;
+    }
+
+    /**
+     * @return int
+     */
+    public function getMin()
+    {
+        return $this->min;
+    }
+
+    /**
+     * @param boolean $allowFloat
+     */
+    public function setAllowFloat($allowFloat)
+    {
+        $this->allowFloat = $allowFloat;
+    }
+
+    /**
+     * @return boolean
+     */
+    public function getAllowFloat()
+    {
+        return $this->allowFloat;
+    }
+
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/Prompt/PromptInterface.php b/wcfsetup/install/files/lib/system/api/zend/Console/Prompt/PromptInterface.php
new file mode 100644 (file)
index 0000000..651d242
--- /dev/null
@@ -0,0 +1,48 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console\Prompt;
+
+use Zend\Console\Adapter\AdapterInterface as ConsoleAdapter;
+
+/**
+ * @category   Zend
+ * @package    Zend_Console
+ */
+interface PromptInterface
+{
+    /**
+     * Show the prompt to user and return the answer.
+     *
+     * @return mixed
+     */
+    public function show();
+
+    /**
+     * Return last answer to this prompt.
+     *
+     * @return mixed
+     */
+    public function getLastResponse();
+
+    /**
+     * Return console adapter to use when showing prompt.
+     *
+     * @return ConsoleAdapter
+     */
+    public function getConsole();
+
+    /**
+     * Set console adapter to use when showing prompt.
+     *
+     * @param ConsoleAdapter $adapter
+     */
+    public function setConsole(ConsoleAdapter $adapter);
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/Prompt/Select.php b/wcfsetup/install/files/lib/system/api/zend/Console/Prompt/Select.php
new file mode 100644 (file)
index 0000000..efa4615
--- /dev/null
@@ -0,0 +1,152 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console\Prompt;
+
+use Zend\Console\Exception;
+
+/**
+ * @category   Zend
+ * @package    Zend_Console
+ * @subpackage Prompt
+ */
+class Select extends Char
+{
+    /**
+     * @var string
+     */
+    protected $promptText = 'Please select an option';
+
+    /**
+     * @var bool
+     */
+    protected $ignoreCase = true;
+
+    /**
+     * @var array
+     */
+    protected $options = array();
+
+    /**
+     * Ask the user to select one of pre-defined options
+     *
+     * @param string    $promptText     The prompt text to display in console
+     * @param array     $options        Allowed options
+     * @param bool      $allowEmpty     Allow empty (no) selection?
+     * @param bool      $echo           True to display selected option?
+     * @throws Exception\BadMethodCallException if no options available
+     */
+    public function __construct(
+        $promptText = 'Please select one option',
+        $options = array(),
+        $allowEmpty = false,
+        $echo = false
+    ) {
+        if ($promptText !== null) {
+            $this->setPromptText($promptText);
+        }
+
+        if (!count($options)) {
+            throw new Exception\BadMethodCallException(
+                'Cannot construct a "select" prompt without any options'
+            );
+        }
+
+        $this->setOptions($options);
+
+        if ($allowEmpty !== null) {
+            $this->setAllowEmpty($allowEmpty);
+        }
+
+        if ($echo !== null) {
+            $this->setEcho($echo);
+        }
+
+    }
+
+    /**
+     * Show a list of options and prompt the user to select one of them.
+     *
+     * @return string       Selected option
+     */
+    public function show()
+    {
+        // Show prompt text and available options
+        $console = $this->getConsole();
+        $console->writeLine($this->promptText);
+        foreach ($this->options as $k => $v) {
+            $console->writeLine('  ' . $k . ') ' . $v);
+        }
+
+        //  Prepare mask
+        $mask = implode("", array_keys($this->options));
+        if ($this->allowEmpty) {
+            $mask .= "\r\n";
+        }
+
+        // Prepare other params for parent class
+        $this->setAllowedChars($mask);
+        $oldPrompt        = $this->promptText;
+        $oldEcho          = $this->echo;
+        $this->echo       = false;
+        $this->promptText = null;
+
+        // Retrieve a single character
+        $response = parent::show();
+
+        // Restore old params
+        $this->promptText = $oldPrompt;
+        $this->echo       = $oldEcho;
+
+        // Display selected option if echo is enabled
+        if ($this->echo) {
+            if (isset($this->options[$response])) {
+                $console->writeLine($this->options[$response]);
+            } else {
+                $console->writeLine();
+            }
+        }
+
+        $this->lastResponse = $response;
+        return $response;
+    }
+
+    /**
+     * Set allowed options
+     *
+     * @param array|\Traversable $options
+     * @throws Exception\BadMethodCallException
+     */
+    public function setOptions($options)
+    {
+        if (!is_array($options) && !$options instanceof \Traversable) {
+            throw new Exception\BadMethodCallException(
+                'Please specify an array or Traversable object as options'
+            );
+        }
+
+        if (!is_array($options)) {
+            $this->options = array();
+            foreach ($options as $k => $v) {
+                $this->options[$k] = $v;
+            }
+        } else {
+            $this->options = $options;
+        }
+    }
+
+    /**
+     * @return array
+     */
+    public function getOptions()
+    {
+        return $this->options;
+    }
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/Request.php b/wcfsetup/install/files/lib/system/api/zend/Console/Request.php
new file mode 100644 (file)
index 0000000..3b57775
--- /dev/null
@@ -0,0 +1,195 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console;
+
+use Zend\Stdlib\Message;
+use Zend\Stdlib\Parameters;
+use Zend\Stdlib\RequestInterface;
+
+/**
+ * @category   Zend
+ * @package    Zend_Console
+ */
+class Request extends Message implements RequestInterface
+{
+    /**
+     * @var \Zend\Stdlib\Parameters
+     */
+    protected $params = null;
+
+    /**
+     * @var \Zend\Stdlib\Parameters
+     */
+    protected $envParams = null;
+
+    /**
+     * @var string
+     */
+    protected $scriptName = null;
+
+    /**
+     * Create a new CLI request
+     *
+     * @param array|null $args Console arguments. If not supplied, $_SERVER['argv'] will be used
+     * @param array|null $env Environment data. If not supplied, $_ENV will be used
+     * @throws Exception\RuntimeException
+     */
+    public function __construct(array $args = null, array $env = null)
+    {
+        if ($args === null) {
+            if (!isset($_SERVER['argv'])) {
+                $errorDescription = (ini_get('register_argc_argv') == false)
+                    ? "Cannot create Console\\Request because PHP ini option 'register_argc_argv' is set Off"
+                    : 'Cannot create Console\\Request because $_SERVER["argv"] is not set for unknown reason.';
+                throw new Exception\RuntimeException($errorDescription);
+            }
+            $args = $_SERVER['argv'];
+        }
+
+        if ($env === null) {
+            $env = $_ENV;
+        }
+
+        /**
+         * Extract first param assuming it is the script name
+         */
+        if (count($args) > 0) {
+            $this->setScriptName(array_shift($args));
+        }
+
+        /**
+         * Store runtime params
+         */
+        $this->params()->fromArray($args);
+        $this->setContent($args);
+
+        /**
+         * Store environment data
+         */
+        $this->env()->fromArray($env);
+    }
+
+    /**
+     * Exchange parameters object
+     *
+     * @param \Zend\Stdlib\Parameters $params
+     * @return Request
+     */
+    public function setParams(Parameters $params)
+    {
+        $this->params = $params;
+        $this->setContent($params);
+        return $this;
+    }
+
+    /**
+     * Return the container responsible for parameters
+     *
+     * @return \Zend\Stdlib\Parameters
+     */
+    public function getParams()
+    {
+        if ($this->params === null) {
+            $this->params = new Parameters();
+        }
+
+        return $this->params;
+    }
+
+    /**
+     * Return a single parameter.
+     * Shortcut for $request->params()->get()
+     *
+     * @param string    $name       Parameter name
+     * @param string    $default    (optional) default value in case the parameter does not exist
+     * @return mixed
+     */
+    public function getParam($name, $default = null)
+    {
+        return $this->params()->get($name, $default);
+    }
+
+    /**
+     * Return the container responsible for parameters
+     *
+     * @return \Zend\Stdlib\Parameters
+     */
+    public function params()
+    {
+        if ($this->params === null) {
+            $this->params = new Parameters();
+        }
+
+        return $this->params;
+    }
+
+    /**
+     * Provide an alternate Parameter Container implementation for env parameters in this object, (this is NOT the
+     * primary API for value setting, for that see env())
+     *
+     * @param \Zend\Stdlib\Parameters $env
+     * @return \Zend\Console\Request
+     */
+    public function setEnv(Parameters $env)
+    {
+        $this->envParams = $env;
+        return $this;
+    }
+
+    /**
+     * Return the parameter container responsible for env parameters
+     *
+     * @return \Zend\Stdlib\Parameters
+     */
+    public function env()
+    {
+        if ($this->envParams === null) {
+            $this->envParams = new Parameters();
+        }
+
+        return $this->envParams;
+    }
+
+    /**
+     * @return string
+     */
+    public function toString()
+    {
+        return trim(implode(' ', $this->params()->toArray()));
+    }
+
+    /**
+     * Allow PHP casting of this object
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        return $this->toString();
+    }
+
+    /**
+     * @param string $scriptName
+     */
+    public function setScriptName($scriptName)
+    {
+        $this->scriptName = $scriptName;
+    }
+
+    /**
+     * @return string
+     */
+    public function getScriptName()
+    {
+        return $this->scriptName;
+    }
+
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/Response.php b/wcfsetup/install/files/lib/system/api/zend/Console/Response.php
new file mode 100644 (file)
index 0000000..2aca8d3
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Console
+ */
+
+namespace Zend\Console;
+
+use Zend\Stdlib\Message;
+use Zend\Stdlib\ResponseInterface;
+
+/**
+ * @category   Zend
+ * @package    Zend_Console
+ */
+class Response extends Message implements ResponseInterface
+{
+    protected $contentSent = false;
+
+    public function contentSent()
+    {
+        return $this->contentSent;
+    }
+
+    /**
+     * Set the error level that will be returned to shell.
+     *
+     * @param integer   $errorLevel
+     * @return Response
+     */
+    public function setErrorLevel($errorLevel)
+    {
+        $this->setMetadata('errorLevel', $errorLevel);
+        return $this;
+    }
+
+    /**
+     * Get response error level that will be returned to shell.
+     *
+     * @return integer|0
+     */
+    public function getErrorLevel()
+    {
+        return $this->getMetadata('errorLevel', 0);
+    }
+
+    public function sendContent()
+    {
+        if ($this->contentSent()) {
+            return $this;
+        }
+        echo $this->getContent();
+        $this->contentSent = true;
+        return $this;
+    }
+
+    public function send()
+    {
+        $this->sendContent();
+        $errorLevel = (int)$this->getMetadata('errorLevel',0);
+        exit($errorLevel);
+    }
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Console/composer.json b/wcfsetup/install/files/lib/system/api/zend/Console/composer.json
new file mode 100644 (file)
index 0000000..bb284f6
--- /dev/null
@@ -0,0 +1,18 @@
+{
+    "name": "zendframework/zend-console",
+    "description": " ",
+    "license": "BSD-3-Clause",
+    "keywords": [
+        "zf2",
+        "console"
+    ],
+    "autoload": {
+        "psr-0": {
+            "Zend\\Console\\": ""
+        }
+    },
+    "target-dir": "Zend/Console",
+    "require": {
+        "php": ">=5.3.3"
+    }
+}
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/api/zend/LICENSE.txt b/wcfsetup/install/files/lib/system/api/zend/LICENSE.txt
new file mode 100644 (file)
index 0000000..36e9760
--- /dev/null
@@ -0,0 +1,27 @@
+Copyright (c) 2005-2012, Zend Technologies USA, Inc.
+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 Zend Technologies USA, Inc. 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.
diff --git a/wcfsetup/install/files/lib/system/api/zend/Loader/AutoloaderFactory.php b/wcfsetup/install/files/lib/system/api/zend/Loader/AutoloaderFactory.php
new file mode 100644 (file)
index 0000000..0a95d26
--- /dev/null
@@ -0,0 +1,227 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Loader
+ */
+
+namespace Zend\Loader;
+
+use ReflectionClass;
+use Traversable;
+
+require_once __DIR__ . '/SplAutoloader.php';
+
+if (class_exists('Zend\Loader\AutoloaderFactory')) {
+    return;
+}
+
+/**
+ * @category   Zend
+ * @package    Zend_Loader
+ */
+abstract class AutoloaderFactory
+{
+    const STANDARD_AUTOLOADER = 'Zend\Loader\StandardAutoloader';
+
+    /**
+     * @var array All autoloaders registered using the factory
+     */
+    protected static $loaders = array();
+
+    /**
+     * @var StandardAutoloader StandardAutoloader instance for resolving
+     * autoloader classes via the include_path
+     */
+    protected static $standardAutoloader;
+
+    /**
+     * Factory for autoloaders
+     *
+     * Options should be an array or Traversable object of the following structure:
+     * <code>
+     * array(
+     *     '<autoloader class name>' => $autoloaderOptions,
+     * )
+     * </code>
+     *
+     * The factory will then loop through and instantiate each autoloader with
+     * the specified options, and register each with the spl_autoloader.
+     *
+     * You may retrieve the concrete autoloader instances later using
+     * {@link getRegisteredAutoloaders()}.
+     *
+     * Note that the class names must be resolvable on the include_path or via
+     * the Zend library, using PSR-0 rules (unless the class has already been
+     * loaded).
+     *
+     * @param  array|Traversable $options (optional) options to use. Defaults to Zend\Loader\StandardAutoloader
+     * @return void
+     * @throws Exception\InvalidArgumentException for invalid options
+     * @throws Exception\InvalidArgumentException for unloadable autoloader classes
+     * @throws Exception\DomainException for autoloader classes not implementing SplAutoloader
+     */
+    public static function factory($options = null)
+    {
+        if (null === $options) {
+            if (!isset(static::$loaders[static::STANDARD_AUTOLOADER])) {
+                $autoloader = static::getStandardAutoloader();
+                $autoloader->register();
+                static::$loaders[static::STANDARD_AUTOLOADER] = $autoloader;
+            }
+
+            // Return so we don't hit the next check's exception (we're done here anyway)
+            return;
+        }
+
+        if (!is_array($options) && !($options instanceof Traversable)) {
+            require_once __DIR__ . '/Exception/InvalidArgumentException.php';
+            throw new Exception\InvalidArgumentException(
+                'Options provided must be an array or Traversable'
+            );
+        }
+
+        foreach ($options as $class => $options) {
+            if (!isset(static::$loaders[$class])) {
+                $autoloader = static::getStandardAutoloader();
+                if (!class_exists($class) && !$autoloader->autoload($class)) {
+                    require_once 'Exception/InvalidArgumentException.php';
+                    throw new Exception\InvalidArgumentException(
+                        sprintf('Autoloader class "%s" not loaded', $class)
+                    );
+                }
+
+                if (!self::isSubclassOf($class, 'Zend\Loader\SplAutoloader')) {
+                    require_once 'Exception/InvalidArgumentException.php';
+                    throw new Exception\InvalidArgumentException(
+                        sprintf('Autoloader class %s must implement Zend\\Loader\\SplAutoloader', $class)
+                    );
+                }
+
+                if ($class === static::STANDARD_AUTOLOADER) {
+                    $autoloader->setOptions($options);
+                } else {
+                    $autoloader = new $class($options);
+                }
+                $autoloader->register();
+                static::$loaders[$class] = $autoloader;
+            } else {
+                static::$loaders[$class]->setOptions($options);
+            }
+        }
+    }
+
+    /**
+     * Get an list of all autoloaders registered with the factory
+     *
+     * Returns an array of autoloader instances.
+     *
+     * @return array
+     */
+    public static function getRegisteredAutoloaders()
+    {
+        return static::$loaders;
+    }
+
+    /**
+     * Retrieves an autoloader by class name
+     *
+     * @param  string $class
+     * @return SplAutoloader
+     * @throws Exception\InvalidArgumentException for non-registered class
+     */
+    public static function getRegisteredAutoloader($class)
+    {
+        if (!isset(static::$loaders[$class])) {
+            require_once 'Exception/InvalidArgumentException.php';
+            throw new Exception\InvalidArgumentException(sprintf('Autoloader class "%s" not loaded', $class));
+        }
+        return static::$loaders[$class];
+    }
+
+    /**
+     * Unregisters all autoloaders that have been registered via the factory.
+     * This will NOT unregister autoloaders registered outside of the fctory.
+     *
+     * @return void
+     */
+    public static function unregisterAutoloaders()
+    {
+        foreach (static::getRegisteredAutoloaders() as $class => $autoloader) {
+            spl_autoload_unregister(array($autoloader, 'autoload'));
+            unset(static::$loaders[$class]);
+        }
+    }
+
+    /**
+     * Unregister a single autoloader by class name
+     *
+     * @param  string $autoloaderClass
+     * @return bool
+     */
+    public static function unregisterAutoloader($autoloaderClass)
+    {
+        if (!isset(static::$loaders[$autoloaderClass])) {
+            return false;
+        }
+
+        $autoloader = static::$loaders[$autoloaderClass];
+        spl_autoload_unregister(array($autoloader, 'autoload'));
+        unset(static::$loaders[$autoloaderClass]);
+        return true;
+    }
+
+    /**
+     * Get an instance of the standard autoloader
+     *
+     * Used to attempt to resolve autoloader classes, using the
+     * StandardAutoloader. The instance is marked as a fallback autoloader, to
+     * allow resolving autoloaders not under the "Zend" namespace.
+     *
+     * @return SplAutoloader
+     */
+    protected static function getStandardAutoloader()
+    {
+        if (null !== static::$standardAutoloader) {
+            return static::$standardAutoloader;
+        }
+
+
+        if (!class_exists(static::STANDARD_AUTOLOADER)) {
+            // Extract the filename from the classname
+            $stdAutoloader = substr(strrchr(static::STANDARD_AUTOLOADER, '\\'), 1);
+            require_once __DIR__ . "/$stdAutoloader.php";
+        }
+        $loader = new StandardAutoloader();
+        static::$standardAutoloader = $loader;
+        return static::$standardAutoloader;
+    }
+
+    /**
+     * Checks if the object has this class as one of its parents
+     *
+     * @see https://bugs.php.net/bug.php?id=53727
+     * @see https://github.com/zendframework/zf2/pull/1807
+     *
+     * @param  string $className
+     * @param  string $type
+     * @return bool
+     */
+    protected static function isSubclassOf($className, $type)
+    {
+        if (is_subclass_of($className, $type)) {
+            return true;
+        }
+        if (version_compare(PHP_VERSION, '5.3.7', '>=')) {
+            return false;
+        }
+        if (!interface_exists($type)) {
+            return false;
+        }
+        $r = new ReflectionClass($className);
+        return $r->implementsInterface($type);
+    }
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Loader/ClassMapAutoloader.php b/wcfsetup/install/files/lib/system/api/zend/Loader/ClassMapAutoloader.php
new file mode 100644 (file)
index 0000000..f5d2770
--- /dev/null
@@ -0,0 +1,221 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Loader
+ */
+
+namespace Zend\Loader;
+
+use Traversable;
+
+// Grab SplAutoloader interface
+require_once __DIR__ . '/SplAutoloader.php';
+
+/**
+ * Class-map autoloader
+ *
+ * Utilizes class-map files to lookup classfile locations.
+ *
+ * @category   Zend
+ * @package    Zend_Loader
+ */
+class ClassMapAutoloader implements SplAutoloader
+{
+    /**
+     * Registry of map files that have already been loaded
+     * @var array
+     */
+    protected $mapsLoaded = array();
+
+    /**
+     * Class name/filename map
+     * @var array
+     */
+    protected $map = array();
+
+    /**
+     * Constructor
+     *
+     * Create a new instance, and optionally configure the autoloader.
+     *
+     * @param  null|array|Traversable $options
+     */
+    public function __construct($options = null)
+    {
+        if (null !== $options) {
+            $this->setOptions($options);
+        }
+    }
+
+    /**
+     * Configure the autoloader
+     *
+     * Proxies to {@link registerAutoloadMaps()}.
+     *
+     * @param  array|Traversable $options
+     * @return ClassMapAutoloader
+     */
+    public function setOptions($options)
+    {
+        $this->registerAutoloadMaps($options);
+        return $this;
+    }
+
+    /**
+     * Register an autoload map
+     *
+     * An autoload map may be either an associative array, or a file returning
+     * an associative array.
+     *
+     * An autoload map should be an associative array containing
+     * classname/file pairs.
+     *
+     * @param  string|array $map
+     * @throws Exception\InvalidArgumentException
+     * @return ClassMapAutoloader
+     */
+    public function registerAutoloadMap($map)
+    {
+        if (is_string($map)) {
+            $location = $map;
+            if ($this === ($map = $this->loadMapFromFile($location))) {
+                return $this;
+            }
+        }
+
+        if (!is_array($map)) {
+            require_once __DIR__ . '/Exception/InvalidArgumentException.php';
+            throw new Exception\InvalidArgumentException(sprintf(
+                'Map file provided does not return a map. Map file: "%s"',
+                (isset($location) && is_string($location) ? $location : 'unexpected type: ' . gettype($map))
+            ));
+        }
+
+        $this->map = array_merge($this->map, $map);
+
+        if (isset($location)) {
+            $this->mapsLoaded[] = $location;
+        }
+
+        return $this;
+    }
+
+    /**
+     * Register many autoload maps at once
+     *
+     * @param  array $locations
+     * @throws Exception\InvalidArgumentException
+     * @return ClassMapAutoloader
+     */
+    public function registerAutoloadMaps($locations)
+    {
+        if (!is_array($locations) && !($locations instanceof Traversable)) {
+            require_once __DIR__ . '/Exception/InvalidArgumentException.php';
+            throw new Exception\InvalidArgumentException('Map list must be an array or implement Traversable');
+        }
+        foreach ($locations as $location) {
+            $this->registerAutoloadMap($location);
+        }
+        return $this;
+    }
+
+    /**
+     * Retrieve current autoload map
+     *
+     * @return array
+     */
+    public function getAutoloadMap()
+    {
+        return $this->map;
+    }
+
+    /**
+     * Defined by Autoloadable
+     *
+     * @param  string $class
+     * @return void
+     */
+    public function autoload($class)
+    {
+        if (isset($this->map[$class])) {
+            require_once $this->map[$class];
+        }
+    }
+
+    /**
+     * Register the autoloader with spl_autoload registry
+     *
+     * @return void
+     */
+    public function register()
+    {
+        spl_autoload_register(array($this, 'autoload'), true, true);
+    }
+
+    /**
+     * Load a map from a file
+     *
+     * If the map has been previously loaded, returns the current instance;
+     * otherwise, returns whatever was returned by calling include() on the
+     * location.
+     *
+     * @param  string $location
+     * @return ClassMapAutoloader|mixed
+     * @throws Exception\InvalidArgumentException for nonexistent locations
+     */
+    protected function loadMapFromFile($location)
+    {
+        if (!file_exists($location)) {
+            require_once __DIR__ . '/Exception/InvalidArgumentException.php';
+            throw new Exception\InvalidArgumentException(sprintf(
+                'Map file provided does not exist. Map file: "%s"',
+                (is_string($location) ? $location : 'unexpected type: ' . gettype($location))
+            ));
+        }
+
+        if (!$path = static::realPharPath($location)) {
+            $path = realpath($location);
+        }
+
+        if (in_array($path, $this->mapsLoaded)) {
+            // Already loaded this map
+            return $this;
+        }
+
+        $map = include $path;
+
+        return $map;
+    }
+
+    /**
+     * Resolve the real_path() to a file within a phar.
+     *
+     * @see https://bugs.php.net/bug.php?id=52769
+     * @param  string $path
+     * @return string
+     */
+    public static function realPharPath($path)
+    {
+        if (strpos($path, 'phar:///') !== 0) {
+            return;
+        }
+
+        $parts = explode('/', str_replace(array('/','\\'), '/', substr($path, 8)));
+        $parts = array_values(array_filter($parts, function($p) { return ($p !== '' && $p !== '.'); }));
+
+        array_walk($parts, function ($value, $key) use(&$parts) {
+            if ($value === '..') {
+                unset($parts[$key], $parts[$key-1]);
+                $parts = array_values($parts);
+            }
+        });
+
+        if (file_exists($realPath = 'phar:///' . implode('/', $parts))) {
+            return $realPath;
+        }
+    }
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Loader/Exception/BadMethodCallException.php b/wcfsetup/install/files/lib/system/api/zend/Loader/Exception/BadMethodCallException.php
new file mode 100644 (file)
index 0000000..3366d5a
--- /dev/null
@@ -0,0 +1,23 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Loader
+ */
+
+namespace Zend\Loader\Exception;
+
+require_once __DIR__ . '/ExceptionInterface.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Loader
+ * @subpackage Exception
+ */
+class BadMethodCallException extends \BadMethodCallException implements
+    ExceptionInterface
+{
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Loader/Exception/DomainException.php b/wcfsetup/install/files/lib/system/api/zend/Loader/Exception/DomainException.php
new file mode 100644 (file)
index 0000000..d74fb70
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Loader
+ */
+
+namespace Zend\Loader\Exception;
+
+require_once __DIR__ . '/ExceptionInterface.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Loader
+ * @subpackage Exception
+ */
+class DomainException extends \DomainException implements ExceptionInterface
+{}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Loader/Exception/ExceptionInterface.php b/wcfsetup/install/files/lib/system/api/zend/Loader/Exception/ExceptionInterface.php
new file mode 100644 (file)
index 0000000..f8525e2
--- /dev/null
@@ -0,0 +1,18 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Loader
+ */
+
+namespace Zend\Loader\Exception;
+
+/**
+ * @category   Zend
+ * @package    Zend_Loader
+ */
+interface ExceptionInterface
+{}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Loader/Exception/InvalidArgumentException.php b/wcfsetup/install/files/lib/system/api/zend/Loader/Exception/InvalidArgumentException.php
new file mode 100644 (file)
index 0000000..a4bcc9e
--- /dev/null
@@ -0,0 +1,22 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Loader
+ */
+
+namespace Zend\Loader\Exception;
+
+require_once __DIR__ . '/ExceptionInterface.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Loader
+ * @subpackage Exception
+ */
+class InvalidArgumentException extends \InvalidArgumentException implements
+    ExceptionInterface
+{}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Loader/Exception/InvalidPathException.php b/wcfsetup/install/files/lib/system/api/zend/Loader/Exception/InvalidPathException.php
new file mode 100644 (file)
index 0000000..5ff8844
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Loader
+ */
+
+namespace Zend\Loader\Exception;
+
+require_once __DIR__ . '/ExceptionInterface.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Loader
+ * @subpackage Exception
+ */
+class InvalidPathException extends \Exception implements ExceptionInterface
+{}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Loader/Exception/MissingResourceNamespaceException.php b/wcfsetup/install/files/lib/system/api/zend/Loader/Exception/MissingResourceNamespaceException.php
new file mode 100644 (file)
index 0000000..bec2e96
--- /dev/null
@@ -0,0 +1,22 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Loader
+ */
+
+namespace Zend\Loader\Exception;
+
+require_once __DIR__ . '/ExceptionInterface.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Loader
+ * @subpackage Exception
+ */
+class MissingResourceNamespaceException extends \Exception implements
+    ExceptionInterface
+{}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Loader/Exception/PluginLoaderException.php b/wcfsetup/install/files/lib/system/api/zend/Loader/Exception/PluginLoaderException.php
new file mode 100644 (file)
index 0000000..2a7cf34
--- /dev/null
@@ -0,0 +1,24 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Loader
+ */
+
+namespace Zend\Loader\Exception;
+
+require_once __DIR__ . '/DomainException.php';
+
+/**
+ * Plugin class loader exceptions
+ *
+ * @category   Zend
+ * @package    Zend_Loader
+ * @subpackage Exception
+ */
+class PluginLoaderException extends DomainException
+{
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Loader/Exception/RuntimeException.php b/wcfsetup/install/files/lib/system/api/zend/Loader/Exception/RuntimeException.php
new file mode 100644 (file)
index 0000000..207f5c9
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Loader
+ */
+
+namespace Zend\Loader\Exception;
+
+require_once __DIR__ . '/ExceptionInterface.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Loader
+ * @subpackage Exception
+ */
+class RuntimeException extends \RuntimeException implements ExceptionInterface
+{}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Loader/Exception/SecurityException.php b/wcfsetup/install/files/lib/system/api/zend/Loader/Exception/SecurityException.php
new file mode 100644 (file)
index 0000000..51523e9
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Loader
+ */
+
+namespace Zend\Loader\Exception;
+
+require_once __DIR__ . '/DomainException.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Loader
+ * @subpackage Exception
+ */
+class SecurityException extends DomainException
+{}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Loader/ModuleAutoloader.php b/wcfsetup/install/files/lib/system/api/zend/Loader/ModuleAutoloader.php
new file mode 100644 (file)
index 0000000..c068c35
--- /dev/null
@@ -0,0 +1,387 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Loader
+ */
+
+namespace Zend\Loader;
+
+// Grab SplAutoloader interface
+require_once __DIR__ . '/SplAutoloader.php';
+
+use GlobIterator;
+use SplFileInfo;
+use Traversable;
+
+class ModuleAutoloader implements SplAutoloader
+{
+    /**
+     * @var array An array of module paths to scan
+     */
+    protected $paths = array();
+
+    /**
+     * @var array An array of modulename => path
+     */
+    protected $explicitPaths = array();
+
+    /**
+     * @var array An array of namespaceName => namespacePath
+     */
+    protected $namespacedPaths = array();
+
+    /**
+     * @var array An array of supported phar extensions (filled on constructor)
+     */
+    protected $pharExtensions = array();
+
+    /**
+     * @var array An array of module classes to their containing files
+     */
+    protected $moduleClassMap = array();
+
+    /**
+     * Constructor
+     *
+     * Allow configuration of the autoloader via the constructor.
+     *
+     * @param  null|array|Traversable $options
+     */
+    public function __construct($options = null)
+    {
+        if (extension_loaded('phar')) {
+            $this->pharExtensions = array(
+                'phar',
+                'phar.tar',
+                'tar',
+            );
+
+            // ext/zlib enabled -> phar can read gzip & zip compressed files
+            if (extension_loaded('zlib')) {
+                $this->pharExtensions[] = 'phar.gz';
+                $this->pharExtensions[] = 'phar.tar.gz';
+                $this->pharExtensions[] = 'tar.gz';
+
+                $this->pharExtensions[] = 'phar.zip';
+                $this->pharExtensions[] = 'zip';
+            }
+
+            // ext/bzip2 enabled -> phar can read bz2 compressed files
+            if (extension_loaded('bzip2')) {
+                $this->pharExtensions[] = 'phar.bz2';
+                $this->pharExtensions[] = 'phar.tar.bz2';
+                $this->pharExtensions[] = 'tar.bz2';
+            }
+        }
+
+        if (null !== $options) {
+            $this->setOptions($options);
+        }
+    }
+
+    /**
+     * Configure the autoloader
+     *
+     * In most cases, $options should be either an associative array or
+     * Traversable object.
+     *
+     * @param  array|Traversable $options
+     * @return ModuleAutoloader
+     */
+    public function setOptions($options)
+    {
+        $this->registerPaths($options);
+        return $this;
+    }
+
+    /**
+     * Autoload a class
+     *
+     * @param   $class
+     * @return  mixed
+     *          False [if unable to load $class]
+     *          get_class($class) [if $class is successfully loaded]
+     */
+    public function autoload($class)
+    {
+        // Limit scope of this autoloader
+        if (substr($class, -7) !== '\Module') {
+            return false;
+        }
+
+        $moduleName = substr($class, 0, -7);
+        if (isset($this->explicitPaths[$moduleName])) {
+            $classLoaded = $this->loadModuleFromDir($this->explicitPaths[$moduleName], $class);
+            if ($classLoaded) {
+                return $classLoaded;
+            }
+
+            $classLoaded = $this->loadModuleFromPhar($this->explicitPaths[$moduleName], $class);
+            if ($classLoaded) {
+                return $classLoaded;
+            }
+        }
+
+        if (count($this->namespacedPaths) >= 1 ) {
+            foreach ( $this->namespacedPaths as $namespace=>$path ) {
+                if ( false === strpos($moduleName,$namespace) ) {
+                    continue;
+                }
+
+                $moduleName_buffer = str_replace($namespace . "\\", "", $moduleName );
+                $path .= DIRECTORY_SEPARATOR . $moduleName_buffer . DIRECTORY_SEPARATOR;
+
+                $classLoaded = $this->loadModuleFromDir($path, $class);
+                if ($classLoaded) {
+                    return $classLoaded;
+                }
+
+                $classLoaded = $this->loadModuleFromPhar($path, $class);
+                if ($classLoaded) {
+                    return $classLoaded;
+                }
+            }
+        }
+
+
+        $moduleClassPath   = str_replace('\\', DIRECTORY_SEPARATOR, $moduleName);
+
+        $pharSuffixPattern = null;
+        if ($this->pharExtensions) {
+            $pharSuffixPattern = '(' . implode('|', array_map('preg_quote', $this->pharExtensions)) . ')';
+        }
+
+        foreach ($this->paths as $path) {
+            $path = $path . $moduleClassPath;
+
+            $classLoaded = $this->loadModuleFromDir($path, $class);
+            if ($classLoaded) {
+                return $classLoaded;
+            }
+
+            // No directory with Module.php, searching for phars
+            if ($pharSuffixPattern) {
+                foreach (new GlobIterator($path . '.*') as $entry) {
+                    if ($entry->isDir()) {
+                        continue;
+                    }
+
+                    if (!preg_match('#.+\.' . $pharSuffixPattern . '$#', $entry->getPathname())) {
+                        continue;
+                    }
+
+                    $classLoaded = $this->loadModuleFromPhar($entry->getPathname(), $class);
+                    if ($classLoaded) {
+                        return $classLoaded;
+                    }
+                }
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * loadModuleFromDir
+     *
+     * @param  string $dirPath
+     * @param  string $class
+     * @return  mixed
+     *          False [if unable to load $class]
+     *          get_class($class) [if $class is successfully loaded]
+     */
+    protected function loadModuleFromDir($dirPath, $class)
+    {
+        $file = new SplFileInfo($dirPath . '/Module.php');
+        if ($file->isReadable() && $file->isFile()) {
+            // Found directory with Module.php in it
+            require_once $file->getRealPath();
+            if (class_exists($class)) {
+                $this->moduleClassMap[$class] = $file->getRealPath();
+                return $class;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * loadModuleFromPhar
+     *
+     * @param  string $pharPath
+     * @param  string $class
+     * @return  mixed
+     *          False [if unable to load $class]
+     *          get_class($class) [if $class is successfully loaded]
+     */
+    protected function loadModuleFromPhar($pharPath, $class)
+    {
+        $pharPath = static::normalizePath($pharPath, false);
+        $file = new SplFileInfo($pharPath);
+        if (!$file->isReadable() || !$file->isFile()) {
+            return false;
+        }
+
+        $fileRealPath = $file->getRealPath();
+
+        // Phase 0: Check for executable phar with Module class in stub
+        if (strpos($fileRealPath, '.phar') !== false) {
+            // First see if the stub makes the Module class available
+            require_once $fileRealPath;
+            if (class_exists($class)) {
+                $this->moduleClassMap[$class] = $fileRealPath;
+                return $class;
+            }
+        }
+
+        // Phase 1: Not executable phar, no stub, or stub did not provide Module class; try Module.php directly
+        $moduleClassFile = 'phar://' . $fileRealPath . '/Module.php';
+        $moduleFile = new SplFileInfo($moduleClassFile);
+        if ($moduleFile->isReadable() && $moduleFile->isFile()) {
+            require_once $moduleClassFile;
+            if (class_exists($class)) {
+                $this->moduleClassMap[$class] = $moduleClassFile;
+                return $class;
+            }
+        }
+
+        // Phase 2: Check for nested module directory within archive
+        // Checks for /path/to/MyModule.tar/MyModule/Module.php
+        // (shell-integrated zip/tar utilities wrap directories like this)
+        $pharBaseName = $this->pharFileToModuleName($fileRealPath);
+        $moduleClassFile = 'phar://' . $fileRealPath . '/' . $pharBaseName  . '/Module.php';
+        $moduleFile = new SplFileInfo($moduleClassFile);
+        if ($moduleFile->isReadable() && $moduleFile->isFile()) {
+            require_once $moduleClassFile;
+            if (class_exists($class)) {
+                $this->moduleClassMap[$class] = $moduleClassFile;
+                return $class;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Register the autoloader with spl_autoload registry
+     *
+     * @return void
+     */
+    public function register()
+    {
+        spl_autoload_register(array($this, 'autoload'));
+    }
+
+    /**
+     * Unregister the autoloader with spl_autoload registry
+     *
+     * @return void
+     */
+    public function unregister()
+    {
+        spl_autoload_unregister(array($this, 'autoload'));
+    }
+
+    /**
+     * registerPaths
+     *
+     * @param  array|Traversable $paths
+     * @throws \InvalidArgumentException
+     * @return ModuleAutoloader
+     */
+    public function registerPaths($paths)
+    {
+        if (!is_array($paths) && !$paths instanceof Traversable) {
+            throw new \InvalidArgumentException(
+                'Parameter to \\Zend\\Loader\\ModuleAutoloader\'s '
+                . 'registerPaths method must be an array or '
+                . 'implement the \\Traversable interface'
+            );
+        }
+
+        foreach ($paths as $module => $path) {
+            if (is_string($module)) {
+                $this->registerPath($path, $module);
+            } else {
+                $this->registerPath($path);
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * registerPath
+     *
+     * @param  string $path
+     * @param  bool|string $moduleName
+     * @throws \InvalidArgumentException
+     * @return ModuleAutoloader
+     */
+    public function registerPath($path, $moduleName = false)
+    {
+        if (!is_string($path)) {
+            throw new \InvalidArgumentException(sprintf(
+                'Invalid path provided; must be a string, received %s',
+                gettype($path)
+            ));
+        }
+        if ($moduleName) {
+            if (in_array( substr($moduleName, -2 ), array('\\*','\\%') ) ) {
+                $this->namespacedPaths[ substr($moduleName, 0, -2 ) ] = static::normalizePath($path);
+            } else {
+                $this->explicitPaths[$moduleName] = static::normalizePath($path);
+            }
+        } else {
+            $this->paths[] = static::normalizePath($path);
+        }
+        return $this;
+    }
+
+    /**
+     * getPaths
+     *
+     * This is primarily for unit testing, but could have other uses.
+     *
+     * @return array
+     */
+    public function getPaths()
+    {
+        return $this->paths;
+    }
+
+    /**
+     * Returns the base module name from the path to a phar
+     *
+     * @param  string $pharPath
+     * @return string
+     */
+    protected function pharFileToModuleName($pharPath)
+    {
+        do {
+            $pathinfo = pathinfo($pharPath);
+            $pharPath = $pathinfo['filename'];
+        } while (isset($pathinfo['extension']));
+        return $pathinfo['filename'];
+    }
+
+    /**
+     * Normalize a path for insertion in the stack
+     *
+     * @param  string $path
+     * @param  bool   $trailingSlash Whether trailing slash should be included
+     * @return string
+     */
+    public static function normalizePath($path, $trailingSlash = true)
+    {
+        $path = rtrim($path, '/');
+        $path = rtrim($path, '\\');
+        if ($trailingSlash) {
+            $path .= DIRECTORY_SEPARATOR;
+        }
+        return $path;
+    }
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Loader/PluginClassLoader.php b/wcfsetup/install/files/lib/system/api/zend/Loader/PluginClassLoader.php
new file mode 100644 (file)
index 0000000..bfcfa4c
--- /dev/null
@@ -0,0 +1,221 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Loader
+ */
+
+namespace Zend\Loader;
+
+use ArrayIterator;
+use IteratorAggregate;
+use Traversable;
+
+/**
+ * Plugin class locator interface
+ *
+ * @category   Zend
+ * @package    Zend_Loader
+ */
+class PluginClassLoader implements PluginClassLocator
+{
+    /**
+     * List of plugin name => class name pairs
+     * @var array
+     */
+    protected $plugins = array();
+
+    /**
+     * Static map allow global seeding of plugin loader
+     * @var array
+     */
+    protected static $staticMap = array();
+
+    /**
+     * Constructor
+     *
+     * @param  null|array|Traversable $map If provided, seeds the loader with a map
+     */
+    public function __construct($map = null)
+    {
+        // Merge in static overrides
+        if (!empty(static::$staticMap)) {
+            $this->registerPlugins(static::$staticMap);
+        }
+
+        // Merge in constructor arguments
+        if ($map !== null) {
+            $this->registerPlugins($map);
+        }
+    }
+
+    /**
+     * Add a static map of plugins
+     *
+     * A null value will clear the static map.
+     *
+     * @param  null|array|Traversable $map
+     * @throws Exception\InvalidArgumentException
+     * @return void
+     */
+    public static function addStaticMap($map)
+    {
+        if (null === $map) {
+            static::$staticMap = array();
+            return;
+        }
+
+        if (!is_array($map) && !$map instanceof \Traversable) {
+            throw new Exception\InvalidArgumentException('Expects an array or Traversable object');
+        }
+        foreach ($map as $key => $value) {
+            static::$staticMap[$key] = $value;
+        }
+    }
+
+    /**
+     * Register a class to a given short name
+     *
+     * @param  string $shortName
+     * @param  string $className
+     * @return PluginClassLoader
+     */
+    public function registerPlugin($shortName, $className)
+    {
+        $this->plugins[strtolower($shortName)] = $className;
+        return $this;
+    }
+
+    /**
+     * Register many plugins at once
+     *
+     * If $map is a string, assumes that the map is the class name of a
+     * Traversable object (likely a ShortNameLocator); it will then instantiate
+     * this class and use it to register plugins.
+     *
+     * If $map is an array or Traversable object, it will iterate it to
+     * register plugin names/classes.
+     *
+     * For all other arguments, or if the string $map is not a class or not a
+     * Traversable class, an exception will be raised.
+     *
+     * @param  string|array|Traversable $map
+     * @return PluginClassLoader
+     * @throws Exception\InvalidArgumentException
+     */
+    public function registerPlugins($map)
+    {
+        if (is_string($map)) {
+            if (!class_exists($map)) {
+                throw new Exception\InvalidArgumentException('Map class provided is invalid');
+            }
+            $map = new $map;
+        }
+        if (is_array($map)) {
+            $map = new ArrayIterator($map);
+        }
+        if (!$map instanceof Traversable) {
+            throw new Exception\InvalidArgumentException('Map provided is invalid; must be traversable');
+        }
+
+        // iterator_apply doesn't work as expected with IteratorAggregate
+        if ($map instanceof IteratorAggregate) {
+            $map = $map->getIterator();
+        }
+
+        foreach ($map as $name => $class) {
+            if (is_int($name) || is_numeric($name)) {
+                if (!is_object($class) && class_exists($class)) {
+                    $class = new $class();
+                }
+
+                if ($class instanceof Traversable) {
+                    $this->registerPlugins($class);
+                    continue;
+                }
+            }
+
+            $this->registerPlugin($name, $class);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Unregister a short name lookup
+     *
+     * @param  mixed $shortName
+     * @return PluginClassLoader
+     */
+    public function unregisterPlugin($shortName)
+    {
+        $lookup = strtolower($shortName);
+        if (array_key_exists($lookup, $this->plugins)) {
+            unset($this->plugins[$lookup]);
+        }
+        return $this;
+    }
+
+    /**
+     * Get a list of all registered plugins
+     *
+     * @return array|Traversable
+     */
+    public function getRegisteredPlugins()
+    {
+        return $this->plugins;
+    }
+
+    /**
+     * Whether or not a plugin by a specific name has been registered
+     *
+     * @param  string $name
+     * @return bool
+     */
+    public function isLoaded($name)
+    {
+        $lookup = strtolower($name);
+        return isset($this->plugins[$lookup]);
+    }
+
+    /**
+     * Return full class name for a named helper
+     *
+     * @param  string $name
+     * @return string|false
+     */
+    public function getClassName($name)
+    {
+        return $this->load($name);
+    }
+
+    /**
+     * Load a helper via the name provided
+     *
+     * @param  string $name
+     * @return string|false
+     */
+    public function load($name)
+    {
+        if (!$this->isLoaded($name)) {
+            return false;
+        }
+        return $this->plugins[strtolower($name)];
+    }
+
+    /**
+     * Defined by IteratorAggregate
+     *
+     * Returns an instance of ArrayIterator, containing a map of
+     * all plugins
+     *
+     * @return ArrayIterator
+     */
+    public function getIterator()
+    {
+        return new ArrayIterator($this->plugins);
+    }
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Loader/PluginClassLocator.php b/wcfsetup/install/files/lib/system/api/zend/Loader/PluginClassLocator.php
new file mode 100644 (file)
index 0000000..2114a5a
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Loader
+ */
+
+namespace Zend\Loader;
+
+use Traversable;
+
+/**
+ * Plugin class locator interface
+ *
+ * @category   Zend
+ * @package    Zend_Loader
+ */
+interface PluginClassLocator extends ShortNameLocator, \IteratorAggregate
+{
+    /**
+     * Register a class to a given short name
+     *
+     * @param  string $shortName
+     * @param  string $className
+     * @return PluginClassLocator
+     */
+    public function registerPlugin($shortName, $className);
+
+    /**
+     * Unregister a short name lookup
+     *
+     * @param  mixed $shortName
+     * @return void
+     */
+    public function unregisterPlugin($shortName);
+
+    /**
+     * Get a list of all registered plugins
+     *
+     * @return array|Traversable
+     */
+    public function getRegisteredPlugins();
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Loader/ShortNameLocator.php b/wcfsetup/install/files/lib/system/api/zend/Loader/ShortNameLocator.php
new file mode 100644 (file)
index 0000000..0a65b10
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Loader
+ */
+
+namespace Zend\Loader;
+
+/**
+ * Short name locator interface
+ *
+ * @category   Zend
+ * @package    Zend_Loader
+ */
+interface ShortNameLocator
+{
+    /**
+     * Whether or not a Helper by a specific name
+     *
+     * @param  string $name
+     * @return bool
+     */
+    public function isLoaded($name);
+
+    /**
+     * Return full class name for a named helper
+     *
+     * @param  string $name
+     * @return string
+     */
+    public function getClassName($name);
+
+    /**
+     * Load a helper via the name provided
+     *
+     * @param  string $name
+     * @return string
+     */
+    public function load($name);
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Loader/SplAutoloader.php b/wcfsetup/install/files/lib/system/api/zend/Loader/SplAutoloader.php
new file mode 100644 (file)
index 0000000..e243d12
--- /dev/null
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Loader
+ */
+
+namespace Zend\Loader;
+
+use Traversable;
+
+if (interface_exists('Zend\Loader\SplAutoloader')) return;
+
+/**
+ * Defines an interface for classes that may register with the spl_autoload
+ * registry
+ *
+ * @package    Zend_Loader
+ */
+interface SplAutoloader
+{
+    /**
+     * Constructor
+     *
+     * Allow configuration of the autoloader via the constructor.
+     *
+     * @param  null|array|Traversable $options
+     */
+    public function __construct($options = null);
+
+    /**
+     * Configure the autoloader
+     *
+     * In most cases, $options should be either an associative array or
+     * Traversable object.
+     *
+     * @param  array|Traversable $options
+     * @return SplAutoloader
+     */
+    public function setOptions($options);
+
+    /**
+     * Autoload a class
+     *
+     * @param   $class
+     * @return  mixed
+     *          False [if unable to load $class]
+     *          get_class($class) [if $class is successfully loaded]
+     */
+    public function autoload($class);
+
+    /**
+     * Register the autoloader with spl_autoload registry
+     *
+     * Typically, the body of this will simply be:
+     * <code>
+     * spl_autoload_register(array($this, 'autoload'));
+     * </code>
+     *
+     * @return void
+     */
+    public function register();
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Loader/StandardAutoloader.php b/wcfsetup/install/files/lib/system/api/zend/Loader/StandardAutoloader.php
new file mode 100644 (file)
index 0000000..c0552e3
--- /dev/null
@@ -0,0 +1,331 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_Loader
+ */
+
+namespace Zend\Loader;
+
+// Grab SplAutoloader interface
+require_once __DIR__ . '/SplAutoloader.php';
+
+/**
+ * PSR-0 compliant autoloader
+ *
+ * Allows autoloading both namespaced and vendor-prefixed classes. Class
+ * lookups are performed on the filesystem. If a class file for the referenced
+ * class is not found, a PHP warning will be raised by include().
+ *
+ * @package    Zend_Loader
+ */
+class StandardAutoloader implements SplAutoloader
+{
+    const NS_SEPARATOR     = '\\';
+    const PREFIX_SEPARATOR = '_';
+    const LOAD_NS          = 'namespaces';
+    const LOAD_PREFIX      = 'prefixes';
+    const ACT_AS_FALLBACK  = 'fallback_autoloader';
+    const AUTOREGISTER_ZF  = 'autoregister_zf';
+
+    /**
+     * @var array Namespace/directory pairs to search; ZF library added by default
+     */
+    protected $namespaces = array();
+
+    /**
+     * @var array Prefix/directory pairs to search
+     */
+    protected $prefixes = array();
+
+    /**
+     * @var bool Whether or not the autoloader should also act as a fallback autoloader
+     */
+    protected $fallbackAutoloaderFlag = false;
+
+    /**
+     * Constructor
+     *
+     * @param  null|array|\Traversable $options
+     */
+    public function __construct($options = null)
+    {
+        if (null !== $options) {
+            $this->setOptions($options);
+        }
+    }
+
+    /**
+     * Configure autoloader
+     *
+     * Allows specifying both "namespace" and "prefix" pairs, using the
+     * following structure:
+     * <code>
+     * array(
+     *     'namespaces' => array(
+     *         'Zend'     => '/path/to/Zend/library',
+     *         'Doctrine' => '/path/to/Doctrine/library',
+     *     ),
+     *     'prefixes' => array(
+     *         'Phly_'     => '/path/to/Phly/library',
+     *     ),
+     *     'fallback_autoloader' => true,
+     * )
+     * </code>
+     *
+     * @param  array|\Traversable $options
+     * @throws Exception\InvalidArgumentException
+     * @return StandardAutoloader
+     */
+    public function setOptions($options)
+    {
+        if (!is_array($options) && !($options instanceof \Traversable)) {
+            require_once __DIR__ . '/Exception/InvalidArgumentException.php';
+            throw new Exception\InvalidArgumentException('Options must be either an array or Traversable');
+        }
+
+        foreach ($options as $type => $pairs) {
+            switch ($type) {
+                case self::AUTOREGISTER_ZF:
+                    if ($pairs) {
+                        $this->registerNamespace('Zend', dirname(__DIR__));
+                    }
+                    break;
+                case self::LOAD_NS:
+                    if (is_array($pairs) || $pairs instanceof \Traversable) {
+                        $this->registerNamespaces($pairs);
+                    }
+                    break;
+                case self::LOAD_PREFIX:
+                    if (is_array($pairs) || $pairs instanceof \Traversable) {
+                        $this->registerPrefixes($pairs);
+                    }
+                    break;
+                case self::ACT_AS_FALLBACK:
+                    $this->setFallbackAutoloader($pairs);
+                    break;
+                default:
+                    // ignore
+            }
+        }
+        return $this;
+    }
+
+    /**
+     * Set flag indicating fallback autoloader status
+     *
+     * @param  bool $flag
+     * @return StandardAutoloader
+     */
+    public function setFallbackAutoloader($flag)
+    {
+        $this->fallbackAutoloaderFlag = (bool) $flag;
+        return $this;
+    }
+
+    /**
+     * Is this autoloader acting as a fallback autoloader?
+     *
+     * @return bool
+     */
+    public function isFallbackAutoloader()
+    {
+        return $this->fallbackAutoloaderFlag;
+    }
+
+    /**
+     * Register a namespace/directory pair
+     *
+     * @param  string $namespace
+     * @param  string $directory
+     * @return StandardAutoloader
+     */
+    public function registerNamespace($namespace, $directory)
+    {
+        $namespace = rtrim($namespace, self::NS_SEPARATOR) . self::NS_SEPARATOR;
+        $this->namespaces[$namespace] = $this->normalizeDirectory($directory);
+        return $this;
+    }
+
+    /**
+     * Register many namespace/directory pairs at once
+     *
+     * @param  array $namespaces
+     * @throws Exception\InvalidArgumentException
+     * @return StandardAutoloader
+     */
+    public function registerNamespaces($namespaces)
+    {
+        if (!is_array($namespaces) && !$namespaces instanceof \Traversable) {
+            require_once __DIR__ . '/Exception/InvalidArgumentException.php';
+            throw new Exception\InvalidArgumentException('Namespace pairs must be either an array or Traversable');
+        }
+
+        foreach ($namespaces as $namespace => $directory) {
+            $this->registerNamespace($namespace, $directory);
+        }
+        return $this;
+    }
+
+    /**
+     * Register a prefix/directory pair
+     *
+     * @param  string $prefix
+     * @param  string $directory
+     * @return StandardAutoloader
+     */
+    public function registerPrefix($prefix, $directory)
+    {
+        $prefix = rtrim($prefix, self::PREFIX_SEPARATOR). self::PREFIX_SEPARATOR;
+        $this->prefixes[$prefix] = $this->normalizeDirectory($directory);
+        return $this;
+    }
+
+    /**
+     * Register many namespace/directory pairs at once
+     *
+     * @param  array $prefixes
+     * @throws Exception\InvalidArgumentException
+     * @return StandardAutoloader
+     */
+    public function registerPrefixes($prefixes)
+    {
+        if (!is_array($prefixes) && !$prefixes instanceof \Traversable) {
+            require_once __DIR__ . '/Exception/InvalidArgumentException.php';
+            throw new Exception\InvalidArgumentException('Prefix pairs must be either an array or Traversable');
+        }
+
+        foreach ($prefixes as $prefix => $directory) {
+            $this->registerPrefix($prefix, $directory);
+        }
+        return $this;
+    }
+
+    /**
+     * Defined by Autoloadable; autoload a class
+     *
+     * @param  string $class
+     * @return false|string
+     */
+    public function autoload($class)
+    {
+        $isFallback = $this->isFallbackAutoloader();
+        if (false !== strpos($class, self::NS_SEPARATOR)) {
+            if ($this->loadClass($class, self::LOAD_NS)) {
+                return $class;
+            } elseif ($isFallback) {
+                return $this->loadClass($class, self::ACT_AS_FALLBACK);
+            }
+            return false;
+        }
+        if (false !== strpos($class, self::PREFIX_SEPARATOR)) {
+            if ($this->loadClass($class, self::LOAD_PREFIX)) {
+                return $class;
+            } elseif ($isFallback) {
+                return $this->loadClass($class, self::ACT_AS_FALLBACK);
+            }
+            return false;
+        }
+        if ($isFallback) {
+            return $this->loadClass($class, self::ACT_AS_FALLBACK);
+        }
+        return false;
+    }
+
+    /**
+     * Register the autoloader with spl_autoload
+     *
+     * @return void
+     */
+    public function register()
+    {
+        spl_autoload_register(array($this, 'autoload'));
+    }
+
+    /**
+     * Transform the class name to a filename
+     *
+     * @param  string $class
+     * @param  string $directory
+     * @return string
+     */
+    protected function transformClassNameToFilename($class, $directory)
+    {
+        // $class may contain a namespace portion, in  which case we need
+        // to preserve any underscores in that portion.
+        $matches = array();
+        preg_match('/(?P<namespace>.+\\\)?(?P<class>[^\\\]+$)/', $class, $matches);
+
+        $class     = (isset($matches['class'])) ? $matches['class'] : '';
+        $namespace = (isset($matches['namespace'])) ? $matches['namespace'] : '';
+
+        return $directory
+             . str_replace(self::NS_SEPARATOR, '/', $namespace)
+             . str_replace(self::PREFIX_SEPARATOR, '/', $class)
+             . '.php';
+    }
+
+    /**
+     * Load a class, based on its type (namespaced or prefixed)
+     *
+     * @param  string $class
+     * @param  string $type
+     * @return bool|string
+     * @throws Exception\InvalidArgumentException
+     */
+    protected function loadClass($class, $type)
+    {
+        if (!in_array($type, array(self::LOAD_NS, self::LOAD_PREFIX, self::ACT_AS_FALLBACK))) {
+            require_once __DIR__ . '/Exception/InvalidArgumentException.php';
+            throw new Exception\InvalidArgumentException();
+        }
+
+        // Fallback autoloading
+        if ($type === self::ACT_AS_FALLBACK) {
+            // create filename
+            $filename     = $this->transformClassNameToFilename($class, '');
+            $resolvedName = stream_resolve_include_path($filename);
+            if ($resolvedName !== false) {
+                return include $resolvedName;
+            }
+            return false;
+        }
+
+        // Namespace and/or prefix autoloading
+        foreach ($this->$type as $leader => $path) {
+            if (0 === strpos($class, $leader)) {
+                // Trim off leader (namespace or prefix)
+                $trimmedClass = substr($class, strlen($leader));
+
+                // create filename
+                $filename = $this->transformClassNameToFilename($trimmedClass, $path);
+                if (file_exists($filename)) {
+                    return include $filename;
+                }
+                return false;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Normalize the directory to include a trailing directory separator
+     *
+     * @param  string $directory
+     * @return string
+     */
+    protected function normalizeDirectory($directory)
+    {
+        $last = $directory[strlen($directory) - 1];
+        if (in_array($last, array('/', '\\'))) {
+            $directory[strlen($directory) - 1] = DIRECTORY_SEPARATOR;
+            return $directory;
+        }
+        $directory .= DIRECTORY_SEPARATOR;
+        return $directory;
+    }
+
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/Loader/composer.json b/wcfsetup/install/files/lib/system/api/zend/Loader/composer.json
new file mode 100644 (file)
index 0000000..9a91a0f
--- /dev/null
@@ -0,0 +1,21 @@
+{
+    "name": "zendframework/zend-loader",
+    "description": " ",
+    "license": "BSD-3-Clause",
+    "keywords": [
+        "zf2",
+        "loader"
+    ],
+    "autoload": {
+        "psr-0": {
+            "Zend\\Loader\\": ""
+        }
+    },
+    "target-dir": "Zend/Loader",
+    "require": {
+        "php": ">=5.3.3"
+    },
+    "suggest": {
+        "zendframework/zend-stdlib": "Zend\\Stdlib component"
+    }
+}
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/api/zend/ProgressBar/Adapter/AbstractAdapter.php b/wcfsetup/install/files/lib/system/api/zend/ProgressBar/Adapter/AbstractAdapter.php
new file mode 100644 (file)
index 0000000..d2e2cba
--- /dev/null
@@ -0,0 +1,93 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_ProgressBar
+ */
+
+namespace Zend\ProgressBar\Adapter;
+
+use Traversable;
+use Zend\Stdlib\ArrayUtils;
+
+/**
+ * Abstract class for Zend_ProgressBar_Adapters
+ *
+ * @category  Zend
+ * @package   Zend_ProgressBar
+ */
+abstract class AbstractAdapter
+{
+    /**
+     * Option keys to skip when calling setOptions()
+     *
+     * @var array
+     */
+    protected $skipOptions = array(
+        'options',
+        'config',
+    );
+
+    /**
+     * Create a new adapter
+     *
+     * $options may be either be an array or a Zend_Config object which
+     * specifies adapter related options.
+     *
+     * @param  array|Traversable $options
+     */
+    public function __construct($options = null)
+    {
+        if ($options instanceof Traversable) {
+            $options = ArrayUtils::iteratorToArray($options);
+        }
+        if (is_array($options)) {
+            $this->setOptions($options);
+        }
+    }
+
+    /**
+     * Set options via an array
+     *
+     * @param  array $options
+     * @return AbstractAdapter
+     */
+    public function setOptions(array $options)
+    {
+        foreach ($options as $key => $value) {
+            if (in_array(strtolower($key), $this->skipOptions)) {
+                continue;
+            }
+
+            $method = 'set' . ucfirst($key);
+            if (method_exists($this, $method)) {
+                $this->$method($value);
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * Notify the adapter about an update
+     *
+     * @param  float   $current       Current progress value
+     * @param  float   $max           Max progress value
+     * @param  float   $percent       Current percent value
+     * @param  integer $timeTaken     Taken time in seconds
+     * @param  integer $timeRemaining Remaining time in seconds
+     * @param  string  $text          Status text
+     * @return void
+     */
+    abstract public function notify($current, $max, $percent, $timeTaken, $timeRemaining, $text);
+
+    /**
+     * Called when the progress is explicitly finished
+     *
+     * @return void
+     */
+    abstract public function finish();
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/ProgressBar/Adapter/Console.php b/wcfsetup/install/files/lib/system/api/zend/ProgressBar/Adapter/Console.php
new file mode 100644 (file)
index 0000000..e379809
--- /dev/null
@@ -0,0 +1,517 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_ProgressBar
+ */
+
+namespace Zend\ProgressBar\Adapter;
+
+use Zend\ProgressBar\Adapter\Exception;
+use Zend\Stdlib\ErrorHandler;
+
+/**
+ * Zend_ProgressBar_Adapter_Console offers a text-based progressbar for console
+ * applications
+ *
+ * @category  Zend
+ * @package   Zend_ProgressBar
+ */
+class Console extends AbstractAdapter
+{
+    /**
+     * Percentage value of the progress
+     */
+    const ELEMENT_PERCENT = 'ELEMENT_PERCENT';
+
+    /**
+     * Visual value of the progress
+     */
+    const ELEMENT_BAR = 'ELEMENT_BAR';
+
+    /**
+     * ETA of the progress
+     */
+    const ELEMENT_ETA = 'ELEMENT_ETA';
+
+    /**
+     * Text part of the progress
+     */
+    const ELEMENT_TEXT = 'ELEMENT_TEXT';
+
+    /**
+     * Finish action: End of Line
+     */
+    const FINISH_ACTION_EOL = 'FINISH_ACTION_EOL';
+
+    /**
+     * Finish action: Clear Line
+     */
+    const FINISH_ACTION_CLEAR_LINE = 'FINISH_ACTION_CLEAR_LINE';
+
+    /**
+     * Finish action: None
+     */
+    const FINISH_ACTION_NONE = 'FINISH_ACTION_NONE';
+
+    /**
+     * Width of the progressbar
+     *
+     * @var integer
+     */
+    protected $width = null;
+
+    /**
+     * Elements to display
+     *
+     * @var array
+     */
+    protected $elements = array(self::ELEMENT_PERCENT,
+                                 self::ELEMENT_BAR,
+                                 self::ELEMENT_ETA);
+
+    /**
+     * Which action to do at finish call
+     *
+     * @var string
+     */
+    protected $finishAction = self::FINISH_ACTION_EOL;
+
+    /**
+     * Width of the bar element
+     *
+     * @var integer
+     */
+    protected $barWidth;
+
+    /**
+     * Left character(s) within the bar
+     *
+     * @var string
+     */
+    protected $barLeftChar = '#';
+
+    /**
+     * Indicator character(s) within the bar
+     *
+     * @var string
+     */
+    protected $barIndicatorChar = '';
+
+    /**
+     * Right character(s) within the bar
+     *
+     * @var string
+     */
+    protected $barRightChar = '-';
+
+    /**
+     * Output-stream, when STDOUT is not defined (e.g. in CGI) or set manually
+     *
+     * @var resource
+     */
+    protected $outputStream = null;
+
+    /**
+     * Width of the text element
+     *
+     * @var string
+     */
+    protected $textWidth = 20;
+
+    /**
+     * Whether the output started yet or not
+     *
+     * @var boolean
+     */
+    protected $outputStarted = false;
+
+    /**
+     * Charset of text element
+     *
+     * @var string
+     */
+    protected $charset = 'utf-8';
+
+    /**
+     * Defined by Zend_ProgressBar_Adapter
+     *
+     * @param  array|\Traversable $options
+     */
+    public function __construct($options = null)
+    {
+        // Call parent constructor with options
+        parent::__construct($options);
+
+        // Check if a width was set, else use auto width
+        if ($this->width === null) {
+            $this->setWidth();
+        }
+    }
+
+    /**
+     * Close local stdout, when open
+     */
+    public function __destruct()
+    {
+        if ($this->outputStream !== null) {
+            fclose($this->outputStream);
+        }
+    }
+
+    /**
+     * Set a different output-stream
+     *
+     * @param  string $resource
+     * @throws Exception\RuntimeException
+     * @return \Zend\ProgressBar\Adapter\Console
+     */
+    public function setOutputStream($resource)
+    {
+        ErrorHandler::start();
+        $stream = fopen($resource, 'w');
+        $error  = ErrorHandler::stop();
+
+        if ($stream === false) {
+            throw new Exception\RuntimeException('Unable to open stream', 0, $error);
+        }
+
+        if ($this->outputStream !== null) {
+            fclose($this->outputStream);
+        }
+
+        $this->outputStream = $stream;
+    }
+
+    /**
+     * Get the current output stream
+     *
+     * @return resource
+     */
+    public function getOutputStream()
+    {
+        if ($this->outputStream === null) {
+            if (!defined('STDOUT')) {
+                $this->outputStream = fopen('php://stdout', 'w');
+            } else {
+                return STDOUT;
+            }
+        }
+
+        return $this->outputStream;
+    }
+
+    /**
+     * Set the width of the progressbar
+     *
+     * @param  integer $width
+     * @return \Zend\ProgressBar\Adapter\Console
+     */
+    public function setWidth($width = null)
+    {
+        if ($width === null || !is_integer($width)) {
+            if (substr(PHP_OS, 0, 3) === 'WIN') {
+                // We have to default to 79 on windows, because the windows
+                // terminal always has a fixed width of 80 characters and the
+                // cursor is counted to the line, else windows would line break
+                // after every update.
+                $this->width = 79;
+            } else {
+                // Set the default width of 80
+                $this->width = 80;
+
+                // Try to determine the width through stty
+                ErrorHandler::start();
+                if (preg_match('#\d+ (\d+)#', shell_exec('stty size'), $match) === 1) {
+                    $this->width = (int) $match[1];
+                } elseif (preg_match('#columns = (\d+);#', shell_exec('stty'), $match) === 1) {
+                    $this->width = (int) $match[1];
+                }
+                ErrorHandler::stop();
+            }
+        } else {
+            $this->width = (int) $width;
+        }
+
+        $this->_calculateBarWidth();
+
+        return $this;
+    }
+
+    /**
+     * Set the elements to display with the progressbar
+     *
+     * @param  array $elements
+     * @throws \Zend\ProgressBar\Adapter\Exception\InvalidArgumentException When an invalid element is found in the array
+     * @return \Zend\ProgressBar\Adapter\Console
+     */
+    public function setElements(array $elements)
+    {
+        $allowedElements = array(self::ELEMENT_PERCENT,
+                                 self::ELEMENT_BAR,
+                                 self::ELEMENT_ETA,
+                                 self::ELEMENT_TEXT);
+
+        if (count(array_diff($elements, $allowedElements)) > 0) {
+            throw new Exception\InvalidArgumentException('Invalid element found in $elements array');
+        }
+
+        $this->elements = $elements;
+
+        $this->_calculateBarWidth();
+
+        return $this;
+    }
+
+    /**
+     * Set the left-hand character for the bar
+     *
+     * @param  string $char
+     * @throws \Zend\ProgressBar\Adapter\Exception\InvalidArgumentException When character is empty
+     * @return \Zend\ProgressBar\Adapter\Console
+     */
+    public function setBarLeftChar($char)
+    {
+        if (empty($char)) {
+            throw new Exception\InvalidArgumentException('Character may not be empty');
+        }
+
+        $this->barLeftChar = (string) $char;
+
+        return $this;
+    }
+
+    /**
+     * Set the right-hand character for the bar
+     *
+     * @param  string $char
+     * @throws \Zend\ProgressBar\Adapter\Exception\InvalidArgumentException When character is empty
+     * @return \Zend\ProgressBar\Adapter\Console
+     */
+    public function setBarRightChar($char)
+    {
+        if (empty($char)) {
+            throw new Exception\InvalidArgumentException('Character may not be empty');
+        }
+
+        $this->barRightChar = (string) $char;
+
+        return $this;
+    }
+
+    /**
+     * Set the indicator character for the bar
+     *
+     * @param  string $char
+     * @return \Zend\ProgressBar\Adapter\Console
+     */
+    public function setBarIndicatorChar($char)
+    {
+        $this->barIndicatorChar = (string) $char;
+
+        return $this;
+    }
+
+    /**
+     * Set the width of the text element
+     *
+     * @param  integer $width
+     * @return \Zend\ProgressBar\Adapter\Console
+     */
+    public function setTextWidth($width)
+    {
+        $this->textWidth = (int) $width;
+
+        $this->_calculateBarWidth();
+
+        return $this;
+    }
+
+    /**
+     * Set the charset of the text element
+     *
+     * @param string $charset
+     */
+    public function setCharset($charset)
+    {
+        $this->charset = $charset;
+    }
+
+    /**
+     * Set the finish action
+     *
+     * @param  string $action
+     * @throws \Zend\ProgressBar\Adapter\Exception\InvalidArgumentException When an invalid action is specified
+     * @return \Zend\ProgressBar\Adapter\Console
+     */
+    public function setFinishAction($action)
+    {
+        $allowedActions = array(self::FINISH_ACTION_CLEAR_LINE,
+                                self::FINISH_ACTION_EOL,
+                                self::FINISH_ACTION_NONE);
+
+        if (!in_array($action, $allowedActions)) {
+            throw new Exception\InvalidArgumentException('Invalid finish action specified');
+        }
+
+        $this->finishAction = $action;
+
+        return $this;
+    }
+
+    /**
+     * Defined by Zend\ProgressBar\Adapter\AbstractAdapter
+     *
+     * @param  float   $current       Current progress value
+     * @param  float   $max           Max progress value
+     * @param  float   $percent       Current percent value
+     * @param  integer $timeTaken     Taken time in seconds
+     * @param  integer $timeRemaining Remaining time in seconds
+     * @param  string  $text          Status text
+     * @return void
+     */
+    public function notify($current, $max, $percent, $timeTaken, $timeRemaining, $text)
+    {
+        // See if we must clear the line
+        if ($this->outputStarted) {
+            $data = str_repeat("\x08", $this->width);
+        } else {
+            $data = '';
+            $this->outputStarted = true;
+        }
+
+        // Build all elements
+        $renderedElements = array();
+
+        foreach ($this->elements as $element) {
+            switch ($element) {
+                case self::ELEMENT_BAR:
+                    $visualWidth = $this->barWidth - 2;
+                    $bar         = '[';
+
+                    $indicatorWidth = strlen($this->barIndicatorChar);
+
+                    $doneWidth = min($visualWidth - $indicatorWidth, round($visualWidth * $percent));
+                    if ($doneWidth > 0) {
+                        $bar .= substr(str_repeat($this->barLeftChar, ceil($doneWidth / strlen($this->barLeftChar))), 0, $doneWidth);
+                    }
+
+                    $bar .= $this->barIndicatorChar;
+
+                    $leftWidth = $visualWidth - $doneWidth - $indicatorWidth;
+                    if ($leftWidth > 0) {
+                        $bar .= substr(str_repeat($this->barRightChar, ceil($leftWidth / strlen($this->barRightChar))), 0, $leftWidth);
+                    }
+
+                    $bar .= ']';
+
+                    $renderedElements[] = $bar;
+                    break;
+
+                case self::ELEMENT_PERCENT:
+                    $renderedElements[] = str_pad(round($percent * 100), 3, ' ', STR_PAD_LEFT) . '%';
+                    break;
+
+                case self::ELEMENT_ETA:
+                    // In the first 5 seconds we don't get accurate results,
+                    // this skipping technique is found in many progressbar
+                    // implementations.
+                    if ($timeTaken < 5) {
+                        $renderedElements[] = str_repeat(' ', 12);
+                        break;
+                    }
+
+                    if ($timeRemaining === null || $timeRemaining > 86400) {
+                        $etaFormatted = '??:??:??';
+                    } else {
+                        $hours   = floor($timeRemaining / 3600);
+                        $minutes = floor(($timeRemaining % 3600) / 60);
+                        $seconds = ($timeRemaining % 3600 % 60);
+
+                        $etaFormatted = sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds);
+                    }
+
+                    $renderedElements[] = 'ETA ' . $etaFormatted;
+                    break;
+
+                case self::ELEMENT_TEXT:
+                    $renderedElements[] = \Zend\Text\MultiByte::strPad(substr($text, 0, $this->textWidth), $this->textWidth, ' ', STR_PAD_RIGHT, $this->charset);
+                    break;
+            }
+        }
+
+        $data .= implode(' ', $renderedElements);
+
+        // Output line data
+        $this->_outputData($data);
+    }
+
+    /**
+     * Defined by Zend\ProgressBar\Adapter\AbstractAdapter
+     *
+     * @return void
+     */
+    public function finish()
+    {
+        switch ($this->finishAction) {
+            case self::FINISH_ACTION_EOL:
+                $this->_outputData(PHP_EOL);
+                break;
+
+            case self::FINISH_ACTION_CLEAR_LINE:
+                if ($this->outputStarted) {
+                    $data = str_repeat("\x08", $this->width)
+                          . str_repeat(' ', $this->width)
+                          . str_repeat("\x08", $this->width);
+
+                    $this->_outputData($data);
+                }
+                break;
+
+            case self::FINISH_ACTION_NONE:
+                break;
+        }
+    }
+
+    /**
+     * Calculate the bar width when other elements changed
+     *
+     * @return void
+     */
+    protected function _calculateBarWidth()
+    {
+        if (in_array(self::ELEMENT_BAR, $this->elements)) {
+            $barWidth = $this->width;
+
+            if (in_array(self::ELEMENT_PERCENT, $this->elements)) {
+                $barWidth -= 4;
+            }
+
+            if (in_array(self::ELEMENT_ETA, $this->elements)) {
+                $barWidth -= 12;
+            }
+
+            if (in_array(self::ELEMENT_TEXT, $this->elements)) {
+                $barWidth -= $this->textWidth;
+            }
+
+            $this->barWidth = $barWidth - (count($this->elements) - 1);
+        }
+    }
+
+    /**
+     * Outputs given data to STDOUT.
+     *
+     * This split-off is required for unit-testing.
+     *
+     * @param  string $data
+     * @return void
+     */
+    protected function _outputData($data)
+    {
+        fwrite($this->getOutputStream(), $data);
+    }
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/ProgressBar/Adapter/Exception/ExceptionInterface.php b/wcfsetup/install/files/lib/system/api/zend/ProgressBar/Adapter/Exception/ExceptionInterface.php
new file mode 100644 (file)
index 0000000..d8feb3a
--- /dev/null
@@ -0,0 +1,23 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_ProgressBar
+ */
+
+namespace Zend\ProgressBar\Adapter\Exception;
+
+use Zend\ProgressBar\Exception\ExceptionInterface as ProgressBarException;
+
+/**
+ * Exception class for Zend_ProgressBar_Adapter
+ *
+ * @category  Zend
+ * @package   Zend_ProgressBar
+ */
+interface ExceptionInterface extends ProgressBarException
+{
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/ProgressBar/Adapter/Exception/InvalidArgumentException.php b/wcfsetup/install/files/lib/system/api/zend/ProgressBar/Adapter/Exception/InvalidArgumentException.php
new file mode 100644 (file)
index 0000000..2219a16
--- /dev/null
@@ -0,0 +1,23 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_ProgressBar
+ */
+
+namespace Zend\ProgressBar\Adapter\Exception;
+
+use Zend\ProgressBar\Exception;
+
+/**
+ * Exception for Zend_Progressbar component.
+ *
+ * @category   Zend
+ * @package    Zend_ProgressBar
+ */
+class InvalidArgumentException extends Exception\InvalidArgumentException implements
+    ExceptionInterface
+{}
diff --git a/wcfsetup/install/files/lib/system/api/zend/ProgressBar/Adapter/Exception/RuntimeException.php b/wcfsetup/install/files/lib/system/api/zend/ProgressBar/Adapter/Exception/RuntimeException.php
new file mode 100644 (file)
index 0000000..f8a5337
--- /dev/null
@@ -0,0 +1,23 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_ProgressBar
+ */
+
+namespace Zend\ProgressBar\Adapter\Exception;
+
+use Zend\ProgressBar\Exception;
+
+/**
+ * Exception for Zend_Progressbar component.
+ *
+ * @category   Zend
+ * @package    Zend_ProgressBar
+ */
+class RuntimeException extends Exception\RuntimeException implements
+    ExceptionInterface
+{}
diff --git a/wcfsetup/install/files/lib/system/api/zend/ProgressBar/Adapter/JsPull.php b/wcfsetup/install/files/lib/system/api/zend/ProgressBar/Adapter/JsPull.php
new file mode 100644 (file)
index 0000000..4744d32
--- /dev/null
@@ -0,0 +1,99 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_ProgressBar
+ */
+
+namespace Zend\ProgressBar\Adapter;
+
+use Zend\Json\Json;
+
+/**
+ * Zend_ProgressBar_Adapter_JsPull offers a simple method for updating a
+ * progressbar in a browser.
+ *
+ * @category  Zend
+ * @package   Zend_ProgressBar
+ */
+class JsPull extends AbstractAdapter
+{
+    /**
+     * Whether to exit after json data send or not
+     *
+     * @var boolean
+     */
+    protected $exitAfterSend = true;
+
+    /**
+     * Set whether to exit after json data send or not
+     *
+     * @param  boolean $exitAfterSend
+     * @return \Zend\ProgressBar\Adapter\JsPull
+     */
+    public function setExitAfterSend($exitAfterSend)
+    {
+        $this->exitAfterSend = $exitAfterSend;
+    }
+
+    /**
+     * Defined by Zend\ProgressBar\Adapter\AbstractAdapter
+     *
+     * @param  float   $current       Current progress value
+     * @param  float   $max           Max progress value
+     * @param  float   $percent       Current percent value
+     * @param  integer $timeTaken     Taken time in seconds
+     * @param  integer $timeRemaining Remaining time in seconds
+     * @param  string  $text          Status text
+     * @return void
+     */
+    public function notify($current, $max, $percent, $timeTaken, $timeRemaining, $text)
+    {
+        $arguments = array(
+            'current'       => $current,
+            'max'           => $max,
+            'percent'       => ($percent * 100),
+            'timeTaken'     => $timeTaken,
+            'timeRemaining' => $timeRemaining,
+            'text'          => $text,
+            'finished'      => false
+        );
+
+        $data = Json::encode($arguments);
+
+        // Output the data
+        $this->_outputData($data);
+    }
+
+    /**
+     * Defined by Zend\ProgressBar\Adapter\AbstractAdapter
+     *
+     * @return void
+     */
+    public function finish()
+    {
+        $data = Json::encode(array('finished' => true));
+
+        $this->_outputData($data);
+    }
+
+    /**
+     * Outputs given data the user agent.
+     *
+     * This split-off is required for unit-testing.
+     *
+     * @param  string $data
+     * @return void
+     */
+    protected function _outputData($data)
+    {
+        echo $data;
+
+        if ($this->exitAfterSend) {
+            exit;
+        }
+    }
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/ProgressBar/Adapter/JsPush.php b/wcfsetup/install/files/lib/system/api/zend/ProgressBar/Adapter/JsPush.php
new file mode 100644 (file)
index 0000000..3903b8b
--- /dev/null
@@ -0,0 +1,130 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_ProgressBar
+ */
+
+namespace Zend\ProgressBar\Adapter;
+
+use Zend\Json\Json;
+
+/**
+ * Zend_ProgressBar_Adapter_JsPush offers a simple method for updating a
+ * progressbar in a browser.
+ *
+ * @category  Zend
+ * @package   Zend_ProgressBar
+ */
+class JsPush extends AbstractAdapter
+{
+    /**
+     * Name of the JavaScript method to call on update
+     *
+     * @var string
+     */
+    protected $updateMethodName = 'Zend\ProgressBar\ProgressBar\Update';
+
+    /**
+     * Name of the JavaScript method to call on finish
+     *
+     * @var string
+     */
+    protected $finishMethodName;
+
+    /**
+     * Set the update method name
+     *
+     * @param  string $methodName
+     * @return \Zend\ProgressBar\Adapter\JsPush
+     */
+    public function setUpdateMethodName($methodName)
+    {
+        $this->updateMethodName = $methodName;
+
+        return $this;
+    }
+
+    /**
+     * Set the finish method name
+     *
+     * @param  string $methodName
+     * @return \Zend\ProgressBar\Adapter\JsPush
+     */
+    public function setFinishMethodName($methodName)
+    {
+        $this->finishMethodName = $methodName;
+
+        return $this;
+    }
+
+    /**
+     * Defined by Zend\ProgressBar\Adapter\AbstractAdapter
+     *
+     * @param  float   $current       Current progress value
+     * @param  float   $max           Max progress value
+     * @param  float   $percent       Current percent value
+     * @param  integer $timeTaken     Taken time in seconds
+     * @param  integer $timeRemaining Remaining time in seconds
+     * @param  string  $text          Status text
+     * @return void
+     */
+    public function notify($current, $max, $percent, $timeTaken, $timeRemaining, $text)
+    {
+        $arguments = array(
+            'current'       => $current,
+            'max'           => $max,
+            'percent'       => ($percent * 100),
+            'timeTaken'     => $timeTaken,
+            'timeRemaining' => $timeRemaining,
+            'text'          => $text
+        );
+
+        $data = '<script type="text/javascript">'
+              . 'parent.' . $this->updateMethodName . '(' . Json::encode($arguments) . ');'
+              . '</script>';
+
+        // Output the data
+        $this->_outputData($data);
+    }
+
+    /**
+     * Defined by Zend\ProgressBar\Adapter\AbstractAdapter
+     *
+     * @return void
+     */
+    public function finish()
+    {
+        if ($this->finishMethodName === null) {
+            return;
+        }
+
+        $data = '<script type="text/javascript">'
+              . 'parent.' . $this->finishMethodName . '();'
+              . '</script>';
+
+        $this->_outputData($data);
+    }
+
+    /**
+     * Outputs given data the user agent.
+     *
+     * This split-off is required for unit-testing.
+     *
+     * @param  string $data
+     * @return void
+     */
+    protected function _outputData($data)
+    {
+        // 1024 padding is required for Safari, while 256 padding is required
+        // for Internet Explorer. The <br /> is required so Safari actually
+        // executes the <script />
+        echo str_pad($data . '<br />', 1024, ' ', STR_PAD_RIGHT) . "\n";
+
+        flush();
+        ob_flush();
+    }
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/ProgressBar/Exception/ExceptionInterface.php b/wcfsetup/install/files/lib/system/api/zend/ProgressBar/Exception/ExceptionInterface.php
new file mode 100644 (file)
index 0000000..cc54ec7
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_ProgressBar
+ */
+
+namespace Zend\ProgressBar\Exception;
+
+/**
+ * Exception class for Zend_ProgressBar
+ *
+ * @category  Zend
+ * @package   Zend_ProgressBar
+ */
+interface ExceptionInterface
+{
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/ProgressBar/Exception/InvalidArgumentException.php b/wcfsetup/install/files/lib/system/api/zend/ProgressBar/Exception/InvalidArgumentException.php
new file mode 100644 (file)
index 0000000..a1fa127
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_ProgressBar
+ */
+
+namespace Zend\ProgressBar\Exception;
+
+/**
+ * Exception for Zend_Progressbar component.
+ *
+ * @category   Zend
+ * @package    Zend_ProgressBar
+ */
+class InvalidArgumentException extends \InvalidArgumentException implements
+    ExceptionInterface
+{}
diff --git a/wcfsetup/install/files/lib/system/api/zend/ProgressBar/Exception/OutOfRangeException.php b/wcfsetup/install/files/lib/system/api/zend/ProgressBar/Exception/OutOfRangeException.php
new file mode 100644 (file)
index 0000000..f8903cd
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_ProgressBar
+ */
+
+namespace Zend\ProgressBar\Exception;
+
+/**
+ * Exception for Zend_Progressbar component.
+ *
+ * @category   Zend
+ * @package    Zend_ProgressBar
+ */
+class OutOfRangeException extends \OutOfRangeException implements ExceptionInterface
+{
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/ProgressBar/Exception/RuntimeException.php b/wcfsetup/install/files/lib/system/api/zend/ProgressBar/Exception/RuntimeException.php
new file mode 100644 (file)
index 0000000..cd4e3a1
--- /dev/null
@@ -0,0 +1,20 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_ProgressBar
+ */
+
+namespace Zend\ProgressBar\Exception;
+
+/**
+ * Exception for Zend_Progressbar component.
+ *
+ * @category   Zend
+ * @package    Zend_ProgressBar
+ */
+class RuntimeException extends \RuntimeException implements ExceptionInterface
+{}
diff --git a/wcfsetup/install/files/lib/system/api/zend/ProgressBar/ProgressBar.php b/wcfsetup/install/files/lib/system/api/zend/ProgressBar/ProgressBar.php
new file mode 100644 (file)
index 0000000..da76822
--- /dev/null
@@ -0,0 +1,201 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link      http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd New BSD License
+ * @package   Zend_ProgressBar
+ */
+
+namespace Zend\ProgressBar;
+
+use Zend\ProgressBar\Exception;
+use Zend\Session;
+
+/**
+ * Zend_ProgressBar offers an interface for multiple environments.
+ *
+ * @category  Zend
+ * @package   Zend_ProgressBar
+ */
+class ProgressBar
+{
+    /**
+     * Min value
+     *
+     * @var float
+     */
+    protected $min;
+
+    /**
+     * Max value
+     *
+     * @var float
+     */
+    protected $max;
+
+    /**
+     * Current value
+     *
+     * @var float
+     */
+    protected $current;
+
+    /**
+     * Start time of the progressbar, required for ETA
+     *
+     * @var integer
+     */
+    protected $startTime;
+
+    /**
+     * Current status text
+     *
+     * @var string
+     */
+    protected $statusText = null;
+
+    /**
+     * Adapter for the output
+     *
+     * @var \Zend\ProgressBar\Adapter\AbstractAdapter
+     */
+    protected $adapter;
+
+    /**
+     * Namespace for keeping the progressbar persistent
+     *
+     * @var string
+     */
+    protected $persistenceNamespace = null;
+
+    /**
+     * Create a new progressbar backend.
+     *
+     * @param  Adapter\AbstractAdapter $adapter
+     * @param  float|int               $min
+     * @param  float|int               $max
+     * @param  string|null             $persistenceNamespace
+     * @throws Exception\OutOfRangeException When $min is greater than $max
+     */
+    public function __construct(Adapter\AbstractAdapter $adapter, $min = 0, $max = 100, $persistenceNamespace = null)
+    {
+        // Check min/max values and set them
+        if ($min > $max) {
+            throw new Exception\OutOfRangeException('$max must be greater than $min');
+        }
+
+        $this->min     = (float) $min;
+        $this->max     = (float) $max;
+        $this->current = (float) $min;
+
+        // See if we have to open a session namespace
+        if ($persistenceNamespace !== null) {
+            $this->persistenceNamespace = new Session\Container($persistenceNamespace);
+        }
+
+        // Set adapter
+        $this->adapter = $adapter;
+
+        // Track the start time
+        $this->startTime = time();
+
+        // See If a persistenceNamespace exists and handle accordingly
+        if ($this->persistenceNamespace !== null) {
+            if (isset($this->persistenceNamespace->isSet)) {
+                $this->startTime  = $this->persistenceNamespace->startTime;
+                $this->current    = $this->persistenceNamespace->current;
+                $this->statusText = $this->persistenceNamespace->statusText;
+            } else {
+                $this->persistenceNamespace->isSet      = true;
+                $this->persistenceNamespace->startTime  = $this->startTime;
+                $this->persistenceNamespace->current    = $this->current;
+                $this->persistenceNamespace->statusText = $this->statusText;
+            }
+        } else {
+            $this->update();
+        }
+    }
+
+    /**
+     * Get the current adapter
+     *
+     * @return Adapter\AbstractAdapter
+     */
+    public function getAdapter()
+    {
+        return $this->adapter;
+    }
+
+    /**
+     * Update the progressbar
+     *
+     * @param  float  $value
+     * @param  string $text
+     * @return void
+     */
+    public function update($value = null, $text = null)
+    {
+        // Update value if given
+        if ($value !== null) {
+            $this->current = min($this->max, max($this->min, $value));
+        }
+
+        // Update text if given
+        if ($text !== null) {
+            $this->statusText = $text;
+        }
+
+        // See if we have to update a namespace
+        if ($this->persistenceNamespace !== null) {
+            $this->persistenceNamespace->current    = $this->current;
+            $this->persistenceNamespace->statusText = $this->statusText;
+        }
+
+        // Calculate percent
+        if ($this->min === $this->max) {
+            $percent = false;
+        } else {
+            $percent = (float) ($this->current - $this->min) / ($this->max - $this->min);
+        }
+
+        // Calculate ETA
+        $timeTaken = time() - $this->startTime;
+
+        if ($percent === .0 || $percent === false) {
+            $timeRemaining = null;
+        } else {
+            $timeRemaining = round(((1 / $percent) * $timeTaken) - $timeTaken);
+        }
+
+        // Poll the adapter
+        $this->adapter->notify($this->current, $this->max, $percent, $timeTaken, $timeRemaining, $this->statusText);
+    }
+
+    /**
+     * Update the progressbar to the next value
+     *
+     * @param  int $diff
+     * @param  string $text
+     * @return void
+     */
+    public function next($diff = 1, $text = null)
+    {
+        $this->update(max($this->min, min($this->max, $this->current + $diff)), $text);
+    }
+
+    /**
+     * Call the adapters finish() behaviour
+     *
+     * @return void
+     */
+    public function finish()
+    {
+        if ($this->persistenceNamespace !== null) {
+            unset($this->persistenceNamespace->isSet);
+        }
+
+        $this->adapter->finish();
+    }
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/ProgressBar/composer.json b/wcfsetup/install/files/lib/system/api/zend/ProgressBar/composer.json
new file mode 100644 (file)
index 0000000..149ceb7
--- /dev/null
@@ -0,0 +1,19 @@
+{
+    "name": "zendframework/zend-progressbar",
+    "description": "component to create and update progressbars in different environments",
+    "license": "BSD-3-Clause",
+    "keywords": [
+        "zf2",
+        "progressbar"
+    ],
+    "autoload": {
+        "psr-0": {
+            "Zend\\ProgressBar\\": ""
+        }
+    },
+    "target-dir": "Zend/ProgressBar",
+    "require": {
+        "php": ">=5.3.3",
+        "zendframework/zend-stdlib": "self.version"
+    }
+}
diff --git a/wcfsetup/install/files/lib/system/api/zend/README-GIT.md b/wcfsetup/install/files/lib/system/api/zend/README-GIT.md
new file mode 100644 (file)
index 0000000..1639d5f
--- /dev/null
@@ -0,0 +1,278 @@
+# USING THE GIT REPOSITORY
+
+## Setup your own public repository
+
+Your first step is to establish a public repository from which we can
+pull your work into the master repository. You have two options: use
+GitHub or other public site, or setup/use your own repository.
+
+While you can use a private repository and utilize ``git format-patch`` to
+submit patches, this is discouraged as it does not facilitate public peer
+review.
+
+### Option 1: GitHub
+
+ 1. Setup a GitHub account (http://github.com/), if you haven't yet
+ 2. Fork the ZF2 repository (http://github.com/zendframework/zf2)
+ 3. Clone your fork locally and enter it (use your own GitHub username
+    in the statement below)
+
+    ```sh
+    % git clone git@github.com:<username>/zf2.git
+    % cd zf2
+    ```
+
+ 4. Add a remote to the canonical ZF repository, so you can keep your fork
+    up-to-date:
+
+    ```sh
+    % git remote add zf2 https://github.com/zendframework/zf2.git
+    % git fetch zf2
+    ```
+
+### Option 2: Personal Repository
+
+We assume you will use gitosis (http://git-scm.com/book/en/Git-on-the-Server-Gitosis)
+or gitolite (http://git-scm.com/book/en/Git-on-the-Server-Gitolite) to host your
+own repository.  If you go this route, we will assume you have the knowledge to
+do so, or know where to obtain it. We will not assist you in setting up such a
+repository.
+
+ 1.  Create a new repository
+
+    ```sh
+    % git init
+    ```
+
+ 2. Add an "origin" remote pointing to your gitosis/gitolite repo:
+
+    ```sh
+    % git remote add origin git://yourdomain/yourrepo.git
+    ```
+
+ 3. Add a remote for the ZF repository and fetch it
+
+    ```sh
+    % git remote add zf2 https://github.com/zendframework/zf2.git
+    % git fetch zf2
+    ```
+
+ 4. Create a new branch for the ZF repository (named "zf/master" here)
+
+    ```sh
+    % git checkout -b zf/master zf2/master
+    ```
+
+ 5. Create your master branch off the ZF branch, and push to your
+    repository
+
+    ```sh
+    % git checkout -b master
+    % git push origin HEAD:master
+    ```
+
+### Pre-Commit Hook (Optional)
+
+The ZF2 Travis-CI will confirm that code style standards are met 
+by using ```php-cs-fixer``` (https://github.com/fabpot/PHP-CS-Fixer) during it's build runs.
+
+To reduce the number of red Travis-CI builds, the following Git pre-commit hook
+can help catch code style issues before committing. Save it as
+```.git/hooks/pre-commit```, and make sure it is executable.
+
+```php
+#!/usr/bin/env php
+<?php
+/**
+ * .git/hooks/pre-commit
+ * 
+ * This pre-commit hooks will check for PHP errors (lint), and make sure the 
+ * code is PSR-2 compliant.
+ * 
+ * Dependecy: PHP-CS-Fixer (https://github.com/fabpot/PHP-CS-Fixer)
+ * 
+ * @author  Mardix  http://github.com/mardix 
+ * @author  Matthew Weier O'Phinney http://mwop.net/
+ * @since   4 Sept 2012
+ */
+
+$exit = 0;
+
+/*
+ * collect all files which have been added, copied or
+ * modified and store them in an array called output
+ */
+$output = array();
+exec('git diff --cached --name-status --diff-filter=ACM', $output);
+
+foreach ($output as $file) {
+    if ('D' === substr($file, 0, 1)) {
+        // deleted file; do nothing
+        continue;
+    }
+
+    $fileName = trim(substr($file, 1));
+
+    /*
+     * Only PHP files
+     */
+    $extension = pathinfo($fileName, PATHINFO_EXTENSION);
+    if (!preg_match('/^ph(p|tml)$/', $extension)) {
+        continue;
+    }
+
+    /*
+     * Check for parse errors
+     */
+    $output = array();
+    $return = 0;
+    exec("php -l " . escapeshellarg($fileName), $output, $return);
+
+    if ($return != 0) {
+        echo "PHP file fails to parse: " . $fileName . ":" . PHP_EOL;
+        echo implode(PHP_EOL, $lintOutput) . PHP_EOL;
+        $exit = 1;
+        continue;
+    }
+
+    /*
+     * PHP-CS-Fixer
+     */
+    $output = array();
+    $return = null;
+    exec("php-cs-fixer --dry-run --level=psr2 " . escapeshellarg($fileName), $output, $return);
+    if ($return != 0 || !empty($output)) {
+        echo "PHP file fails contains CS issues: " . $fileName . ":" . PHP_EOL;
+        echo implode(PHP_EOL, $output) . PHP_EOL;
+        $exit = 1;
+        continue;
+    }
+}
+
+exit($exit);
+```
+
+## Keeping Up-to-Date
+
+Periodically, you should update your fork or personal repository to
+match the canonical ZF repository. In each of the above setups, we have
+added a remote to the Zend Framework repository, which allows you to do
+the following:
+
+
+```sh
+% git checkout master
+% git pull zf2 master
+- OPTIONALLY, to keep your remote up-to-date -
+% git push origin
+```
+
+If you're tracking other branches -- for example, the "develop" branch, where
+new feature development occurs -- you'll want to do the same operations for that
+branch; simply substibute "develop" for "master".
+
+## Working on Zend Framework
+
+When working on Zend Framework, we recommend you do each new feature or
+bugfix in a new branch. This simplifies the task of code review as well
+as of merging your changes into the canonical repository.
+
+A typical work flow will then consist of the following:
+
+ 1. Create a new local branch based off your master branch.
+ 2. Switch to your new local branch. (This step can be combined with the
+    previous step with the use of `git checkout -b`.)
+ 3. Do some work, commit, repeat as necessary.
+ 4. Push the local branch to your remote repository.
+ 5. Send a pull request.
+
+The mechanics of this process are actually quite trivial. Below, we will
+create a branch for fixing an issue in the tracker.
+
+```sh
+% git checkout -b zf9295
+Switched to a new branch 'zf9295'
+```
+... do some work ...
+  
+```sh
+% git commit
+```
+... write your log message ...
+  
+```sh
+% git push origin HEAD:zf9295
+Counting objects: 38, done.
+Delta compression using up to 2 threads.
+Compression objects: 100% (18/18), done.
+Writing objects: 100% (20/20), 8.19KiB, done.
+Total 20 (delta 12), reused 0 (delta 0)
+To ssh://git@github.com/weierophinney/zf2.git
+   b5583aa..4f51698  HEAD -> master
+```
+
+
+To send a pull request, you have two options.
+
+If using GitHub, you can do the pull request from there. Navigate to
+your repository, select the branch you just created, and then select the
+"Pull Request" button in the upper right. Select the user
+"zendframework" as the recipient.
+
+If using your own repository - or even if using GitHub - you can send an
+email indicating you have changes to pull:
+
+ -  Send to <zf-devteam@zend.com>
+
+ -  In your message, specify:
+     -  The URL to your repository (e.g., `git://mwop.net/zf2.git`)
+     -  The branch containing the changes you want pulled (e.g., `zf9295`)
+     -  The nature of the changes (e.g., `implements
+        Zend_Service_Twitter`, `fixes ZF-9295`, etc.)
+
+### What branch to issue the pull request against?
+
+Which branch should you issue a pull request against?
+
+- For fixes against the stable release, issue the pull request against the
+  "master" branch.
+- For new features, or fixes that introduce new elements to the public API (such
+  as new public methods or properties), issue the pull request against the
+  "develop" branch.
+
+## Branch Cleanup
+
+As you might imagine, if you are a frequent contributor, you'll start to
+get a ton of branches both locally and on your remote.
+
+Once you know that your changes have been accepted to the master
+repository, we suggest doing some cleanup of these branches.
+
+ -  Local branch cleanup
+    
+    ```sh
+    % git branch -d <branchname>
+    ```
+
+ -  Remote branch removal
+
+    ```sh
+    % git push origin :<branchname>
+    ```
+
+
+## FEEDS AND EMAILS
+
+RSS feeds may be found at:
+
+`https://github.com/zendframework/zf2/commits/<branch>.atom`
+
+where &lt;branch&gt; is a branch in the repository.
+
+To subscribe to git email notifications, simply watch or fork the zf2 repository
+on GitHub.
+
+## CONTRIBUTORS AND COMMITTERS
+
+Both Zend's internal Zend Framework team and the members of the Community Review
+team have push privileges to the ZF2 repository. 
diff --git a/wcfsetup/install/files/lib/system/api/zend/README.md b/wcfsetup/install/files/lib/system/api/zend/README.md
new file mode 100644 (file)
index 0000000..1639d5f
--- /dev/null
@@ -0,0 +1,278 @@
+# USING THE GIT REPOSITORY
+
+## Setup your own public repository
+
+Your first step is to establish a public repository from which we can
+pull your work into the master repository. You have two options: use
+GitHub or other public site, or setup/use your own repository.
+
+While you can use a private repository and utilize ``git format-patch`` to
+submit patches, this is discouraged as it does not facilitate public peer
+review.
+
+### Option 1: GitHub
+
+ 1. Setup a GitHub account (http://github.com/), if you haven't yet
+ 2. Fork the ZF2 repository (http://github.com/zendframework/zf2)
+ 3. Clone your fork locally and enter it (use your own GitHub username
+    in the statement below)
+
+    ```sh
+    % git clone git@github.com:<username>/zf2.git
+    % cd zf2
+    ```
+
+ 4. Add a remote to the canonical ZF repository, so you can keep your fork
+    up-to-date:
+
+    ```sh
+    % git remote add zf2 https://github.com/zendframework/zf2.git
+    % git fetch zf2
+    ```
+
+### Option 2: Personal Repository
+
+We assume you will use gitosis (http://git-scm.com/book/en/Git-on-the-Server-Gitosis)
+or gitolite (http://git-scm.com/book/en/Git-on-the-Server-Gitolite) to host your
+own repository.  If you go this route, we will assume you have the knowledge to
+do so, or know where to obtain it. We will not assist you in setting up such a
+repository.
+
+ 1.  Create a new repository
+
+    ```sh
+    % git init
+    ```
+
+ 2. Add an "origin" remote pointing to your gitosis/gitolite repo:
+
+    ```sh
+    % git remote add origin git://yourdomain/yourrepo.git
+    ```
+
+ 3. Add a remote for the ZF repository and fetch it
+
+    ```sh
+    % git remote add zf2 https://github.com/zendframework/zf2.git
+    % git fetch zf2
+    ```
+
+ 4. Create a new branch for the ZF repository (named "zf/master" here)
+
+    ```sh
+    % git checkout -b zf/master zf2/master
+    ```
+
+ 5. Create your master branch off the ZF branch, and push to your
+    repository
+
+    ```sh
+    % git checkout -b master
+    % git push origin HEAD:master
+    ```
+
+### Pre-Commit Hook (Optional)
+
+The ZF2 Travis-CI will confirm that code style standards are met 
+by using ```php-cs-fixer``` (https://github.com/fabpot/PHP-CS-Fixer) during it's build runs.
+
+To reduce the number of red Travis-CI builds, the following Git pre-commit hook
+can help catch code style issues before committing. Save it as
+```.git/hooks/pre-commit```, and make sure it is executable.
+
+```php
+#!/usr/bin/env php
+<?php
+/**
+ * .git/hooks/pre-commit
+ * 
+ * This pre-commit hooks will check for PHP errors (lint), and make sure the 
+ * code is PSR-2 compliant.
+ * 
+ * Dependecy: PHP-CS-Fixer (https://github.com/fabpot/PHP-CS-Fixer)
+ * 
+ * @author  Mardix  http://github.com/mardix 
+ * @author  Matthew Weier O'Phinney http://mwop.net/
+ * @since   4 Sept 2012
+ */
+
+$exit = 0;
+
+/*
+ * collect all files which have been added, copied or
+ * modified and store them in an array called output
+ */
+$output = array();
+exec('git diff --cached --name-status --diff-filter=ACM', $output);
+
+foreach ($output as $file) {
+    if ('D' === substr($file, 0, 1)) {
+        // deleted file; do nothing
+        continue;
+    }
+
+    $fileName = trim(substr($file, 1));
+
+    /*
+     * Only PHP files
+     */
+    $extension = pathinfo($fileName, PATHINFO_EXTENSION);
+    if (!preg_match('/^ph(p|tml)$/', $extension)) {
+        continue;
+    }
+
+    /*
+     * Check for parse errors
+     */
+    $output = array();
+    $return = 0;
+    exec("php -l " . escapeshellarg($fileName), $output, $return);
+
+    if ($return != 0) {
+        echo "PHP file fails to parse: " . $fileName . ":" . PHP_EOL;
+        echo implode(PHP_EOL, $lintOutput) . PHP_EOL;
+        $exit = 1;
+        continue;
+    }
+
+    /*
+     * PHP-CS-Fixer
+     */
+    $output = array();
+    $return = null;
+    exec("php-cs-fixer --dry-run --level=psr2 " . escapeshellarg($fileName), $output, $return);
+    if ($return != 0 || !empty($output)) {
+        echo "PHP file fails contains CS issues: " . $fileName . ":" . PHP_EOL;
+        echo implode(PHP_EOL, $output) . PHP_EOL;
+        $exit = 1;
+        continue;
+    }
+}
+
+exit($exit);
+```
+
+## Keeping Up-to-Date
+
+Periodically, you should update your fork or personal repository to
+match the canonical ZF repository. In each of the above setups, we have
+added a remote to the Zend Framework repository, which allows you to do
+the following:
+
+
+```sh
+% git checkout master
+% git pull zf2 master
+- OPTIONALLY, to keep your remote up-to-date -
+% git push origin
+```
+
+If you're tracking other branches -- for example, the "develop" branch, where
+new feature development occurs -- you'll want to do the same operations for that
+branch; simply substibute "develop" for "master".
+
+## Working on Zend Framework
+
+When working on Zend Framework, we recommend you do each new feature or
+bugfix in a new branch. This simplifies the task of code review as well
+as of merging your changes into the canonical repository.
+
+A typical work flow will then consist of the following:
+
+ 1. Create a new local branch based off your master branch.
+ 2. Switch to your new local branch. (This step can be combined with the
+    previous step with the use of `git checkout -b`.)
+ 3. Do some work, commit, repeat as necessary.
+ 4. Push the local branch to your remote repository.
+ 5. Send a pull request.
+
+The mechanics of this process are actually quite trivial. Below, we will
+create a branch for fixing an issue in the tracker.
+
+```sh
+% git checkout -b zf9295
+Switched to a new branch 'zf9295'
+```
+... do some work ...
+  
+```sh
+% git commit
+```
+... write your log message ...
+  
+```sh
+% git push origin HEAD:zf9295
+Counting objects: 38, done.
+Delta compression using up to 2 threads.
+Compression objects: 100% (18/18), done.
+Writing objects: 100% (20/20), 8.19KiB, done.
+Total 20 (delta 12), reused 0 (delta 0)
+To ssh://git@github.com/weierophinney/zf2.git
+   b5583aa..4f51698  HEAD -> master
+```
+
+
+To send a pull request, you have two options.
+
+If using GitHub, you can do the pull request from there. Navigate to
+your repository, select the branch you just created, and then select the
+"Pull Request" button in the upper right. Select the user
+"zendframework" as the recipient.
+
+If using your own repository - or even if using GitHub - you can send an
+email indicating you have changes to pull:
+
+ -  Send to <zf-devteam@zend.com>
+
+ -  In your message, specify:
+     -  The URL to your repository (e.g., `git://mwop.net/zf2.git`)
+     -  The branch containing the changes you want pulled (e.g., `zf9295`)
+     -  The nature of the changes (e.g., `implements
+        Zend_Service_Twitter`, `fixes ZF-9295`, etc.)
+
+### What branch to issue the pull request against?
+
+Which branch should you issue a pull request against?
+
+- For fixes against the stable release, issue the pull request against the
+  "master" branch.
+- For new features, or fixes that introduce new elements to the public API (such
+  as new public methods or properties), issue the pull request against the
+  "develop" branch.
+
+## Branch Cleanup
+
+As you might imagine, if you are a frequent contributor, you'll start to
+get a ton of branches both locally and on your remote.
+
+Once you know that your changes have been accepted to the master
+repository, we suggest doing some cleanup of these branches.
+
+ -  Local branch cleanup
+    
+    ```sh
+    % git branch -d <branchname>
+    ```
+
+ -  Remote branch removal
+
+    ```sh
+    % git push origin :<branchname>
+    ```
+
+
+## FEEDS AND EMAILS
+
+RSS feeds may be found at:
+
+`https://github.com/zendframework/zf2/commits/<branch>.atom`
+
+where &lt;branch&gt; is a branch in the repository.
+
+To subscribe to git email notifications, simply watch or fork the zf2 repository
+on GitHub.
+
+## CONTRIBUTORS AND COMMITTERS
+
+Both Zend's internal Zend Framework team and the members of the Community Review
+team have push privileges to the ZF2 repository. 
diff --git a/wcfsetup/install/files/lib/system/api/zend/version b/wcfsetup/install/files/lib/system/api/zend/version
new file mode 100644 (file)
index 0000000..ea60123
--- /dev/null
@@ -0,0 +1 @@
+Version of Zend Framework is release-2.0.3
\ No newline at end of file
diff --git a/wcfsetup/install/files/lib/system/cli/DatabaseCommandHistory.class.php b/wcfsetup/install/files/lib/system/cli/DatabaseCommandHistory.class.php
new file mode 100644 (file)
index 0000000..5605f62
--- /dev/null
@@ -0,0 +1,71 @@
+<?php
+namespace wcf\system\cli;
+use phpline\console\history\MemoryHistory;
+use wcf\system\WCF;
+
+/**
+ * A phpline history that saves the items in database.
+ *
+ * @author     Tim Düsterhus
+ * @copyright  2001-2012 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system
+ * @category   Community Framework
+ */
+class DatabaseCommandHistory extends MemoryHistory {
+       /**
+        * should the history automatically be saved
+        * @var boolean
+        */
+       public $autoSave = true;
+       
+       /**
+        * Saves the history.
+        * 
+        * @param boolean $append
+        */
+       public function save($append = false) {
+               if (!$append) {
+                       $sql = "DELETE FROM     wcf".WCF_N."_cli_history
+                               WHERE           userID = ?";
+                       $statement = WCF::getDB()->prepareStatement($sql);
+                       $statement->execute(array(WCF::getUser()->userID));
+               }
+               
+               $sql = "INSERT INTO     wcf".WCF_N."_cli_history (userID, command)
+                       VALUES (?, ?)";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               WCF::getDB()->beginTransaction();
+               foreach ($this as $item) {
+                       $statement->execute(array(WCF::getUser()->userID, $item));
+               }
+               WCF::getDB()->commitTransaction();
+       }
+       
+       /**
+        * Loads the history.
+        */
+       public function load() {
+               $sql = "SELECT  *
+                       FROM    wcf".WCF_N."_cli_history
+                       WHERE   userID = ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute(array(WCF::getUser()->userID));
+               
+               while ($row = $statement->fetchArray()) {
+                       $this->add($row['command']);
+               }
+               
+               $this->moveToEnd();
+       }
+       
+       /**
+        * Automatically saves the history if $autoSave is set to true.
+        */
+       public function __destruct() {
+               if ($this->autoSave) {
+                       $this->save();
+               }
+       }
+}
index 259a24a0ac39549fb898d8330b62228eae7ef672..3a94c60bc8151cc09c3e77bdda7941e78344e451 100644 (file)
@@ -127,6 +127,14 @@ CREATE TABLE wcf1_cleanup_log (
        KEY objectType (objectType)
 );
 
+DROP TABLE IF EXISTS wcf1_cli_history;
+CREATE TABLE wcf1_cli_history (
+       historyItem INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
+       userID INT(10) NOT NULL,
+       command VARCHAR(255) NOT NULL,
+       KEY (userID)
+);
+
 DROP TABLE IF EXISTS wcf1_clipboard_action;
 CREATE TABLE wcf1_clipboard_action (
        actionID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
@@ -796,6 +804,8 @@ ALTER TABLE wcf1_cleanup_listener ADD FOREIGN KEY (packageID) REFERENCES wcf1_pa
 
 ALTER TABLE wcf1_cleanup_log ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;
 
+ALTER TABLE wcf1_cli_history ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE CASCADE;
+
 ALTER TABLE wcf1_clipboard_action ADD FOREIGN KEY (packageID) REFERENCES wcf1_package (packageID) ON DELETE CASCADE;
 
 ALTER TABLE wcf1_clipboard_item ADD FOREIGN KEY (objectTypeID) REFERENCES wcf1_object_type (objectTypeID) ON DELETE CASCADE;