Merge branch 'feature-diagnostic'

This commit is contained in:
alban 2014-07-08 22:39:50 +02:00
commit 9951fd6902
50 changed files with 6634 additions and 64 deletions

View File

@ -2,27 +2,54 @@
class system_bind {
var $ZONE_TEMPLATE ="/etc/alternc/templates/bind/templates/zone.template";
var $NAMED_TEMPLATE ="/etc/alternc/templates/bind/templates/named.template";
var $NAMED_CONF ="/var/lib/alternc/bind/automatic.conf";
var $RNDC ="/usr/sbin/rndc";
var $ZONE_TEMPLATE = "/etc/alternc/templates/bind/templates/zone.template";
var $NAMED_TEMPLATE = "/etc/alternc/templates/bind/templates/named.template";
var $NAMED_CONF = "/var/lib/alternc/bind/automatic.conf";
var $RNDC = "/usr/sbin/rndc";
var $dkim_trusted_host_file = "/etc/opendkim/TrustedHosts";
var $dkim_keytable_file = "/etc/opendkim/KeyTable";
var $dkim_signingtable_file = "/etc/opendkim/SigningTable";
var $dkim_trusted_host_file = "/etc/opendkim/TrustedHosts";
var $dkim_keytable_file = "/etc/opendkim/KeyTable";
var $dkim_signingtable_file = "/etc/opendkim/SigningTable";
var $cache_conf_db = array();
var $cache_get_persistent = array();
var $cache_zone_file = array();
var $cache_domain_summary = array();
var $zone_file_directory = '/var/lib/alternc/bind/zones/';
var $cache_conf_db = array();
var $cache_get_persistent = array();
var $cache_zone_file = array();
var $cache_domain_summary = array();
var $zone_file_directory = '/var/lib/alternc/bind/zones/';
/**
*
* @param array $options optional parameters
*/
function system_bind() {
// Constructeur
}
public function __construct($options = null) {
if (isset($options["ZONE_TEMPLATE"])) {
$this->ZONE_TEMPLATE = $options["ZONE_TEMPLATE"];
}
if (isset($options["NAMED_TEMPLATE"])) {
$this->NAMED_TEMPLATE = $options["NAMED_TEMPLATE"];
}
if (isset($options["NAMED_CONF"])) {
$this->NAMED_CONF = $options["NAMED_CONF"];
}
if (isset($options["RNDC"])) {
$this->RNDC = $options["RNDC"];
}
if (isset($options["dkim_trusted_host_file"])) {
$this->dkim_trusted_host_file = $options["dkim_trusted_host_file"];
}
if (isset($options["dkim_keytable_file"])) {
$this->dkim_keytable_file = $options["dkim_keytable_file"];
}
if (isset($options["dkim_signingtable_file"])) {
$this->dkim_signingtable_file = $options["dkim_signingtable_file"];
}
if (isset($options["zone_file_directory"])) {
$this->zone_file_directory = $options["zone_file_directory"];
}
}
/**
* Return the part of the conf we got from the database
@ -43,14 +70,14 @@ class system_bind {
sub_domaines sd,
domaines_type dt
where
sd.type=dt.name
sd.type = dt.name
and sd.enable in ('ENABLE', 'ENABLED')
order by entry ;");
$t=array();
$t = array();
while ($db->next_record()) {
$t[$db->f('domaine')][] = $db->f('entry');
}
$this->cache_conf_db = $t;
$this->cache_conf_db = $t;
}
if ($domain) {
if (isset($this->cache_conf_db[$domain])) {
@ -99,14 +126,14 @@ class system_bind {
// Choose between a generated and an incremented.
// Calculated :
$calc = date('Ymd').'00'."\n";
$calc = date('Ymd').'00'."\n";
// Old one :
$old=$calc; // default value
$file = $this->get_zone_file($domain);
$old = $calc; // default value
$file = $this->get_zone_file($domain);
preg_match_all("/\s*(\d{10})\s+\;\sserial\s?/", $file, $output_array);
if (isset($output_array[1][0]) && !empty($output_array[1][0])) {
$old = $output_array[1][0];
$old = $output_array[1][0];
}
// Return max between newly calculated, and old one incremented
@ -150,7 +177,7 @@ class system_bind {
// Use cache if is filled, if not, fill it
if (empty($this->cache_domain_summary)) {
$this->cache_domain_summary = $dom->get_domain_all_summary();
$this->cache_domain_summary = $dom->get_domain_all_summary();
}
if ($domain) return $this->cache_domain_summary[$domain];
@ -163,7 +190,7 @@ class system_bind {
* @return boolean
*/
function dkim_delete($domain) {
$target_dir = "/etc/opendkim/keys/$domain";
$target_dir = "/etc/opendkim/keys/$domain";
if (file_exists($target_dir)) {
@unlink("$target_dir/alternc_private");
@unlink("$target_dir/alternc.txt");
@ -180,17 +207,17 @@ class system_bind {
*/
function dkim_generate_key($domain) {
// Stop here if we do not manage the mail
$domainInfo = $this->get_domain_summary($domain);
$domainInfo = $this->get_domain_summary($domain);
if ( ! $domainInfo['gesmx'] ) return;
$target_dir = "/etc/opendkim/keys/$domain";
$target_dir = "/etc/opendkim/keys/$domain";
if (file_exists($target_dir.'/alternc.txt')) return; // Do not generate if exist
if (! is_dir($target_dir)) mkdir($target_dir); // create dir
// Generate the key
$old_dir=getcwd();
$old_dir = getcwd();
chdir($target_dir);
exec('opendkim-genkey -r -d "'.escapeshellarg($domain).'" -s "alternc" ');
chdir($old_dir);
@ -207,9 +234,9 @@ class system_bind {
*/
function dkim_refresh_list() {
// so ugly... but there is only 1 pass, not 3. Still ugly.
$trusted_host_new = "# WARNING: this file is auto generated by AlternC.\n# Add your changes after the last line\n";
$keytable_new = "# WARNING: this file is auto generated by AlternC.\n# Add your changes after the last line\n";
$signingtable_new = "# WARNING: this file is auto generated by AlternC.\n# Add your changes after the last line\n";
$trusted_host_new = "# WARNING: this file is auto generated by AlternC.\n# Add your changes after the last line\n";
$keytable_new = "# WARNING: this file is auto generated by AlternC.\n# Add your changes after the last line\n";
$signingtable_new = "# WARNING: this file is auto generated by AlternC.\n# Add your changes after the last line\n";
# Generate automatic entry
foreach ($this->get_domain_summary() as $domain => $ds ) {
@ -220,31 +247,31 @@ class system_bind {
if (! file_exists("/etc/opendkim/keys/$domain/alternc.txt")) continue;
// Modif the files.
$trusted_host_new.="$domain\n";
$keytable_new .="alternc._domainkey.$domain $domain:alternc:/etc/opendkim/keys/$domain/alternc.private\n";
$signingtable_new.="$domain alternc._domainkey.$domain\n";
$trusted_host_new .= "$domain\n";
$keytable_new .= "alternc._domainkey.$domain $domain:alternc:/etc/opendkim/keys/$domain/alternc.private\n";
$signingtable_new .= "$domain alternc._domainkey.$domain\n";
}
$trusted_host_new.="# END AUTOMATIC FILE. ADD YOUR CHANGES AFTER THIS LINE\n";
$keytable_new .="# END AUTOMATIC FILE. ADD YOUR CHANGES AFTER THIS LINE\n";
$signingtable_new.="# END AUTOMATIC FILE. ADD YOUR CHANGES AFTER THIS LINE\n";
$trusted_host_new .= "# END AUTOMATIC FILE. ADD YOUR CHANGES AFTER THIS LINE\n";
$keytable_new .= "# END AUTOMATIC FILE. ADD YOUR CHANGES AFTER THIS LINE\n";
$signingtable_new .= "# END AUTOMATIC FILE. ADD YOUR CHANGES AFTER THIS LINE\n";
# Get old files
$trusted_host_old=@file_get_contents($this->dkim_trusted_host_file);
$keytable_old =@file_get_contents($this->dkim_keytable_file);
$signingtable_old=@file_get_contents($this->dkim_signingtable_file);
$trusted_host_old = @file_get_contents($this->dkim_trusted_host_file);
$keytable_old = @file_get_contents($this->dkim_keytable_file);
$signingtable_old = @file_get_contents($this->dkim_signingtable_file);
# Keep manuel entry
preg_match_all('/\#\s*END\ AUTOMATIC\ FILE\.\ ADD\ YOUR\ CHANGES\ AFTER\ THIS\ LINE(.*)/s', $trusted_host_old, $output_array);
if (isset($output_array[1][0]) && !empty($output_array[1][0])) {
$trusted_host_new.=$output_array[1][0];
$trusted_host_new .= $output_array[1][0];
}
preg_match_all('/\#\s*END\ AUTOMATIC\ FILE\.\ ADD\ YOUR\ CHANGES\ AFTER\ THIS\ LINE(.*)/s', $keytable_old, $output_array);
if (isset($output_array[1][0]) && !empty($output_array[1][0])) {
$keytable_new.=$output_array[1][0];
$keytable_new .= $output_array[1][0];
}
preg_match_all('/\#\s*END\ AUTOMATIC\ FILE\.\ ADD\ YOUR\ CHANGES\ AFTER\ THIS\ LINE(.*)/s', $signingtable_old, $output_array);
if (isset($output_array[1][0]) && !empty($output_array[1][0])) {
$signingtable_new.=$output_array[1][0];
$signingtable_new .= $output_array[1][0];
}
// Save if there are some diff
@ -265,8 +292,8 @@ class system_bind {
* @return string
*/
function dkim_entry($domain) {
$keyfile="/etc/opendkim/keys/$domain/alternc.txt";
$domainInfo = $this->get_domain_summary($domain);
$keyfile = "/etc/opendkim/keys/$domain/alternc.txt";
$domainInfo = $this->get_domain_summary($domain);
if (! file_exists($keyfile) && $domainInfo['gesmx'] ) {
$this->dkim_generate_key($domain);
}
@ -281,20 +308,20 @@ class system_bind {
* @return string
*/
function mail_autoconfig_entry($domain) {
$zone= implode("\n",$this->conf_from_db($domain))."\n".$this->get_persistent($domain);
$zone = implode("\n",$this->conf_from_db($domain))."\n".$this->get_persistent($domain);
$entry='';
$domainInfo = $this->get_domain_summary($domain);
$entry = '';
$domainInfo = $this->get_domain_summary($domain);
if ( $domainInfo['gesmx'] ) {
// If we manage the mail
// Check if there is no the same entry (defined or manual)
// can be toto IN A or toto.fqdn.tld. IN A
if (! preg_match("/autoconfig(\s|\.".str_replace('.','\.',$domain)."\.)/", $zone )) {
$entry.="autoconfig IN CNAME %%fqdn%%.\n";
$entry .= "autoconfig IN CNAME %%fqdn%%.\n";
}
if (! preg_match("/autodiscover(\s|\.".str_replace('.','\.',$domain)."\.)/", $zone )) {
$entry.="autodiscover IN CNAME %%fqdn%%.\n";
$entry .= "autodiscover IN CNAME %%fqdn%%.\n";
}
} // if gesmx
return $entry;
@ -317,19 +344,19 @@ class system_bind {
function get_zone($domain) {
global $L_FQDN, $L_NS1_HOSTNAME, $L_NS2_HOSTNAME, $L_DEFAULT_MX, $L_DEFAULT_SECONDARY_MX, $L_PUBLIC_IP;
$zone =$this->get_zone_header();
$zone.=implode("\n",$this->conf_from_db($domain));
$zone.="\n;;;HOOKED ENTRY\n";
$zone = $this->get_zone_header();
$zone .= implode("\n",$this->conf_from_db($domain));
$zone .= "\n;;;HOOKED ENTRY\n";
$zone.= $this->dkim_entry($domain);
$zone.= $this->mail_autoconfig_entry($domain);
$zone .= $this->dkim_entry($domain);
$zone .= $this->mail_autoconfig_entry($domain);
$zone.="\n;;;END ALTERNC AUTOGENERATE CONFIGURATION\n";
$zone.=$this->get_persistent($domain);
$domainInfo = $this->get_domain_summary($domain);
$zone .= "\n;;;END ALTERNC AUTOGENERATE CONFIGURATION\n";
$zone .= $this->get_persistent($domain);
$domainInfo = $this->get_domain_summary($domain);
// FIXME check those vars
$zone = strtr($zone, array(
$zone = strtr($zone, array(
"%%fqdn%%"=>"$L_FQDN",
"%%ns1%%"=>"$L_NS1_HOSTNAME",
"%%ns2%%"=>"$L_NS2_HOSTNAME",
@ -392,7 +419,7 @@ class system_bind {
}
// Save file, and apply chmod/chown
$file=$this->get_zone_file_uri($domain);
$file = $this->get_zone_file_uri($domain);
file_put_contents($file, $this->get_zone($domain));
chown($file, 'bind');
chmod($file, 0640);
@ -408,7 +435,7 @@ class system_bind {
* @return boolean
*/
function delete_zone($domain) {
$file=$this->get_zone_file_uri($domain);
$file = $this->get_zone_file_uri($domain);
if (file_exists($file)) {
unlink($file);
}
@ -424,15 +451,15 @@ class system_bind {
function reload_named() {
global $hooks;
// Generate the new conf file
$new_named_conf="// DO NOT EDIT\n// This file is generated by Alternc.\n// Every changes you'll make will be overwrited.\n";
$tpl=file_get_contents($this->NAMED_TEMPLATE);
$new_named_conf = "// DO NOT EDIT\n// This file is generated by Alternc.\n// Every changes you'll make will be overwrited.\n";
$tpl = file_get_contents($this->NAMED_TEMPLATE);
foreach ($this->get_domain_summary() as $domain => $ds ) {
if ( ! $ds['gesdns'] || strtoupper($ds['dns_action']) == 'DELETE' ) continue;
$new_named_conf.=strtr($tpl, array("@@DOMAINE@@"=>$domain, "@@ZONE_FILE@@"=>$this->get_zone_file_uri($domain)));
$new_named_conf .= strtr($tpl, array("@@DOMAINE@@"=>$domain, "@@ZONE_FILE@@"=>$this->get_zone_file_uri($domain)));
}
// Get the actual conf file
$old_named_conf = @file_get_contents($this->NAMED_CONF);
$old_named_conf = @file_get_contents($this->NAMED_CONF);
// Apply new configuration only if there are some differences
if ($old_named_conf != $new_named_conf ) {

View File

@ -0,0 +1,22 @@
<?php
/**
* Console aware class, encapsulates the Console CommandLine class
*/
class Alternc_Diagnostic_Console extends Console_CommandLine{
const DESCRIPTION = "Handles diagnostics of an alternc server.";
const VERSION = "0.1";
function __construct(array $params = array()) {
$params = array(
'description' => self::DESCRIPTION,
'version' => self::VERSION
);
parent::__construct($params);
}
}

View File

@ -0,0 +1,118 @@
<?php
/**
* Uniform data component containing other components or real data
*/
class Alternc_Diagnostic_Data {
public $index = array();
public $data = array();
public $type = "";
public $metadata = null;
const TYPE_ROOT = "root";
const TYPE_DOMAIN = "service";
const TYPE_SECTION = "section";
public function __construct( $type, $sectionData = null) {
$this->type = $type;
if( $sectionData){
$this->data = $sectionData;
}
}
/**
* Sets
*
* @param string $sectionname
* @param Alternc_Diagnostic_Data $data
* @return boolean
*/
function addData( $sectionname, Alternc_Diagnostic_Data $data){
$this->index[] = $sectionname;
$this->data[$sectionname] = $data;
return true;
}
/**
* @param array index
*/
public function setIndex($index) {
$this->index = $index;
return $this;
}
/**
* @return array
*/
public function getIndex() {
return $this->index;
}
/**
* @param array data
*/
public function setData($data) {
$this->data = $data;
return $this;
}
/**
* @return array
*/
public function getData() {
return $this->data;
}
/**
* @param string type
*/
public function setType($type) {
$this->type = $type;
return $this;
}
/**
* @return string
*/
public function getType() {
return $this->type;
}
/**
* @param array metadata
*/
public function setMetadata($metadata) {
$this->metadata = $metadata;
return $this;
}
/**
* @return array
*/
public function getMetadata() {
return $this->metadata;
}
/**
* Retrieves a given section of the data
*
*
* @param string $section_name
* @return boolean
*/
public function getSection( $section_name ){
if( !in_array($section_name, $this->index)){
return FALSE;
}
return $this->data[$section_name];
}
}

View File

@ -0,0 +1,28 @@
<?php
class Alternc_Diagnostic_Diff{
/**
*
* @param type $file_reference_1
* Either a number or a string refering to the file
* Default = Last file
* @param type $file_reference_2
* Either a number or a string refering to the file
* Default = pre-last file
*/
function compare($file_reference_1, $file_reference_2){
}
/**
* Finds a file by reference or name
*
* @param string $file_reference
* @return Alternc_Diagnostic_Data Resulting data
*/
function resolve( $file_reference){
}
}

View File

@ -0,0 +1,50 @@
<?php
class Alternc_Diagnostic_Directory {
/**
* Location of diagnostic files
*
* @var string
*/
protected $file_path;
public function __construct( $file_path) {
if( null == $file_path){
throw new \Exception("Empty file_path in Diagnostic Format handler");
}
if( !file_exists($file_path)){
if( !mkdir($file_path, 0774, true)){
throw new \Exception("Could not access path $file_path in Diagnostic Format handler");
}
}
$this->file_path = $file_path;
}
function getList( $max = null){
$dir = new DirectoryIterator($this->file_path);
}
/**
* @param string file_path
*/
public function setFile_path($file_path) {
$this->file_path = $file_path;
return $this;
}
/**
* @return string
*/
public function getFile_path() {
if( null == $this->file_path){
throw new \Exception("Missing property 'file_path' in format instance");
}
return $this->file_path;
}
}

View File

@ -0,0 +1,88 @@
<?php
class Alternc_Diagnostic_Format_Abstract {
/**
*
* @var Alternc_Diagnostic_Data
*/
public $data;
/**
*
* @var Alternc_Diagnostic_Directory
*/
public $directory;
/**
* Files extension for the format
*
* @var string
*/
protected $extension;
/**
* @param string extension
*/
public function setExtension($extension) {
$this->extension = $extension;
return $this;
}
/**
* @return string
*/
public function getExtension() {
return $this->extension;
}
public function __construct(Alternc_Diagnostic_Directory $directory) {
$this->directory = $directory;
}
/**
* @param Alternc_Diagnostic_Data data
*/
public function setData(Alternc_Diagnostic_Data $data) {
$this->data = $data;
return $this;
}
/**
* @return Alternc_Diagnostic_Data
*/
public function getData() {
if(is_null($this->data)){
throw new \Exception("Missing property 'data' in format instance");
}
return $this->data;
}
public function getFilename(){
return $this->getDirectory()->getFile_path()."/".time().".".$this->getExtension();
}
/**
* @param Alternc_Diagnostic_Directory directory
*/
public function setDirectory($directory) {
$this->directory = $directory;
return $this;
}
/**
* @return Alternc_Diagnostic_Directory
*/
public function getDirectory() {
if( null == $this->directory){
throw new \Exception("Missing property 'directory' in format instance");
}
return $this->directory;
}
}

View File

@ -0,0 +1,21 @@
<?php
interface Alternc_Diagnostic_Format_Interface{
/**
*
* @param mixed $file_reference
* Either a number or a string refering to the file
* @return Alternc_Diagnostic_Data A diagnostic file
*/
function read( $file_reference );
/**
* Writes a Data object to file
*
* @return boolean
*/
function write();
}

View File

@ -0,0 +1,47 @@
<?php
/**
* JSON implementation of the format interface : writes, reads, compares
*/
class Alternc_Diagnostic_Format_Json
extends Alternc_Diagnostic_Format_Abstract
implements Alternc_Diagnostic_Format_Interface
{
/**
* @inherit
*/
public function __construct(Alternc_Diagnostic_Directory $directory) {
parent::__construct($directory);
$this->setExtension("json");
}
/**
* @inherit
*/
function read( $file_reference ){
}
/**
* @inherit
*/
function write(Alternc_Diagnostic_Data $data = null ){
if( $data ){
$this->setData($data);
}
$file_content = json_encode($this->getData());
$filename = $this->getFilename();
if(json_last_error()){
throw new \Exception("Json conversion failed with error #".json_last_error()."for data".serialize($this->getData()));
}
if( ! file_put_contents($filename, $file_content) ){
throw new \Exception("Failed to write in json format to file $filename for data".serialize($this->getData()));
}
return true;
}
}

View File

@ -0,0 +1,86 @@
<?php
/**
* Central service which provides the glue and intelligence for all parts
*/
class Alternc_Diagnostic_Manager{
/**
* @var Alternc_Diagnost_Format_Abstract
*/
public $formatInstance;
/**
* @var Alternc_Diagnost_Directory
*/
public $directoryInstance;
/** @var string the Alternc version */
public $version;
/**
* Constructor with dependancy injection
*
* @param array $options
* @throws \Exception
*/
public function __construct($options) {
// Attempts to retrieve formatInstance
if (isset($options["formatInstance"]) && ! is_null($options["formatInstance"])) {
$this->formatInstance = $options["formatInstance"];
} else {
throw new \Exception("Missing parameter formatInstance");
}
// Attempts to retrieve directoryInstance
if (isset($options["directoryInstance"]) && ! is_null($options["directoryInstance"])) {
$this->directoryInstance = $options["directoryInstance"];
} else {
throw new \Exception("Missing parameter directoryInstance");
}
// Attempts to retrieve version
if (isset($options["version"]) && ! is_null($options["version"])) {
$this->version = $options["version"];
} else {
throw new \Exception("Missing parameter version");
}
}
/**
* Controls the diagnostics creation
*
* @param Console_CommandLine_Result $options
* @throws \Exception
*/
function create(Console_CommandLine_Result $options){
$args = $options->args;
$options = $options->options;
$diagnosticData = new Alternc_Diagnostic_Data(Alternc_Diagnostic_Data::TYPE_ROOT);
$serviceList = explode(',',$options["services"]);
foreach ($serviceList as $service) {
$class_name = "Alternc_Diagnostic_Service_".trim(ucfirst($service));
if(!class_exists($class_name)){
throw new \Exception("Invalid service $service");
}
/** @var Alternc_Diagnostic_Service_Interface */
$serviceAgent = new $class_name( array("service" => $this) );
// Runs the service agent and store the results
$diagnosticData->addData($serviceAgent->name, $serviceAgent->run());
}
$this->formatInstance->setData($diagnosticData)->write();
}
function compare( $options ){}
function index( $options ){}
function show( $options ){}
function delete( $options ){}
}

View File

@ -0,0 +1,220 @@
<?php
/**
* This abstract defines properties and provides helpers to service classes
*
*/
abstract class Alternc_Diagnostic_Service_Abstract{
/** @var Alternc_Diagnostic_Data*/
protected $data;
/** @var DB_Sql*/
public $db;
/** @var m_mysql */
protected $mysql;
/** @var m_mem */
protected $mem;
/** @var m_admin */
protected $admin;
/** @var m_authip */
protected $authip;
/** @var m_cron */
protected $cron;
/** @var m_dom */
protected $dom;
/** @var m_ftp */
protected $ftp;
/** @var m_hta */
protected $hta;
/** @var m_mail */
protected $mail;
/** @var m_quota */
protected $quota;
/** @var Alternc_Diagnostic_Service */
protected $service;
public function __construct( $options ) {
$this->data = new Alternc_Diagnostic_Data(Alternc_Diagnostic_Data::TYPE_DOMAIN);
global $db;
$this->db = $db;
global $mem;
$this->mem = $mem;
global $mysql;
$this->mysql = $mysql;
global $quota;
$this->quota= $quota;
global $mail;
$this->mail= $mail;
global $hta;
$this->hta= $hta;
global $ftp;
$this->ftp= $ftp;
global $dom;
$this->dom= $dom;
global $cron;
$this->cron= $cron;
global $authip;
$this->authip= $authip;
global $admin;
$this->admin= $admin;
if( array_key_exists("service",$options) && is_object($options["service"] ) ){
$this->service = $options["service"];
}
}
/**
*
* @param string $cmd
* @return array
* @throws \Exception
*/
protected function execCmd( $cmd ){
exec(escapeshellcmd("$cmd")." 2>&1", $output, $return_var);
if( 0 != $return_var ){
throw new \Exception("Invalid return for command $cmd returned error code #$return_var with output :". json_encode($output));
}
return $output;
}
/**
* Filters lines of a result to only include the matching lines
*
* @param string $pattern
* @param array $result
* @return type
*/
protected function filterRegexp($result,$pattern){
$returnArray = array();
foreach ($result as $line) {
$captures_count = preg_match($pattern, $line, $matches);
if($captures_count){
array_shift($matches);
$returnArray[] = implode(" ", $matches);
}
}
return $returnArray;
}
/**
* @param Alternc_Diagnostic_Data data
*/
public function setData($data) {
$this->data = $data;
return $this;
}
/**
* @return Alternc_Diagnostic_Data
*/
public function getData() {
return $this->data;
}
/**
* Utility for filling the service agent data holder
*
* @param string $name
* @param mixed $content
* @return boolean
*/
function writeSectionData( $name, $content){
$section = new Alternc_Diagnostic_Data(Alternc_Diagnostic_Data::TYPE_SECTION,$content);
$this->data->addData($name, $section);
return true;
}
/**
* Reads an array of URL and returns the CURL results
*
* @param array $urlList
* @param array $fieldsList curlInfo array keys
* @param int $sockets_max
* @return array
*/
function curlRequest($urlList,$fieldsList = array("http_code","url"),$sockets_max = 8){
$returnArray = array();
// Attempts to retrive a multi connection curl handle
$multiCurlHandle = curl_multi_init();
for ($index = 0; $index < $sockets_max; $index++) {
$ch = "ch".$index;
$$ch = curl_init();
curl_setopt($$ch, CURLOPT_HEADER, 1);
curl_setopt($$ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($$ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($$ch, CURLOPT_TIMEOUT, 3);
curl_setopt($$ch, CURLOPT_NOBODY, 1);
curl_multi_add_handle($multiCurlHandle,$$ch);
}
$url_count = count($urlList);
$url_pointer = 0;
while( $url_pointer < $url_count){
$sockets = $url_count - $url_pointer > $sockets_max ? $sockets_max : $url_count - $url_pointer ;
$loopUrlList = array();
for ($index2 = 0; $index2 < $sockets; $index2++) {
$ch = "ch".$index2;
$url = $urlList[$url_pointer];
$loopUrlList[$index2] = $url;
curl_setopt($$ch, CURLOPT_URL, $url);
$url_pointer++;
}
do {
curl_multi_exec($multiCurlHandle, $running);
curl_multi_select($multiCurlHandle);
} while ($running > 0);
for ($index3 = 0; $index3 < $sockets; $index3++) {
$ch = "ch".$index3;
$url = $loopUrlList[$index3];
$curlInfo = curl_getinfo($$ch);
$urlInfo = array();
foreach ($fieldsList as $field) {
$urlInfo[$field] = $curlInfo[$field];
}
$returnArray[] = $urlInfo;
}
}
//close the handles
curl_multi_close($multiCurlHandle);
for ($index = 0; $index < $sockets_max; $index++) {
$ch = "ch".$index;
curl_close($$ch);
}
return $returnArray;
}
}

View File

@ -0,0 +1,77 @@
<?php
/**
* Lists vhosts
* Lists redirections
* Checks vhosts
* Checks redirections
*/
class Alternc_Diagnostic_Service_Apache2
extends Alternc_Diagnostic_Service_Abstract
implements Alternc_Diagnostic_Service_Interface
{
public $name = "apache2";
const SECTION_VHOSTS = "vhosts";
const SECTION_MODULES = "modules";
const SECTION_REDIRECTIONS = "redirections";
const SECTION_RESPONSES = "responses";
function run(){
// Writes the modules
$this->writeSectionData (self::SECTION_MODULES,$this->filterRegexp ($this->execCmd("apache2ctl -M"), "/^[\W]*(\w+).*\(.*$/u" ));
// Writes the vhosts in the form "port servername"
$this->writeSectionData (self::SECTION_VHOSTS,$this->getVhosts());
// Writes the redirects
$this->writeSectionData (self::SECTION_REDIRECTIONS, $this->getRedirects());
// Writes the tests
$this->writeSectionData (self::SECTION_RESPONSES,$this->testServers());
return $this->data;
}
function getVhosts(){
$list = $this->filterRegexp( $this->execCmd("apache2ctl -S"), "/^[\D]*(\d{2,4}).* (.*) \(\/.*$/u");
$returnArray = array();
foreach( $list as $vhost){
$returnArray[] = explode(" ",$vhost);
}
return $returnArray;
}
function getRedirects(){
$mysqlResource = $this->db->query("SELECT domaine as domain, valeur as url from sub_domaines where type='url';");
$resultArray = array();
if ($this->db->num_rows()) {
while(($resultArray[] = mysql_fetch_assoc($mysqlResource)) || array_pop($resultArray));
}
return $resultArray;
}
function testServers(){
$sockets_max = 8;
$fieldsList = array("http_code","url");
$vhostUrlList = array();
// Retrieves and tests local vhosts
$vhostList = $this->data->getSection(self::SECTION_VHOSTS)->getData();
foreach( $vhostList as $vhostInfo){
$protocol = $vhostInfo[0] == 443 ? "https://":"http://";
$vhostUrlList[] = "{$protocol}{$vhostInfo[1]}";
}
$vhostResult = $this->curlRequest($vhostUrlList,$fieldsList,$sockets_max);
// Retrieves and tests local redirs
$redirList = $this->data->getSection(self::SECTION_REDIRECTIONS)->getData();
foreach( $redirList as $redirInfo){
$redirUrlList[] = $redirInfo["url"];
}
$redirResult = $this->curlRequest($redirUrlList,$fieldsList,$sockets_max);
return array_merge($vhostResult,$redirResult);
}
}

View File

@ -0,0 +1,189 @@
<?php
/**
* List domains
* Check domains
* domains response
* zones locked
* slaves
*/
class Alternc_Diagnostic_Service_Dns
extends Alternc_Diagnostic_Service_Abstract
implements Alternc_Diagnostic_Service_Interface
{
public $name = "dns";
/** @var array */
protected $domainList;
/** @var array */
protected $zonesList;
/** var system_bind */
protected $bind;
const SECTION_LIST = "list";
const SECTION_HOST = "host";
const SECTION_NAMESERVERS = "nameservers";
const SECTION_ZONES = "zones";
const SECTION_ZONES_LOCKED = "zones_locked";
const SECTION_SLAVES = "slaves";
function run(){
/** @var m_dom */
global $dom;
$version = $this->service->version;
if( $version < 3.2 ) {
$this->bind = new system_bind(array(
"zone_file_directory" => "/var/alternc/bind/zones/"));
$this->domainList = $this->get_domain_all_summary();
}else{
$this->bind = new system_bind();
$this->domainList = $dom->get_domain_all_summary();
}
// Attempts to retrieve zone list
$this->zonesList = $this->getZonesList();
// Writes the dns slaves
$this->writeSectionData (self::SECTION_SLAVES,$this->getSlaves());
// Writes the domains list
$this->writeSectionData (self::SECTION_LIST,$this->domainList);
// Writes the domains hosts
$this->writeSectionData (self::SECTION_HOST, $this->getHosts());
// Writes the domains nameservers
$this->writeSectionData (self::SECTION_NAMESERVERS,$this->getNameservers());
// Writes the domains zones
$this->writeSectionData (self::SECTION_ZONES,$this->zonesList);
// Writes the domains zones locked
$this->writeSectionData (self::SECTION_ZONES_LOCKED,$this->getZonesLocked());
// Writes the domains zones with custom records
$this->writeSectionData (self::SECTION_ZONES_LOCKED,$this->getZonesCustomRecords());
return $this->data;
}
/**
* Local override if not available (1.0)
* @return array
*/
function get_domain_all_summary() {
global $db, $err;
$res = array();
$db->query("SELECT domaine, gesdns, gesmx, dns_action FROM domaines ORDER BY domaine");
while ($db->next_record()) {
$res[$db->f("domaine")] = array(
"gesdns" => $db->f("gesdns"),
"gesmx" => $db->f("gesmx"),
"dns_action" => $db->f("dns_action"),
);
}
return $res;
}
/**
* Lists domains `host $DOMAIN` data
* @return array
*/
function getHosts(){
$resultArray = array();
foreach ($this->domainList as $domain => $domainInfo) {
try{
$resultArray[$domain] = $this->execCmd("host {$domain}");
}catch( \Exception $e){
echo $e->getMessage()."\n";
}
}
return $resultArray;
}
/**
* Lists domains NS
*
* @return array
*/
function getNameservers(){
$resultArray = array();
foreach ($this->domainList as $domain => $domainInfo) {
try{
$resultArray[$domain] = $this->execCmd("dig NS {$domain} +short");
}catch( \Exception $e){
echo $e->getMessage()."\n";
}
}
return $resultArray;
}
/**
* Lists zones content
*
* @return array
*/
function getZonesList(){
$resultArray = array();
foreach ($this->domainList as $domain => $domainInfo) {
try{
$resultArray[$domain] = $this->bind->get_zone_file($domain);
}catch( \Exception $e){
echo $e->getMessage()."\n";
}
}
return $resultArray;
}
/**
* Lists which domains zones are locked
*
* @return array
*/
function getZonesLocked(){
$resultArray = array();
foreach ($this->domainList as $domain => $domainInfo) {
try{
$resultArray[$domain] = $this->bind->is_locked($domain);
}catch( \Exception $e){
echo $e->getMessage()."\n";
}
}
return $resultArray;
}
/**
* Lists which domains zones have custom records
*
* @return array
*/
function getZonesCustomRecords(){
$resultArray = array();
$regexp = ";;; END ALTERNC AUTOGENERATE CONFIGURATION\n(.+\w+.+)";
foreach ($this->zonesList as $domain => $zone) {
$is_custom = false;
try{
if(preg_match("/$regexp/ms", $zone, $matches)){
$is_custom = $matches[1];
}
}catch( \Exception $e){
echo $e->getMessage()."\n";
}
$resultArray[$domain] = $is_custom;
}
return $resultArray;
}
/**
* Lists servers DNS slaves accounts
*
* @return array
*/
function getSlaves(){
return $this->dom->enum_slave_account();
}
}

View File

@ -0,0 +1,69 @@
<?php
/**
* Lists accounts
* Checks root
*/
class Alternc_Diagnostic_Service_Ftp
extends Alternc_Diagnostic_Service_Abstract
implements Alternc_Diagnostic_Service_Interface
{
public $name = "ftp";
// /** @var m_ftp */
// protected $ftp;
/** @var array */
protected $ftpList;
const SECTION_LIST = "list";
const SECTION_CHECK_HOMEDIR = "check_homedir";
function run(){
$this->ftpList = $this->get_list();
// Writes the domains list
$this->writeSectionData (self::SECTION_LIST,$this->ftpList);
// Checks the homedir existence
$this->writeSectionData (self::SECTION_CHECK_HOMEDIR, $this->checkHomeDir());
return $this->data;
}
function checkHomeDir() {
$returnArray = array();
foreach( $this->ftpList as $login => $ftpData){
$exists = false;
$homedir = $ftpData["dir"];
if(is_dir($homedir) ){
$exists = true;
}
$returnArray[$login] = $exists;
}
return $returnArray;
}
function get_list() {
$returnArray = array();
$this->db->query("SELECT id, name, homedir, enabled FROM ftpusers ORDER BY name;");
if ($this->db->num_rows()) {
while ($this->db->next_record()) {
$returnArray[$this->db->f("name")]=array(
"enabled" => $this->db->f("enabled"),
"dir" => $this->db->f("homedir")
);
}
}
return $returnArray;
}
}

View File

@ -0,0 +1,11 @@
<?php
/**
*
*/
interface Alternc_Diagnostic_Service_Interface{
function run();
}

View File

@ -0,0 +1,119 @@
<?php
/**
* Lists emails
* Stats pop / alias
* Checks SMTP / SIEVE
*/
class Alternc_Diagnostic_Service_Mail
extends Alternc_Diagnostic_Service_Abstract
implements Alternc_Diagnostic_Service_Interface
{
public $name = "email";
protected $mailList = array();
const SECTION_LIST = "list";
const SECTION_STAT_ALIAS = "stat_alias";
const SECTION_CHECK_STORAGE = "check_storage";
function run(){
// Attempts to retrieve all email addresses
$this->mailList = $this->getList();
// Writes the domains list
$this->writeSectionData (self::SECTION_LIST,$this->getList());
// Writes the alias stats
$this->writeSectionData (self::SECTION_STAT_ALIAS,$this->getStatAlias());
// Writes the quota stats
$this->writeSectionData (self::SECTION_CHECK_STORAGE,$this->getCheckStorage());
return $this->data;
}
/**
* Gets list from db
*
* @return array
*/
function getList(){
$returnArray = array();
// Check the availability
$this->db->query('
SELECT CONCAT(a.address,"@",d.domaine) as email, a.type, a.enabled, r.recipients, m.path,m.quota,m.bytes/(1024*1024) as size_mo,m.messages
FROM address a
LEFT JOIN recipient r ON r.address_id = a.id
LEFT JOIN mailbox m ON m.address_id = a.id
JOIN domaines d ON a.domain_id = d.id;');
if ($this->db->num_rows()) {
while ($this->db->next_record()) {
$email = $this->db->f("email");
$returnArray[$email] = array(
"enabled" => $this->db->f("enabled"),
"type" => $this->db->f("type"),
"recipients" => $this->db->f("recipients"),
"path" => $this->db->f("path"),
"quota" => $this->db->f("quota"),
"size_mo" => $this->db->f("size_mo"),
"messages" => $this->db->f("messages"),
);
}
}
return $returnArray;
}
/**
* Searches mails with alias
*
* @return array
*/
function getStatAlias() {
$returnArray = array();
foreach ($this->mailList as $email => $emailInfo) {
$is_alias = false;
if( !is_null($emailInfo["recipients"])){
$is_alias = true;
}
$returnArray[$email] = $is_alias;
}
return $returnArray;
}
/**
* Checks the box oversize and effective existence
*
* @return array
*/
function getCheckStorage() {
$returnArray = array();
foreach ($this->mailList as $email => $emailInfo) {
// Only account real boxes
if( ! $emailInfo["path"]){
continue;
}
$quota_pct = "0";
$box_exists = true;
$quota = $emailInfo["quota"];
$size_mo = $emailInfo["size_mo"] ;
if( $quota > 0 ){
$quota_pct = $size_mo * 100 / $quota;
}
if( !is_dir($emailInfo["path"]) ){
$box_exists = false;
}
$returnArray[$email] = array(
"percent" => number_format($quota_pct, 2),
"box_exists" => $box_exists
);
}
return $returnArray;
}
}

View File

@ -0,0 +1,16 @@
<?php
/**
* Lists mailing lists
*/
class Alternc_Diagnostic_Service_Mailman
extends Alternc_Diagnostic_Service_Abstract
implements Alternc_Diagnostic_Service_Interface
{
public $name = "mailman";
function run(){
return $this->data;
}
}

View File

@ -0,0 +1,168 @@
<?php
/**
* Lists databases
* Lists users
*/
class Alternc_Diagnostic_Service_Mysql
extends Alternc_Diagnostic_Service_Abstract
implements Alternc_Diagnostic_Service_Interface {
public $name = "mysql";
protected $dbList;
protected $usersList;
protected $serversList;
const SECTION_DB_LIST = "dbs_list";
const SECTION_USER_LIST = "users_list";
const SECTION_SERVERS_LIST = "servers_list";
const SECTION_STAT_SIZE = "stat_size";
const SECTION_CHECK_ACCESS = "check_access";
/**
*
* @inherit
*/
function run() {
$this->dbList = $this->getDbList();
$this->usersList = $this->getUsersList();
$this->serversList = $this->getServersList();
// Writes the mysql db list
$this->writeSectionData(self::SECTION_DB_LIST, $this->dbList);
// Writes the mysql user list
$this->writeSectionData(self::SECTION_USER_LIST, $this->usersList);
// Writes the mysql servers list
$this->writeSectionData(self::SECTION_SERVERS_LIST, $this->serversList);
// Writes the mysql size stats
$this->writeSectionData(self::SECTION_STAT_SIZE, $this->getSizeStats());
// Writes the mysql access check
$this->writeSectionData(self::SECTION_CHECK_ACCESS, $this->getCheckAccess());
return $this->data;
}
/**
* Returns a db_name -> dbInfo array
*
* @return array
*/
function getDbList() {
$returnArray = array();
$this->db->query("SELECT login,pass,db, bck_mode, bck_dir FROM db ORDER BY db;");
if ($this->db->num_rows()) {
while ($this->db->next_record()) {
$db = $this->db->f("db");
list($dbu,$dbn) = split_mysql_database_name($db);
$returnArray[$db] = array(
"user" => $dbu,
"bck_mode" => $this->db->f("bck_mode"),
"bck_dir" => $this->db->f("bck_dir"),
"login" => $this->db->f("login"),
"pass" => $this->db->f("pass")
);
}
}
return $returnArray;
}
/**
* Returns a db_user_name -> dbUserInfo array
*
* @return array
*/
function getUsersList() {
$returnArray = array();
$this->db->query("SELECT name, password, enable FROM dbusers ORDER BY name;");
if ($this->db->num_rows()) {
while ($this->db->next_record()) {
$returnArray[$this->db->f("name")] = array(
"enable" => $this->db->f("enable"),
"password" => $this->db->f("password")
);
}
}
return $returnArray;
}
/**
* Returns a server_name -> serverInfo array
*
* @return array
*/
function getServersList() {
$returnArray = array();
$this->db->query("SELECT name, host, login, password FROM db_servers ORDER BY host;");
if ($this->db->num_rows()) {
while ($this->db->next_record()) {
$returnArray[$this->db->f("name")] = array(
"host" => $this->db->f("host"),
"login" => $this->db->f("login"),
"password" => $this->db->f("password")
);
}
}
return $returnArray;
}
/**
* Returns a db_name -> db_size array
*
* @return array
*/
function getSizeStats(){
$returnArray = array();
global $L_MYSQL_LOGIN, $L_MYSQL_HOST, $L_MYSQL_PWD;
$db = new DB_Sql();
$db->Host = $L_MYSQL_HOST;
$db->User = $L_MYSQL_LOGIN;
$db->Password = $L_MYSQL_PWD;
$db->Database = "mysql";
foreach ($this->dbList as $dbname => $dbInfo) {
$db->query("SHOW TABLE STATUS FROM `$dbname`;");
$size = 0;
while ($db->next_record()) {
$size += $db->f('Data_length') + $db->f('Index_length');
if ( $db->f('Engine') != 'InnoDB') $size += $db->f('Data_free');
}
$returnArray[$dbname] = $size;
}
return $returnArray;
}
/**
* Returns a user_name -> has_access array
*
* @return array
*/
function getCheckAccess(){
$returnArray = array();
global $L_MYSQL_LOGIN, $L_MYSQL_HOST, $L_MYSQL_PWD;
$db = new DB_Sql();
$db->Host = $L_MYSQL_HOST;
$db->User = $L_MYSQL_LOGIN;
$db->Password = $L_MYSQL_PWD;
$db->Database = "mysql";
foreach ($this->usersList as $user => $userInfo) {
$has_access = false;
$password = $userInfo["password"];
$db->query("SELECT FROM user where user='".$user."' and password=PASSWORD('".$password."') ORDER BY host;");
if ($this->db->num_rows()) {
$has_access = true;
}
$returnArray[$user] = $has_access;
}
return $returnArray;
}
}

View File

@ -0,0 +1,16 @@
<?php
/**
* Lists members
*/
class Alternc_Diagnostic_Service_Panel
extends Alternc_Diagnostic_Service_Abstract
implements Alternc_Diagnostic_Service_Interface
{
public $name = "panel";
function run(){
return $this->data;
}
}

View File

@ -0,0 +1,17 @@
<?php
/**
* Lists versions : php mysql posfix dovecot roundcubke squirrelmail courier mailman alternc-* acl quota sasl
*
*/
class Alternc_Diagnostic_Service_System
extends Alternc_Diagnostic_Service_Abstract
implements Alternc_Diagnostic_Service_Interface
{
public $name = "system";
function run(){
$this->writeSectionData("ip list", $this->execCmd("ip a"));
return $this->data;
}
}

1289
lib/Console/CommandLine.php Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,142 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This file is part of the PEAR Console_CommandLine package.
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT license that is available
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_CommandLine
* @since File available since release 0.1.0
* @filesource
*/
/**
* Class that represent an option action.
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version Release: 1.2.0
* @link http://pear.php.net/package/Console_CommandLine
* @since Class available since release 0.1.0
*/
abstract class Console_CommandLine_Action
{
// Properties {{{
/**
* A reference to the result instance.
*
* @var Console_CommandLine_Result $result The result instance
*/
protected $result;
/**
* A reference to the option instance.
*
* @var Console_CommandLine_Option $option The action option
*/
protected $option;
/**
* A reference to the parser instance.
*
* @var Console_CommandLine $parser The parser
*/
protected $parser;
// }}}
// __construct() {{{
/**
* Constructor
*
* @param Console_CommandLine_Result $result The result instance
* @param Console_CommandLine_Option $option The action option
* @param Console_CommandLine $parser The current parser
*
* @return void
*/
public function __construct($result, $option, $parser)
{
$this->result = $result;
$this->option = $option;
$this->parser = $parser;
}
// }}}
// getResult() {{{
/**
* Convenience method to retrieve the value of result->options[name].
*
* @return mixed The result value or null
*/
public function getResult()
{
if (isset($this->result->options[$this->option->name])) {
return $this->result->options[$this->option->name];
}
return null;
}
// }}}
// format() {{{
/**
* Allow a value to be pre-formatted prior to being used in a choices test.
* Setting $value to the new format will keep the formatting.
*
* @param mixed &$value The value to format
*
* @return mixed The formatted value
*/
public function format(&$value)
{
return $value;
}
// }}}
// setResult() {{{
/**
* Convenience method to assign the result->options[name] value.
*
* @param mixed $result The result value
*
* @return void
*/
public function setResult($result)
{
$this->result->options[$this->option->name] = $result;
}
// }}}
// execute() {{{
/**
* Executes the action with the value entered by the user.
* All children actions must implement this method.
*
* @param mixed $value The option value
* @param array $params An optional array of parameters
*
* @return string
*/
abstract public function execute($value = false, $params = array());
// }}}
}

View File

@ -0,0 +1,80 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This file is part of the PEAR Console_CommandLine package.
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT license that is available
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_CommandLine
* @since File available since release 0.1.0
* @filesource
*/
/**
* Required by this class.
*/
require_once 'Console/CommandLine/Action.php';
/**
* Class that represent the Callback action.
*
* The result option array entry value is set to the return value of the
* callback defined in the option.
*
* There are two steps to defining a callback option:
* - define the option itself using the callback action
* - write the callback; this is a function (or method) that takes five
* arguments, as described below.
*
* All callbacks are called as follows:
* <code>
* callable_func(
* $value, // the value of the option
* $option_instance, // the option instance
* $result_instance, // the result instance
* $parser_instance, // the parser instance
* $params // an array of params as specified in the option
* );
* </code>
* and *must* return the option value.
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version Release: 1.2.0
* @link http://pear.php.net/package/Console_CommandLine
* @since Class available since release 0.1.0
*/
class Console_CommandLine_Action_Callback extends Console_CommandLine_Action
{
// execute() {{{
/**
* Executes the action with the value entered by the user.
*
* @param mixed $value The value of the option
* @param array $params An optional array of parameters
*
* @return string
*/
public function execute($value = false, $params = array())
{
$this->setResult(call_user_func($this->option->callback, $value,
$this->option, $this->result, $this->parser, $params));
}
// }}}
}

View File

@ -0,0 +1,86 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This file is part of the PEAR Console_CommandLine package.
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT license that is available
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_CommandLine
* @since File available since release 0.1.0
* @filesource
*/
/**
* Required by this class.
*/
require_once 'Console/CommandLine/Action.php';
/**
* Class that represent the Version action.
*
* The execute methode add 1 to the value of the result option array entry.
* The value is incremented each time the option is found, for example
* with an option defined like that:
*
* <code>
* $parser->addOption(
* 'verbose',
* array(
* 'short_name' => '-v',
* 'action' => 'Counter'
* )
* );
* </code>
* If the user type:
* <code>
* $ script.php -v -v -v
* </code>
* or:
* <code>
* $ script.php -vvv
* </code>
* the verbose variable will be set to to 3.
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version Release: 1.2.0
* @link http://pear.php.net/package/Console_CommandLine
* @since Class available since release 0.1.0
*/
class Console_CommandLine_Action_Counter extends Console_CommandLine_Action
{
// execute() {{{
/**
* Executes the action with the value entered by the user.
*
* @param mixed $value The option value
* @param array $params An optional array of parameters
*
* @return string
*/
public function execute($value = false, $params = array())
{
$result = $this->getResult();
if ($result === null) {
$result = 0;
}
$this->setResult(++$result);
}
// }}}
}

View File

@ -0,0 +1,60 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This file is part of the PEAR Console_CommandLine package.
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT license that is available
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_CommandLine
* @since File available since release 0.1.0
* @filesource
*/
/**
* Required by this class.
*/
require_once 'Console/CommandLine/Action.php';
/**
* Class that represent the Help action, a special action that displays the
* help message, telling the user how to use the program.
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version Release: 1.2.0
* @link http://pear.php.net/package/Console_CommandLine
* @since Class available since release 0.1.0
*/
class Console_CommandLine_Action_Help extends Console_CommandLine_Action
{
// execute() {{{
/**
* Executes the action with the value entered by the user.
*
* @param mixed $value The option value
* @param array $params An optional array of parameters
*
* @return string
*/
public function execute($value = false, $params = array())
{
return $this->parser->displayUsage();
}
// }}}
}

View File

@ -0,0 +1,73 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This file is part of the PEAR Console_CommandLine package.
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT license that is available
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_CommandLine
* @since File available since release 0.1.0
* @filesource
*/
/**
* Required by this class.
*/
require_once 'Console/CommandLine/Action.php';
/**
* Class that represent the List action, a special action that simply output an
* array as a list.
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version Release: 1.2.0
* @link http://pear.php.net/package/Console_CommandLine
* @since Class available since release 0.1.0
*/
class Console_CommandLine_Action_List extends Console_CommandLine_Action
{
// execute() {{{
/**
* Executes the action with the value entered by the user.
* Possible parameters are:
* - message: an alternative message to display instead of the default
* message,
* - delimiter: an alternative delimiter instead of the comma,
* - post: a string to append after the message (default is the new line
* char).
*
* @param mixed $value The option value
* @param array $params An optional array of parameters
*
* @return string
*/
public function execute($value = false, $params = array())
{
$list = isset($params['list']) ? $params['list'] : array();
$msg = isset($params['message'])
? $params['message']
: $this->parser->message_provider->get('LIST_DISPLAYED_MESSAGE');
$del = isset($params['delimiter']) ? $params['delimiter'] : ', ';
$post = isset($params['post']) ? $params['post'] : "\n";
$this->parser->outputter->stdout($msg . implode($del, $list) . $post);
exit(0);
}
// }}}
}

View File

@ -0,0 +1,90 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This file is part of the PEAR Console_CommandLine package.
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT license that is available
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_CommandLine
* @since File available since release 0.1.0
* @filesource
*/
/**
* Required by this class.
*/
require_once 'Console/CommandLine/Action.php';
/**
* Class that represent the Password action, a special action that allow the
* user to specify the password on the commandline or to be prompted for
* entering it.
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version Release: 1.2.0
* @link http://pear.php.net/package/Console_CommandLine
* @since Class available since release 0.1.0
*/
class Console_CommandLine_Action_Password extends Console_CommandLine_Action
{
// execute() {{{
/**
* Executes the action with the value entered by the user.
*
* @param mixed $value The option value
* @param array $params An array of optional parameters
*
* @return string
*/
public function execute($value = false, $params = array())
{
$this->setResult(empty($value) ? $this->_promptPassword() : $value);
}
// }}}
// _promptPassword() {{{
/**
* Prompts the password to the user without echoing it.
*
* @return string
* @todo not echo-ing the password does not work on windows is there a way
* to make this work ?
*/
private function _promptPassword()
{
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
fwrite(STDOUT,
$this->parser->message_provider->get('PASSWORD_PROMPT_ECHO'));
@flock(STDIN, LOCK_EX);
$passwd = fgets(STDIN);
@flock(STDIN, LOCK_UN);
} else {
fwrite(STDOUT, $this->parser->message_provider->get('PASSWORD_PROMPT'));
// disable echoing
system('stty -echo');
@flock(STDIN, LOCK_EX);
$passwd = fgets(STDIN);
@flock(STDIN, LOCK_UN);
system('stty echo');
}
return trim($passwd);
}
// }}}
}

View File

@ -0,0 +1,78 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This file is part of the PEAR Console_CommandLine package.
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT license that is available
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_CommandLine
* @since File available since release 0.1.0
* @filesource
*/
/**
* Required by this class.
*/
require_once 'Console/CommandLine/Action.php';
/**
* Class that represent the StoreArray action.
*
* The execute method appends the value of the option entered by the user to
* the result option array entry.
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version Release: 1.2.0
* @link http://pear.php.net/package/Console_CommandLine
* @since Class available since release 0.1.0
*/
class Console_CommandLine_Action_StoreArray extends Console_CommandLine_Action
{
// Protected properties {{{
/**
* Force a clean result when first called, overriding any defaults assigned.
*
* @var object $firstPass First time this action has been called.
*/
protected $firstPass = true;
// }}}
// execute() {{{
/**
* Executes the action with the value entered by the user.
*
* @param mixed $value The option value
* @param array $params An optional array of parameters
*
* @return string
*/
public function execute($value = false, $params = array())
{
$result = $this->getResult();
if (null === $result || $this->firstPass) {
$result = array();
$this->firstPass = false;
}
$result[] = $value;
$this->setResult($result);
}
// }}}
}

View File

@ -0,0 +1,64 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This file is part of the PEAR Console_CommandLine package.
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT license that is available
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_CommandLine
* @since File available since release 0.1.0
* @filesource
*/
/**
* Required by this class.
*/
require_once 'Console/CommandLine/Action.php';
/**
* Class that represent the StoreFalse action.
*
* The execute method store the boolean 'false' in the corrsponding result
* option array entry (the value is true if the option is not present in the
* command line entered by the user).
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version Release: 1.2.0
* @link http://pear.php.net/package/Console_CommandLine
* @since Class available since release 0.1.0
*/
class Console_CommandLine_Action_StoreFalse extends Console_CommandLine_Action
{
// execute() {{{
/**
* Executes the action with the value entered by the user.
*
* @param mixed $value The option value
* @param array $params An array of optional parameters
*
* @return string
*/
public function execute($value = false, $params = array())
{
$this->setResult(false);
}
// }}}
}

View File

@ -0,0 +1,76 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This file is part of the PEAR Console_CommandLine package.
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT license that is available
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_CommandLine
* @since File available since release 0.1.0
* @filesource
*/
/**
* Required by this class.
*/
require_once 'Console/CommandLine/Action.php';
/**
* Class that represent the StoreFloat action.
*
* The execute method store the value of the option entered by the user as a
* float in the result option array entry, if the value passed is not a float
* an Exception is raised.
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version Release: 1.2.0
* @link http://pear.php.net/package/Console_CommandLine
* @since Class available since release 0.1.0
*/
class Console_CommandLine_Action_StoreFloat extends Console_CommandLine_Action
{
// execute() {{{
/**
* Executes the action with the value entered by the user.
*
* @param mixed $value The option value
* @param array $params An array of optional parameters
*
* @return string
* @throws Console_CommandLine_Exception
*/
public function execute($value = false, $params = array())
{
if (!is_numeric($value)) {
include_once 'Console/CommandLine/Exception.php';
throw Console_CommandLine_Exception::factory(
'OPTION_VALUE_TYPE_ERROR',
array(
'name' => $this->option->name,
'type' => 'float',
'value' => $value
),
$this->parser
);
}
$this->setResult((float)$value);
}
// }}}
}

View File

@ -0,0 +1,76 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This file is part of the PEAR Console_CommandLine package.
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT license that is available
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_CommandLine
* @since File available since release 0.1.0
* @filesource
*/
/**
* Required by this class.
*/
require_once 'Console/CommandLine/Action.php';
/**
* Class that represent the StoreInt action.
*
* The execute method store the value of the option entered by the user as an
* integer in the result option array entry, if the value passed is not an
* integer an Exception is raised.
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version Release: 1.2.0
* @link http://pear.php.net/package/Console_CommandLine
* @since Class available since release 0.1.0
*/
class Console_CommandLine_Action_StoreInt extends Console_CommandLine_Action
{
// execute() {{{
/**
* Executes the action with the value entered by the user.
*
* @param mixed $value The option value
* @param array $params An array of optional parameters
*
* @return string
* @throws Console_CommandLine_Exception
*/
public function execute($value = false, $params = array())
{
if (!is_numeric($value)) {
include_once 'Console/CommandLine/Exception.php';
throw Console_CommandLine_Exception::factory(
'OPTION_VALUE_TYPE_ERROR',
array(
'name' => $this->option->name,
'type' => 'int',
'value' => $value
),
$this->parser
);
}
$this->setResult((int)$value);
}
// }}}
}

View File

@ -0,0 +1,62 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This file is part of the PEAR Console_CommandLine package.
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT license that is available
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_CommandLine
* @since File available since release 0.1.0
* @filesource
*/
/**
* Required by this class.
*/
require_once 'Console/CommandLine/Action.php';
/**
* Class that represent the StoreString action.
*
* The execute method store the value of the option entered by the user as a
* string in the result option array entry.
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version Release: 1.2.0
* @link http://pear.php.net/package/Console_CommandLine
* @since Class available since release 0.1.0
*/
class Console_CommandLine_Action_StoreString extends Console_CommandLine_Action
{
// execute() {{{
/**
* Executes the action with the value entered by the user.
*
* @param mixed $value The option value
* @param array $params An array of optional parameters
*
* @return string
*/
public function execute($value = false, $params = array())
{
$this->setResult((string)$value);
}
// }}}
}

View File

@ -0,0 +1,63 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This file is part of the PEAR Console_CommandLine package.
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT license that is available
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_CommandLine
* @since File available since release 0.1.0
* @filesource
*/
/**
* Required by this class.
*/
require_once 'Console/CommandLine/Action.php';
/**
* Class that represent the StoreTrue action.
*
* The execute method store the boolean 'true' in the corrsponding result
* option array entry (the value is false if the option is not present in the
* command line entered by the user).
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version Release: 1.2.0
* @link http://pear.php.net/package/Console_CommandLine
* @since Class available since release 0.1.0
*/
class Console_CommandLine_Action_StoreTrue extends Console_CommandLine_Action
{
// execute() {{{
/**
* Executes the action with the value entered by the user.
*
* @param mixed $value The option value
* @param array $params An array of optional parameters
*
* @return string
*/
public function execute($value = false, $params = array())
{
$this->setResult(true);
}
// }}}
}

View File

@ -0,0 +1,60 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This file is part of the PEAR Console_CommandLine package.
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT license that is available
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_CommandLine
* @since File available since release 0.1.0
* @filesource
*/
/**
* Required by this class.
*/
require_once 'Console/CommandLine/Action.php';
/**
* Class that represent the Version action, a special action that displays the
* version string of the program.
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version Release: 1.2.0
* @link http://pear.php.net/package/Console_CommandLine
* @since Class available since release 0.1.0
*/
class Console_CommandLine_Action_Version extends Console_CommandLine_Action
{
// execute() {{{
/**
* Executes the action with the value entered by the user.
*
* @param mixed $value The option value
* @param array $params An array of optional parameters
*
* @return string
*/
public function execute($value = false, $params = array())
{
return $this->parser->displayVersion();
}
// }}}
}

View File

@ -0,0 +1,102 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This file is part of the PEAR Console_CommandLine package.
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT license that is available
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_CommandLine
* @since File available since release 0.1.0
* @filesource
*/
/**
* Include base element class.
*/
require_once 'Console/CommandLine/Element.php';
/**
* Class that represent a command line argument.
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version Release: 1.2.0
* @link http://pear.php.net/package/Console_CommandLine
* @since Class available since release 0.1.0
*/
class Console_CommandLine_Argument extends Console_CommandLine_Element
{
// Public properties {{{
/**
* Setting this to true will tell the parser that the argument expects more
* than one argument and that argument values should be stored in an array.
*
* @var boolean $multiple Whether the argument expects multiple values
*/
public $multiple = false;
/**
* Setting this to true will tell the parser that the argument is optional
* and can be ommited.
* Note that it is not a good practice to make arguments optional, it is
* the role of the options to be optional, by essence.
*
* @var boolean $optional Whether the argument is optional or not.
*/
public $optional = false;
/**
* An array of possible values for the argument.
*
* @var array $choices Valid choices for the argument
*/
public $choices = array();
// }}}
// validate() {{{
/**
* Validates the argument instance.
*
* @return void
* @throws Console_CommandLine_Exception
* @todo use exceptions
*/
public function validate()
{
// check if the argument name is valid
if (!preg_match('/^[a-zA-Z_\x7f-\xff]+[a-zA-Z0-9_\x7f-\xff]*$/',
$this->name)) {
Console_CommandLine::triggerError(
'argument_bad_name',
E_USER_ERROR,
array('{$name}' => $this->name)
);
}
if (!$this->optional && $this->default !== null) {
Console_CommandLine::triggerError(
'argument_no_default',
E_USER_ERROR
);
}
parent::validate();
}
// }}}
}

View File

@ -0,0 +1,76 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This file is part of the PEAR Console_CommandLine package.
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT license that is available
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_CommandLine
* @since File available since release 0.1.0
* @filesource
*/
/**
* File containing the parent class.
*/
require_once 'Console/CommandLine.php';
/**
* Class that represent a command with option and arguments.
*
* This class exist just to clarify the interface but at the moment it is
* strictly identical to Console_CommandLine class, it could change in the
* future though.
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version Release: 1.2.0
* @link http://pear.php.net/package/Console_CommandLine
* @since Class available since release 0.1.0
*/
class Console_CommandLine_Command extends Console_CommandLine
{
// Public properties {{{
/**
* An array of aliases for the subcommand.
*
* @var array $aliases Aliases for the subcommand.
*/
public $aliases = array();
// }}}
// __construct() {{{
/**
* Constructor.
*
* @param array $params An optional array of parameters
*
* @return void
*/
public function __construct($params = array())
{
if (isset($params['aliases'])) {
$this->aliases = $params['aliases'];
}
parent::__construct($params);
}
// }}}
}

View File

@ -0,0 +1,66 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This file is part of the PEAR Console_CommandLine package.
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT license that is available
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @author Michael Gauthier <mike@silverorange.com>
* @copyright 2007 David JEAN LOUIS, 2009 silverorange
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_CommandLine
* @since File available since release 1.1.0
* @filesource
*/
/**
* Common interfacefor message providers that allow overriding with custom
* messages
*
* Message providers may optionally implement this interface.
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @author Michael Gauthier <mike@silverorange.com>
* @copyright 2007 David JEAN LOUIS, 2009 silverorange
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version Release: 1.2.0
* @link http://pear.php.net/package/Console_CommandLine
* @since Interface available since release 1.1.0
*/
interface Console_CommandLine_CustomMessageProvider
{
// getWithCustomMesssages() {{{
/**
* Retrieves the given string identifier corresponding message.
*
* For a list of identifiers please see the provided default message
* provider.
*
* @param string $code The string identifier of the message
* @param array $vars An array of template variables
* @param array $messages An optional array of messages to use. Array
* indexes are message codes.
*
* @return string
* @see Console_CommandLine_MessageProvider
* @see Console_CommandLine_MessageProvider_Default
*/
public function getWithCustomMessages(
$code, $vars = array(), $messages = array()
);
// }}}
}

View File

@ -0,0 +1,151 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This file is part of the PEAR Console_CommandLine package.
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT license that is available
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_CommandLine
* @since File available since release 0.1.0
* @filesource
*/
/**
* Class that represent a command line element (an option, or an argument).
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version Release: 1.2.0
* @link http://pear.php.net/package/Console_CommandLine
* @since Class available since release 0.1.0
*/
abstract class Console_CommandLine_Element
{
// Public properties {{{
/**
* The element name.
*
* @var string $name Element name
*/
public $name;
/**
* The name of variable displayed in the usage message, if no set it
* defaults to the "name" property.
*
* @var string $help_name Element "help" variable name
*/
public $help_name;
/**
* The element description.
*
* @var string $description Element description
*/
public $description;
/**
* The default value of the element if not provided on the command line.
*
* @var mixed $default Default value of the option.
*/
public $default;
/**
* Custom errors messages for this element
*
* This array is of the form:
* <code>
* <?php
* array(
* $messageName => $messageText,
* $messageName => $messageText,
* ...
* );
* ?>
* </code>
*
* If specified, these messages override the messages provided by the
* default message provider. For example:
* <code>
* <?php
* $messages = array(
* 'ARGUMENT_REQUIRED' => 'The argument foo is required.',
* );
* ?>
* </code>
*
* @var array
* @see Console_CommandLine_MessageProvider_Default
*/
public $messages = array();
// }}}
// __construct() {{{
/**
* Constructor.
*
* @param string $name The name of the element
* @param array $params An optional array of parameters
*
* @return void
*/
public function __construct($name = null, $params = array())
{
$this->name = $name;
foreach ($params as $attr => $value) {
if (property_exists($this, $attr)) {
$this->$attr = $value;
}
}
}
// }}}
// toString() {{{
/**
* Returns the string representation of the element.
*
* @return string The string representation of the element
* @todo use __toString() instead
*/
public function toString()
{
return $this->help_name;
}
// }}}
// validate() {{{
/**
* Validates the element instance and set it's default values.
*
* @return void
* @throws Console_CommandLine_Exception
*/
public function validate()
{
// if no help_name passed, default to name
if ($this->help_name == null) {
$this->help_name = $this->name;
}
}
// }}}
}

View File

@ -0,0 +1,97 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This file is part of the PEAR Console_CommandLine package.
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT license that is available
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_CommandLine
* @since File available since release 0.1.0
* @filesource
*/
/**
* Include the PEAR_Exception class
*/
require_once 'PEAR/Exception.php';
/**
* Interface for custom message provider.
*/
require_once 'Console/CommandLine/CustomMessageProvider.php';
/**
* Class for exceptions raised by the Console_CommandLine package.
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version Release: 1.2.0
* @link http://pear.php.net/package/Console_CommandLine
* @since Class available since release 0.1.0
*/
class Console_CommandLine_Exception extends PEAR_Exception
{
// Codes constants {{{
/**#@+
* Exception code constants.
*/
const OPTION_VALUE_REQUIRED = 1;
const OPTION_VALUE_UNEXPECTED = 2;
const OPTION_VALUE_TYPE_ERROR = 3;
const OPTION_UNKNOWN = 4;
const ARGUMENT_REQUIRED = 5;
const INVALID_SUBCOMMAND = 6;
/**#@-*/
// }}}
// factory() {{{
/**
* Convenience method that builds the exception with the array of params by
* calling the message provider class.
*
* @param string $code The string identifier of the
* exception.
* @param array $params Array of template vars/values
* @param Console_CommandLine $parser An instance of the parser
* @param array $messages An optional array of messages
* passed to the message provider.
*
* @return object an instance of Console_CommandLine_Exception
*/
public static function factory(
$code, $params, $parser, array $messages = array()
) {
$provider = $parser->message_provider;
if ($provider instanceof Console_CommandLine_CustomMessageProvider) {
$msg = $provider->getWithCustomMessages(
$code,
$params,
$messages
);
} else {
$msg = $provider->get($code, $params);
}
$const = 'Console_CommandLine_Exception::' . $code;
$code = defined($const) ? constant($const) : 0;
return new Console_CommandLine_Exception($msg, $code);
}
// }}}
}

View File

@ -0,0 +1,56 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This file is part of the PEAR Console_CommandLine package.
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT license that is available
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_CommandLine
* @since File available since release 0.1.0
* @filesource
*/
/**
* Message providers common interface, all message providers must implement
* this interface.
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version Release: 1.2.0
* @link http://pear.php.net/package/Console_CommandLine
* @since Class available since release 0.1.0
*/
interface Console_CommandLine_MessageProvider
{
// get() {{{
/**
* Retrieves the given string identifier corresponding message.
* For a list of identifiers please see the provided default message
* provider.
*
* @param string $code The string identifier of the message
* @param array $vars An array of template variables
*
* @return string
* @see Console_CommandLine_MessageProvider_Default
*/
public function get($code, $vars=array());
// }}}
}

View File

@ -0,0 +1,153 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This file is part of the PEAR Console_CommandLine package.
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT license that is available
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_CommandLine
* @since File available since release 0.1.0
* @filesource
*/
/**
* The message provider interface.
*/
require_once 'Console/CommandLine/MessageProvider.php';
/**
* The custom message provider interface.
*/
require_once 'Console/CommandLine/CustomMessageProvider.php';
/**
* Lightweight class that manages messages used by Console_CommandLine package,
* allowing the developper to customize these messages, for example to
* internationalize a command line frontend.
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version Release: 1.2.0
* @link http://pear.php.net/package/Console_CommandLine
* @since Class available since release 0.1.0
*/
class Console_CommandLine_MessageProvider_Default
implements Console_CommandLine_MessageProvider,
Console_CommandLine_CustomMessageProvider
{
// Properties {{{
/**
* Associative array of messages
*
* @var array $messages
*/
protected $messages = array(
'OPTION_VALUE_REQUIRED' => 'Option "{$name}" requires a value.',
'OPTION_VALUE_UNEXPECTED' => 'Option "{$name}" does not expect a value (got "{$value}").',
'OPTION_VALUE_NOT_VALID' => 'Option "{$name}" must be one of the following: "{$choices}" (got "{$value}").',
'ARGUMENT_VALUE_NOT_VALID'=> 'Argument "{$name}" must be one of the following: "{$choices}" (got "{$value}").',
'OPTION_VALUE_TYPE_ERROR' => 'Option "{$name}" requires a value of type {$type} (got "{$value}").',
'OPTION_AMBIGUOUS' => 'Ambiguous option "{$name}", can be one of the following: {$matches}.',
'OPTION_UNKNOWN' => 'Unknown option "{$name}".',
'ARGUMENT_REQUIRED' => 'You must provide at least {$argnum} argument{$plural}.',
'PROG_HELP_LINE' => 'Type "{$progname} --help" to get help.',
'PROG_VERSION_LINE' => '{$progname} version {$version}.',
'COMMAND_HELP_LINE' => 'Type "{$progname} <command> --help" to get help on specific command.',
'USAGE_WORD' => 'Usage',
'OPTION_WORD' => 'Options',
'ARGUMENT_WORD' => 'Arguments',
'COMMAND_WORD' => 'Commands',
'PASSWORD_PROMPT' => 'Password: ',
'PASSWORD_PROMPT_ECHO' => 'Password (warning: will echo): ',
'INVALID_CUSTOM_INSTANCE' => 'Instance does not implement the required interface',
'LIST_OPTION_MESSAGE' => 'lists valid choices for option {$name}',
'LIST_DISPLAYED_MESSAGE' => 'Valid choices are: ',
'INVALID_SUBCOMMAND' => 'Command "{$command}" is not valid.',
'SUBCOMMAND_REQUIRED' => 'Please enter one of the following command: {$commands}.',
);
// }}}
// get() {{{
/**
* Retrieve the given string identifier corresponding message.
*
* @param string $code The string identifier of the message
* @param array $vars An array of template variables
*
* @return string
*/
public function get($code, $vars = array())
{
if (!isset($this->messages[$code])) {
return 'UNKNOWN';
}
return $this->replaceTemplateVars($this->messages[$code], $vars);
}
// }}}
// getWithCustomMessages() {{{
/**
* Retrieve the given string identifier corresponding message.
*
* @param string $code The string identifier of the message
* @param array $vars An array of template variables
* @param array $messages An optional array of messages to use. Array
* indexes are message codes.
*
* @return string
*/
public function getWithCustomMessages(
$code, $vars = array(), $messages = array()
) {
// get message
if (isset($messages[$code])) {
$message = $messages[$code];
} elseif (isset($this->messages[$code])) {
$message = $this->messages[$code];
} else {
$message = 'UNKNOWN';
}
return $this->replaceTemplateVars($message, $vars);
}
// }}}
// replaceTemplateVars() {{{
/**
* Replaces template vars in a message
*
* @param string $message The message
* @param array $vars An array of template variables
*
* @return string
*/
protected function replaceTemplateVars($message, $vars = array())
{
$tmpkeys = array_keys($vars);
$keys = array();
foreach ($tmpkeys as $key) {
$keys[] = '{$' . $key . '}';
}
return str_replace($keys, array_values($vars), $message);
}
// }}}
}

View File

@ -0,0 +1,366 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This file is part of the PEAR Console_CommandLine package.
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT license that is available
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_CommandLine
* @since File available since release 0.1.0
* @filesource
*/
/**
* Required by this class.
*/
require_once 'Console/CommandLine.php';
require_once 'Console/CommandLine/Element.php';
/**
* Class that represent a commandline option.
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version Release: 1.2.0
* @link http://pear.php.net/package/Console_CommandLine
* @since Class available since release 0.1.0
*/
class Console_CommandLine_Option extends Console_CommandLine_Element
{
// Public properties {{{
/**
* The option short name (ex: -v).
*
* @var string $short_name Short name of the option
*/
public $short_name;
/**
* The option long name (ex: --verbose).
*
* @var string $long_name Long name of the option
*/
public $long_name;
/**
* The option action, defaults to "StoreString".
*
* @var string $action Option action
*/
public $action = 'StoreString';
/**
* An array of possible values for the option. If this array is not empty
* and the value passed is not in the array an exception is raised.
* This only make sense for actions that accept values of course.
*
* @var array $choices Valid choices for the option
*/
public $choices = array();
/**
* The callback function (or method) to call for an action of type
* Callback, this can be any callable supported by the php function
* call_user_func.
*
* Example:
*
* <code>
* $parser->addOption('myoption', array(
* 'short_name' => '-m',
* 'long_name' => '--myoption',
* 'action' => 'Callback',
* 'callback' => 'myCallbackFunction'
* ));
* </code>
*
* @var callable $callback The option callback
*/
public $callback;
/**
* An associative array of additional params to pass to the class
* corresponding to the action, this array will also be passed to the
* callback defined for an action of type Callback, Example:
*
* <code>
* // for a custom action
* $parser->addOption('myoption', array(
* 'short_name' => '-m',
* 'long_name' => '--myoption',
* 'action' => 'MyCustomAction',
* 'action_params' => array('foo'=>true, 'bar'=>false)
* ));
*
* // if the user type:
* // $ <yourprogram> -m spam
* // in your MyCustomAction class the execute() method will be called
* // with the value 'spam' as first parameter and
* // array('foo'=>true, 'bar'=>false) as second parameter
* </code>
*
* @var array $action_params Additional parameters to pass to the action
*/
public $action_params = array();
/**
* For options that expect an argument, this property tells the parser if
* the option argument is optional and can be ommited.
*
* @var bool $argumentOptional Whether the option arg is optional or not
*/
public $argument_optional = false;
/**
* For options that uses the "choice" property only.
* Adds a --list-<choice> option to the parser that displays the list of
* choices for the option.
*
* @var bool $add_list_option Whether to add a list option or not
*/
public $add_list_option = false;
// }}}
// Private properties {{{
/**
* When an action is called remember it to allow for multiple calls.
*
* @var object $action_instance Placeholder for action
*/
private $_action_instance = null;
// }}}
// __construct() {{{
/**
* Constructor.
*
* @param string $name The name of the option
* @param array $params An optional array of parameters
*
* @return void
*/
public function __construct($name = null, $params = array())
{
parent::__construct($name, $params);
if ($this->action == 'Password') {
// special case for Password action, password can be passed to the
// commandline or prompted by the parser
$this->argument_optional = true;
}
}
// }}}
// toString() {{{
/**
* Returns the string representation of the option.
*
* @param string $delim Delimiter to use between short and long option
*
* @return string The string representation of the option
* @todo use __toString() instead
*/
public function toString($delim = ", ")
{
$ret = '';
$padding = '';
if ($this->short_name != null) {
$ret .= $this->short_name;
if ($this->expectsArgument()) {
$ret .= ' ' . $this->help_name;
}
$padding = $delim;
}
if ($this->long_name != null) {
$ret .= $padding . $this->long_name;
if ($this->expectsArgument()) {
$ret .= '=' . $this->help_name;
}
}
return $ret;
}
// }}}
// expectsArgument() {{{
/**
* Returns true if the option requires one or more argument and false
* otherwise.
*
* @return bool Whether the option expects an argument or not
*/
public function expectsArgument()
{
if ($this->action == 'StoreTrue' || $this->action == 'StoreFalse' ||
$this->action == 'Help' || $this->action == 'Version' ||
$this->action == 'Counter' || $this->action == 'List') {
return false;
}
return true;
}
// }}}
// dispatchAction() {{{
/**
* Formats the value $value according to the action of the option and
* updates the passed Console_CommandLine_Result object.
*
* @param mixed $value The value to format
* @param Console_CommandLine_Result $result The result instance
* @param Console_CommandLine $parser The parser instance
*
* @return void
* @throws Console_CommandLine_Exception
*/
public function dispatchAction($value, $result, $parser)
{
$actionInfo = Console_CommandLine::$actions[$this->action];
if (true === $actionInfo[1]) {
// we have a "builtin" action
$tokens = explode('_', $actionInfo[0]);
include_once implode('/', $tokens) . '.php';
}
$clsname = $actionInfo[0];
if ($this->_action_instance === null) {
$this->_action_instance = new $clsname($result, $this, $parser);
}
// check value is in option choices
if (!empty($this->choices) && !in_array($this->_action_instance->format($value), $this->choices)) {
throw Console_CommandLine_Exception::factory(
'OPTION_VALUE_NOT_VALID',
array(
'name' => $this->name,
'choices' => implode('", "', $this->choices),
'value' => $value,
),
$parser,
$this->messages
);
}
$this->_action_instance->execute($value, $this->action_params);
}
// }}}
// validate() {{{
/**
* Validates the option instance.
*
* @return void
* @throws Console_CommandLine_Exception
* @todo use exceptions instead
*/
public function validate()
{
// check if the option name is valid
if (!preg_match('/^[a-zA-Z_\x7f-\xff]+[a-zA-Z0-9_\x7f-\xff]*$/',
$this->name)) {
Console_CommandLine::triggerError('option_bad_name',
E_USER_ERROR, array('{$name}' => $this->name));
}
// call the parent validate method
parent::validate();
// a short_name or a long_name must be provided
if ($this->short_name == null && $this->long_name == null) {
Console_CommandLine::triggerError('option_long_and_short_name_missing',
E_USER_ERROR, array('{$name}' => $this->name));
}
// check if the option short_name is valid
if ($this->short_name != null &&
!(preg_match('/^\-[a-zA-Z]{1}$/', $this->short_name))) {
Console_CommandLine::triggerError('option_bad_short_name',
E_USER_ERROR, array(
'{$name}' => $this->name,
'{$short_name}' => $this->short_name
));
}
// check if the option long_name is valid
if ($this->long_name != null &&
!preg_match('/^\-\-[a-zA-Z]+[a-zA-Z0-9_\-]*$/', $this->long_name)) {
Console_CommandLine::triggerError('option_bad_long_name',
E_USER_ERROR, array(
'{$name}' => $this->name,
'{$long_name}' => $this->long_name
));
}
// check if we have a valid action
if (!is_string($this->action)) {
Console_CommandLine::triggerError('option_bad_action',
E_USER_ERROR, array('{$name}' => $this->name));
}
if (!isset(Console_CommandLine::$actions[$this->action])) {
Console_CommandLine::triggerError('option_unregistered_action',
E_USER_ERROR, array(
'{$action}' => $this->action,
'{$name}' => $this->name
));
}
// if the action is a callback, check that we have a valid callback
if ($this->action == 'Callback' && !is_callable($this->callback)) {
Console_CommandLine::triggerError('option_invalid_callback',
E_USER_ERROR, array('{$name}' => $this->name));
}
}
// }}}
// setDefaults() {{{
/**
* Set the default value according to the configured action.
*
* Note that for backward compatibility issues this method is only called
* when the 'force_options_defaults' is set to true, it will become the
* default behaviour in the next major release of Console_CommandLine.
*
* @return void
*/
public function setDefaults()
{
if ($this->default !== null) {
// already set
return;
}
switch ($this->action) {
case 'Counter':
case 'StoreInt':
$this->default = 0;
break;
case 'StoreFloat':
$this->default = 0.0;
break;
case 'StoreArray':
$this->default = array();
break;
case 'StoreTrue':
$this->default = false;
break;
case 'StoreFalse':
$this->default = true;
break;
default:
return;
}
}
// }}}
}

View File

@ -0,0 +1,63 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This file is part of the PEAR Console_CommandLine package.
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT license that is available
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_CommandLine
* @since File available since release 0.1.0
* @filesource
*/
/**
* Outputters common interface, all outputters must implement this interface.
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version Release: 1.2.0
* @link http://pear.php.net/package/Console_CommandLine
* @since Class available since release 0.1.0
*/
interface Console_CommandLine_Outputter
{
// stdout() {{{
/**
* Processes the output for a message that should be displayed on STDOUT.
*
* @param string $msg The message to output
*
* @return void
*/
public function stdout($msg);
// }}}
// stderr() {{{
/**
* Processes the output for a message that should be displayed on STDERR.
*
* @param string $msg The message to output
*
* @return void
*/
public function stderr($msg);
// }}}
}

View File

@ -0,0 +1,82 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This file is part of the PEAR Console_CommandLine package.
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT license that is available
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_CommandLine
* @since File available since release 0.1.0
* @filesource
*/
/**
* The Outputter interface.
*/
require_once 'Console/CommandLine/Outputter.php';
/**
* Console_CommandLine default Outputter.
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version Release: 1.2.0
* @link http://pear.php.net/package/Console_CommandLine
* @since Class available since release 0.1.0
*/
class Console_CommandLine_Outputter_Default implements Console_CommandLine_Outputter
{
// stdout() {{{
/**
* Writes the message $msg to STDOUT.
*
* @param string $msg The message to output
*
* @return void
*/
public function stdout($msg)
{
if (defined('STDOUT')) {
fwrite(STDOUT, $msg);
} else {
echo $msg;
}
}
// }}}
// stderr() {{{
/**
* Writes the message $msg to STDERR.
*
* @param string $msg The message to output
*
* @return void
*/
public function stderr($msg)
{
if (defined('STDERR')) {
fwrite(STDERR, $msg);
} else {
echo $msg;
}
}
// }}}
}

View File

@ -0,0 +1,71 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This file is part of the PEAR Console_CommandLine package.
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT license that is available
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_CommandLine
* @since File available since release 0.1.0
* @filesource
*/
/**
* Renderers common interface, all renderers must implement this interface.
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version Release: 1.2.0
* @link http://pear.php.net/package/Console_CommandLine
* @since Class available since release 0.1.0
*/
interface Console_CommandLine_Renderer
{
// usage() {{{
/**
* Returns the full usage message.
*
* @return string The usage message
*/
public function usage();
// }}}
// error() {{{
/**
* Returns a formatted error message.
*
* @param string $error The error message to format
*
* @return string The error string
*/
public function error($error);
// }}}
// version() {{{
/**
* Returns the program version string.
*
* @return string The version string
*/
public function version();
// }}}
}

View File

@ -0,0 +1,424 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This file is part of the PEAR Console_CommandLine package.
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT license that is available
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_CommandLine
* @since File available since release 0.1.0
* @filesource
*/
/**
* The renderer interface.
*/
require_once 'Console/CommandLine/Renderer.php';
/**
* Console_CommandLine default renderer.
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version Release: 1.2.0
* @link http://pear.php.net/package/Console_CommandLine
* @since Class available since release 0.1.0
*/
class Console_CommandLine_Renderer_Default implements Console_CommandLine_Renderer
{
// Properties {{{
/**
* Integer that define the max width of the help text.
*
* @var integer $line_width Line width
*/
public $line_width = 75;
/**
* Integer that define the max width of the help text.
*
* @var integer $line_width Line width
*/
public $options_on_different_lines = false;
/**
* An instance of Console_CommandLine.
*
* @var Console_CommandLine $parser The parser
*/
public $parser = false;
// }}}
// __construct() {{{
/**
* Constructor.
*
* @param object $parser A Console_CommandLine instance
*
* @return void
*/
public function __construct($parser = false)
{
$this->parser = $parser;
}
// }}}
// usage() {{{
/**
* Returns the full usage message.
*
* @return string The usage message
*/
public function usage()
{
$ret = '';
if (!empty($this->parser->description)) {
$ret .= $this->description() . "\n\n";
}
$ret .= $this->usageLine() . "\n";
if (count($this->parser->commands) > 0) {
$ret .= $this->commandUsageLine() . "\n";
}
if (count($this->parser->options) > 0) {
$ret .= "\n" . $this->optionList() . "\n";
}
if (count($this->parser->args) > 0) {
$ret .= "\n" . $this->argumentList() . "\n";
}
if (count($this->parser->commands) > 0) {
$ret .= "\n" . $this->commandList() . "\n";
}
$ret .= "\n";
return $ret;
}
// }}}
// error() {{{
/**
* Returns a formatted error message.
*
* @param string $error The error message to format
*
* @return string The error string
*/
public function error($error)
{
$ret = 'Error: ' . $error . "\n";
if ($this->parser->add_help_option) {
$name = $this->name();
$ret .= $this->wrap($this->parser->message_provider->get('PROG_HELP_LINE',
array('progname' => $name))) . "\n";
if (count($this->parser->commands) > 0) {
$ret .= $this->wrap($this->parser->message_provider->get('COMMAND_HELP_LINE',
array('progname' => $name))) . "\n";
}
}
return $ret;
}
// }}}
// version() {{{
/**
* Returns the program version string.
*
* @return string The version string
*/
public function version()
{
return $this->parser->message_provider->get('PROG_VERSION_LINE', array(
'progname' => $this->name(),
'version' => $this->parser->version
)) . "\n";
}
// }}}
// name() {{{
/**
* Returns the full name of the program or the sub command
*
* @return string The name of the program
*/
protected function name()
{
$name = $this->parser->name;
$parent = $this->parser->parent;
while ($parent) {
if (count($parent->options) > 0) {
$name = '['
. strtolower($this->parser->message_provider->get('OPTION_WORD',
array('plural' => 's')))
. '] ' . $name;
}
$name = $parent->name . ' ' . $name;
$parent = $parent->parent;
}
return $this->wrap($name);
}
// }}}
// description() {{{
/**
* Returns the command line description message.
*
* @return string The description message
*/
protected function description()
{
return $this->wrap($this->parser->description);
}
// }}}
// usageLine() {{{
/**
* Returns the command line usage message
*
* @return string the usage message
*/
protected function usageLine()
{
$usage = $this->parser->message_provider->get('USAGE_WORD') . ":\n";
$ret = $usage . ' ' . $this->name();
if (count($this->parser->options) > 0) {
$ret .= ' ['
. strtolower($this->parser->message_provider->get('OPTION_WORD'))
. ']';
}
if (count($this->parser->args) > 0) {
foreach ($this->parser->args as $name=>$arg) {
$arg_str = $arg->help_name;
if ($arg->multiple) {
$arg_str .= '1 ' . $arg->help_name . '2 ...';
}
if ($arg->optional) {
$arg_str = '[' . $arg_str . ']';
}
$ret .= ' ' . $arg_str;
}
}
return $this->columnWrap($ret, 2);
}
// }}}
// commandUsageLine() {{{
/**
* Returns the command line usage message for subcommands.
*
* @return string The usage line
*/
protected function commandUsageLine()
{
if (count($this->parser->commands) == 0) {
return '';
}
$ret = ' ' . $this->name();
if (count($this->parser->options) > 0) {
$ret .= ' ['
. strtolower($this->parser->message_provider->get('OPTION_WORD'))
. ']';
}
$ret .= " <command>";
$hasArgs = false;
$hasOptions = false;
foreach ($this->parser->commands as $command) {
if (!$hasArgs && count($command->args) > 0) {
$hasArgs = true;
}
if (!$hasOptions && ($command->add_help_option ||
$command->add_version_option || count($command->options) > 0)) {
$hasOptions = true;
}
}
if ($hasOptions) {
$ret .= ' [options]';
}
if ($hasArgs) {
$ret .= ' [args]';
}
return $this->columnWrap($ret, 2);
}
// }}}
// argumentList() {{{
/**
* Render the arguments list that will be displayed to the user, you can
* override this method if you want to change the look of the list.
*
* @return string The formatted argument list
*/
protected function argumentList()
{
$col = 0;
$args = array();
foreach ($this->parser->args as $arg) {
$argstr = ' ' . $arg->toString();
$args[] = array($argstr, $arg->description);
$ln = strlen($argstr);
if ($col < $ln) {
$col = $ln;
}
}
$ret = $this->parser->message_provider->get('ARGUMENT_WORD') . ":";
foreach ($args as $arg) {
$text = str_pad($arg[0], $col) . ' ' . $arg[1];
$ret .= "\n" . $this->columnWrap($text, $col+2);
}
return $ret;
}
// }}}
// optionList() {{{
/**
* Render the options list that will be displayed to the user, you can
* override this method if you want to change the look of the list.
*
* @return string The formatted option list
*/
protected function optionList()
{
$col = 0;
$options = array();
foreach ($this->parser->options as $option) {
$delim = $this->options_on_different_lines ? "\n" : ', ';
$optstr = $option->toString($delim);
$lines = explode("\n", $optstr);
$lines[0] = ' ' . $lines[0];
if (count($lines) > 1) {
$lines[1] = ' ' . $lines[1];
$ln = strlen($lines[1]);
} else {
$ln = strlen($lines[0]);
}
$options[] = array($lines, $option->description);
if ($col < $ln) {
$col = $ln;
}
}
$ret = $this->parser->message_provider->get('OPTION_WORD') . ":";
foreach ($options as $option) {
if (count($option[0]) > 1) {
$text = str_pad($option[0][1], $col) . ' ' . $option[1];
$pre = $option[0][0] . "\n";
} else {
$text = str_pad($option[0][0], $col) . ' ' . $option[1];
$pre = '';
}
$ret .= "\n" . $pre . $this->columnWrap($text, $col+2);
}
return $ret;
}
// }}}
// commandList() {{{
/**
* Render the command list that will be displayed to the user, you can
* override this method if you want to change the look of the list.
*
* @return string The formatted subcommand list
*/
protected function commandList()
{
$commands = array();
$col = 0;
foreach ($this->parser->commands as $cmdname=>$command) {
$cmdname = ' ' . $cmdname;
$commands[] = array($cmdname, $command->description, $command->aliases);
$ln = strlen($cmdname);
if ($col < $ln) {
$col = $ln;
}
}
$ret = $this->parser->message_provider->get('COMMAND_WORD') . ":";
foreach ($commands as $command) {
$text = str_pad($command[0], $col) . ' ' . $command[1];
if ($aliasesCount = count($command[2])) {
$pad = '';
$text .= ' (';
$text .= $aliasesCount > 1 ? 'aliases: ' : 'alias: ';
foreach ($command[2] as $alias) {
$text .= $pad . $alias;
$pad = ', ';
}
$text .= ')';
}
$ret .= "\n" . $this->columnWrap($text, $col+2);
}
return $ret;
}
// }}}
// wrap() {{{
/**
* Wraps the text passed to the method.
*
* @param string $text The text to wrap
* @param int $lw The column width (defaults to line_width property)
*
* @return string The wrapped text
*/
protected function wrap($text, $lw=null)
{
if ($this->line_width > 0) {
if ($lw === null) {
$lw = $this->line_width;
}
return wordwrap($text, $lw, "\n", false);
}
return $text;
}
// }}}
// columnWrap() {{{
/**
* Wraps the text passed to the method at the specified width.
*
* @param string $text The text to wrap
* @param int $cw The wrap width
*
* @return string The wrapped text
*/
protected function columnWrap($text, $cw)
{
$tokens = explode("\n", $this->wrap($text));
$ret = $tokens[0];
$chunks = $this->wrap(trim(substr($text, strlen($ret))),
$this->line_width - $cw);
$tokens = explode("\n", $chunks);
foreach ($tokens as $token) {
if (!empty($token)) {
$ret .= "\n" . str_repeat(' ', $cw) . $token;
}
}
return $ret;
}
// }}}
}

View File

@ -0,0 +1,71 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This file is part of the PEAR Console_CommandLine package.
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT license that is available
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_CommandLine
* @since File available since release 0.1.0
* @filesource
*/
/**
* A lightweight class to store the result of the command line parsing.
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version Release: 1.2.0
* @link http://pear.php.net/package/Console_CommandLine
* @since Class available since release 0.1.0
*/
class Console_CommandLine_Result
{
// Public properties {{{
/**
* The result options associative array.
* Key is the name of the option and value its value.
*
* @var array $options Result options array
*/
public $options = array();
/**
* The result arguments array.
*
* @var array $args Result arguments array
*/
public $args = array();
/**
* Name of the command invoked by the user, false if no command invoked.
*
* @var string $command_name Result command name
*/
public $command_name = false;
/**
* A result instance for the subcommand.
*
* @var Console_CommandLine_Result Result instance for the subcommand
*/
public $command = false;
// }}}
}

View File

@ -0,0 +1,312 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This file is part of the PEAR Console_CommandLine package.
*
* PHP version 5
*
* LICENSE: This source file is subject to the MIT license that is available
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_CommandLine
* @since File available since release 0.1.0
* @filesource
*/
/**
* Required file
*/
require_once 'Console/CommandLine.php';
/**
* Parser for command line xml definitions.
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version Release: @package_version@
* @link http://pear.php.net/package/Console_CommandLine
* @since Class available since release 0.1.0
*/
class Console_CommandLine_XmlParser
{
// parse() {{{
/**
* Parses the given xml definition file and returns a
* Console_CommandLine instance constructed with the xml data.
*
* @param string $xmlfile The xml file to parse
*
* @return Console_CommandLine A parser instance
*/
public static function parse($xmlfile)
{
if (!is_readable($xmlfile)) {
Console_CommandLine::triggerError('invalid_xml_file',
E_USER_ERROR, array('{$file}' => $xmlfile));
}
$doc = new DomDocument();
$doc->load($xmlfile);
self::validate($doc);
$nodes = $doc->getElementsByTagName('command');
$root = $nodes->item(0);
return self::_parseCommandNode($root, true);
}
// }}}
// parseString() {{{
/**
* Parses the given xml definition string and returns a
* Console_CommandLine instance constructed with the xml data.
*
* @param string $xmlstr The xml string to parse
*
* @return Console_CommandLine A parser instance
*/
public static function parseString($xmlstr)
{
$doc = new DomDocument();
$doc->loadXml($xmlstr);
self::validate($doc);
$nodes = $doc->getElementsByTagName('command');
$root = $nodes->item(0);
return self::_parseCommandNode($root, true);
}
// }}}
// validate() {{{
/**
* Validates the xml definition using Relax NG.
*
* @param DomDocument $doc The document to validate
*
* @return boolean Whether the xml data is valid or not.
* @throws Console_CommandLine_Exception
* @todo use exceptions
*/
public static function validate($doc)
{
if (is_dir('@data_dir@' . DIRECTORY_SEPARATOR . 'Console_CommandLine')) {
$rngfile = '@data_dir@' . DIRECTORY_SEPARATOR
. 'Console_CommandLine' . DIRECTORY_SEPARATOR . 'data'
. DIRECTORY_SEPARATOR . 'xmlschema.rng';
} else {
$rngfile = dirname(__FILE__) . DIRECTORY_SEPARATOR . '..'
. DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'data'
. DIRECTORY_SEPARATOR . 'xmlschema.rng';
}
if (!is_readable($rngfile)) {
Console_CommandLine::triggerError('invalid_xml_file',
E_USER_ERROR, array('{$file}' => $rngfile));
}
return $doc->relaxNGValidate($rngfile);
}
// }}}
// _parseCommandNode() {{{
/**
* Parses the root command node or a command node and returns the
* constructed Console_CommandLine or Console_CommandLine_Command instance.
*
* @param DomDocumentNode $node The node to parse
* @param bool $isRootNode Whether it is a root node or not
*
* @return mixed Console_CommandLine or Console_CommandLine_Command
*/
private static function _parseCommandNode($node, $isRootNode = false)
{
if ($isRootNode) {
$obj = new Console_CommandLine();
} else {
include_once 'Console/CommandLine/Command.php';
$obj = new Console_CommandLine_Command();
}
foreach ($node->childNodes as $cNode) {
$cNodeName = $cNode->nodeName;
switch ($cNodeName) {
case 'name':
case 'description':
case 'version':
$obj->$cNodeName = trim($cNode->nodeValue);
break;
case 'add_help_option':
case 'add_version_option':
case 'force_posix':
$obj->$cNodeName = self::_bool(trim($cNode->nodeValue));
break;
case 'option':
$obj->addOption(self::_parseOptionNode($cNode));
break;
case 'argument':
$obj->addArgument(self::_parseArgumentNode($cNode));
break;
case 'command':
$obj->addCommand(self::_parseCommandNode($cNode));
break;
case 'aliases':
if (!$isRootNode) {
foreach ($cNode->childNodes as $subChildNode) {
if ($subChildNode->nodeName == 'alias') {
$obj->aliases[] = trim($subChildNode->nodeValue);
}
}
}
break;
case 'messages':
$obj->messages = self::_messages($cNode);
break;
default:
break;
}
}
return $obj;
}
// }}}
// _parseOptionNode() {{{
/**
* Parses an option node and returns the constructed
* Console_CommandLine_Option instance.
*
* @param DomDocumentNode $node The node to parse
*
* @return Console_CommandLine_Option The built option
*/
private static function _parseOptionNode($node)
{
include_once 'Console/CommandLine/Option.php';
$obj = new Console_CommandLine_Option($node->getAttribute('name'));
foreach ($node->childNodes as $cNode) {
$cNodeName = $cNode->nodeName;
switch ($cNodeName) {
case 'choices':
foreach ($cNode->childNodes as $subChildNode) {
if ($subChildNode->nodeName == 'choice') {
$obj->choices[] = trim($subChildNode->nodeValue);
}
}
break;
case 'messages':
$obj->messages = self::_messages($cNode);
break;
default:
if (property_exists($obj, $cNodeName)) {
$obj->$cNodeName = trim($cNode->nodeValue);
}
break;
}
}
if ($obj->action == 'Password') {
$obj->argument_optional = true;
}
return $obj;
}
// }}}
// _parseArgumentNode() {{{
/**
* Parses an argument node and returns the constructed
* Console_CommandLine_Argument instance.
*
* @param DomDocumentNode $node The node to parse
*
* @return Console_CommandLine_Argument The built argument
*/
private static function _parseArgumentNode($node)
{
include_once 'Console/CommandLine/Argument.php';
$obj = new Console_CommandLine_Argument($node->getAttribute('name'));
foreach ($node->childNodes as $cNode) {
$cNodeName = $cNode->nodeName;
switch ($cNodeName) {
case 'description':
case 'help_name':
case 'default':
$obj->$cNodeName = trim($cNode->nodeValue);
break;
case 'multiple':
$obj->multiple = self::_bool(trim($cNode->nodeValue));
break;
case 'optional':
$obj->optional = self::_bool(trim($cNode->nodeValue));
break;
case 'choices':
foreach ($cNode->childNodes as $subChildNode) {
if ($subChildNode->nodeName == 'choice') {
$obj->choices[] = trim($subChildNode->nodeValue);
}
}
break;
case 'messages':
$obj->messages = self::_messages($cNode);
break;
default:
break;
}
}
return $obj;
}
// }}}
// _bool() {{{
/**
* Returns a boolean according to true/false possible strings.
*
* @param string $str The string to process
*
* @return boolean
*/
private static function _bool($str)
{
return in_array(strtolower((string)$str), array('true', '1', 'on', 'yes'));
}
// }}}
// _messages() {{{
/**
* Returns an array of custom messages for the element
*
* @param DOMNode $node The messages node to process
*
* @return array an array of messages
*
* @see Console_CommandLine::$messages
* @see Console_CommandLine_Element::$messages
*/
private static function _messages(DOMNode $node)
{
$messages = array();
foreach ($node->childNodes as $cNode) {
if ($cNode->nodeType == XML_ELEMENT_NODE) {
$name = $cNode->getAttribute('name');
$value = trim($cNode->nodeValue);
$messages[$name] = $value;
}
}
return $messages;
}
// }}}
}

65
lib/Console/Exception.php Normal file
View File

@ -0,0 +1,65 @@
<?php
/**
* Class for exceptions raised by the Console_CommandLine package.
*
* @category Console
* @package Console_CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license. MIT License
* @version Release: 1.2.0
* @link http://pear..net/package/Console_CommandLine
* @since Class available since release 0.1.0
*/
class Console_CommandLine_Exception extends PEAR_Exception
{
// Codes constants {{{
/**#@+
* Exception code constants.
*/
const OPTION_VALUE_REQUIRED = 1;
const OPTION_VALUE_UNEXPECTED = 2;
const OPTION_VALUE_TYPE_ERROR = 3;
const OPTION_UNKNOWN = 4;
const ARGUMENT_REQUIRED = 5;
const INVALID_SUBCOMMAND = 6;
/**#@-*/
// }}}
// factory() {{{
/**
* Convenience method that builds the exception with the array of params by
* calling the message provider class.
*
* @param string $code The string identifier of the
* exception.
* @param array $params Array of template vars/values
* @param Console_CommandLine $parser An instance of the parser
* @param array $messages An optional array of messages
* passed to the message provider.
*
* @return object an instance of Console_CommandLine_Exception
*/
public static function factory(
$code, $params, $parser, array $messages = array()
) {
$provider = $parser->message_provider;
if ($provider instanceof Console_CommandLine_CustomMessageProvider) {
$msg = $provider->getWithCustomMessages(
$code,
$params,
$messages
);
} else {
$msg = $provider->get($code, $params);
}
$const = 'Console_CommandLine_Exception::' . $code;
$code = defined($const) ? constant($const) : 0;
return new Console_CommandLine_Exception($msg, $code);
}
// }}}
}

388
lib/PEAR/Exception.php Normal file
View File

@ -0,0 +1,388 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
/**
* PEAR_Exception
*
* PHP version 5
*
* @category pear
* @package PEAR_Exception
* @author Tomas V. V. Cox <cox@idecnet.com>
* @author Hans Lellelid <hans@velum.net>
* @author Bertrand Mansion <bmansion@mamasam.com>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR_Exception
* @since File available since Release 1.0.0
*/
/**
* Base PEAR_Exception Class
*
* 1) Features:
*
* - Nestable exceptions (throw new PEAR_Exception($msg, $prev_exception))
* - Definable triggers, shot when exceptions occur
* - Pretty and informative error messages
* - Added more context info available (like class, method or cause)
* - cause can be a PEAR_Exception or an array of mixed
* PEAR_Exceptions/PEAR_ErrorStack warnings
* - callbacks for specific exception classes and their children
*
* 2) Ideas:
*
* - Maybe a way to define a 'template' for the output
*
* 3) Inherited properties from PHP Exception Class:
*
* protected $message
* protected $code
* protected $line
* protected $file
* private $trace
*
* 4) Inherited methods from PHP Exception Class:
*
* __clone
* __construct
* getMessage
* getCode
* getFile
* getLine
* getTraceSafe
* getTraceSafeAsString
* __toString
*
* 5) Usage example
*
* <code>
* require_once 'PEAR/Exception.php';
*
* class Test {
* function foo() {
* throw new PEAR_Exception('Error Message', ERROR_CODE);
* }
* }
*
* function myLogger($pear_exception) {
* echo $pear_exception->getMessage();
* }
* // each time a exception is thrown the 'myLogger' will be called
* // (its use is completely optional)
* PEAR_Exception::addObserver('myLogger');
* $test = new Test;
* try {
* $test->foo();
* } catch (PEAR_Exception $e) {
* print $e;
* }
* </code>
*
* @category pear
* @package PEAR_Exception
* @author Tomas V.V.Cox <cox@idecnet.com>
* @author Hans Lellelid <hans@velum.net>
* @author Bertrand Mansion <bmansion@mamasam.com>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.0.0beta1
* @link http://pear.php.net/package/PEAR_Exception
* @since Class available since Release 1.0.0
*
*/
class PEAR_Exception extends Exception
{
const OBSERVER_PRINT = -2;
const OBSERVER_TRIGGER = -4;
const OBSERVER_DIE = -8;
protected $cause;
private static $_observers = array();
private static $_uniqueid = 0;
private $_trace;
/**
* Supported signatures:
* - PEAR_Exception(string $message);
* - PEAR_Exception(string $message, int $code);
* - PEAR_Exception(string $message, Exception $cause);
* - PEAR_Exception(string $message, Exception $cause, int $code);
* - PEAR_Exception(string $message, PEAR_Error $cause);
* - PEAR_Exception(string $message, PEAR_Error $cause, int $code);
* - PEAR_Exception(string $message, array $causes);
* - PEAR_Exception(string $message, array $causes, int $code);
* @param string exception message
* @param int|Exception|PEAR_Error|array|null exception cause
* @param int|null exception code or null
*/
public function __construct($message, $p2 = null, $p3 = null)
{
if (is_int($p2)) {
$code = $p2;
$this->cause = null;
} elseif (is_object($p2) || is_array($p2)) {
// using is_object allows both Exception and PEAR_Error
if (is_object($p2) && !($p2 instanceof Exception)) {
if (!class_exists('PEAR_Error') || !($p2 instanceof PEAR_Error)) {
throw new PEAR_Exception('exception cause must be Exception, ' .
'array, or PEAR_Error');
}
}
$code = $p3;
if (is_array($p2) && isset($p2['message'])) {
// fix potential problem of passing in a single warning
$p2 = array($p2);
}
$this->cause = $p2;
} else {
$code = null;
$this->cause = null;
}
parent::__construct($message, $code);
$this->signal();
}
/**
* @param mixed $callback - A valid php callback, see php func is_callable()
* - A PEAR_Exception::OBSERVER_* constant
* - An array(const PEAR_Exception::OBSERVER_*,
* mixed $options)
* @param string $label The name of the observer. Use this if you want
* to remove it later with removeObserver()
*/
public static function addObserver($callback, $label = 'default')
{
self::$_observers[$label] = $callback;
}
public static function removeObserver($label = 'default')
{
unset(self::$_observers[$label]);
}
/**
* @return int unique identifier for an observer
*/
public static function getUniqueId()
{
return self::$_uniqueid++;
}
private function signal()
{
foreach (self::$_observers as $func) {
if (is_callable($func)) {
call_user_func($func, $this);
continue;
}
settype($func, 'array');
switch ($func[0]) {
case self::OBSERVER_PRINT :
$f = (isset($func[1])) ? $func[1] : '%s';
printf($f, $this->getMessage());
break;
case self::OBSERVER_TRIGGER :
$f = (isset($func[1])) ? $func[1] : E_USER_NOTICE;
trigger_error($this->getMessage(), $f);
break;
case self::OBSERVER_DIE :
$f = (isset($func[1])) ? $func[1] : '%s';
die(printf($f, $this->getMessage()));
break;
default:
trigger_error('invalid observer type', E_USER_WARNING);
}
}
}
/**
* Return specific error information that can be used for more detailed
* error messages or translation.
*
* This method may be overridden in child exception classes in order
* to add functionality not present in PEAR_Exception and is a placeholder
* to define API
*
* The returned array must be an associative array of parameter => value like so:
* <pre>
* array('name' => $name, 'context' => array(...))
* </pre>
* @return array
*/
public function getErrorData()
{
return array();
}
/**
* Returns the exception that caused this exception to be thrown
* @access public
* @return Exception|array The context of the exception
*/
public function getCause()
{
return $this->cause;
}
/**
* Function must be public to call on caused exceptions
* @param array
*/
public function getCauseMessage(&$causes)
{
$trace = $this->getTraceSafe();
$cause = array('class' => get_class($this),
'message' => $this->message,
'file' => 'unknown',
'line' => 'unknown');
if (isset($trace[0])) {
if (isset($trace[0]['file'])) {
$cause['file'] = $trace[0]['file'];
$cause['line'] = $trace[0]['line'];
}
}
$causes[] = $cause;
if ($this->cause instanceof PEAR_Exception) {
$this->cause->getCauseMessage($causes);
} elseif ($this->cause instanceof Exception) {
$causes[] = array('class' => get_class($this->cause),
'message' => $this->cause->getMessage(),
'file' => $this->cause->getFile(),
'line' => $this->cause->getLine());
} elseif (class_exists('PEAR_Error') && $this->cause instanceof PEAR_Error) {
$causes[] = array('class' => get_class($this->cause),
'message' => $this->cause->getMessage(),
'file' => 'unknown',
'line' => 'unknown');
} elseif (is_array($this->cause)) {
foreach ($this->cause as $cause) {
if ($cause instanceof PEAR_Exception) {
$cause->getCauseMessage($causes);
} elseif ($cause instanceof Exception) {
$causes[] = array('class' => get_class($cause),
'message' => $cause->getMessage(),
'file' => $cause->getFile(),
'line' => $cause->getLine());
} elseif (class_exists('PEAR_Error') && $cause instanceof PEAR_Error) {
$causes[] = array('class' => get_class($cause),
'message' => $cause->getMessage(),
'file' => 'unknown',
'line' => 'unknown');
} elseif (is_array($cause) && isset($cause['message'])) {
// PEAR_ErrorStack warning
$causes[] = array(
'class' => $cause['package'],
'message' => $cause['message'],
'file' => isset($cause['context']['file']) ?
$cause['context']['file'] :
'unknown',
'line' => isset($cause['context']['line']) ?
$cause['context']['line'] :
'unknown',
);
}
}
}
}
public function getTraceSafe()
{
if (!isset($this->_trace)) {
$this->_trace = $this->getTrace();
if (empty($this->_trace)) {
$backtrace = debug_backtrace();
$this->_trace = array($backtrace[count($backtrace)-1]);
}
}
return $this->_trace;
}
public function getErrorClass()
{
$trace = $this->getTraceSafe();
return $trace[0]['class'];
}
public function getErrorMethod()
{
$trace = $this->getTraceSafe();
return $trace[0]['function'];
}
public function __toString()
{
if (isset($_SERVER['REQUEST_URI'])) {
return $this->toHtml();
}
return $this->toText();
}
public function toHtml()
{
$trace = $this->getTraceSafe();
$causes = array();
$this->getCauseMessage($causes);
$html = '<table style="border: 1px" cellspacing="0">' . "\n";
foreach ($causes as $i => $cause) {
$html .= '<tr><td colspan="3" style="background: #ff9999">'
. str_repeat('-', $i) . ' <b>' . $cause['class'] . '</b>: '
. htmlspecialchars($cause['message']) . ' in <b>' . $cause['file'] . '</b> '
. 'on line <b>' . $cause['line'] . '</b>'
. "</td></tr>\n";
}
$html .= '<tr><td colspan="3" style="background-color: #aaaaaa; text-align: center; font-weight: bold;">Exception trace</td></tr>' . "\n"
. '<tr><td style="text-align: center; background: #cccccc; width:20px; font-weight: bold;">#</td>'
. '<td style="text-align: center; background: #cccccc; font-weight: bold;">Function</td>'
. '<td style="text-align: center; background: #cccccc; font-weight: bold;">Location</td></tr>' . "\n";
foreach ($trace as $k => $v) {
$html .= '<tr><td style="text-align: center;">' . $k . '</td>'
. '<td>';
if (!empty($v['class'])) {
$html .= $v['class'] . $v['type'];
}
$html .= $v['function'];
$args = array();
if (!empty($v['args'])) {
foreach ($v['args'] as $arg) {
if (is_null($arg)) $args[] = 'null';
elseif (is_array($arg)) $args[] = 'Array';
elseif (is_object($arg)) $args[] = 'Object('.get_class($arg).')';
elseif (is_bool($arg)) $args[] = $arg ? 'true' : 'false';
elseif (is_int($arg) || is_double($arg)) $args[] = $arg;
else {
$arg = (string)$arg;
$str = htmlspecialchars(substr($arg, 0, 16));
if (strlen($arg) > 16) $str .= '&hellip;';
$args[] = "'" . $str . "'";
}
}
}
$html .= '(' . implode(', ',$args) . ')'
. '</td>'
. '<td>' . (isset($v['file']) ? $v['file'] : 'unknown')
. ':' . (isset($v['line']) ? $v['line'] : 'unknown')
. '</td></tr>' . "\n";
}
$html .= '<tr><td style="text-align: center;">' . ($k+1) . '</td>'
. '<td>{main}</td>'
. '<td>&nbsp;</td></tr>' . "\n"
. '</table>';
return $html;
}
public function toText()
{
$causes = array();
$this->getCauseMessage($causes);
$causeMsg = '';
foreach ($causes as $i => $cause) {
$causeMsg .= str_repeat(' ', $i) . $cause['class'] . ': '
. $cause['message'] . ' in ' . $cause['file']
. ' on line ' . $cause['line'] . "\n";
}
return $causeMsg . $this->getTraceAsString();
}
}

339
src/diagnostic.php Normal file
View File

@ -0,0 +1,339 @@
#!/usr/bin/php -q
<?php
/*
$Id: diagnostic.php 2014/05/19 alban Exp $
----------------------------------------------------------------------
AlternC - Web Hosting System
Copyright (C) 2002 by the AlternC Development Team.
http://alternc.org/
----------------------------------------------------------------------
Based on:
Valentin Lacambre's web hosting softwares: http://altern.org/
----------------------------------------------------------------------
LICENSE
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License (GPL)
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
To read the license please visit http://www.gnu.org/copyleft/gpl.html
----------------------------------------------------------------------
Original Author of file: alban
Purpose of file: Provide a diagnostic of the server state
----------------------------------------------------------------------
*/
/*
Handles diagnostics of an alternc server.
Notes
The diagnostic files are located by default in /var/lib/alternc/diagnostics
*/
/**
* Attempts to load a class in multiple path, the PSR-0 or old style way
*
* @staticvar array $srcPathList
* @staticvar boolean $init
* @param string $class_name
* @return boolean
*/
function __autoload($class_name)
{
// Contains (Namespace) => directory
static $srcPathList = array();
static $init;
// Attempts to set include path and directories once
if( is_null( $init )){
// Sets init flag
$init = true;
// Sets a contextual directory
$srcPathList["standard"] = __DIR__."/../lib";
// Updates include_path according to this list
$includePathList = explode(PATH_SEPARATOR, get_include_path());
foreach($srcPathList as $path){
if ( !in_array($path, $includePathList)){
$includePathList[] = $path;
}
}
// Reverses the path for search efficiency
$finalIncludePathList = array_reverse($includePathList);
// Sets the updated include_path
set_include_path(implode(PATH_SEPARATOR, $finalIncludePathList));
}
// Accepts old Foo_Bar namespacing
if(preg_match("/_/", $class_name)){
$file_name = str_replace('_', DIRECTORY_SEPARATOR, $class_name) . '.php';
// Accepts 5.3 Foo\Bar PSR-0 namespacing
} else if(preg_match("/\\/", $class_name)){
$file_name = str_replace('\\', DIRECTORY_SEPARATOR, ltrim($class_name,'\\')) . '.php';
// Accepts non namespaced classes
} else {
$file_name = $class_name . '.php';
}
// Attempts to find file in namespace
foreach($srcPathList as $namespace => $path ){
$file_path = $path.DIRECTORY_SEPARATOR.$file_name;
if(is_file($file_path) && is_readable($file_path)){
require $file_path;
return true;
}
}
// Failed to find file
return false;
}
// ==================================================================
// ==================================================================
// alternc config
// ==================================================================
// ==================================================================
$version = "3.2";
// alternc 1.0
if(is_file("/usr/share/alternc/panel/class/config_nochk.php")){
require_once("/usr/share/alternc/panel/class/config_nochk.php");
}else{
$version = "1.0";
require_once("/var/alternc/bureau/class/config_nochk.php");
include "../bureau/class/class_system_bind.php";
}
$directoryInstance = new Alternc_Diagnostic_Directory("/tmp/diagnostic");
// instanciation of the diagnosticManager service
$diagnosticManager = new Alternc_Diagnostic_Manager( array(
"directoryInstance" => $directoryInstance,
"formatInstance" => new Alternc_Diagnostic_Format_Json($directoryInstance),
"version" => $version
));
// ==================================================================
// ==================================================================
// Console parser configuration
// ==================================================================
// ==================================================================
$consoleParser = new Alternc_Diagnostic_Console();
$createCommmand = $consoleParser->addCommand('create', array('multiple'=>true,"alias"=>"c","description" => "Creates a new diagnostic"));
$createCommmand->addOption('services', array(
'short_name' => '-s',
'long_name' => '--services',
'action' => 'StoreString',
'default' => 'apache2,dns,mail,system,mailman,mysql,panel,ftp',
'description' => 'Sets the services to use for diagnostics separated by comma
ex: -d apache2,dns,mail',
'help_name' => 'services'
));
$createCommmand->addOption('format', array(
'short_name' => '-f',
'long_name' => '--format',
'action' => 'StoreString',
'default' => 'json',
'description' => 'Sets the format of the diagnostic file : json (default)',
'help_name' => 'format'
));
$indexCommmand = $consoleParser->addCommand('index', array('multiple'=>false,"alias"=>"i","description" => "Shows all available diagnostics"));
$compareCommmand = $consoleParser->addCommand('compare', array('multiple'=>false,"alias"=>"x","description" => "Removes one or more diagnotics"));
$compareCommmand = $consoleParser->addCommand('show', array('multiple'=>false,"alias"=>"s","description" => "Prints a diagnotic content"));
$deleteCommmand = $consoleParser->addCommand('delete', array('multiple'=>false,"alias"=>"d","description" => "Deletes diagnostic files"));
// Attempts to parse command line
try {
$result = $consoleParser->parse();
if ($result->command_name){
$command_name = $result->command_name;
$command = $result->command;
}else{
throw new \Exception("Command missing, use -h to learn about available commands.");
}
if( !method_exists($diagnosticManager, $command_name)){
throw new \Exception("Invalid command : $command");
}
$diagnosticManager->$command_name($command);
} catch (\Exception $exc) {
$consoleParser->displayError($exc->getMessage());
}
/*
// Put this var to 1 if you want to enable debug prints
$admin->stop_if_jobs_locked();
$LOCK_FIL E= '/var/run/alternc/do_actions_cron.lock';
$SCRIP T= '/usr/bin/php do_actions.php';
$MY_PI D= getmypid();
$FIXPER M= '/usr/lib/alternc/fixperms.sh';
// Check if script isn't already running
if (file_exists($LOCK_FILE) !== false){
d("Lock file already exists. ");
// Check if file is in process list
$PI D= file_get_contents($LOCK_FILE);
d("My PID is $MY_PID, PID in the lock file is $PID");
if ($PID == exec("pidof $SCRIPT | tr ' ' '\n' | grep -v $MY_PID")){
// Previous cron is not finished yet, just exit
d("Previous cron is already running, we just exit and let it finish :-)");
exit(0);
}else{
// Previous cron failed!
$error_raise .= "Lock file already exists. No process with PID $PID found! Previous cron failed...\n";
d("Removing lock file and trying to process the failed action...");
// Delete the lock and continue to the next action
unlink($LOCK_FILE);
// Lock with the current script's PID
if (file_put_contents($LOCK_FILE,$MY_PID) === false){
$error_raise .= "Cannot open/write $LOCK_FILE\n";
mail_it();
exit(1);
}
// Get the action(s) that was processing when previous script failed
// (Normally, there will be at most 1 job pending... but who know?)
while($cc=$action->get_job()){
$ c= $cc[0];
$param s= unserialize($c["parameters"]);
// We can resume these types of action, so we reset the job to process it later
d("Previous job was the n°".$c["id"]." : '".$c["type"]."'");
if($c["type"] == "CREATE_FILE" && is_dir(dirname($params["file"])) || $c["type"] == "CREATE_DIR" || $c["type"] == "DELETE" || $c["type"] == "FIXDIR" || $c["type"] == "FIXFILE"){
d("Reset of the job! So it will be resumed...");
$action->reset_job($c["id"]);
}else{
// We can't resume the others types, notify the fail and finish this action
$error_raise .= "Can't resume the job n°".$c["id"]." action '".$c["type"]."', finishing it with a fail status.\n";
if(!$action->finish($c["id"],"Fail: Previous script crashed while processing this action, cannot resume it.")){
$error_raise .= "Cannot finish the action! Error while inserting the error value in the DB for action n°".$c["id"]." : action '".$c["type"]."'\n";
break; // Else we go into an infinite loop... AAAAHHHHHH
}
}
}
}
}else{
// Lock with the current script's PID
if (file_put_contents($LOCK_FILE,$MY_PID) === false){
$error_raise .= "Cannot open/write $LOCK_FILE\n";
mail_it();
exit(1);
}
}
//We get the next action to do
while ($rr=$action->get_action()){
$ r= $rr[0];
$retur n= "OK";
// Do we have to do this action with a specific user?
if($r["user"] != "root")
$S U= "su ".$r["user"]." 2>&1 ;";
else
$S U= "";
unset($output);
// We lock the action
d("-----------\nBeginning action n°".$r["id"]);
$action->begin($r["id"]);
// We process it
$param s= @unserialize($r["parameters"]);
// We exec with the specified user
d("Executing action '".$r["type"]."' with user '".$r["user"]."'");
switch ($r["type"]){
case "FIX_USER" :
// Create the directory and make parent directories as needed
@exec("$FIXPERM -u ".$params["uid"]." 2>&1", $trash, $code);
break;
case "CREATE_FILE" :
if(!file_exists($params["file"]))
@exec("$SU touch ".$params["file"]." 2>&1 ; echo '".$params["content"]."' > '".$params["file"]."' 2>&1", $output);
else
$outpu t= array("Fail: file already exists");
break;
case "CREATE_DIR" :
// Create the directory and make parent directories as needed
@exec("$SU mkdir -p ".$params["dir"]." 2>&1",$output);
break;
case "DELETE" :
// Delete file/directory and its contents recursively
@exec("$SU rm -rf ".$params["dir"]." 2>&1", $output);
break;
case "MOVE" :
// If destination dir does not exists, create it
if(!is_dir($params["dst"]))
@exec("$SU mkdir -p ".$params["dst"]." 2>&1",$output);
if(!isset($output[0]))
@exec("$SU mv -f ".$params["src"]." ".$params["dst"]." 2>&1", $output);
break;
case "FIXDIR" :
@exec("$FIXPERM -d ".$params["dir"]." 2>&1", $trash, $code);
if($code!=0)
$output[0]="Fixperms.sh failed, returned error code : $code";
break;
case "FIXFILE" :
@exec("$FIXPERM -f ".$params["file"]." 2>&1", $trash, $code);
if($code!=0)
$output[0]="Fixperms.sh failed, returned error code : $code";
break;
default :
$outpu t= array("Fail: Sorry dude, i do not know this type of action");
break;
}
// Get the error (if exists).
if(isset($output[0])){
$retur n= $output[0];
$error_raise .= "Action n°".$r["id"]." '".$r["type"]."' failed! With user: ".$r["user"]."\nHere is the complete output:\n".print_r($output);
}
// We finished the action, notify the DB.
d("Finishing... return value is : $return\n");
if(!$action->finish($r["id"],addslashes($return))){
$error_raise .= "Cannot finish the action! Error while inserting the error value in the DB for action n°".$c["id"]." : action '".$c["type"]."'\nReturn value: ".addslashes($return)."\n";
break; // Else we go into an infinite loop... AAAAHHHHHH
}
}
// If something have failed, notify it to the admin
if($error_raise !== '')
mail_it();
// Unlock the script
unlink($LOCK_FILE);
// Exit this script
exit(0);
?>
*/