home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / PEAR / System / Daemon / Options.php < prev    next >
Encoding:
PHP Script  |  2008-07-02  |  15.5 KB  |  514 lines

  1. <?php
  2. /* vim: set noai expandtab tabstop=4 softtabstop=4 shiftwidth=4: */
  3. /**
  4.  * System_Daemon turns PHP-CLI scripts into daemons.
  5.  * 
  6.  * PHP version 5
  7.  *
  8.  * @category  System
  9.  * @package   System_Daemon
  10.  * @author    Kevin van Zonneveld <kevin@vanzonneveld.net>
  11.  * @copyright 2008 Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  12.  * @license   http://www.opensource.org/licenses/bsd-license.php New BSD Licence
  13.  * @version   SVN: Release: $Id$
  14.  * @link      http://trac.plutonia.nl/projects/system_daemon
  15.  */
  16.  
  17. /**
  18.  * Mechanism for validating, getting and setting a predefined set of options.
  19.  *
  20.  * @category  System
  21.  * @package   System_Daemon
  22.  * @author    Kevin van Zonneveld <kevin@vanzonneveld.net>
  23.  * @copyright 2008 Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  24.  * @license   http://www.opensource.org/licenses/bsd-license.php New BSD Licence
  25.  * @version   SVN: Release: $Id$
  26.  * @link      http://trac.plutonia.nl/projects/system_daemon
  27.  * 
  28.  */
  29. class System_Daemon_Options
  30. {
  31.     /**
  32.      * Keep track of active state for all Options
  33.      *
  34.      * @var array
  35.      */
  36.     private $_options = array();
  37.     
  38.     /**
  39.      * Definitions for all Options
  40.      *
  41.      * @var array
  42.      */
  43.     private $_definitions = array();
  44.     
  45.     /**
  46.      * Wether all the options have been initialized
  47.      *
  48.      * @var boolean
  49.      */
  50.     private $_isInitialized = false;
  51.  
  52.     /**
  53.      * Holds errors
  54.      *
  55.      * @var array
  56.      */
  57.     public $errors = array();
  58.     
  59.     
  60.     /**
  61.      * Constructor
  62.      * 
  63.      * @param array $definitions The predefined option definitions
  64.      */
  65.     public function __construct($definitions) 
  66.     {
  67.         if (!is_array($definitions) || !count($definitions)) {
  68.             return false;
  69.         }
  70.         
  71.         $this->_definitions = $definitions;
  72.     }
  73.     
  74.     /**
  75.      * Retrieves any option found in $_definitions
  76.      * 
  77.      * @param string $name Name of the Option
  78.      *
  79.      * @return boolean
  80.      */
  81.     public function getOption($name)
  82.     {
  83.         if (!isset($this->_options[$name])) {
  84.             return null;
  85.         }
  86.         return $this->_options[$name];
  87.     }//end getOption()    
  88.     
  89.     /**
  90.      * Gets an array of options found in $_definitions
  91.      *
  92.      * @return array
  93.      */
  94.     public function getOptions()
  95.     {
  96.         return $this->_options;
  97.     }//end getOptions()    
  98.     
  99.     /**
  100.      * Sets any option found in $_definitions
  101.      * 
  102.      * @param string $name  Name of the Option
  103.      * @param mixed  $value Value of the Option
  104.      *
  105.      * @return boolean
  106.      */
  107.     public function setOption($name, $value)
  108.     {
  109.         // Not validated?
  110.         if (!$this->_validate($name, $value, $reason)) {
  111.             // Default not used or failed as well!
  112.             $this->errors[] = "Option ".$name." invalid: ".$reason;
  113.             return false;
  114.         }
  115.         
  116.         $this->_options[$name] = $value;
  117.     }//end setOption()
  118.         
  119.     /**
  120.      * Sets an array of options found in $_definitions
  121.      * 
  122.      * @param array $use_options Array with Options
  123.      *
  124.      * @return boolean
  125.      */
  126.     public function setOptions($use_options)
  127.     {
  128.         $success = true;
  129.         foreach ($use_options as $name=>$value) {
  130.             if (!$this->setOption($name, $value)) {
  131.                 $success = false;
  132.             }
  133.         }
  134.         return $success;
  135.     }//end setOptions()
  136.     
  137.     /**
  138.      * Wether options are initialized
  139.      *
  140.      * @return boolean
  141.      */
  142.     public function isInitialized()
  143.     {
  144.         return $this->_isInitialized;
  145.     }//end isInitialized()        
  146.     
  147.     /**
  148.      * Checks if all the required options are set & met.
  149.      * Initializes, sanitizes & defaults unset variables
  150.      * 
  151.      * @param boolean $premature Whether to do a premature option init
  152.      *
  153.      * @return mixed integer or boolean
  154.      */
  155.     public function init($premature=false) 
  156.     {
  157.         // If already initialized, skip
  158.         if (!$premature && $this->isInitialized()) {
  159.             return true;
  160.         }        
  161.         
  162.         $options_met = 0;
  163.         
  164.         foreach ($this->_definitions as $name=>$definition) {
  165.             // Skip non-required options
  166.             if (!isset($definition["required"]) 
  167.                 || $definition["required"] !== true ) {
  168.                 continue;
  169.             }
  170.             
  171.             // Required options remain
  172.             if (!isset($this->_options[$name])) {                
  173.                 if (!$this->_setDefault($name) && !$premature) {
  174.                     $this->errors[] = "Required option: ".$name. 
  175.                         " not set. No default value available either.";
  176.                     return false;
  177.                 } 
  178.             }
  179.             
  180.             $options_met++;
  181.         }
  182.                 
  183.         if (!$premature) {
  184.             $this->_isInitialized = true;
  185.         }
  186.         
  187.         return $options_met;
  188.         
  189.     }//end init()       
  190.     
  191.     
  192.     
  193.     /**
  194.      * Validates any option found in $_definitions
  195.      * 
  196.      * @param string $name    Name of the Option
  197.      * @param mixed  $value   Value of the Option
  198.      * @param string &$reason Why something does not validate
  199.      *
  200.      * @return boolean
  201.      */
  202.     private function _validate($name, $value, &$reason="")
  203.     {
  204.         $reason = false;
  205.         
  206.         if (!$reason && !isset($this->_definitions[$name])) {
  207.             $reason = "Option ".$name." not found in definitions";
  208.         }
  209.         
  210.         $definition = $this->_definitions[$name];
  211.         
  212.         if (!$reason && !isset($definition["type"])) {
  213.             $reason = "Option ".$name.":type not found in definitions";
  214.         }
  215.         
  216.         // Compile array of allowd main & subtypes
  217.         $_allowedTypes = $this->_allowedTypes($definition["type"]);
  218.         
  219.         // Loop over main & subtypes to detect matching format
  220.         if (!$reason) {
  221.             $type_valid = false;
  222.             foreach ($_allowedTypes as $type_a=>$sub_types) {
  223.                 foreach ($sub_types as $type_b) {
  224.                     
  225.                     // Determine range based on subtype
  226.                     // Range is used to contain an integer or strlen 
  227.                     // between min-max
  228.                     $parts = explode("-", $type_b);
  229.                     $from  = $to = false;
  230.                     if (count($parts) == 2 ) {
  231.                         $from   = $parts[0];
  232.                         $to     = $parts[1];
  233.                         $type_b = "range";
  234.                     }
  235.             
  236.                     switch ($type_a) {
  237.                     case "boolean":
  238.                         $type_valid = is_bool($value);
  239.                         break;
  240.                     case "object":
  241.                         $type_valid = is_object($value) || is_resource($value);
  242.                         break;
  243.                     case "string":
  244.                         switch ($type_b) {
  245.                         case "email":
  246.                             $exp  = "^[a-z0-9]+([._-][a-z0-9]+)*@([a-z0-9]+";
  247.                             $exp .= "([._-][a-z0-9]+))+$";
  248.                             if (eregi($exp, $value)) {
  249.                                 $type_valid = true;
  250.                             }
  251.                             break;
  252.                         case "unix":
  253.                             if ($this->strIsUnix($value)) {
  254.                                 $type_valid = true;
  255.                             }
  256.                             break;
  257.                         case "existing_dirpath":
  258.                             if (is_dir($value)) {
  259.                                 $type_valid = true;
  260.                             }
  261.                             break;
  262.                         case "existing_filepath":
  263.                             if (is_file($value)) {
  264.                                 $type_valid = true;
  265.                             }
  266.                             break;
  267.                         case "creatable_filepath":
  268.                             if (is_dir(dirname($value)) 
  269.                                 && is_writable(dirname($value))) {
  270.                                 $type_valid = true;
  271.                             }
  272.                             break;
  273.                         case "normal":
  274.                         default: 
  275.                             // String?
  276.                             if (!is_resource($value) && !is_array($value) 
  277.                                 && !is_object($value)) {
  278.                                 // Range?
  279.                                 if ($from === false && $to === false) {
  280.                                     $type_valid = true;
  281.                                 } else {
  282.                                     // Enfore range as well
  283.                                     if (strlen($value) >= $from 
  284.                                         && strlen($value) <= $to) {
  285.                                         $type_valid = true;
  286.                                     }
  287.                                 }
  288.                             }
  289.                             break;
  290.                         }
  291.                         break;
  292.                     case "number":
  293.                         switch ($type_b) {
  294.                         default:
  295.                         case "normal":
  296.                             // Numeric?
  297.                             if (is_numeric($value)) {
  298.                                 // Range ?
  299.                                 if ($from === false && $to === false) {
  300.                                     $type_valid = true;
  301.                                 } else {
  302.                                     // Enfore range as well
  303.                                     if ($value >= $from && $value <= $to) {
  304.                                         $type_valid = true;
  305.                                     }
  306.                                 }
  307.                             }
  308.                             break;                            
  309.                         }
  310.                         break;
  311.                     default:
  312.                         $this->errors[] =  "Type ".
  313.                             $type_a." not defined";
  314.                         break;
  315.                     }                
  316.                 }
  317.             }
  318.         }
  319.         
  320.         if (!$type_valid) {
  321.             $reason = "Option ".$name." does not match type: ".
  322.                 $definition["type"]."";
  323.         }
  324.         
  325.         if ($reason !== false) {
  326.             $this->errors[] = $reason;
  327.             return false;
  328.         }
  329.         
  330.         return true;
  331.     }//end _validate()    
  332.  
  333.     /**
  334.      * Sets any option found in $_definitions to its default value
  335.      * 
  336.      * @param string $name Name of the Option
  337.      *
  338.      * @return boolean
  339.      */
  340.     private function _setDefault($name)
  341.     {
  342.         if (!isset($this->_definitions[$name])) {
  343.             return false;
  344.         }        
  345.         $definition = $this->_definitions[$name];
  346.  
  347.         if (!isset($definition["type"])) {
  348.             return false;
  349.         }
  350.         if (!isset($definition["default"])) {
  351.             return false;
  352.         }
  353.         
  354.         // Compile array of allowd main & subtypes
  355.         $_allowedTypes = $this->_allowedTypes($definition["type"]);        
  356.         
  357.         $type  = $definition["type"];
  358.         $value = $definition["default"];
  359.  
  360.         if (isset($_allowedTypes["string"]) && !is_bool($value)) {
  361.             // Replace variables
  362.             $value = preg_replace_callback('/\{([^\{\}]+)\}/is', 
  363.                 array("self", "_replaceVars"), $value);
  364.             
  365.             // Replace functions
  366.             $value = preg_replace_callback('/\@([\w_]+)\(([^\)]+)\)/is', 
  367.                 array("self", "_replaceFuncs"), $value);
  368.         }
  369.                         
  370.         $this->_options[$name] = $value;
  371.         return true;
  372.     }//end _setDefault()    
  373.     
  374.     /**
  375.      * Callback function to replace variables in defaults
  376.      *
  377.      * @param array $matches Matched functions
  378.      * 
  379.      * @return string
  380.      */
  381.     private function _replaceVars($matches)
  382.     {
  383.         // Init
  384.         $allowedVars = array(
  385.             "SERVER.SCRIPT_NAME", 
  386.             "OPTIONS.*"
  387.         );
  388.         $filterVars  = array(
  389.             "SERVER.SCRIPT_NAME"=>array("realpath")
  390.         );
  391.         
  392.         $fullmatch          = array_shift($matches);
  393.         $fullvar            = array_shift($matches);
  394.         $parts              = explode(".", $fullvar);
  395.         list($source, $var) = $parts;
  396.         $var_use            = false;
  397.         $var_key            = $source.".".$var; 
  398.         
  399.         // Allowed
  400.         if (!in_array($var_key, $allowedVars) 
  401.             && !in_array($source.".*", $allowedVars)) {
  402.             return "FORBIDDEN_VAR_".$var_key;
  403.         }
  404.         
  405.         // Mapping of textual sources to real sources
  406.         if ($source == "SERVER") {
  407.             $source_use = &$_SERVER;
  408.         } elseif ($source == "OPTIONS") {
  409.             $source_use = &$this->_options; 
  410.         } else {
  411.             $source_use = false;
  412.         }
  413.         
  414.         // Exists?
  415.         if ($source_use === false) {
  416.             return "UNUSABLE_VARSOURCE_".$source;
  417.         }
  418.         if (!isset($source_use[$var])) { 
  419.             return "NONEXISTING_VAR_".$var_key;     
  420.         }
  421.         
  422.         $var_use = $source_use[$var];
  423.         
  424.         // Filtering
  425.         if (isset($filterVars[$var_key]) && is_array($filterVars[$var_key])) {
  426.             foreach ($filterVars[$var_key] as $filter_function) {
  427.                 if (!function_exists($filter_function)) {
  428.                     return "NONEXISTING_FILTER_".$filter_function;
  429.                 }
  430.                 $var_use = call_user_func($filter_function, $var_use);
  431.             }
  432.         }        
  433.         
  434.         return $var_use;        
  435.     }//end _replaceVars()
  436.     
  437.     /**
  438.      * Callback function to replace function calls in defaults
  439.      *
  440.      * @param array $matches Matched functions
  441.      * 
  442.      * @return string
  443.      */
  444.     private function _replaceFuncs($matches)
  445.     {
  446.         $allowedFunctions = array("basename", "dirname");
  447.         
  448.         $fullmatch = array_shift($matches);
  449.         $function  = array_shift($matches);
  450.         $arguments = $matches;
  451.         
  452.         if (!in_array($function, $allowedFunctions)) {
  453.             return "FORBIDDEN_FUNCTION_".$function;            
  454.         }
  455.         
  456.         if (!function_exists($function)) {
  457.             return "NONEXISTING_FUNCTION_".$function; 
  458.         }
  459.         
  460.         return call_user_func_array($function, $arguments);
  461.     }//end _replaceFuncs()
  462.  
  463.     /**
  464.      * Compile array of allowed types
  465.      * 
  466.      * @param string $str String that contains allowed type information
  467.      * 
  468.      * @return array      
  469.      */
  470.     private function _allowedTypes($str) 
  471.     {
  472.         $allowed_types = array();
  473.         $raw_types     = explode("|", $str);
  474.         foreach ($raw_types as $raw_type) {
  475.             $raw_subtypes = explode("/", $raw_type);
  476.             $type_a       = array_shift($raw_subtypes);
  477.             if (!count($raw_subtypes)) {
  478.                 $raw_subtypes = array("normal");
  479.             } 
  480.             $allowed_types[$type_a] = $raw_subtypes;
  481.         }
  482.         return $allowed_types;
  483.     }    
  484.     
  485.     
  486.     
  487.     /**
  488.      * Check if a string has a unix proof format (stripped spaces, 
  489.      * special chars, etc)
  490.      *
  491.      * @param string $str What string to test for unix compliance
  492.      * 
  493.      * @return boolean
  494.      */   
  495.     protected function strIsUnix( $str )
  496.     {
  497.         return preg_match('/^[a-z0-9_]+$/', $str);
  498.     }//end strIsUnix()
  499.  
  500.     /**
  501.      * Convert a string to a unix proof format (strip spaces, 
  502.      * special chars, etc)
  503.      * 
  504.      * @param string $str What string to make unix compliant
  505.      * 
  506.      * @return string
  507.      */
  508.     protected function strToUnix( $str )
  509.     {
  510.         return preg_replace('/[^0-9a-z_]/', '', strtolower($str));
  511.     }//end strToUnix()
  512.         
  513. }//end class
  514. ?>