From: Michael M Slusarz Date: Wed, 10 Jun 2009 19:33:17 +0000 (-0600) Subject: Import Horde_Cli:: from CVS HEAD X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=9da0b0ee14f5b152dc3a1e4f8dd531c59c37c90c;p=horde.git Import Horde_Cli:: from CVS HEAD --- diff --git a/framework/Cli/doc/Horde/Cli/colors.php b/framework/Cli/doc/Horde/Cli/colors.php new file mode 100644 index 000000000..c7fc4ed8a --- /dev/null +++ b/framework/Cli/doc/Horde/Cli/colors.php @@ -0,0 +1,21 @@ +#!/usr/bin/env php +writeln($cli->red('Red')); +$cli->writeln($cli->yellow('Yellow')); +$cli->writeln($cli->green('Green')); +$cli->writeln($cli->blue('Blue')); +$cli->writeln(); + +/* These messages are automatically colorized based on the message type. */ +$cli->message('test', 'cli.error'); +$cli->message('test', 'cli.warning'); +$cli->message('test', 'cli.success'); +$cli->message('test', 'cli.message'); diff --git a/framework/Cli/lib/Horde/Cli.php b/framework/Cli/lib/Horde/Cli.php new file mode 100644 index 000000000..b1226d9c6 --- /dev/null +++ b/framework/Cli/lib/Horde/Cli.php @@ -0,0 +1,480 @@ + + * @author Jan Schneider + * @package Horde_Cli + */ +class Horde_Cli +{ + /** + * Singleton instance + * + * @var Horde_Cli + */ + static protected $_instance; + + /** + * Are we running on a console? + * + * @var boolean + */ + protected $_console; + + /** + * The newline string to use. + * + * @var string + */ + protected $_newline; + + /** + * The string to use for clearing the screen. + * + * @var string + */ + protected $_clearscreen = ''; + + /** + * The indent string to use. + * + * @var string + */ + protected $_indent; + + /** + * The string to mark the beginning of bold text. + * + * @var string + */ + protected $_bold_start = ''; + + /** + * The string to mark the end of bold text. + * + * @var string + */ + protected $_bold_end = ''; + + /** + * The strings to mark the beginning of coloured text. + * + * @var string + */ + protected $_red_start = ''; + protected $_green_start = ''; + protected $_yellow_start = ''; + protected $_blue_start = ''; + + /** + * The strings to mark the end of coloured text. + * + * @var string + */ + protected $_red_end = ''; + protected $_green_end = ''; + protected $_yellow_end = ''; + protected $_blue_end = ''; + + /** + * Terminal foreground color codes. Not used yet. + * + * @var array + */ + protected $_terminalForegrounds = array( + 'normal' => "\x1B[0m", + 'black' => "\x1B[0m", + 'bold' => "\x1b[1m", + 'red' => "\x1B[31m", + 'green' => "\x1B[32m", + 'brown' => "\x1B[33m", + 'blue' => "\x1B[34m", + 'magenta' => "\x1B[35m", + 'cyan' => "\x1B[36m", + 'lightgray' => "\x1B[37m", + 'white' => "\x1B[1m\x1B[37m", + 'darkgray' => "\x1B[1m\x1B[0m", + 'lightred' => "\x1B[1m\x1B[31m", + 'lightgreen' => "\x1B[1m\x1B[32m", + 'yellow' => "\x1B[1m\x1B[33m", + 'lightblue' => "\x1B[1m\x1B[34m", + 'lightmagenta' => "\x1B[1m\x1B[35m", + 'lightcyan' => "\x1B[1m\x1B[36m", + ); + + /** + * Terminal background color codes. Not used yet. + * + * @var array + */ + protected $_terminalBackgrounds = array( + 'normal' => "\x1B[0m", + 'black' => "\x1B[0m", + 'red' => "\x1B[41m", + 'green' => "\x1B[42m", + 'brown' => "\x1B[43m", + 'blue' => "\x1B[44m", + 'magenta' => "\x1B[45m", + 'cyan' => "\x1B[46m", + 'lightgray' => "\x1B[47m", + ); + + /** + * Returns a single instance of the Horde_Cli class. + */ + static public function singleton() + { + if (!isset(self::$_instance)) { + self::$_instance = new Horde_Cli(); + } + + return self::$_instance; + } + + /** + * Detect the current environment (web server or console) and sets + * internal values accordingly. + * + * The constructor must not be called after init(). Either use the + * singleton() method to retrieve a Horde_Cli object, or don't call init() + * statically. + */ + public function __construct() + { + $this->_console = $this->runningFromCLI(); + + if ($this->_console) { + $this->_newline = "\n"; + $this->_indent = ' '; + + $term = getenv('TERM'); + if ($term) { + if (preg_match('/^(xterm|vt220|linux)/', $term)) { + $this->_clearscreen = "\x1b[2J\x1b[H"; + $this->_bold_start = "\x1b[1m"; + $this->_red_start = "\x1b[01;31m"; + $this->_green_start = "\x1b[01;32m"; + $this->_yellow_start = "\x1b[01;33m"; + $this->_blue_start = "\x1b[01;34m"; + $this->_bold_end = $this->_red_end = $this->_green_end = $this->_yellow_end = $this->_blue_end = "\x1b[0m"; + } elseif (preg_match('/^vt100/', $term)) { + $this->_clearscreen = "\x1b[2J\x1b[H"; + $this->_bold_start = "\x1b[1m"; + $this->_bold_end = "\x1b[0m"; + } + } + } else { + $this->_newline = '
'; + $this->_indent = str_repeat(' ', 4); + + $this->_bold_start = ''; + $this->_bold_end = ''; + $this->_red_start = ''; + $this->_green_start = ''; + $this->_yellow_start = ''; + $this->_blue_start = ''; + $this->_red_end = $this->_green_end = $this->_yellow_end = $this->_blue_end = ''; + } + } + + /** + * Prints $text on a single line. + * + * @param string $text The text to print. + * @param boolean $pre If true the linebreak is printed before + * the text instead of after it. + */ + public function writeln($text = '', $pre = false) + { + if ($pre) { + echo $this->_newline . $text; + } else { + echo $text . $this->_newline; + } + } + + /** + * Clears the entire screen, if possible. + */ + public function clearScreen() + { + echo $this->_clearscreen; + } + + /** + * Returns the indented string. + * + * @param string $text The text to indent. + * + * @return string The indented text. + */ + public function indent($text) + { + return $this->_indent . $text; + } + + /** + * Returns a bold version of $text. + * + * @param string $text The text to bold. + * + * @return string The bolded text. + */ + public function bold($text) + { + return $this->_bold_start . $text . $this->_bold_end; + } + + /** + * Returns a red version of $text. + * + * @param string $text The text to print in red. + * + * @return string The red text. + */ + public function red($text) + { + return $this->_red_start . $text . $this->_red_end; + } + + /** + * Returns a green version of $text. + * + * @param string $text The text to print in green. + * + * @return string The green text. + */ + public function green($text) + { + return $this->_green_start . $text . $this->_green_end; + } + + /** + * Returns a blue version of $text. + * + * @param string $text The text to print in blue. + * + * @return string The blue text. + */ + public function blue($text) + { + return $this->_blue_start . $text . $this->_blue_end; + } + + /** + * Returns a yellow version of $text. + * + * @param string $text The text to print in yellow. + * + * @return string The yellow text. + */ + public function yellow($text) + { + return $this->_yellow_start . $text . $this->_yellow_end; + } + + /** + * Displays a message. + * + * @param string $event The message string. + * @param string $type The type of message: 'cli.error', 'cli.warning', + * 'cli.success', or 'cli.message'. + */ + public function message($message, $type = 'cli.message') + { + $message = wordwrap(str_replace("\n", "\n ", $message), + 68, "\n ", true); + + switch ($type) { + case 'cli.error': + $type_message = $this->red('[ ERROR! ] '); + break; + + case 'cli.warning': + $type_message = $this->yellow('[ WARN ] '); + break; + + case 'cli.success': + $type_message = $this->green('[ OK ] '); + break; + + case 'cli.message': + $type_message = $this->blue('[ INFO ] '); + break; + } + + $this->writeln($type_message . $message); + } + + /** + * Displays a fatal error message. + * + * @param string $error The error text to display. + */ + public function fatal($error) + { + $this->writeln($this->red('====================')); + $this->writeln(); + $this->writeln($this->red(_("Fatal Error:"))); + $this->writeln($this->red($error)); + $this->writeln(); + $this->writeln($this->red('====================')); + exit(1); + } + + /** + * Prompts for a user response. + * + * @todo Horde 4: switch $choices and $default + * + * @param string $prompt The message to display when prompting the user. + * @param array $choices The choices available to the user or null for a + * text input. + * @param string $default The default value if no value specified. + * + * @return mixed The user's response to the prompt. + */ + public function prompt($prompt, $choices = null, $default = null) + { + if ($default !== null) { + $prompt .= ' [' . $default . ']'; + } + + // Main event loop to capture top level command. + while (true) { + // Print out the prompt message. + $this->writeln($prompt . ' ', !is_array($choices)); + if (is_array($choices) && !empty($choices)) { + foreach ($choices as $key => $choice) { + $this->writeln($this->indent('(' . $this->bold($key) . ') ' . $choice)); + } + $this->writeln(_("Type your choice: "), true); + @ob_flush(); + + // Get the user choice. + $response = trim(fgets(STDIN)); + if ($response === '' && $default !== null) { + $response = $default; + } + if (isset($choices[$response])) { + return $response; + } else { + $this->writeln($this->red(sprintf(_("\"%s\" is not a valid choice."), $response))); + } + } else { + @ob_flush(); + $response = trim(fgets(STDIN)); + if ($response === '' && $default !== null) { + $response = $default; + } + return $response; + } + } + + return true; + } + + /** + * Interactively prompts for input without echoing to the terminal. + * Requires a bash shell or Windows and won't work with safe_mode settings + * (uses shell_exec). + * + * From: http://www.sitepoint.com/blogs/2009/05/01/interactive-cli-password-prompt-in-php/ + * + * @param string $prompt The message to display when prompting the user. + * + * @return string The user's response to the prompt. + */ + public function passwordPrompt($prompt) + { + $prompt .= ' '; + + if (preg_match('/^win/i', PHP_OS)) { + $vbscript = sys_get_temp_dir() . 'prompt_password.vbs'; + file_put_contents($vbscript, 'wscript.echo(InputBox("' . addslashes($prompt) . '", "", "password here"))'); + $command = "cscript //nologo " . escapeshellarg($vbscript); + $password = rtrim(shell_exec($command)); + unlink($vbscript); + } else { + $command = '/usr/bin/env bash -c "echo OK"'; + if (rtrim(shell_exec($command)) !== 'OK') { + trigger_error("Can't invoke bash"); + return; + } + $command = '/usr/bin/env bash -c "read -s -p ' . escapeshellarg($prompt) . ' mypassword && echo \$mypassword"'; + $password = rtrim(shell_exec($command)); + echo "\n"; + } + + return $password; + } + + /** + * Reads everything that is sent through standard input and returns it + * as a single string. + * + * @return string The contents of the standard input. + */ + public function readStdin() + { + $in = ''; + while (!feof(STDIN)) { + $in .= fgets(STDIN, 1024); + } + return $in; + } + + /** + * CLI scripts shouldn't timeout, so try to set the time limit to + * none. Also initialize a few variables in $_SERVER that aren't present + * from the CLI. + * + * You must not call init() statically before calling the constructor. + * Either use the singleton() method to retrieve a Horde_Cli object after + * calling init(), or don't call init() statically. + */ + static public function init() + { + /* Run constructor now because it requires $_SERVER['SERVER_NAME'] to + * be empty if called with a CGI SAPI. */ + $cli = &self::singleton(); + + @set_time_limit(0); + ob_implicit_flush(true); + ini_set('html_errors', false); + $_SERVER['HTTP_HOST'] = '127.0.0.1'; + $_SERVER['SERVER_NAME'] = '127.0.0.1'; + $_SERVER['SERVER_PORT'] = ''; + $_SERVER['REMOTE_ADDR'] = ''; + $_SERVER['PHP_SELF'] = isset($argv) ? $argv[0] : ''; + if (!defined('STDIN')) { + define('STDIN', fopen('php://stdin', 'r')); + } + if (!defined('STDOUT')) { + define('STDOUT', fopen('php://stdout', 'r')); + } + if (!defined('STDERR')) { + define('STDERR', fopen('php://stderr', 'r')); + } + } + + /** + * Make sure we're being called from the command line, and not via + * the web. + * + * @return boolean True if we are, false otherwise. + */ + static public function runningFromCLI() + { + return (PHP_SAPI == 'cli') || + (((PHP_SAPI == 'cgi') || (PHP_SAPI == 'cgi-fcgi')) && + empty($_SERVER['SERVER_NAME'])); + } + +} diff --git a/framework/Cli/package.xml b/framework/Cli/package.xml new file mode 100644 index 000000000..eceada0d5 --- /dev/null +++ b/framework/Cli/package.xml @@ -0,0 +1,114 @@ + + + Cli + pear.horde.org + Horde Command Line Interface API + Horde_Cli:: API for basic command-line functionality/checks + + + Chuck Hagenbuch + chuck + chuck@horde.org + yes + + + Jan Schneider + jan + jan@horde.org + yes + + 2009-06-10 + + 0.2.0 + 0.2.0 + + + beta + beta + + LGPL + * Horde_CLI:: -> Horde_Cli:: + * Initial Horde 4 package. + + + + + + + + + + + + + + + + + + + + + 5.2.0 + + + 1.5.4 + + + gettext + + + + + + + + + + + 2006-12-31 + + 0.1.0 + 0.1.0 + + + alpha + alpha + + LGPL + Add 'default' parameter to Horde_CLI::prompt(). + + + + + 0.0.2 + 0.0.2 + + + alpha + alpha + + 2006-05-08 + LGPL + Converted to package.xml 2.0 for pear.horde.org + + + + + 0.0.1 + 0.0.1 + + + alpha + alpha + + 2003-07-04 + LGPL + Initial release as a PEAR package + + + + diff --git a/framework/Memcache/scripts/Horde/Memcache/stats.php b/framework/Memcache/scripts/Horde/Memcache/stats.php index d0dba50cb..ae4cd6f31 100755 --- a/framework/Memcache/scripts/Horde/Memcache/stats.php +++ b/framework/Memcache/scripts/Horde/Memcache/stats.php @@ -26,13 +26,13 @@ require_once HORDE_BASE . '/lib/core.php'; // Make sure no one runs this from the web. -if (!Horde_CLI::runningFromCLI()) { +if (!Horde_Cli::runningFromCLI()) { exit("Must be run from the command line\n"); } // Load the CLI environment - make sure there's no time limit, init some // variables, etc. -$cli = &Horde_CLI::singleton(); +$cli = &Horde_Cli::singleton(); $cli->init(); require_once HORDE_BASE . '/lib/base.php'; diff --git a/framework/SessionHandler/scripts/Horde/SessionHandler/horde-active-sessions.php b/framework/SessionHandler/scripts/Horde/SessionHandler/horde-active-sessions.php index 191f69c84..c950a87c6 100755 --- a/framework/SessionHandler/scripts/Horde/SessionHandler/horde-active-sessions.php +++ b/framework/SessionHandler/scripts/Horde/SessionHandler/horde-active-sessions.php @@ -23,13 +23,13 @@ require_once HORDE_BASE . '/lib/core.php'; require_once 'Horde/CLI.php'; // Make sure no one runs this from the web. -if (!Horde_CLI::runningFromCLI()) { +if (!Horde_Cli::runningFromCLI()) { exit("Must be run from the command line\n"); } // Load the CLI environment - make sure there's no time limit, init some // variables, etc. -$cli = &Horde_CLI::singleton(); +$cli = &Horde_Cli::singleton(); $cli->init(); require_once HORDE_BASE . '/lib/base.php';