2010-09-27 01:14:42 +02:00
#!/usr/bin/php
< ? php
/**
* Command - line code generation utility to automate administrator tasks .
*
* Shell dispatcher class
*
* PHP versions 4 and 5
*
* CakePHP ( tm ) : Rapid Development Framework < http :// www . cakephp . org />
* Copyright 2005 - 2008 , Cake Software Foundation , Inc .
* 1785 E . Sahara Avenue , Suite 490 - 204
* Las Vegas , Nevada 89104
2013-11-13 20:17:05 +01:00
* Modified for PostfixAdmin by Valkum 2011
* Modified for PostfixAdmin by Christian Boltz 2011 - 2013
2010-09-27 01:14:42 +02:00
*
* Copyright 2010
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice .
*
* @ filesource
* @ copyright Copyright 2005 - 2008 , Cake Software Foundation , Inc .
* @ link http :// postfixadmin . sourceforge . net / Postfixadmin on Sourceforge
* @ package postfixadmin
* @ subpackage -
* @ since -
* @ version $Revision $
* @ modifiedby $LastChangedBy $
* @ lastmodified $Date $
* @ license http :// www . opensource . org / licenses / mit - license . php The MIT License
*/
class PostfixAdmin {
2016-05-20 21:55:55 +02:00
/**
2016-05-20 22:58:13 +02:00
* Version
2016-05-20 21:55:55 +02:00
*
* @ var string
*/
public $version = '0.2' ;
/**
* Standard input stream .
*
* @ var filehandle
*/
public $stdin ;
/**
* Standard output stream .
*
* @ var filehandle
*/
public $stdout ;
/**
* Standard error stream .
*
* @ var filehandle
*/
public $stderr ;
/**
* Contains command switches parsed from the command line .
*
* @ var array
*/
public $params = array ();
/**
* Contains arguments parsed from the command line .
*
* @ var array
*/
public $args = array ();
/**
* The file name of the shell that was invoked .
*
* @ var string
*/
public $shell = null ;
/**
* The class name of the shell that was invoked .
*
* @ var string
*/
public $shellClass = null ;
/**
* The command called if public methods are available .
*
* @ var string
*/
public $shellCommand = null ;
/**
* The name of the shell in camelized .
*
* @ var string
*/
public $shellName = null ;
/**
* Constructor
*
* @ param array $args the argv .
*/
public function __construct ( $args = array ()) {
set_time_limit ( 0 );
$this -> __initConstants ();
$this -> parseParams ( $args );
$this -> __initEnvironment ();
}
/**
* Defines core configuration .
*/
private function __initConstants () {
ini_set ( 'display_errors' , '1' );
ini_set ( 'error_reporting' , E_ALL );
ini_set ( 'html_errors' , false );
ini_set ( 'implicit_flush' , true );
ini_set ( 'max_execution_time' , 0 );
define ( 'DS' , DIRECTORY_SEPARATOR );
define ( 'CORE_INCLUDE_PATH' , dirname ( __FILE__ ));
define ( 'CORE_PATH' , dirname ( CORE_INCLUDE_PATH ) ); # CORE_INCLUDE_PATH/../
if ( ! defined ( 'POSTFIXADMIN' )) { # already defined if called from setup.php
define ( 'POSTFIXADMIN' , 1 ); # checked in included files
}
}
/**
* Defines current working environment .
*/
private function __initEnvironment () {
$this -> stdin = fopen ( 'php://stdin' , 'r' );
$this -> stdout = fopen ( 'php://stdout' , 'w' );
$this -> stderr = fopen ( 'php://stderr' , 'w' );
if ( ! $this -> __bootstrap ()) {
$this -> stderr ( " " );
$this -> stderr ( " Unable to load. " );
$this -> stderr ( " \t Make sure /config.inc.php exists in " . PATH );
exit ( 1 );
}
2010-09-27 01:14:42 +02:00
2016-05-20 21:55:55 +02:00
if ( basename ( __FILE__ ) != basename ( $this -> args [ 0 ])) {
$this -> stderr ( 'Warning: the dispatcher may have been loaded incorrectly, which could lead to unexpected results...' );
if ( $this -> getInput ( 'Continue anyway?' , array ( 'y' , 'n' ), 'y' ) == 'n' ) {
exit ( 1 );
}
2010-09-27 01:14:42 +02:00
}
2016-05-20 21:55:55 +02:00
$this -> shiftArgs ();
}
/**
* Initializes the environment and loads the Cake core .
*
* @ return boolean Success .
*/
private function __bootstrap () {
if ( $this -> params [ 'webroot' ] != '' ) {
define ( 'PATH' , $this -> params [ 'webroot' ] );
} else {
define ( 'PATH' , CORE_PATH );
2016-05-20 22:58:13 +02:00
}
2016-05-20 21:55:55 +02:00
if ( ! file_exists ( PATH )) {
$this -> stderr ( PATH . " don't exists " );
return false ;
}
2010-09-27 01:14:42 +02:00
2016-05-22 21:58:54 +02:00
# make sure global variables fron functions.inc.php end up in the global namespace, instead of being local to this function
global $version , $min_db_version ;
2016-05-20 21:55:55 +02:00
if ( ! require_once ( PATH . '/common.php' )) {
$this -> stderr ( " Failed to load " . PATH . '/common.php' );
return false ;
2010-09-27 01:14:42 +02:00
}
2016-05-20 21:55:55 +02:00
return true ;
}
2010-09-27 01:14:42 +02:00
2016-05-20 21:55:55 +02:00
/**
* Dispatches a CLI request
*/
public function dispatch () {
$CONF = Config :: read ( 'all' );
2010-09-27 01:14:42 +02:00
2016-05-22 21:58:54 +02:00
check_db_version (); # ensure the database layout is up to date
2016-05-20 21:55:55 +02:00
if ( ! isset ( $this -> args [ 0 ])) {
$this -> help ();
return ;
}
$this -> shell = $this -> args [ 0 ];
$this -> shiftArgs ();
$this -> shellName = ucfirst ( $this -> shell );
$this -> shellClass = $this -> shellName . 'Handler' ;
2010-09-27 01:14:42 +02:00
2016-05-20 21:55:55 +02:00
if ( $this -> shell == 'help' ) {
$this -> help ();
return ;
}
# TODO: move shells/shell.php to model/ to enable autoloading
if ( ! class_exists ( 'Shell' )) {
require CORE_INCLUDE_PATH . DS . " shells " . DS . 'shell.php' ;
}
$command = 'help' ; # not the worst default ;-)
if ( isset ( $this -> args [ 0 ])) {
$command = $this -> args [ 0 ];
2010-09-27 01:14:42 +02:00
}
2013-11-14 22:48:52 +01:00
2016-05-20 21:55:55 +02:00
$this -> shellCommand = $command ;
$this -> shellClass = 'Cli' . ucfirst ( $command );
2011-10-18 01:19:57 +02:00
2016-05-20 21:55:55 +02:00
if ( ucfirst ( $command ) == 'Add' || ucfirst ( $command ) == 'Update' ) {
$this -> shellClass = 'CliEdit' ;
2010-09-27 01:14:42 +02:00
}
2016-05-20 21:55:55 +02:00
if ( ! class_exists ( $this -> shellClass )) {
$this -> stderr ( 'Unknown task ' . $this -> shellCommand );
return ;
}
2010-09-27 01:14:42 +02:00
2016-05-20 21:55:55 +02:00
$shell = new $this -> shellClass ( $this );
2013-11-13 20:07:12 +01:00
2016-05-20 21:55:55 +02:00
$shell -> handler_to_use = ucfirst ( $this -> shell ) . 'Handler' ;
2013-11-13 20:07:12 +01:00
2016-05-20 21:55:55 +02:00
if ( ! class_exists ( $shell -> handler_to_use )) {
$this -> stderr ( 'Unknown module ' . $this -> shell );
return ;
}
2013-11-13 20:07:12 +01:00
2016-05-20 21:55:55 +02:00
$task = ucfirst ( $command );
2013-11-13 20:07:12 +01:00
2016-05-20 21:55:55 +02:00
$shell -> new = 0 ;
if ( $task == 'Add' ) {
$shell -> new = 1 ;
}
# TODO: add a way to Cli* to signal if the selected handler is supported (for example, not all *Handler support changing the password)
2013-11-13 20:07:12 +01:00
2016-05-20 21:55:55 +02:00
if ( strtolower ( get_parent_class ( $shell )) == 'shell' ) {
$shell -> initialize ();
2013-11-13 20:07:12 +01:00
2016-05-20 21:55:55 +02:00
$handler = new $shell -> handler_to_use ;
if ( in_array ( $task , $handler -> taskNames )) {
$this -> shiftArgs ();
$shell -> startup ();
if ( isset ( $this -> args [ 0 ]) && $this -> args [ 0 ] == 'help' ) {
if ( method_exists ( $shell , 'help' )) {
$shell -> help ();
exit ();
} else {
$this -> help ();
}
}
$shell -> execute ();
return ;
2013-11-13 20:07:12 +01:00
}
2016-05-20 21:55:55 +02:00
}
$classMethods = get_class_methods ( $shell );
2013-11-13 20:07:12 +01:00
2016-05-20 21:55:55 +02:00
$privateMethod = $missingCommand = false ;
if (( in_array ( $command , $classMethods ) || in_array ( strtolower ( $command ), $classMethods )) && strpos ( $command , '_' , 0 ) === 0 ) {
$privateMethod = true ;
2010-09-27 01:14:42 +02:00
}
2016-05-20 21:55:55 +02:00
if ( ! in_array ( $command , $classMethods ) && ! in_array ( strtolower ( $command ), $classMethods )) {
$missingCommand = true ;
}
2010-09-27 01:14:42 +02:00
2016-05-20 21:55:55 +02:00
$protectedCommands = array (
'initialize' , 'in' , 'out' , 'err' , 'hr' ,
'createfile' , 'isdir' , 'copydir' , 'object' , 'tostring' ,
'requestaction' , 'log' , 'cakeerror' , 'shelldispatcher' ,
'__initconstants' , '__initenvironment' , '__construct' ,
'dispatch' , '__bootstrap' , 'getinput' , 'stdout' , 'stderr' , 'parseparams' , 'shiftargs'
);
2010-09-27 01:14:42 +02:00
2016-05-20 21:55:55 +02:00
if ( in_array ( strtolower ( $command ), $protectedCommands )) {
$missingCommand = true ;
}
2010-09-27 01:14:42 +02:00
2016-05-20 21:55:55 +02:00
if ( $missingCommand && method_exists ( $shell , 'main' )) {
$shell -> startup ();
$shell -> main ();
} elseif ( ! $privateMethod && method_exists ( $shell , $command )) {
$this -> shiftArgs ();
$shell -> startup ();
$shell -> { $command }();
} else {
$this -> stderr ( " Unknown { $this -> shellName } command ' $command '. \n For usage, try 'postfixadmin-cli { $this -> shell } help'. \n \n " );
2010-09-27 01:14:42 +02:00
}
2016-05-20 21:55:55 +02:00
}
/**
* Prompts the user for input , and returns it .
*
* @ param string $prompt Prompt text .
* @ param mixed $options Array or string of options .
* @ param string $default Default input value .
* @ return Either the default value , or the user - provided input .
*/
public function getInput ( $prompt , $options = null , $default = null ) {
if ( ! is_array ( $options )) {
$print_options = '' ;
} else {
$print_options = '(' . implode ( '/' , $options ) . ')' ;
2010-09-27 01:14:42 +02:00
}
2016-05-20 21:55:55 +02:00
if ( $default == null ) {
$this -> stdout ( $prompt . " $print_options \n " . '> ' , false );
} else {
$this -> stdout ( $prompt . " $print_options \n " . " [ $default ] > " , false );
2010-09-27 01:14:42 +02:00
}
2016-05-20 21:55:55 +02:00
$result = fgets ( $this -> stdin );
2010-09-27 01:14:42 +02:00
2016-05-20 21:55:55 +02:00
if ( $result === false ){
exit ( 1 );
}
$result = trim ( $result );
2010-09-27 01:14:42 +02:00
2016-05-20 21:55:55 +02:00
if ( $default != null && empty ( $result )) {
return $default ;
}
return $result ;
}
/**
* Outputs to the stdout filehandle .
*
* @ param string $string String to output .
* @ param boolean $newline If true , the outputs gets an added newline .
*/
public function stdout ( $string , $newline = true ) {
if ( $newline ) {
fwrite ( $this -> stdout , $string . " \n " );
} else {
fwrite ( $this -> stdout , $string );
}
}
2010-09-27 01:14:42 +02:00
2016-05-20 21:55:55 +02:00
/**
* Outputs to the stderr filehandle .
*
* @ param string $string Error text to output .
*/
public function stderr ( $string ) {
fwrite ( $this -> stderr , 'Error: ' . $string . " \n " );
}
2010-09-27 01:14:42 +02:00
2016-05-20 21:55:55 +02:00
/**
* Parses command line options
*
* @ param array $params Parameters to parse
*/
public function parseParams ( $params ) {
$this -> __parseParams ( $params );
2010-09-27 01:14:42 +02:00
2016-05-20 21:55:55 +02:00
$defaults = array ( 'webroot' => CORE_PATH );
2010-09-27 01:14:42 +02:00
2016-05-20 21:55:55 +02:00
$params = array_merge ( $defaults , array_intersect_key ( $this -> params , $defaults ));
2010-09-27 01:14:42 +02:00
2016-05-20 21:55:55 +02:00
$isWin = array_filter ( array_map ( 'strpos' , $params , array ( '\\' )));
2010-09-27 01:14:42 +02:00
2016-05-20 21:55:55 +02:00
$params = str_replace ( '\\' , '/' , $params );
2010-09-27 01:14:42 +02:00
2016-05-20 21:55:55 +02:00
if ( ! empty ( $matches [ 0 ]) || ! empty ( $isWin )) {
$params = str_replace ( '/' , '\\' , $params );
2010-09-27 01:14:42 +02:00
}
2016-05-20 21:55:55 +02:00
$this -> params = array_merge ( $this -> params , $params );
}
/**
* Helper for recursively paraing params
*
* @ return array params
*/
private function __parseParams ( $params ) {
$count = count ( $params );
for ( $i = 0 ; $i < $count ; $i ++ ) {
if ( isset ( $params [ $i ])) {
if ( $params [ $i ] != '' && $params [ $i ]{ 0 } === '-' ) {
$key = substr ( $params [ $i ], 1 );
$this -> params [ $key ] = true ;
unset ( $params [ $i ]);
if ( isset ( $params [ ++ $i ])) {
# TODO: ideally we should know if a parameter can / must have a value instead of whitelisting known valid values starting with '-' (probably only bool doesn't need a value)
if ( $params [ $i ]{ 0 } !== '-' or $params [ $i ] != '-1' ) {
$this -> params [ $key ] = $params [ $i ];
unset ( $params [ $i ]);
2010-09-27 01:14:42 +02:00
} else {
2016-05-20 21:55:55 +02:00
$i -- ;
$this -> __parseParams ( $params );
2010-09-27 01:14:42 +02:00
}
2016-05-20 21:55:55 +02:00
}
} else {
$this -> args [] = $params [ $i ];
unset ( $params [ $i ]);
2010-09-27 01:14:42 +02:00
}
2016-05-20 21:55:55 +02:00
}
2010-09-27 01:14:42 +02:00
}
2016-05-20 21:55:55 +02:00
}
/**
* Removes first argument and shifts other arguments up
*
* @ return boolean False if there are no arguments
*/
public function shiftArgs () {
if ( empty ( $this -> args )) {
return false ;
2010-09-27 01:14:42 +02:00
}
2016-05-20 21:55:55 +02:00
unset ( $this -> args [ 0 ]);
$this -> args = array_values ( $this -> args );
return true ;
}
/**
* prints help message and exits .
*/
public function help () {
$this -> stdout ( " \n Welcome to Postfixadmin-CLI v " . $this -> version );
$this -> stdout ( " --------------------------------------------------------------- " );
$this -> stdout ( " Usage: " );
$this -> stdout ( " postfixadmin-cli <module> <task> [--option value --option2 value] " );
$this -> stdout ( " " );
$this -> stdout ( " Available modules: " );
$modules = explode ( ',' , 'admin,domain,mailbox,alias,aliasdomain,fetchmail' );
foreach ( $modules as $module ) {
$this -> stdout ( " $module " );
}
$this -> stdout ( " " );
$this -> stdout ( " Most modules support the following tasks: " );
$this -> stdout ( " view View an item " );
$this -> stdout ( " add Add an item " );
$this -> stdout ( " update Update an item " );
$this -> stdout ( " delete Delete an item " );
$this -> stdout ( " scheme Print database scheme (useful for developers only) " );
$this -> stdout ( " help Print help output " );
$this -> stdout ( " " );
$this -> stdout ( " " );
$this -> stdout ( " For module-specific help, see: " );
$this -> stdout ( " " );
$this -> stdout ( " postfixadmin-cli <module> help " );
$this -> stdout ( " print a detailed list of available commands " );
$this -> stdout ( " " );
$this -> stdout ( " postfixadmin-cli <module> <task> help " );
$this -> stdout ( " print a list of available options. " );
$this -> stdout ( " " );
exit ();
}
2010-09-27 01:14:42 +02:00
}
2011-02-15 22:59:03 +01:00
define ( " POSTFIXADMIN_CLI " , 1 );
2010-09-27 01:14:42 +02:00
$dispatcher = new PostfixAdmin ( $argv );
$CONF = Config :: read ( 'all' );
$dispatcher -> dispatch ();
2013-12-08 20:41:01 +01:00
/* vim: set expandtab softtabstop=4 tabstop=4 shiftwidth=4: */