]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
Update PEAR to v1.10.9 and patch it so it works quietly
authorDiogo Cordeiro <diogo@fc.up.pt>
Sun, 28 Apr 2019 22:39:36 +0000 (23:39 +0100)
committerDiogo Cordeiro <diogo@fc.up.pt>
Sun, 28 Apr 2019 22:39:36 +0000 (23:39 +0100)
extlib/DB.php
extlib/PEAR.php
extlib/PEAR/ErrorStack.php
extlib/PEAR/Exception.php
extlib/PEAR/FixPHP5PEARWarnings.php [deleted file]
extlib/PEAR5.php [deleted file]
extlib/System.php

index 1aa9477065ba1e20a6621a1d83fb02f74b32ef6b..e43f6091aba107862d52cb1e7b211740e1470434 100644 (file)
@@ -164,7 +164,7 @@ define('DB_ERROR_CONNECT_FAILED', -24);
 /**
  * The PHP extension needed for this DBMS could not be found
  */
-define('DB_ERROR_EXTENSION_NOT_FOUND',-25);
+define('DB_ERROR_EXTENSION_NOT_FOUND', -25);
 
 /**
  * The present user has inadequate permissions to perform the task requestd
@@ -179,7 +179,7 @@ define('DB_ERROR_NOSUCHDB', -27);
 /**
  * Tried to insert a null value into a column that doesn't allow nulls
  */
-define('DB_ERROR_CONSTRAINT_NOT_NULL',-29);
+define('DB_ERROR_CONSTRAINT_NOT_NULL', -29);
 /**#@-*/
 
 
@@ -212,7 +212,7 @@ define('DB_PARAM_OPAQUE', 2);
  *
  * The value should not be quoted or escaped.
  */
-define('DB_PARAM_MISC',   3);
+define('DB_PARAM_MISC', 3);
 /**#@-*/
 
 
@@ -287,7 +287,7 @@ define('DB_FETCHMODE_FLIPPED', 4);
  * Old fetch modes.  Left here for compatibility.
  */
 define('DB_GETMODE_ORDERED', DB_FETCHMODE_ORDERED);
-define('DB_GETMODE_ASSOC',   DB_FETCHMODE_ASSOC);
+define('DB_GETMODE_ASSOC', DB_FETCHMODE_ASSOC);
 define('DB_GETMODE_FLIPPED', DB_FETCHMODE_FLIPPED);
 /**#@-*/
 
@@ -437,14 +437,14 @@ class DB
      * Create a new DB object for the specified database type but don't
      * connect to the database
      *
-     * @param string $type     the database type (eg "mysql")
-     * @param array  $options  an associative array of option names and values
+     * @param string $type the database type (eg "mysql")
+     * @param array $options an associative array of option names and values
      *
      * @return object  a new DB object.  A DB_Error object on failure.
      *
      * @see DB_common::setOption()
      */
-    public static function factory($type, $options = false)
+    public static function factory($type, $options = [])
     {
         if (!is_array($options)) {
             $options = array('persistent' => $options);
@@ -461,9 +461,9 @@ class DB
 
         if (!class_exists($classname)) {
             $tmp = PEAR::raiseError(null, DB_ERROR_NOT_FOUND, null, null,
-                                    "Unable to include the DB/{$type}.php"
-                                    . " file for '$dsn'",
-                                    'DB_Error', true);
+                "Unable to include the DB/{$type}.php"
+                . " file for '$dsn'",
+                'DB_Error', true);
             return $tmp;
         }
 
@@ -482,6 +482,21 @@ class DB
     // }}}
     // {{{ connect()
 
+    /**
+     * Determines if a variable is a DB_Error object
+     *
+     * @param mixed $value the variable to check
+     *
+     * @return bool  whether $value is DB_Error object
+     */
+    public static function isError($value)
+    {
+        return is_object($value) && is_a($value, 'DB_Error');
+    }
+
+    // }}}
+    // {{{ apiVersion()
+
     /**
      * Create a new DB object including a connection to the specified database
      *
@@ -501,9 +516,9 @@ class DB
      * }
      * </code>
      *
-     * @param mixed $dsn      the string "data source name" or array in the
+     * @param mixed $dsn the string "data source name" or array in the
      *                         format returned by DB::parseDSN()
-     * @param array $options  an associative array of option names and values
+     * @param array $options an associative array of option names and values
      *
      * @return object  a new DB object.  A DB_Error object on failure.
      *
@@ -538,10 +553,10 @@ class DB
         $classname = "DB_${type}";
         if (!class_exists($classname)) {
             $tmp = PEAR::raiseError(null, DB_ERROR_NOT_FOUND, null, null,
-                                    "Unable to include the DB/{$type}.php"
-                                    . " file for '"
-                                    . DB::getDSNString($dsn, true) . "'",
-                                    'DB_Error', true);
+                "Unable to include the DB/{$type}.php"
+                . " file for '"
+                . DB::getDSNString($dsn, true) . "'",
+                'DB_Error', true);
             return $tmp;
         }
 
@@ -567,136 +582,9 @@ class DB
         return $obj;
     }
 
-    // }}}
-    // {{{ apiVersion()
-
-    /**
-     * Return the DB API version
-     *
-     * @return string  the DB API version number
-     */
-    function apiVersion()
-    {
-        return '1.9.2';
-    }
-
     // }}}
     // {{{ isError()
 
-    /**
-     * Determines if a variable is a DB_Error object
-     *
-     * @param mixed $value  the variable to check
-     *
-     * @return bool  whether $value is DB_Error object
-     */
-    public static function isError($value)
-    {
-        return is_object($value) && is_a($value, 'DB_Error');          
-    }
-
-    // }}}
-    // {{{ isConnection()
-
-    /**
-     * Determines if a value is a DB_<driver> object
-     *
-     * @param mixed $value  the value to test
-     *
-     * @return bool  whether $value is a DB_<driver> object
-     */
-    public static function isConnection($value)
-    {
-        return (is_object($value) &&
-                is_subclass_of($value, 'db_common') &&
-                method_exists($value, 'simpleQuery'));
-    }
-
-    // }}}
-    // {{{ isManip()
-
-    /**
-     * Tell whether a query is a data manipulation or data definition query
-     *
-     * Examples of data manipulation queries are INSERT, UPDATE and DELETE.
-     * Examples of data definition queries are CREATE, DROP, ALTER, GRANT,
-     * REVOKE.
-     *
-     * @param string $query  the query
-     *
-     * @return boolean  whether $query is a data manipulation query
-     */
-    public static function isManip($query)
-    {
-        $manips = 'INSERT|UPDATE|DELETE|REPLACE|'
-                . 'CREATE|DROP|'
-                . 'LOAD DATA|SELECT .* INTO .* FROM|COPY|'
-                . 'ALTER|GRANT|REVOKE|'
-                . 'LOCK|UNLOCK';
-        if (preg_match('/^\s*"?(' . $manips . ')\s+/i', $query)) {
-            return true;
-        }
-        return false;
-    }
-
-    // }}}
-    // {{{ errorMessage()
-
-    /**
-     * Return a textual error message for a DB error code
-     *
-     * @param integer $value  the DB error code
-     *
-     * @return string  the error message or false if the error code was
-     *                  not recognized
-     */
-    public static function errorMessage($value)
-    {
-        static $errorMessages;
-        if (!isset($errorMessages)) {
-            $errorMessages = array(
-                DB_ERROR                    => 'unknown error',
-                DB_ERROR_ACCESS_VIOLATION   => 'insufficient permissions',
-                DB_ERROR_ALREADY_EXISTS     => 'already exists',
-                DB_ERROR_CANNOT_CREATE      => 'can not create',
-                DB_ERROR_CANNOT_DROP        => 'can not drop',
-                DB_ERROR_CONNECT_FAILED     => 'connect failed',
-                DB_ERROR_CONSTRAINT         => 'constraint violation',
-                DB_ERROR_CONSTRAINT_NOT_NULL=> 'null value violates not-null constraint',
-                DB_ERROR_DIVZERO            => 'division by zero',
-                DB_ERROR_EXTENSION_NOT_FOUND=> 'extension not found',
-                DB_ERROR_INVALID            => 'invalid',
-                DB_ERROR_INVALID_DATE       => 'invalid date or time',
-                DB_ERROR_INVALID_DSN        => 'invalid DSN',
-                DB_ERROR_INVALID_NUMBER     => 'invalid number',
-                DB_ERROR_MISMATCH           => 'mismatch',
-                DB_ERROR_NEED_MORE_DATA     => 'insufficient data supplied',
-                DB_ERROR_NODBSELECTED       => 'no database selected',
-                DB_ERROR_NOSUCHDB           => 'no such database',
-                DB_ERROR_NOSUCHFIELD        => 'no such field',
-                DB_ERROR_NOSUCHTABLE        => 'no such table',
-                DB_ERROR_NOT_CAPABLE        => 'DB backend not capable',
-                DB_ERROR_NOT_FOUND          => 'not found',
-                DB_ERROR_NOT_LOCKED         => 'not locked',
-                DB_ERROR_SYNTAX             => 'syntax error',
-                DB_ERROR_UNSUPPORTED        => 'not supported',
-                DB_ERROR_TRUNCATED          => 'truncated',
-                DB_ERROR_VALUE_COUNT_ON_ROW => 'value count on row',
-                DB_OK                       => 'no error',
-            );
-        }
-
-        if (DB::isError($value)) {
-            $value = $value->getCode();
-        }
-
-        return isset($errorMessages[$value]) ? $errorMessages[$value]
-                     : $errorMessages[DB_ERROR];
-    }
-
-    // }}}
-    // {{{ parseDSN()
-
     /**
      * Parse a data source name
      *
@@ -734,14 +622,14 @@ class DB
     public static function parseDSN($dsn)
     {
         $parsed = array(
-            'phptype'  => false,
+            'phptype' => false,
             'dbsyntax' => false,
             'username' => false,
             'password' => false,
             'protocol' => false,
             'hostspec' => false,
-            'port'     => false,
-            'socket'   => false,
+            'port' => false,
+            'socket' => false,
             'database' => false,
         );
 
@@ -765,10 +653,10 @@ class DB
         // Get phptype and dbsyntax
         // $str => phptype(dbsyntax)
         if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) {
-            $parsed['phptype']  = $arr[1];
+            $parsed['phptype'] = $arr[1];
             $parsed['dbsyntax'] = !$arr[2] ? $arr[1] : $arr[2];
         } else {
-            $parsed['phptype']  = $str;
+            $parsed['phptype'] = $str;
             $parsed['dbsyntax'] = $str;
         }
 
@@ -778,7 +666,7 @@ class DB
 
         // Get (if found): username and password
         // $dsn => username:password@protocol+hostspec/database
-        if (($at = strrpos($dsn,'@')) !== false) {
+        if (($at = strrpos($dsn, '@')) !== false) {
             $str = substr($dsn, 0, $at);
             $dsn = substr($dsn, $at + 1);
             if (($pos = strpos($str, ':')) !== false) {
@@ -793,9 +681,9 @@ class DB
 
         if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match)) {
             // $dsn => proto(proto_opts)/database
-            $proto       = $match[1];
-            $proto_opts  = $match[2] ? $match[2] : false;
-            $dsn         = $match[3];
+            $proto = $match[1];
+            $proto_opts = $match[2] ? $match[2] : false;
+            $dsn = $match[3];
 
         } else {
             // $dsn => protocol+hostspec/database (old format)
@@ -851,7 +739,7 @@ class DB
     }
 
     // }}}
-    // {{{ getDSNString()
+    // {{{ isConnection()
 
     /**
      * Returns the given DSN in a string format suitable for output.
@@ -860,12 +748,13 @@ class DB
      * @param boolean true to hide the password, false to include it
      * @return string
      */
-    public static function getDSNString($dsn, $hidePassword) {
+    public static function getDSNString($dsn, $hidePassword)
+    {
         /* Calling parseDSN will ensure that we have all the array elements
          * defined, and means that we deal with strings and array in the same
          * manner. */
         $dsnArray = DB::parseDSN($dsn);
-        
+
         if ($hidePassword) {
             $dsnArray['password'] = 'PASSWORD';
         }
@@ -875,42 +764,42 @@ class DB
         if (is_string($dsn) && strpos($dsn, 'tcp') === false && $dsnArray['protocol'] == 'tcp') {
             $dsnArray['protocol'] = false;
         }
-        
+
         // Now we just have to construct the actual string. This is ugly.
         $dsnString = $dsnArray['phptype'];
         if ($dsnArray['dbsyntax']) {
-            $dsnString .= '('.$dsnArray['dbsyntax'].')';
+            $dsnString .= '(' . $dsnArray['dbsyntax'] . ')';
         }
         $dsnString .= '://'
-                     .$dsnArray['username']
-                     .':'
-                     .$dsnArray['password']
-                     .'@'
-                     .$dsnArray['protocol'];
+            $dsnArray['username']
+            ':'
+            $dsnArray['password']
+            '@'
+            $dsnArray['protocol'];
         if ($dsnArray['socket']) {
-            $dsnString .= '('.$dsnArray['socket'].')';
+            $dsnString .= '(' . $dsnArray['socket'] . ')';
         }
         if ($dsnArray['protocol'] && $dsnArray['hostspec']) {
             $dsnString .= '+';
         }
         $dsnString .= $dsnArray['hostspec'];
         if ($dsnArray['port']) {
-            $dsnString .= ':'.$dsnArray['port'];
+            $dsnString .= ':' . $dsnArray['port'];
         }
-        $dsnString .= '/'.$dsnArray['database'];
-        
+        $dsnString .= '/' . $dsnArray['database'];
+
         /* Option handling. Unfortunately, parseDSN simply places options into
          * the top-level array, so we'll first get rid of the fields defined by
          * DB and see what's left. */
         unset($dsnArray['phptype'],
-              $dsnArray['dbsyntax'],
-              $dsnArray['username'],
-              $dsnArray['password'],
-              $dsnArray['protocol'],
-              $dsnArray['socket'],
-              $dsnArray['hostspec'],
-              $dsnArray['port'],
-              $dsnArray['database']
+            $dsnArray['dbsyntax'],
+            $dsnArray['username'],
+            $dsnArray['password'],
+            $dsnArray['protocol'],
+            $dsnArray['socket'],
+            $dsnArray['hostspec'],
+            $dsnArray['port'],
+            $dsnArray['database']
         );
         if (count($dsnArray) > 0) {
             $dsnString .= '?';
@@ -919,13 +808,125 @@ class DB
                 if (++$i > 1) {
                     $dsnString .= '&';
                 }
-                $dsnString .= $key.'='.$value;
+                $dsnString .= $key . '=' . $value;
             }
         }
 
         return $dsnString;
     }
-    
+
+    // }}}
+    // {{{ isManip()
+
+    /**
+     * Determines if a value is a DB_<driver> object
+     *
+     * @param mixed $value the value to test
+     *
+     * @return bool  whether $value is a DB_<driver> object
+     */
+    public static function isConnection($value)
+    {
+        return (is_object($value) &&
+            is_subclass_of($value, 'db_common') &&
+            method_exists($value, 'simpleQuery'));
+    }
+
+    // }}}
+    // {{{ errorMessage()
+
+    /**
+     * Tell whether a query is a data manipulation or data definition query
+     *
+     * Examples of data manipulation queries are INSERT, UPDATE and DELETE.
+     * Examples of data definition queries are CREATE, DROP, ALTER, GRANT,
+     * REVOKE.
+     *
+     * @param string $query the query
+     *
+     * @return boolean  whether $query is a data manipulation query
+     */
+    public static function isManip($query)
+    {
+        $manips = 'INSERT|UPDATE|DELETE|REPLACE|'
+            . 'CREATE|DROP|'
+            . 'LOAD DATA|SELECT .* INTO .* FROM|COPY|'
+            . 'ALTER|GRANT|REVOKE|'
+            . 'LOCK|UNLOCK';
+        if (preg_match('/^\s*"?(' . $manips . ')\s+/i', $query)) {
+            return true;
+        }
+        return false;
+    }
+
+    // }}}
+    // {{{ parseDSN()
+
+    /**
+     * Return a textual error message for a DB error code
+     *
+     * @param integer $value the DB error code
+     *
+     * @return string  the error message or false if the error code was
+     *                  not recognized
+     */
+    public static function errorMessage($value)
+    {
+        static $errorMessages;
+        if (!isset($errorMessages)) {
+            $errorMessages = array(
+                DB_ERROR => 'unknown error',
+                DB_ERROR_ACCESS_VIOLATION => 'insufficient permissions',
+                DB_ERROR_ALREADY_EXISTS => 'already exists',
+                DB_ERROR_CANNOT_CREATE => 'can not create',
+                DB_ERROR_CANNOT_DROP => 'can not drop',
+                DB_ERROR_CONNECT_FAILED => 'connect failed',
+                DB_ERROR_CONSTRAINT => 'constraint violation',
+                DB_ERROR_CONSTRAINT_NOT_NULL => 'null value violates not-null constraint',
+                DB_ERROR_DIVZERO => 'division by zero',
+                DB_ERROR_EXTENSION_NOT_FOUND => 'extension not found',
+                DB_ERROR_INVALID => 'invalid',
+                DB_ERROR_INVALID_DATE => 'invalid date or time',
+                DB_ERROR_INVALID_DSN => 'invalid DSN',
+                DB_ERROR_INVALID_NUMBER => 'invalid number',
+                DB_ERROR_MISMATCH => 'mismatch',
+                DB_ERROR_NEED_MORE_DATA => 'insufficient data supplied',
+                DB_ERROR_NODBSELECTED => 'no database selected',
+                DB_ERROR_NOSUCHDB => 'no such database',
+                DB_ERROR_NOSUCHFIELD => 'no such field',
+                DB_ERROR_NOSUCHTABLE => 'no such table',
+                DB_ERROR_NOT_CAPABLE => 'DB backend not capable',
+                DB_ERROR_NOT_FOUND => 'not found',
+                DB_ERROR_NOT_LOCKED => 'not locked',
+                DB_ERROR_SYNTAX => 'syntax error',
+                DB_ERROR_UNSUPPORTED => 'not supported',
+                DB_ERROR_TRUNCATED => 'truncated',
+                DB_ERROR_VALUE_COUNT_ON_ROW => 'value count on row',
+                DB_OK => 'no error',
+            );
+        }
+
+        if (DB::isError($value)) {
+            $value = $value->getCode();
+        }
+
+        return isset($errorMessages[$value]) ? $errorMessages[$value]
+            : $errorMessages[DB_ERROR];
+    }
+
+    // }}}
+    // {{{ getDSNString()
+
+    /**
+     * Return the DB API version
+     *
+     * @return string  the DB API version number
+     */
+    function apiVersion()
+    {
+        return '1.9.2';
+    }
+
     // }}}
 }
 
@@ -951,23 +952,23 @@ class DB_Error extends PEAR_Error
     /**
      * DB_Error constructor
      *
-     * @param mixed $code       DB error code, or string with error message
-     * @param int   $mode       what "error mode" to operate in
-     * @param int   $level      what error level to use for $mode &
+     * @param mixed $code DB error code, or string with error message
+     * @param int $mode what "error mode" to operate in
+     * @param int $level what error level to use for $mode &
      *                           PEAR_ERROR_TRIGGER
-     * @param mixed $debuginfo  additional debug info, such as the last query
+     * @param mixed $debuginfo additional debug info, such as the last query
      *
      * @see PEAR_Error
      */
     function __construct($code = DB_ERROR, $mode = PEAR_ERROR_RETURN,
-                      $level = E_USER_NOTICE, $debuginfo = null)
+                         $level = E_USER_NOTICE, $debuginfo = null)
     {
         if (is_int($code)) {
             parent::__construct('DB Error: ' . DB::errorMessage($code), $code,
-                              $mode, $level, $debuginfo);
+                $mode, $level, $debuginfo);
         } else {
             parent::__construct("DB Error: $code", DB_ERROR,
-                              $mode, $level, $debuginfo);
+                $mode, $level, $debuginfo);
         }
     }
 
@@ -975,6 +976,9 @@ class DB_Error extends PEAR_Error
      * Workaround to both avoid the "Redefining already defined constructor"
      * PHP error and provide backward compatibility in case someone is calling
      * DB_Error() dynamically
+     * @param $method
+     * @param $arguments
+     * @return bool|mixed
      */
     public function __call($method, $arguments)
     {
@@ -984,6 +988,7 @@ class DB_Error extends PEAR_Error
         trigger_error(
             'Call to undefined method DB_Error::' . $method . '()', E_USER_ERROR
         );
+        return false;
     }
     // }}}
 }
@@ -1103,22 +1108,22 @@ class DB_result
     /**
      * This constructor sets the object's properties
      *
-     * @param object   &$dbh     the DB object reference
-     * @param resource $result   the result resource id
-     * @param array    $options  an associative array with result options
+     * @param object   &$dbh the DB object reference
+     * @param resource $result the result resource id
+     * @param array $options an associative array with result options
      *
      * @return void
      */
     function __construct(&$dbh, $result, $options = array())
     {
-        $this->autofree    = $dbh->options['autofree'];
-        $this->dbh         = &$dbh;
-        $this->fetchmode   = $dbh->fetchmode;
+        $this->autofree = $dbh->options['autofree'];
+        $this->dbh = &$dbh;
+        $this->fetchmode = $dbh->fetchmode;
         $this->fetchmode_object_class = $dbh->fetchmode_object_class;
-        $this->parameters  = $dbh->last_parameters;
-        $this->query       = $dbh->last_query;
-        $this->result      = $result;
-        $this->statement   = empty($dbh->last_stmt) ? null : $dbh->last_stmt;
+        $this->parameters = $dbh->last_parameters;
+        $this->query = $dbh->last_query;
+        $this->result = $result;
+        $this->statement = empty($dbh->last_stmt) ? null : $dbh->last_stmt;
         foreach ($options as $key => $value) {
             $this->setOption($key, $value);
         }
@@ -1127,8 +1132,8 @@ class DB_result
     /**
      * Set options for the DB_result object
      *
-     * @param string $key    the option to set
-     * @param mixed  $value  the value to set the option to
+     * @param string $key the option to set
+     * @param mixed $value the value to set the option to
      *
      * @return void
      */
@@ -1164,8 +1169,8 @@ class DB_result
      *   + <var>DB_PORTABILITY_RTRIM</var>
      *     right trim the data
      *
-     * @param int $fetchmode  the constant indicating how to format the data
-     * @param int $rownum     the row number to fetch (index starts at 0)
+     * @param int $fetchmode the constant indicating how to format the data
+     * @param int $rownum the row number to fetch (index starts at 0)
      *
      * @return mixed  an array or object containing the row's data,
      *                 NULL when the end of the result set is reached
@@ -1193,8 +1198,7 @@ class DB_result
                     }
                 }
             }
-            if ($this->row_counter >= ($this->limit_from + $this->limit_count))
-            {
+            if ($this->row_counter >= ($this->limit_from + $this->limit_count)) {
                 if ($this->autofree) {
                     $this->free();
                 }
@@ -1212,7 +1216,7 @@ class DB_result
                 // The default mode is specified in the
                 // DB_common::fetchmode_object_class property
                 if ($object_class == 'stdClass') {
-                    $arr = (object) $arr;
+                    $arr = (object)$arr;
                 } else {
                     $arr = new $object_class($arr);
                 }
@@ -1228,6 +1232,25 @@ class DB_result
     // }}}
     // {{{ fetchInto()
 
+    /**
+     * Frees the resources allocated for this result set
+     *
+     * @return bool  true on success.  A DB_Error object on failure.
+     */
+    function free()
+    {
+        $err = $this->dbh->freeResult($this->result);
+        if (DB::isError($err)) {
+            return $err;
+        }
+        $this->result = false;
+        $this->statement = false;
+        return true;
+    }
+
+    // }}}
+    // {{{ numCols()
+
     /**
      * Fetch a row of data into an array which is passed by reference
      *
@@ -1246,9 +1269,9 @@ class DB_result
      *   + <var>DB_PORTABILITY_RTRIM</var>
      *     right trim the data
      *
-     * @param array &$arr       the variable where the data should be placed
-     * @param int   $fetchmode  the constant indicating how to format the data
-     * @param int   $rownum     the row number to fetch (index starts at 0)
+     * @param array &$arr the variable where the data should be placed
+     * @param int $fetchmode the constant indicating how to format the data
+     * @param int $rownum the row number to fetch (index starts at 0)
      *
      * @return mixed  DB_OK if a row is processed, NULL when the end of the
      *                 result set is reached or a DB_Error object on failure
@@ -1276,8 +1299,7 @@ class DB_result
                 }
             }
             if ($this->row_counter >= (
-                    $this->limit_from + $this->limit_count))
-            {
+                    $this->limit_from + $this->limit_count)) {
                 if ($this->autofree) {
                     $this->free();
                 }
@@ -1295,7 +1317,7 @@ class DB_result
                 // default mode specified in the
                 // DB_common::fetchmode_object_class property
                 if ($object_class == 'stdClass') {
-                    $arr = (object) $arr;
+                    $arr = (object)$arr;
                 } else {
                     $arr = new $object_class($arr);
                 }
@@ -1309,7 +1331,7 @@ class DB_result
     }
 
     // }}}
-    // {{{ numCols()
+    // {{{ numRows()
 
     /**
      * Get the the number of columns in a result set
@@ -1322,7 +1344,7 @@ class DB_result
     }
 
     // }}}
-    // {{{ numRows()
+    // {{{ nextResult()
 
     /**
      * Get the number of rows in a result set
@@ -1332,8 +1354,7 @@ class DB_result
     function numRows()
     {
         if ($this->dbh->features['numrows'] === 'emulate'
-            && $this->dbh->options['portability'] & DB_PORTABILITY_NUMROWS)
-        {
+            && $this->dbh->options['portability'] & DB_PORTABILITY_NUMROWS) {
             if ($this->dbh->features['prepare']) {
                 $res = $this->dbh->query($this->query, $this->parameters);
             } else {
@@ -1360,7 +1381,7 @@ class DB_result
          * because that only gets the result resource, rather than the full
          * DB_Result object. */
         if (($this->dbh->features['limit'] === 'emulate'
-             && $this->limit_from !== null)
+                && $this->limit_from !== null)
             || $this->dbh->phptype == 'fbsql') {
             $limit_count = is_null($this->limit_count) ? $count : $this->limit_count;
             if ($count < $this->limit_from) {
@@ -1376,7 +1397,7 @@ class DB_result
     }
 
     // }}}
-    // {{{ nextResult()
+    // {{{ free()
 
     /**
      * Get the next result if a batch of queries was executed
@@ -1388,29 +1409,12 @@ class DB_result
         return $this->dbh->nextResult($this->result);
     }
 
-    // }}}
-    // {{{ free()
-
-    /**
-     * Frees the resources allocated for this result set
-     *
-     * @return bool  true on success.  A DB_Error object on failure.
-     */
-    function free()
-    {
-        $err = $this->dbh->freeResult($this->result);
-        if (DB::isError($err)) {
-            return $err;
-        }
-        $this->result = false;
-        $this->statement = false;
-        return true;
-    }
-
     // }}}
     // {{{ tableInfo()
 
     /**
+     * @param null $mode
+     * @return
      * @see DB_common::tableInfo()
      * @deprecated Method deprecated some time before Release 1.2
      */
@@ -1499,6 +1503,4 @@ class DB_row
  * tab-width: 4
  * c-basic-offset: 4
  * End:
- */
-
-?>
+ */
\ No newline at end of file
index 2aa85259d62dc69c0cad3f38320bc82fdcf28af9..c1fc361e5041b7a12194b7d75eabd774c856407a 100644 (file)
@@ -14,7 +14,6 @@
  * @author     Greg Beaver <cellog@php.net>
  * @copyright  1997-2010 The Authors
  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
- * @version    CVS: $Id: PEAR.php 313023 2011-07-06 19:17:11Z dufuz $
  * @link       http://pear.php.net/package/PEAR
  * @since      File available since Release 0.1
  */
 /**#@+
  * ERROR constants
  */
-define('PEAR_ERROR_RETURN',     1);
-define('PEAR_ERROR_PRINT',      2);
-define('PEAR_ERROR_TRIGGER',    4);
-define('PEAR_ERROR_DIE',        8);
-define('PEAR_ERROR_CALLBACK',  16);
+define('PEAR_ERROR_RETURN', 1);
+define('PEAR_ERROR_PRINT', 2);
+define('PEAR_ERROR_TRIGGER', 4);
+define('PEAR_ERROR_DIE', 8);
+define('PEAR_ERROR_CALLBACK', 16);
 /**
  * WARNING: obsolete
  * @deprecated
  */
 define('PEAR_ERROR_EXCEPTION', 32);
 /**#@-*/
-define('PEAR_ZE2', (function_exists('version_compare') &&
-                    version_compare(zend_version(), "2-dev", "ge")));
 
 if (substr(PHP_OS, 0, 3) == 'WIN') {
     define('OS_WINDOWS', true);
-    define('OS_UNIX',    false);
-    define('PEAR_OS',    'Windows');
+    define('OS_UNIX', false);
+    define('PEAR_OS', 'Windows');
 } else {
     define('OS_WINDOWS', false);
-    define('OS_UNIX',    true);
-    define('PEAR_OS',    'Unix'); // blatant assumption
+    define('OS_UNIX', true);
+    define('PEAR_OS', 'Unix'); // blatant assumption
 }
 
-$GLOBALS['_PEAR_default_error_mode']     = PEAR_ERROR_RETURN;
-$GLOBALS['_PEAR_default_error_options']  = E_USER_NOTICE;
+$GLOBALS['_PEAR_default_error_mode'] = PEAR_ERROR_RETURN;
+$GLOBALS['_PEAR_default_error_options'] = E_USER_NOTICE;
 $GLOBALS['_PEAR_destructor_object_list'] = array();
-$GLOBALS['_PEAR_shutdown_funcs']         = array();
-$GLOBALS['_PEAR_error_handler_stack']    = array();
+$GLOBALS['_PEAR_shutdown_funcs'] = array();
+$GLOBALS['_PEAR_error_handler_stack'] = array();
 
 @ini_set('track_errors', true);
 
@@ -78,7 +75,7 @@ $GLOBALS['_PEAR_error_handler_stack']    = array();
  * @author     Greg Beaver <cellog@php.net>
  * @copyright  1997-2006 The PHP Group
  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
- * @version    Release: 1.9.4
+ * @version    Release: @package_version@
  * @link       http://pear.php.net/package/PEAR
  * @see        PEAR_Error
  * @since      Class available since PHP 4.0.2
@@ -86,6 +83,17 @@ $GLOBALS['_PEAR_error_handler_stack']    = array();
  */
 class PEAR
 {
+    /**
+     * List of methods that can be called both statically and non-statically.
+     * @var array
+     */
+    protected static $bivalentMethods = array(
+        'setErrorHandling' => true,
+        'raiseError' => true,
+        'throwError' => true,
+        'pushErrorHandling' => true,
+        'popErrorHandling' => true,
+    );
     /**
      * Whether to enable internal debug messages.
      *
@@ -93,7 +101,6 @@ class PEAR
      * @access  private
      */
     var $_debug = false;
-
     /**
      * Default error mode for this object.
      *
@@ -101,7 +108,6 @@ class PEAR
      * @access  private
      */
     var $_default_error_mode = null;
-
     /**
      * Default error options used for this object when error mode
      * is PEAR_ERROR_TRIGGER.
@@ -110,7 +116,6 @@ class PEAR
      * @access  private
      */
     var $_default_error_options = null;
-
     /**
      * Default error handler (callback) for this object, if error mode is
      * PEAR_ERROR_CALLBACK.
@@ -119,7 +124,6 @@ class PEAR
      * @access  private
      */
     var $_default_error_handler = '';
-
     /**
      * Which class to use for error objects.
      *
@@ -127,7 +131,6 @@ class PEAR
      * @access  private
      */
     var $_error_class = 'PEAR_Error';
-
     /**
      * An array of expected errors.
      *
@@ -136,73 +139,31 @@ class PEAR
      */
     var $_expected_errors = array();
 
-    /**
-     * Constructor.  Registers this object in
-     * $_PEAR_destructor_object_list for destructor emulation if a
-     * destructor object exists.
-     *
-     * @param string $error_class  (optional) which class to use for
-     *        error objects, defaults to PEAR_Error.
-     * @access public
-     * @return void
-     */
-    function PEAR($error_class = null)
+    public static function __callStatic($method, $arguments)
     {
-        $classname = strtolower(get_class($this));
-        if ($this->_debug) {
-            print "PEAR constructor called, class=$classname\n";
-        }
-
-        if ($error_class !== null) {
-            $this->_error_class = $error_class;
-        }
-
-        while ($classname && strcasecmp($classname, "pear")) {
-            $destructor = "_$classname";
-            if (method_exists($this, $destructor)) {
-                global $_PEAR_destructor_object_list;
-                $_PEAR_destructor_object_list[] = &$this;
-                if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
-                    register_shutdown_function("_PEAR_call_destructors");
-                    $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
-                }
-                break;
-            } else {
-                $classname = get_parent_class($classname);
-            }
+        if (!isset(self::$bivalentMethods[$method])) {
+            trigger_error(
+                'Call to undefined method PEAR::' . $method . '()', E_USER_ERROR
+            );
         }
+        return call_user_func_array(
+            array(get_class(), '_' . $method),
+            array_merge(array(null), $arguments)
+        );
     }
 
     /**
-     * Destructor (the emulated type of...).  Does nothing right now,
-     * but is included for forward compatibility, so subclass
-     * destructors should always call it.
+     * If you have a class that's mostly/entirely static, and you need static
+     * properties, you can use this method to simulate them. Eg. in your method(s)
+     * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar');
+     * You MUST use a reference, or they will not persist!
      *
-     * See the note in the class desciption about output from
-     * destructors.
-     *
-     * @access public
-     * @return void
+     * @param string $class The calling classname, to prevent clashes
+     * @param string $var The variable to retrieve.
+     * @return mixed   A reference to the variable. If not set it will be
+     *                 auto initialised to NULL.
      */
-    function _PEAR() {
-        if ($this->_debug) {
-            printf("PEAR destructor called, class=%s\n", strtolower(get_class($this)));
-        }
-    }
-
-    /**
-    * If you have a class that's mostly/entirely static, and you need static
-    * properties, you can use this method to simulate them. Eg. in your method(s)
-    * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar');
-    * You MUST use a reference, or they will not persist!
-    *
-    * @access public
-    * @param  string $class  The calling classname, to prevent clashes
-    * @param  string $var    The variable to retrieve.
-    * @return mixed   A reference to the variable. If not set it will be
-    *                 auto initialised to NULL.
-    */
-    function &getStaticProperty($class, $var)
+    public static function &getStaticProperty($class, $var)
     {
         static $properties;
         if (!isset($properties[$class])) {
@@ -217,15 +178,15 @@ class PEAR
     }
 
     /**
-    * Use this function to register a shutdown method for static
-    * classes.
-    *
-    * @access public
-    * @param  mixed $func  The function name (or array of class/method) to call
-    * @param  mixed $args  The arguments to pass to the function
-    * @return void
-    */
-    function registerShutdownFunc($func, $args = array())
+     * Use this function to register a shutdown method for static
+     * classes.
+     *
+     * @param mixed $func The function name (or array of class/method) to call
+     * @param mixed $args The arguments to pass to the function
+     *
+     * @return void
+     */
+    public static function registerShutdownFunc($func, $args = array())
     {
         // if we are called statically, there is a potential
         // that no shutdown func is registered.  Bug #6445
@@ -239,15 +200,15 @@ class PEAR
     /**
      * Tell whether a value is a PEAR error.
      *
-     * @param   mixed $data   the value to test
-     * @param   int   $code   if $data is an error object, return true
+     * @param mixed $data the value to test
+     * @param int $code if $data is an error object, return true
      *                        only if $code is a string and
      *                        $obj->getMessage() == $code or
      *                        $code is an integer and $obj->getCode() == $code
-     * @access  public
+     *
      * @return  bool    true if parameter is an error
      */
-    function isError($data, $code = null)
+    public static function isError($data, $code = null)
     {
         if (!is_a($data, 'PEAR_Error')) {
             return false;
@@ -262,6 +223,113 @@ class PEAR
         return $data->getCode() == $code;
     }
 
+    public static function staticPushErrorHandling($mode, $options = null)
+    {
+        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
+        $def_mode = &$GLOBALS['_PEAR_default_error_mode'];
+        $def_options = &$GLOBALS['_PEAR_default_error_options'];
+        $stack[] = array($def_mode, $def_options);
+        switch ($mode) {
+            case PEAR_ERROR_EXCEPTION:
+            case PEAR_ERROR_RETURN:
+            case PEAR_ERROR_PRINT:
+            case PEAR_ERROR_TRIGGER:
+            case PEAR_ERROR_DIE:
+            case null:
+                $def_mode = $mode;
+                $def_options = $options;
+                break;
+
+            case PEAR_ERROR_CALLBACK:
+                $def_mode = $mode;
+                // class/object method callback
+                if (is_callable($options)) {
+                    $def_options = $options;
+                } else {
+                    trigger_error("invalid error callback", E_USER_WARNING);
+                }
+                break;
+
+            default:
+                trigger_error("invalid error mode", E_USER_WARNING);
+                break;
+        }
+        $stack[] = array($mode, $options);
+        return true;
+    }
+
+    public static function staticPopErrorHandling()
+    {
+        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
+        $setmode = &$GLOBALS['_PEAR_default_error_mode'];
+        $setoptions = &$GLOBALS['_PEAR_default_error_options'];
+        array_pop($stack);
+        list($mode, $options) = $stack[sizeof($stack) - 1];
+        array_pop($stack);
+        switch ($mode) {
+            case PEAR_ERROR_EXCEPTION:
+            case PEAR_ERROR_RETURN:
+            case PEAR_ERROR_PRINT:
+            case PEAR_ERROR_TRIGGER:
+            case PEAR_ERROR_DIE:
+            case null:
+                $setmode = $mode;
+                $setoptions = $options;
+                break;
+
+            case PEAR_ERROR_CALLBACK:
+                $setmode = $mode;
+                // class/object method callback
+                if (is_callable($options)) {
+                    $setoptions = $options;
+                } else {
+                    trigger_error("invalid error callback", E_USER_WARNING);
+                }
+                break;
+
+            default:
+                trigger_error("invalid error mode", E_USER_WARNING);
+                break;
+        }
+        return true;
+    }
+
+    /**
+     * OS independent PHP extension load. Remember to take care
+     * on the correct extension name for case sensitive OSes.
+     *
+     * @param string $ext The extension name
+     * @return bool Success or not on the dl() call
+     */
+    public static function loadExtension($ext)
+    {
+        if (extension_loaded($ext)) {
+            return true;
+        }
+
+        // if either returns true dl() will produce a FATAL error, stop that
+        if (
+            function_exists('dl') === false ||
+            ini_get('enable_dl') != 1
+        ) {
+            return false;
+        }
+
+        if (OS_WINDOWS) {
+            $suffix = '.dll';
+        } elseif (PHP_OS == 'HP-UX') {
+            $suffix = '.sl';
+        } elseif (PHP_OS == 'AIX') {
+            $suffix = '.a';
+        } elseif (PHP_OS == 'OSX') {
+            $suffix = '.bundle';
+        } else {
+            $suffix = '.so';
+        }
+
+        return @dl('php_' . $ext . $suffix) || @dl($ext . $suffix);
+    }
+
     /**
      * Sets how errors generated by this object should be handled.
      * Can be invoked both in objects and statically.  If called
@@ -269,6 +337,9 @@ class PEAR
      * PEAR objects.  If called in an object, setErrorHandling sets
      * the default behaviour for that object.
      *
+     * @param object $object
+     *        Object the method was called on (non-static mode)
+     *
      * @param int $mode
      *        One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
      *        PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
@@ -300,14 +371,16 @@ class PEAR
      *
      * @since PHP 4.0.5
      */
-    function setErrorHandling($mode = null, $options = null)
+    protected static function _setErrorHandling(
+        $object, $mode = null, $options = null
+    )
     {
-        if (isset($this) && is_a($this, 'PEAR')) {
-            $setmode     = &$this->_default_error_mode;
-            $setoptions  = &$this->_default_error_options;
+        if ($object !== null) {
+            $setmode = &$object->_default_error_mode;
+            $setoptions = &$object->_default_error_options;
         } else {
-            $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
-            $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
+            $setmode = &$GLOBALS['_PEAR_default_error_mode'];
+            $setoptions = &$GLOBALS['_PEAR_default_error_options'];
         }
 
         switch ($mode) {
@@ -337,113 +410,19 @@ class PEAR
         }
     }
 
-    /**
-     * This method is used to tell which errors you expect to get.
-     * Expected errors are always returned with error mode
-     * PEAR_ERROR_RETURN.  Expected error codes are stored in a stack,
-     * and this method pushes a new element onto it.  The list of
-     * expected errors are in effect until they are popped off the
-     * stack with the popExpect() method.
-     *
-     * Note that this method can not be called statically
-     *
-     * @param mixed $code a single error code or an array of error codes to expect
-     *
-     * @return int     the new depth of the "expected errors" stack
-     * @access public
-     */
-    function expectError($code = '*')
-    {
-        if (is_array($code)) {
-            array_push($this->_expected_errors, $code);
-        } else {
-            array_push($this->_expected_errors, array($code));
-        }
-        return count($this->_expected_errors);
-    }
-
-    /**
-     * This method pops one element off the expected error codes
-     * stack.
-     *
-     * @return array   the list of error codes that were popped
-     */
-    function popExpect()
-    {
-        return array_pop($this->_expected_errors);
-    }
-
-    /**
-     * This method checks unsets an error code if available
-     *
-     * @param mixed error code
-     * @return bool true if the error code was unset, false otherwise
-     * @access private
-     * @since PHP 4.3.0
-     */
-    function _checkDelExpect($error_code)
-    {
-        $deleted = false;
-        foreach ($this->_expected_errors as $key => $error_array) {
-            if (in_array($error_code, $error_array)) {
-                unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);
-                $deleted = true;
-            }
-
-            // clean up empty arrays
-            if (0 == count($this->_expected_errors[$key])) {
-                unset($this->_expected_errors[$key]);
-            }
-        }
-
-        return $deleted;
-    }
-
-    /**
-     * This method deletes all occurences of the specified element from
-     * the expected error codes stack.
-     *
-     * @param  mixed $error_code error code that should be deleted
-     * @return mixed list of error codes that were deleted or error
-     * @access public
-     * @since PHP 4.3.0
-     */
-    function delExpect($error_code)
-    {
-        $deleted = false;
-        if ((is_array($error_code) && (0 != count($error_code)))) {
-            // $error_code is a non-empty array here; we walk through it trying
-            // to unset all values
-            foreach ($error_code as $key => $error) {
-                $deleted =  $this->_checkDelExpect($error) ? true : false;
-            }
-
-            return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
-        } elseif (!empty($error_code)) {
-            // $error_code comes alone, trying to unset it
-            if ($this->_checkDelExpect($error_code)) {
-                return true;
-            }
-
-            return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
-        }
-
-        // $error_code is empty
-        return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME
-    }
-
     /**
      * This method is a wrapper that returns an instance of the
      * configured error class with this object's default error
      * handling applied.  If the $mode and $options parameters are not
      * specified, the object's defaults are used.
      *
+     * @param $object
      * @param mixed $message a text error message or a PEAR error object
      *
-     * @param int $code      a numeric error code (it is up to your class
+     * @param int $code a numeric error code (it is up to your class
      *                  to define these if you want to use codes)
      *
-     * @param int $mode      One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
+     * @param int $mode One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
      *                  PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
      *                  PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION.
      *
@@ -464,35 +443,35 @@ class PEAR
      * @param bool $skipmsg If true, raiseError will only pass error codes,
      *                  the error message parameter will be dropped.
      *
-     * @access public
      * @return object   a PEAR error object
      * @see PEAR::setErrorHandling
      * @since PHP 4.0.5
      */
-    function &raiseError($message = null,
-                         $code = null,
-                         $mode = null,
-                         $options = null,
-                         $userinfo = null,
-                         $error_class = null,
-                         $skipmsg = false)
+    protected static function _raiseError($object,
+                                          $message = null,
+                                          $code = null,
+                                          $mode = null,
+                                          $options = null,
+                                          $userinfo = null,
+                                          $error_class = null,
+                                          $skipmsg = false)
     {
         // The error is yet a PEAR error object
         if (is_object($message)) {
-            $code        = $message->getCode();
-            $userinfo    = $message->getUserInfo();
+            $code = $message->getCode();
+            $userinfo = $message->getUserInfo();
             $error_class = $message->getType();
             $message->error_message_prefix = '';
-            $message     = $message->getMessage();
+            $message = $message->getMessage();
         }
 
         if (
-            isset($this) &&
-            isset($this->_expected_errors) &&
-            count($this->_expected_errors) > 0 &&
-            count($exp = end($this->_expected_errors))
+            $object !== null &&
+            isset($object->_expected_errors) &&
+            count($object->_expected_errors) > 0 &&
+            count($exp = end($object->_expected_errors))
         ) {
-            if ($exp[0] == "*" ||
+            if ($exp[0] === "*" ||
                 (is_int(reset($exp)) && in_array($code, $exp)) ||
                 (is_string(reset($exp)) && in_array($message, $exp))
             ) {
@@ -503,30 +482,24 @@ class PEAR
         // No mode given, try global ones
         if ($mode === null) {
             // Class error handler
-            if (isset($this) && isset($this->_default_error_mode)) {
-                $mode    = $this->_default_error_mode;
-                $options = $this->_default_error_options;
-            // Global error handler
+            if ($object !== null && isset($object->_default_error_mode)) {
+                $mode = $object->_default_error_mode;
+                $options = $object->_default_error_options;
+                // Global error handler
             } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {
-                $mode    = $GLOBALS['_PEAR_default_error_mode'];
+                $mode = $GLOBALS['_PEAR_default_error_mode'];
                 $options = $GLOBALS['_PEAR_default_error_options'];
             }
         }
 
         if ($error_class !== null) {
             $ec = $error_class;
-        } elseif (isset($this) && isset($this->_error_class)) {
-            $ec = $this->_error_class;
+        } elseif ($object !== null && isset($object->_error_class)) {
+            $ec = $object->_error_class;
         } else {
             $ec = 'PEAR_Error';
         }
 
-        if (intval(PHP_VERSION) < 5) {
-            // little non-eval hack to fix bug #12147
-            include 'PEAR/FixPHP5PEARWarnings.php';
-            return $a;
-        }
-
         if ($skipmsg) {
             $a = new $ec($code, $mode, $options, $userinfo);
         } else {
@@ -540,105 +513,35 @@ class PEAR
      * Simpler form of raiseError with fewer options.  In most cases
      * message, code and userinfo are enough.
      *
+     * @param $object
      * @param mixed $message a text error message or a PEAR error object
      *
-     * @param int $code      a numeric error code (it is up to your class
+     * @param int $code a numeric error code (it is up to your class
      *                  to define these if you want to use codes)
      *
      * @param string $userinfo If you need to pass along for example debug
      *                  information, this parameter is meant for that.
      *
-     * @access public
      * @return object   a PEAR error object
      * @see PEAR::raiseError
      */
-    function &throwError($message = null, $code = null, $userinfo = null)
+    protected static function _throwError($object, $message = null, $code = null, $userinfo = null)
     {
-        if (isset($this) && is_a($this, 'PEAR')) {
-            $a = &$this->raiseError($message, $code, null, null, $userinfo);
+        if ($object !== null) {
+            $a = $object->raiseError($message, $code, null, null, $userinfo);
             return $a;
         }
 
-        $a = &PEAR::raiseError($message, $code, null, null, $userinfo);
+        $a = PEAR::raiseError($message, $code, null, null, $userinfo);
         return $a;
     }
 
-    function staticPushErrorHandling($mode, $options = null)
-    {
-        $stack       = &$GLOBALS['_PEAR_error_handler_stack'];
-        $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
-        $def_options = &$GLOBALS['_PEAR_default_error_options'];
-        $stack[] = array($def_mode, $def_options);
-        switch ($mode) {
-            case PEAR_ERROR_EXCEPTION:
-            case PEAR_ERROR_RETURN:
-            case PEAR_ERROR_PRINT:
-            case PEAR_ERROR_TRIGGER:
-            case PEAR_ERROR_DIE:
-            case null:
-                $def_mode = $mode;
-                $def_options = $options;
-                break;
-
-            case PEAR_ERROR_CALLBACK:
-                $def_mode = $mode;
-                // class/object method callback
-                if (is_callable($options)) {
-                    $def_options = $options;
-                } else {
-                    trigger_error("invalid error callback", E_USER_WARNING);
-                }
-                break;
-
-            default:
-                trigger_error("invalid error mode", E_USER_WARNING);
-                break;
-        }
-        $stack[] = array($mode, $options);
-        return true;
-    }
-
-    function staticPopErrorHandling()
-    {
-        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
-        $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
-        $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
-        array_pop($stack);
-        list($mode, $options) = $stack[sizeof($stack) - 1];
-        array_pop($stack);
-        switch ($mode) {
-            case PEAR_ERROR_EXCEPTION:
-            case PEAR_ERROR_RETURN:
-            case PEAR_ERROR_PRINT:
-            case PEAR_ERROR_TRIGGER:
-            case PEAR_ERROR_DIE:
-            case null:
-                $setmode = $mode;
-                $setoptions = $options;
-                break;
-
-            case PEAR_ERROR_CALLBACK:
-                $setmode = $mode;
-                // class/object method callback
-                if (is_callable($options)) {
-                    $setoptions = $options;
-                } else {
-                    trigger_error("invalid error callback", E_USER_WARNING);
-                }
-                break;
-
-            default:
-                trigger_error("invalid error mode", E_USER_WARNING);
-                break;
-        }
-        return true;
-    }
-
     /**
      * Push a new error handler on top of the error handler options stack. With this
      * you can easily override the actual error handler for some code and restore
      * it later with popErrorHandling.
      *
+     * @param $object
      * @param mixed $mode (same as setErrorHandling)
      * @param mixed $options (same as setErrorHandling)
      *
@@ -646,20 +549,20 @@ class PEAR
      *
      * @see PEAR::setErrorHandling
      */
-    function pushErrorHandling($mode, $options = null)
+    protected static function _pushErrorHandling($object, $mode, $options = null)
     {
         $stack = &$GLOBALS['_PEAR_error_handler_stack'];
-        if (isset($this) && is_a($this, 'PEAR')) {
-            $def_mode    = &$this->_default_error_mode;
-            $def_options = &$this->_default_error_options;
+        if ($object !== null) {
+            $def_mode = &$object->_default_error_mode;
+            $def_options = &$object->_default_error_options;
         } else {
-            $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
+            $def_mode = &$GLOBALS['_PEAR_default_error_mode'];
             $def_options = &$GLOBALS['_PEAR_default_error_options'];
         }
         $stack[] = array($def_mode, $def_options);
 
-        if (isset($this) && is_a($this, 'PEAR')) {
-            $this->setErrorHandling($mode, $options);
+        if ($object !== null) {
+            $object->setErrorHandling($mode, $options);
         } else {
             PEAR::setErrorHandling($mode, $options);
         }
@@ -668,20 +571,21 @@ class PEAR
     }
 
     /**
-    * Pop the last error handler used
-    *
-    * @return bool Always true
-    *
-    * @see PEAR::pushErrorHandling
-    */
-    function popErrorHandling()
+     * Pop the last error handler used
+     *
+     * @param $object
+     * @return bool Always true
+     *
+     * @see PEAR::pushErrorHandling
+     */
+    protected static function _popErrorHandling($object)
     {
         $stack = &$GLOBALS['_PEAR_error_handler_stack'];
         array_pop($stack);
         list($mode, $options) = $stack[sizeof($stack) - 1];
         array_pop($stack);
-        if (isset($this) && is_a($this, 'PEAR')) {
-            $this->setErrorHandling($mode, $options);
+        if ($object !== null) {
+            $object->setErrorHandling($mode, $options);
         } else {
             PEAR::setErrorHandling($mode, $options);
         }
@@ -689,65 +593,195 @@ class PEAR
     }
 
     /**
-    * OS independant PHP extension load. Remember to take care
-    * on the correct extension name for case sensitive OSes.
-    *
-    * @param string $ext The extension name
-    * @return bool Success or not on the dl() call
-    */
-    function loadExtension($ext)
+     * Only here for backwards compatibility.
+     * E.g. Archive_Tar calls $this->PEAR() in its constructor.
+     *
+     * @param string $error_class Which class to use for error objects,
+     *                            defaults to PEAR_Error.
+     */
+    public function PEAR($error_class = null)
     {
-        if (extension_loaded($ext)) {
-            return true;
+        self::__construct($error_class);
+    }
+
+    /**
+     * Constructor.  Registers this object in
+     * $_PEAR_destructor_object_list for destructor emulation if a
+     * destructor object exists.
+     *
+     * @param string $error_class (optional) which class to use for
+     *        error objects, defaults to PEAR_Error.
+     * @access public
+     * @return void
+     */
+    function __construct($error_class = null)
+    {
+        $classname = strtolower(get_class($this));
+        if ($this->_debug) {
+            print "PEAR constructor called, class=$classname\n";
         }
 
-        // if either returns true dl() will produce a FATAL error, stop that
-        if (
-            function_exists('dl') === false ||
-            ini_get('enable_dl') != 1 ||
-            ini_get('safe_mode') == 1
-        ) {
-            return false;
+        if ($error_class !== null) {
+            $this->_error_class = $error_class;
         }
 
-        if (OS_WINDOWS) {
-            $suffix = '.dll';
-        } elseif (PHP_OS == 'HP-UX') {
-            $suffix = '.sl';
-        } elseif (PHP_OS == 'AIX') {
-            $suffix = '.a';
-        } elseif (PHP_OS == 'OSX') {
-            $suffix = '.bundle';
+        while ($classname && strcasecmp($classname, "pear")) {
+            $destructor = "_$classname";
+            if (method_exists($this, $destructor)) {
+                global $_PEAR_destructor_object_list;
+                $_PEAR_destructor_object_list[] = $this;
+                if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
+                    register_shutdown_function("_PEAR_call_destructors");
+                    $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
+                }
+                break;
+            } else {
+                $classname = get_parent_class($classname);
+            }
+        }
+    }
+
+    /**
+     * Destructor (the emulated type of...).  Does nothing right now,
+     * but is included for forward compatibility, so subclass
+     * destructors should always call it.
+     *
+     * See the note in the class desciption about output from
+     * destructors.
+     *
+     * @access public
+     * @return void
+     */
+    function _PEAR()
+    {
+        if ($this->_debug) {
+            printf("PEAR destructor called, class=%s\n", strtolower(get_class($this)));
+        }
+    }
+
+    public function __call($method, $arguments)
+    {
+        if (!isset(self::$bivalentMethods[$method])) {
+            trigger_error(
+                'Call to undefined method PEAR::' . $method . '()', E_USER_ERROR
+            );
+        }
+        return call_user_func_array(
+            array(get_class(), '_' . $method),
+            array_merge(array($this), $arguments)
+        );
+    }
+
+    /**
+     * This method is used to tell which errors you expect to get.
+     * Expected errors are always returned with error mode
+     * PEAR_ERROR_RETURN.  Expected error codes are stored in a stack,
+     * and this method pushes a new element onto it.  The list of
+     * expected errors are in effect until they are popped off the
+     * stack with the popExpect() method.
+     *
+     * Note that this method can not be called statically
+     *
+     * @param mixed $code a single error code or an array of error codes to expect
+     *
+     * @return int     the new depth of the "expected errors" stack
+     * @access public
+     */
+    function expectError($code = '*')
+    {
+        if (is_array($code)) {
+            array_push($this->_expected_errors, $code);
         } else {
-            $suffix = '.so';
+            array_push($this->_expected_errors, array($code));
         }
+        return count($this->_expected_errors);
+    }
 
-        return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix);
+    /**
+     * This method pops one element off the expected error codes
+     * stack.
+     *
+     * @return array   the list of error codes that were popped
+     */
+    function popExpect()
+    {
+        return array_pop($this->_expected_errors);
     }
-}
 
-if (PEAR_ZE2) {
-    include_once 'PEAR5.php';
+    /**
+     * This method deletes all occurrences of the specified element from
+     * the expected error codes stack.
+     *
+     * @param mixed $error_code error code that should be deleted
+     * @return mixed list of error codes that were deleted or error
+     * @access public
+     * @since PHP 4.3.0
+     */
+    function delExpect($error_code)
+    {
+        $deleted = false;
+        if ((is_array($error_code) && (0 != count($error_code)))) {
+            // $error_code is a non-empty array here; we walk through it trying
+            // to unset all values
+            foreach ($error_code as $key => $error) {
+                $deleted = $this->_checkDelExpect($error) ? true : false;
+            }
+
+            return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
+        } elseif (!empty($error_code)) {
+            // $error_code comes alone, trying to unset it
+            if ($this->_checkDelExpect($error_code)) {
+                return true;
+            }
+
+            return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
+        }
+
+        // $error_code is empty
+        return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME
+    }
+
+    /**
+     * This method checks unsets an error code if available
+     *
+     * @param mixed error code
+     * @return bool true if the error code was unset, false otherwise
+     * @access private
+     * @since PHP 4.3.0
+     */
+    function _checkDelExpect($error_code)
+    {
+        $deleted = false;
+        foreach ($this->_expected_errors as $key => $error_array) {
+            if (in_array($error_code, $error_array)) {
+                unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);
+                $deleted = true;
+            }
+
+            // clean up empty arrays
+            if (0 == count($this->_expected_errors[$key])) {
+                unset($this->_expected_errors[$key]);
+            }
+        }
+
+        return $deleted;
+    }
 }
 
 function _PEAR_call_destructors()
 {
     global $_PEAR_destructor_object_list;
     if (is_array($_PEAR_destructor_object_list) &&
-        sizeof($_PEAR_destructor_object_list))
-    {
+        sizeof($_PEAR_destructor_object_list)) {
         reset($_PEAR_destructor_object_list);
-        if (PEAR_ZE2) {
-            $destructLifoExists = PEAR5::getStaticProperty('PEAR', 'destructlifo');
-        } else {
-            $destructLifoExists = PEAR::getStaticProperty('PEAR', 'destructlifo');
-        }
+
+        $destructLifoExists = PEAR::getStaticProperty('PEAR', 'destructlifo');
 
         if ($destructLifoExists) {
             $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list);
         }
 
-        while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
+        foreach ($_PEAR_destructor_object_list as $k => $objref) {
             $classname = get_class($objref);
             while ($classname) {
                 $destructor = "_$classname";
@@ -788,7 +822,7 @@ function _PEAR_call_destructors()
  * @author     Gregory Beaver <cellog@php.net>
  * @copyright  1997-2006 The PHP Group
  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
- * @version    Release: 1.9.4
+ * @version    Release: @package_version@
  * @link       http://pear.php.net/manual/en/core.pear.pear-error.php
  * @see        PEAR::raiseError(), PEAR::throwError()
  * @since      Class available since PHP 4.0.2
@@ -796,25 +830,44 @@ function _PEAR_call_destructors()
 class PEAR_Error
 {
     var $error_message_prefix = '';
-    var $mode                 = PEAR_ERROR_RETURN;
-    var $level                = E_USER_NOTICE;
-    var $code                 = -1;
-    var $message              = '';
-    var $userinfo             = '';
-    var $backtrace            = null;
+    var $mode = PEAR_ERROR_RETURN;
+    var $level = E_USER_NOTICE;
+    var $code = -1;
+    var $message = '';
+    var $userinfo = '';
+    var $backtrace = null;
+
+    /**
+     * Only here for backwards compatibility.
+     *
+     * Class "Cache_Error" still uses it, among others.
+     *
+     * @param string $message Message
+     * @param int $code Error code
+     * @param int $mode Error mode
+     * @param mixed $options See __construct()
+     * @param string $userinfo Additional user/debug info
+     */
+    public function PEAR_Error(
+        $message = 'unknown error', $code = null, $mode = null,
+        $options = null, $userinfo = null
+    )
+    {
+        self::__construct($message, $code, $mode, $options, $userinfo);
+    }
 
     /**
      * PEAR_Error constructor
      *
-     * @param string $message  message
+     * @param string $message message
      *
-     * @param int $code     (optional) error code
+     * @param int $code (optional) error code
      *
-     * @param int $mode     (optional) error mode, one of: PEAR_ERROR_RETURN,
+     * @param int $mode (optional) error mode, one of: PEAR_ERROR_RETURN,
      * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER,
      * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION
      *
-     * @param mixed $options   (optional) error level, _OR_ in the case of
+     * @param mixed $options (optional) error level, _OR_ in the case of
      * PEAR_ERROR_CALLBACK, the callback function or object/method
      * tuple.
      *
@@ -823,22 +876,18 @@ class PEAR_Error
      * @access public
      *
      */
-    function PEAR_Error($message = 'unknown error', $code = null,
-                        $mode = null, $options = null, $userinfo = null)
+    function __construct($message = 'unknown error', $code = null,
+                         $mode = null, $options = null, $userinfo = null)
     {
         if ($mode === null) {
             $mode = PEAR_ERROR_RETURN;
         }
-        $this->message   = $message;
-        $this->code      = $code;
-        $this->mode      = $mode;
-        $this->userinfo  = $userinfo;
+        $this->message = $message;
+        $this->code = $code;
+        $this->mode = $mode;
+        $this->userinfo = $userinfo;
 
-        if (PEAR_ZE2) {
-            $skiptrace = PEAR5::getStaticProperty('PEAR_Error', 'skiptrace');
-        } else {
-            $skiptrace = PEAR::getStaticProperty('PEAR_Error', 'skiptrace');
-        }
+        $skiptrace = PEAR::getStaticProperty('PEAR_Error', 'skiptrace');
 
         if (!$skiptrace) {
             $this->backtrace = debug_backtrace();
@@ -883,7 +932,8 @@ class PEAR_Error
             } else {
                 $format = $options;
             }
-            die(sprintf($format, $msg));
+            printf($format, $msg);
+            exit($code);
         }
 
         if ($this->mode & PEAR_ERROR_CALLBACK && is_callable($this->callback)) {
@@ -896,6 +946,17 @@ class PEAR_Error
         }
     }
 
+    /**
+     * Get the error message from an error object.
+     *
+     * @return  string  full error message
+     * @access public
+     */
+    function getMessage()
+    {
+        return ($this->error_message_prefix . $this->message);
+    }
+
     /**
      * Get the error mode from an error object.
      *
@@ -918,27 +979,16 @@ class PEAR_Error
         return $this->callback;
     }
 
-    /**
-     * Get the error message from an error object.
-     *
-     * @return  string  full error message
-     * @access public
-     */
-    function getMessage()
-    {
-        return ($this->error_message_prefix . $this->message);
-    }
-
     /**
      * Get error code from an error object
      *
      * @return int error code
      * @access public
      */
-     function getCode()
-     {
+    function getCode()
+    {
         return $this->code;
-     }
+    }
 
     /**
      * Get the name of this error/exception.
@@ -952,25 +1002,25 @@ class PEAR_Error
     }
 
     /**
-     * Get additional user-supplied information.
+     * Get additional debug information supplied by the application.
      *
-     * @return string user-supplied information
+     * @return string debug information
      * @access public
      */
-    function getUserInfo()
+    function getDebugInfo()
     {
-        return $this->userinfo;
+        return $this->getUserInfo();
     }
 
     /**
-     * Get additional debug information supplied by the application.
+     * Get additional user-supplied information.
      *
-     * @return string debug information
+     * @return string user-supplied information
      * @access public
      */
-    function getDebugInfo()
+    function getUserInfo()
     {
-        return $this->getUserInfo();
+        return $this->userinfo;
     }
 
     /**
@@ -1015,23 +1065,23 @@ class PEAR_Error
     function toString()
     {
         $modes = array();
-        $levels = array(E_USER_NOTICE  => 'notice',
-                        E_USER_WARNING => 'warning',
-                        E_USER_ERROR   => 'error');
+        $levels = array(E_USER_NOTICE => 'notice',
+            E_USER_WARNING => 'warning',
+            E_USER_ERROR => 'error');
         if ($this->mode & PEAR_ERROR_CALLBACK) {
             if (is_array($this->callback)) {
                 $callback = (is_object($this->callback[0]) ?
-                    strtolower(get_class($this->callback[0])) :
-                    $this->callback[0]) . '::' .
+                        strtolower(get_class($this->callback[0])) :
+                        $this->callback[0]) . '::' .
                     $this->callback[1];
             } else {
                 $callback = $this->callback;
             }
-            return sprintf('[%s: message="%s" code=%d mode=callback '.
-                           'callback=%s prefix="%s" info="%s"]',
-                           strtolower(get_class($this)), $this->message, $this->code,
-                           $callback, $this->error_message_prefix,
-                           $this->userinfo);
+            return sprintf('[%s: message="%s" code=%d mode=callback ' .
+                'callback=%s prefix="%s" info="%s"]',
+                strtolower(get_class($this)), $this->message, $this->code,
+                $callback, $this->error_message_prefix,
+                $this->userinfo);
         }
         if ($this->mode & PEAR_ERROR_PRINT) {
             $modes[] = 'print';
@@ -1045,12 +1095,12 @@ class PEAR_Error
         if ($this->mode & PEAR_ERROR_RETURN) {
             $modes[] = 'return';
         }
-        return sprintf('[%s: message="%s" code=%d mode=%s level=%s '.
-                       'prefix="%s" info="%s"]',
-                       strtolower(get_class($this)), $this->message, $this->code,
-                       implode("|", $modes), $levels[$this->level],
-                       $this->error_message_prefix,
-                       $this->userinfo);
+        return sprintf('[%s: message="%s" code=%d mode=%s level=%s ' .
+            'prefix="%s" info="%s"]',
+            strtolower(get_class($this)), $this->message, $this->code,
+            implode("|", $modes), $levels[$this->level],
+            $this->error_message_prefix,
+            $this->userinfo);
     }
 }
 
index 0303f5273adb45d68c77368ac99bd1910e1d4edd..f166ccd4370fc0a7ce7d93c1d12039b4cd138f8f 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 /**
  * Error Stack Implementation
- * 
+ *
  * This is an incredibly simple implementation of a very complex error handling
  * facility.  It contains the ability
  * to track multiple errors from multiple packages simultaneously.  In addition,
@@ -9,10 +9,10 @@
  * information such as the exact file, line number, class and function that
  * generated the error, and if necessary, it can raise a traditional PEAR_Error.
  * It has built-in support for PEAR::Log, to log errors as they occur
- * 
+ *
  * Since version 0.2alpha, it is also possible to selectively ignore errors,
  * through the use of an error callback, see {@link pushCallback()}
- * 
+ *
  * Since version 0.3alpha, it is possible to specify the exception class
  * returned from {@link push()}
  *
  * @author     Greg Beaver <cellog@php.net>
  * @copyright  2004-2008 Greg Beaver
  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
- * @version    CVS: $Id: ErrorStack.php 313023 2011-07-06 19:17:11Z dufuz $
  * @link       http://pear.php.net/package/PEAR_ErrorStack
  */
 
 /**
  * Singleton storage
- * 
+ *
  * Format:
  * <pre>
  * array(
@@ -45,7 +44,7 @@ $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] = array();
 
 /**
  * Global error callback (default)
- * 
+ *
  * This is only used if set to non-false.  * is the default callback for
  * all packages, whereas specific packages may set a default callback
  * for all instances, regardless of whether they are a singleton or not.
@@ -61,7 +60,7 @@ $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] = array(
 
 /**
  * Global Log object (default)
- * 
+ *
  * This is only used if set to non-false.  Use to set a default log object for
  * all stacks, regardless of instantiation order or location
  * @see PEAR_ErrorStack::setDefaultLogger()
@@ -72,7 +71,7 @@ $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = false;
 
 /**
  * Global Overriding Callback
- * 
+ *
  * This callback will override any error callbacks that specific loggers have set.
  * Use with EXTREME caution
  * @see PEAR_ErrorStack::staticPushCallback()
@@ -132,12 +131,11 @@ define('PEAR_ERRORSTACK_ERR_OBJTOSTRING', 2);
  * $local_stack = new PEAR_ErrorStack('MyPackage');
  * </code>
  * @author     Greg Beaver <cellog@php.net>
- * @version    1.9.4
+ * @version    @package_version@
  * @package    PEAR_ErrorStack
  * @category   Debugging
  * @copyright  2004-2008 Greg Beaver
  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
- * @version    CVS: $Id: ErrorStack.php 313023 2011-07-06 19:17:11Z dufuz $
  * @link       http://pear.php.net/package/PEAR_ErrorStack
  */
 class PEAR_ErrorStack {
@@ -167,14 +165,14 @@ class PEAR_ErrorStack {
      * @access protected
      */
     var $_package;
-    
+
     /**
      * Determines whether a PEAR_Error is thrown upon every error addition
      * @var boolean
      * @access private
      */
     var $_compat = false;
-    
+
     /**
      * If set to a valid callback, this will be used to generate the error
      * message from the error code, otherwise the message passed in will be
@@ -183,7 +181,7 @@ class PEAR_ErrorStack {
      * @access private
      */
     var $_msgCallback = false;
-    
+
     /**
      * If set to a valid callback, this will be used to generate the error
      * context for an error.  For PHP-related errors, this will be a file
@@ -194,43 +192,43 @@ class PEAR_ErrorStack {
      * @access protected
      */
     var $_contextCallback = false;
-    
+
     /**
      * If set to a valid callback, this will be called every time an error
      * is pushed onto the stack.  The return value will be used to determine
      * whether to allow an error to be pushed or logged.
-     * 
+     *
      * The return value must be one an PEAR_ERRORSTACK_* constant
      * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
      * @var false|string|array
      * @access protected
      */
     var $_errorCallback = array();
-    
+
     /**
      * PEAR::Log object for logging errors
      * @var false|Log
      * @access protected
      */
     var $_logger = false;
-    
+
     /**
      * Error messages - designed to be overridden
      * @var array
      * @abstract
      */
     var $_errorMsgs = array();
-    
+
     /**
      * Set up a new error stack
-     * 
+     *
      * @param string   $package name of the package this error stack represents
      * @param callback $msgCallback callback used for error message generation
      * @param callback $contextCallback callback used for context generation,
      *                 defaults to {@link getFileLine()}
      * @param boolean  $throwPEAR_Error
      */
-    function PEAR_ErrorStack($package, $msgCallback = false, $contextCallback = false,
+    function __construct($package, $msgCallback = false, $contextCallback = false,
                          $throwPEAR_Error = false)
     {
         $this->_package = $package;
@@ -238,10 +236,10 @@ class PEAR_ErrorStack {
         $this->setContextCallback($contextCallback);
         $this->_compat = $throwPEAR_Error;
     }
-    
+
     /**
      * Return a single error stack for this package.
-     * 
+     *
      * Note that all parameters are ignored if the stack for package $package
      * has already been instantiated
      * @param string   $package name of the package this error stack represents
@@ -250,12 +248,13 @@ class PEAR_ErrorStack {
      *                 defaults to {@link getFileLine()}
      * @param boolean  $throwPEAR_Error
      * @param string   $stackClass class to instantiate
-     * @static
+     *
      * @return PEAR_ErrorStack
      */
-    function &singleton($package, $msgCallback = false, $contextCallback = false,
-                         $throwPEAR_Error = false, $stackClass = 'PEAR_ErrorStack')
-    {
+    public static function &singleton(
+        $package, $msgCallback = false, $contextCallback = false,
+        $throwPEAR_Error = false, $stackClass = 'PEAR_ErrorStack'
+    ) {
         if (isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
             return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package];
         }
@@ -276,7 +275,7 @@ class PEAR_ErrorStack {
 
     /**
      * Internal error handler for PEAR_ErrorStack class
-     * 
+     *
      * Dies if the error is an exception (and would have died anyway)
      * @access private
      */
@@ -293,24 +292,23 @@ class PEAR_ErrorStack {
             die($message);
         }
     }
-    
+
     /**
      * Set up a PEAR::Log object for all error stacks that don't have one
-     * @param Log $log 
-     * @static
+     * @param Log $log
      */
-    function setDefaultLogger(&$log)
+    public static function setDefaultLogger(&$log)
     {
         if (is_object($log) && method_exists($log, 'log') ) {
             $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log;
         } elseif (is_callable($log)) {
             $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log;
-       }
+        }
     }
-    
+
     /**
      * Set up a PEAR::Log object for this error stack
-     * @param Log $log 
+     * @param Log $log
      */
     function setLogger(&$log)
     {
@@ -320,10 +318,10 @@ class PEAR_ErrorStack {
             $this->_logger = &$log;
         }
     }
-    
+
     /**
      * Set an error code => error message mapping callback
-     * 
+     *
      * This method sets the callback that can be used to generate error
      * messages for any instance
      * @param array|string Callback function/method
@@ -338,10 +336,10 @@ class PEAR_ErrorStack {
             }
         }
     }
-    
+
     /**
      * Get an error code => error message mapping callback
-     * 
+     *
      * This method returns the current callback that can be used to generate error
      * messages
      * @return array|string|false Callback function/method or false if none
@@ -350,17 +348,16 @@ class PEAR_ErrorStack {
     {
         return $this->_msgCallback;
     }
-    
+
     /**
      * Sets a default callback to be used by all error stacks
-     * 
+     *
      * This method sets the callback that can be used to generate error
      * messages for a singleton
      * @param array|string Callback function/method
      * @param string Package name, or false for all packages
-     * @static
      */
-    function setDefaultCallback($callback = false, $package = false)
+    public static function setDefaultCallback($callback = false, $package = false)
     {
         if (!is_callable($callback)) {
             $callback = false;
@@ -368,14 +365,16 @@ class PEAR_ErrorStack {
         $package = $package ? $package : '*';
         $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$package] = $callback;
     }
-    
+
     /**
      * Set a callback that generates context information (location of error) for an error stack
-     * 
+     *
      * This method sets the callback that can be used to generate context
      * information for an error.  Passing in NULL will disable context generation
      * and remove the expensive call to debug_backtrace()
      * @param array|string|null Callback function/method
+     * @return bool
+     * @return array|bool|callable|false|string
      */
     function setContextCallback($contextCallback)
     {
@@ -383,22 +382,23 @@ class PEAR_ErrorStack {
             return $this->_contextCallback = false;
         }
         if (!$contextCallback) {
-            $this->_contextCallback = array(&$this, 'getFileLine');
+            $this->_contextCallback = [&$this, 'getFileLine'];
         } else {
             if (is_callable($contextCallback)) {
                 $this->_contextCallback = $contextCallback;
             }
         }
+        return $this->_contextCallback;
     }
-    
+
     /**
      * Set an error Callback
      * If set to a valid callback, this will be called every time an error
      * is pushed onto the stack.  The return value will be used to determine
      * whether to allow an error to be pushed or logged.
-     * 
+     *
      * The return value must be one of the ERRORSTACK_* constants.
-     * 
+     *
      * This functionality can be used to emulate PEAR's pushErrorHandling, and
      * the PEAR_ERROR_CALLBACK mode, without affecting the integrity of
      * the error stack or logging
@@ -410,7 +410,7 @@ class PEAR_ErrorStack {
     {
         array_push($this->_errorCallback, $cb);
     }
-    
+
     /**
      * Remove a callback from the error callback stack
      * @see pushCallback()
@@ -423,7 +423,7 @@ class PEAR_ErrorStack {
         }
         return array_pop($this->_errorCallback);
     }
-    
+
     /**
      * Set a temporary overriding error callback for every package error stack
      *
@@ -432,20 +432,18 @@ class PEAR_ErrorStack {
      * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
      * @see staticPopCallback(), pushCallback()
      * @param string|array $cb
-     * @static
      */
-    function staticPushCallback($cb)
+    public static function staticPushCallback($cb)
     {
         array_push($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'], $cb);
     }
-    
+
     /**
      * Remove a temporary overriding error callback
      * @see staticPushCallback()
      * @return array|string|false
-     * @static
      */
-    function staticPopCallback()
+    public static function staticPopCallback()
     {
         $ret = array_pop($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK']);
         if (!is_array($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'])) {
@@ -453,15 +451,15 @@ class PEAR_ErrorStack {
         }
         return $ret;
     }
-    
+
     /**
      * Add an error to the stack
-     * 
+     *
      * If the message generator exists, it is called with 2 parameters.
      *  - the current Error Stack object
      *  - an array that is in the same format as an error.  Available indices
      *    are 'code', 'package', 'time', 'params', 'level', and 'context'
-     * 
+     *
      * Next, if the error should contain context information, this is
      * handled by the context grabbing method.
      * Finally, the error is pushed onto the proper error stack
@@ -479,7 +477,7 @@ class PEAR_ErrorStack {
      * @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also
      * thrown.  If a PEAR_Error is returned, the userinfo
      * property is set to the following array:
-     * 
+     *
      * <code>
      * array(
      *    'code' => $code,
@@ -492,7 +490,7 @@ class PEAR_ErrorStack {
      * //['repackage' => $err] repackaged error array/Exception class
      * );
      * </code>
-     * 
+     *
      * Normally, the previous array is returned.
      */
     function push($code, $level = 'error', $params = array(), $msg = false,
@@ -506,19 +504,19 @@ class PEAR_ErrorStack {
             }
             $context = call_user_func($this->_contextCallback, $code, $params, $backtrace);
         }
-        
+
         // save error
         $time = explode(' ', microtime());
         $time = $time[1] + $time[0];
         $err = array(
-                'code' => $code,
-                'params' => $params,
-                'package' => $this->_package,
-                'level' => $level,
-                'time' => $time,
-                'context' => $context,
-                'message' => $msg,
-               );
+            'code' => $code,
+            'params' => $params,
+            'package' => $this->_package,
+            'level' => $level,
+            'time' => $time,
+            'context' => $context,
+            'message' => $msg,
+        );
 
         if ($repackage) {
             $err['repackage'] = $repackage;
@@ -527,9 +525,9 @@ class PEAR_ErrorStack {
         // set up the error message, if necessary
         if ($this->_msgCallback) {
             $msg = call_user_func_array($this->_msgCallback,
-                                        array(&$this, $err));
+                array(&$this, $err));
             $err['message'] = $msg;
-        }        
+        }
         $push = $log = true;
         $die = false;
         // try the overriding callback first
@@ -551,18 +549,18 @@ class PEAR_ErrorStack {
         }
         if (is_callable($callback)) {
             switch(call_user_func($callback, $err)){
-               case PEAR_ERRORSTACK_IGNORE: 
-                       return $err;
-                       break;
-               case PEAR_ERRORSTACK_PUSH: 
-                       $log = false;
-                       break;
-               case PEAR_ERRORSTACK_LOG: 
-                       $push = false;
-                       break;
-               case PEAR_ERRORSTACK_DIE: 
-                       $die = true;
-                       break;
+                case PEAR_ERRORSTACK_IGNORE:
+                    return $err;
+                    break;
+                case PEAR_ERRORSTACK_PUSH:
+                    $log = false;
+                    break;
+                case PEAR_ERRORSTACK_LOG:
+                    $push = false;
+                    break;
+                case PEAR_ERRORSTACK_DIE:
+                    $die = true;
+                    break;
                 // anything else returned has the same effect as pushandlog
             }
         }
@@ -586,10 +584,10 @@ class PEAR_ErrorStack {
         }
         return $err;
     }
-    
+
     /**
      * Static version of {@link push()}
-     * 
+     *
      * @param string $package   Package name this error belongs to
      * @param int    $code      Package-specific error code
      * @param string $level     Error level.  This is NOT spell-checked
@@ -604,11 +602,11 @@ class PEAR_ErrorStack {
      *                          to find error context
      * @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also
      *                          thrown.  see docs for {@link push()}
-     * @static
      */
-    function staticPush($package, $code, $level = 'error', $params = array(),
-                        $msg = false, $repackage = false, $backtrace = false)
-    {
+    public static function staticPush(
+        $package, $code, $level = 'error', $params = array(),
+        $msg = false, $repackage = false, $backtrace = false
+    ) {
         $s = &PEAR_ErrorStack::singleton($package);
         if ($s->_contextCallback) {
             if (!$backtrace) {
@@ -619,7 +617,7 @@ class PEAR_ErrorStack {
         }
         return $s->push($code, $level, $params, $msg, $repackage, $backtrace);
     }
-    
+
     /**
      * Log an error using PEAR::Log
      * @param array $err Error array
@@ -654,10 +652,10 @@ class PEAR_ErrorStack {
         }
     }
 
-    
+
     /**
      * Pop an error off of the error stack
-     * 
+     *
      * @return false|array
      * @since 0.4alpha it is no longer possible to specify a specific error
      * level to return - the last error pushed will be returned, instead
@@ -681,7 +679,7 @@ class PEAR_ErrorStack {
      * @return boolean
      * @since PEAR1.5.0a1
      */
-    function staticPop($package)
+    static function staticPop($package)
     {
         if ($package) {
             if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
@@ -689,11 +687,12 @@ class PEAR_ErrorStack {
             }
             return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->pop();
         }
+        return false;
     }
 
     /**
      * Determine whether there are any errors on the stack
-     * @param string|array Level name.  Use to determine if any errors
+     * @param string|array|bool $level name.  Use to determine if any errors
      * of level (string), or levels (array) have been pushed
      * @return boolean
      */
@@ -704,10 +703,10 @@ class PEAR_ErrorStack {
         }
         return count($this->_errors);
     }
-    
+
     /**
      * Retrieve all errors since last purge
-     * 
+     *
      * @param boolean set in order to empty the error stack
      * @param string level name, to return only errors of a particular severity
      * @return array
@@ -741,7 +740,7 @@ class PEAR_ErrorStack {
         $this->_errorsByLevel = array();
         return $ret;
     }
-    
+
     /**
      * Determine whether there are any errors on a single error stack, or on any error stack
      *
@@ -750,9 +749,8 @@ class PEAR_ErrorStack {
      * @param string|false Package name to check for errors
      * @param string Level name to check for a particular severity
      * @return boolean
-     * @static
      */
-    function staticHasErrors($package = false, $level = false)
+    public static function staticHasErrors($package = false, $level = false)
     {
         if ($package) {
             if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
@@ -767,7 +765,7 @@ class PEAR_ErrorStack {
         }
         return false;
     }
-    
+
     /**
      * Get a list of all errors since last purge, organized by package
      * @since PEAR 1.4.0dev BC break! $level is now in the place $merge used to be
@@ -776,12 +774,13 @@ class PEAR_ErrorStack {
      * @param boolean $merge Set to return a flat array, not organized by package
      * @param array   $sortfunc Function used to sort a merged array - default
      *        sorts by time, and should be good for most cases
-     * @static
-     * @return array 
+     *
+     * @return array
      */
-    function staticGetErrors($purge = false, $level = false, $merge = false,
-                             $sortfunc = array('PEAR_ErrorStack', '_sortErrors'))
-    {
+    public static function staticGetErrors(
+        $purge = false, $level = false, $merge = false,
+        $sortfunc = array('PEAR_ErrorStack', '_sortErrors')
+    ) {
         $ret = array();
         if (!is_callable($sortfunc)) {
             $sortfunc = array('PEAR_ErrorStack', '_sortErrors');
@@ -801,12 +800,12 @@ class PEAR_ErrorStack {
         }
         return $ret;
     }
-    
+
     /**
      * Error sorting function, sorts by time
      * @access private
      */
-    function _sortErrors($a, $b)
+    public static function _sortErrors($a, $b)
     {
         if ($a['time'] == $b['time']) {
             return 0;
@@ -829,9 +828,8 @@ class PEAR_ErrorStack {
      * @param unused
      * @param integer backtrace frame.
      * @param array Results of debug_backtrace()
-     * @static
      */
-    function getFileLine($code, $params, $backtrace = null)
+    public static function getFileLine($code, $params, $backtrace = null)
     {
         if ($backtrace === null) {
             return false;
@@ -842,8 +840,8 @@ class PEAR_ErrorStack {
             $functionframe = 0;
         } else {
             while (isset($backtrace[$functionframe]['function']) &&
-                  $backtrace[$functionframe]['function'] == 'eval' &&
-                  isset($backtrace[$functionframe + 1])) {
+                $backtrace[$functionframe]['function'] == 'eval' &&
+                isset($backtrace[$functionframe + 1])) {
                 $functionframe++;
             }
         }
@@ -854,11 +852,11 @@ class PEAR_ErrorStack {
             $funcbacktrace = $backtrace[$functionframe];
             $filebacktrace = $backtrace[$frame];
             $ret = array('file' => $filebacktrace['file'],
-                         'line' => $filebacktrace['line']);
+                'line' => $filebacktrace['line']);
             // rearrange for eval'd code or create function errors
-            if (strpos($filebacktrace['file'], '(') && 
-                 preg_match(';^(.*?)\((\d+)\) : (.*?)\\z;', $filebacktrace['file'],
-                  $matches)) {
+            if (strpos($filebacktrace['file'], '(') &&
+                preg_match(';^(.*?)\((\d+)\) : (.*?)\\z;', $filebacktrace['file'],
+                    $matches)) {
                 $ret['file'] = $matches[1];
                 $ret['line'] = $matches[2] + 0;
             }
@@ -878,35 +876,35 @@ class PEAR_ErrorStack {
         }
         return false;
     }
-    
+
     /**
      * Standard error message generation callback
-     * 
+     *
      * This method may also be called by a custom error message generator
      * to fill in template values from the params array, simply
      * set the third parameter to the error message template string to use
-     * 
+     *
      * The special variable %__msg% is reserved: use it only to specify
      * where a message passed in by the user should be placed in the template,
      * like so:
-     * 
+     *
      * Error message: %msg% - internal error
-     * 
+     *
      * If the message passed like so:
-     * 
+     *
      * <code>
      * $stack->push(ERROR_CODE, 'error', array(), 'server error 500');
      * </code>
-     * 
+     *
      * The returned error message will be "Error message: server error 500 -
      * internal error"
      * @param PEAR_ErrorStack
      * @param array
      * @param string|false Pre-generated error message template
-     * @static
+     *
      * @return string
      */
-    function getErrorMessage(&$stack, $err, $template = false)
+    public static function getErrorMessage(&$stack, $err, $template = false)
     {
         if ($template) {
             $mainmsg = $template;
@@ -935,7 +933,7 @@ class PEAR_ErrorStack {
         }
         return $mainmsg;
     }
-    
+
     /**
      * Standard Error Message Template generator from code
      * @return string
@@ -947,39 +945,42 @@ class PEAR_ErrorStack {
         }
         return $this->_errorMsgs[$code];
     }
-    
+
     /**
      * Set the Error Message Template array
-     * 
+     *
      * The array format must be:
      * <pre>
      * array(error code => 'message template',...)
      * </pre>
-     * 
+     *
      * Error message parameters passed into {@link push()} will be used as input
      * for the error message.  If the template is 'message %foo% was %bar%', and the
      * parameters are array('foo' => 'one', 'bar' => 'six'), the error message returned will
      * be 'message one was six'
-     * @return string
+     *
+     * Returns string via property
+     * @param $template
+     * @return null
      */
     function setErrorMessageTemplate($template)
     {
         $this->_errorMsgs = $template;
+        return null;
     }
-    
-    
+
+
     /**
      * emulate PEAR::raiseError()
-     * 
+     *
      * @return PEAR_Error
      */
     function raiseError()
     {
-        require_once 'PEAR.php';
+        require_once '../PEAR.php';
         $args = func_get_args();
         return call_user_func_array(array('PEAR', 'raiseError'), $args);
     }
 }
 $stack = &PEAR_ErrorStack::singleton('PEAR_ErrorStack');
-$stack->pushCallback(array('PEAR_ErrorStack', '_handleError'));
-?>
+$stack->pushCallback(array('PEAR_ErrorStack', '_handleError'));
\ No newline at end of file
index 4a0e7b86fac7a953773f2f3a841d36e2380b7664..8755a4242ad577d6b5c2e2e43df81a55810aaf22 100644 (file)
@@ -99,9 +99,9 @@ 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;
+    protected $cause;
     private $_trace;
 
     /**
@@ -117,6 +117,7 @@ class PEAR_Exception extends Exception
      * @param string exception message
      * @param int|Exception|PEAR_Error|array|null exception cause
      * @param int|null exception code or null
+     * @throws PEAR_Exception
      */
     public function __construct($message, $p2 = null, $p3 = null)
     {
@@ -145,32 +146,6 @@ class PEAR_Exception extends Exception
         $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) {
@@ -198,6 +173,32 @@ class PEAR_Exception extends Exception
         }
     }
 
+    /**
+     * @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++;
+    }
+
     /**
      * Return specific error information that can be used for more detailed
      * error messages or translation.
@@ -227,79 +228,6 @@ class PEAR_Exception extends Exception
         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();
@@ -325,22 +253,22 @@ class PEAR_Exception extends Exception
         $trace = $this->getTraceSafe();
         $causes = array();
         $this->getCauseMessage($causes);
-        $html =  '<table style="border: 1px" cellspacing="0">' . "\n";
+        $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";
+                . 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";
+            . '<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>';
+                . '<td>';
             if (!empty($v['class'])) {
                 $html .= $v['class'] . $v['type'];
             }
@@ -350,7 +278,7 @@ class PEAR_Exception extends Exception
                 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_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 {
@@ -361,19 +289,92 @@ class PEAR_Exception extends Exception
                     }
                 }
             }
-            $html .= '(' . implode(', ',$args) . ')'
-                   . '</td>'
-                   . '<td>' . (isset($v['file']) ? $v['file'] : 'unknown')
-                   . ':' . (isset($v['line']) ? $v['line'] : 'unknown')
-                   . '</td></tr>' . "\n";
+            $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>';
+        $html .= '<tr><td style="text-align: center;">' . ($k + 1) . '</td>'
+            . '<td>{main}</td>'
+            . '<td>&nbsp;</td></tr>' . "\n"
+            . '</table>';
         return $html;
     }
 
+    /**
+     * 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 toText()
     {
         $causes = array();
@@ -381,8 +382,8 @@ class PEAR_Exception extends Exception
         $causeMsg = '';
         foreach ($causes as $i => $cause) {
             $causeMsg .= str_repeat(' ', $i) . $cause['class'] . ': '
-                   . $cause['message'] . ' in ' . $cause['file']
-                   . ' on line ' . $cause['line'] . "\n";
+                . $cause['message'] . ' in ' . $cause['file']
+                . ' on line ' . $cause['line'] . "\n";
         }
         return $causeMsg . $this->getTraceAsString();
     }
diff --git a/extlib/PEAR/FixPHP5PEARWarnings.php b/extlib/PEAR/FixPHP5PEARWarnings.php
deleted file mode 100644 (file)
index be5dc3c..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?php
-if ($skipmsg) {
-    $a = &new $ec($code, $mode, $options, $userinfo);
-} else {
-    $a = &new $ec($message, $code, $mode, $options, $userinfo);
-}
-?>
\ No newline at end of file
diff --git a/extlib/PEAR5.php b/extlib/PEAR5.php
deleted file mode 100644 (file)
index 4286067..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-/**
- * This is only meant for PHP 5 to get rid of certain strict warning
- * that doesn't get hidden since it's in the shutdown function
- */
-class PEAR5
-{
-    /**
-    * If you have a class that's mostly/entirely static, and you need static
-    * properties, you can use this method to simulate them. Eg. in your method(s)
-    * do this: $myVar = &PEAR5::getStaticProperty('myclass', 'myVar');
-    * You MUST use a reference, or they will not persist!
-    *
-    * @access public
-    * @param  string $class  The calling classname, to prevent clashes
-    * @param  string $var    The variable to retrieve.
-    * @return mixed   A reference to the variable. If not set it will be
-    *                 auto initialised to NULL.
-    */
-    static function &getStaticProperty($class, $var)
-    {
-        static $properties;
-        if (!isset($properties[$class])) {
-            $properties[$class] = array();
-        }
-
-        if (!array_key_exists($var, $properties[$class])) {
-            $properties[$class][$var] = null;
-        }
-
-        return $properties[$class][$var];
-    }
-}
\ No newline at end of file
index c27d44658e3eed375e5e3763b753fe2024b2235f..7841ae51dc8001d9a6cb2df3ae9d9764e0e9e070 100644 (file)
@@ -9,7 +9,6 @@
  * @author     Tomas V.V.Cox <cox@idecnet.com>
  * @copyright  1997-2009 The Authors
  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
- * @version    CVS: $Id: System.php 313024 2011-07-06 19:51:24Z dufuz $
  * @link       http://pear.php.net/package/PEAR
  * @since      File available since Release 0.1
  */
@@ -23,281 +22,41 @@ require_once 'Console/Getopt.php';
 $GLOBALS['_System_temp_files'] = array();
 
 /**
-* System offers cross plattform compatible system functions
-*
-* Static functions for different operations. Should work under
-* Unix and Windows. The names and usage has been taken from its respectively
-* GNU commands. The functions will return (bool) false on error and will
-* trigger the error with the PHP trigger_error() function (you can silence
-* the error by prefixing a '@' sign after the function call, but this
-* is not recommended practice.  Instead use an error handler with
-* {@link set_error_handler()}).
-*
-* Documentation on this class you can find in:
-* http://pear.php.net/manual/
-*
-* Example usage:
-* if (!@System::rm('-r file1 dir1')) {
-*    print "could not delete file1 or dir1";
-* }
-*
-* In case you need to to pass file names with spaces,
-* pass the params as an array:
-*
-* System::rm(array('-r', $file1, $dir1));
-*
-* @category   pear
-* @package    System
-* @author     Tomas V.V. Cox <cox@idecnet.com>
-* @copyright  1997-2006 The PHP Group
-* @license    http://opensource.org/licenses/bsd-license.php New BSD License
-* @version    Release: 1.9.4
-* @link       http://pear.php.net/package/PEAR
-* @since      Class available since Release 0.1
-* @static
-*/
+ * System offers cross platform compatible system functions
+ *
+ * Static functions for different operations. Should work under
+ * Unix and Windows. The names and usage has been taken from its respectively
+ * GNU commands. The functions will return (bool) false on error and will
+ * trigger the error with the PHP trigger_error() function (you can silence
+ * the error by prefixing a '@' sign after the function call, but this
+ * is not recommended practice.  Instead use an error handler with
+ * {@link set_error_handler()}).
+ *
+ * Documentation on this class you can find in:
+ * http://pear.php.net/manual/
+ *
+ * Example usage:
+ * if (!@System::rm('-r file1 dir1')) {
+ *    print "could not delete file1 or dir1";
+ * }
+ *
+ * In case you need to to pass file names with spaces,
+ * pass the params as an array:
+ *
+ * System::rm(array('-r', $file1, $dir1));
+ *
+ * @category   pear
+ * @package    System
+ * @author     Tomas V.V. Cox <cox@idecnet.com>
+ * @copyright  1997-2006 The PHP Group
+ * @license    http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version    Release: @package_version@
+ * @link       http://pear.php.net/package/PEAR
+ * @since      Class available since Release 0.1
+ * @static
+ */
 class System
 {
-    /**
-     * returns the commandline arguments of a function
-     *
-     * @param    string  $argv           the commandline
-     * @param    string  $short_options  the allowed option short-tags
-     * @param    string  $long_options   the allowed option long-tags
-     * @return   array   the given options and there values
-     * @static
-     * @access private
-     */
-    function _parseArgs($argv, $short_options, $long_options = null)
-    {
-        if (!is_array($argv) && $argv !== null) {
-            // Find all items, quoted or otherwise
-            preg_match_all("/(?:[\"'])(.*?)(?:['\"])|([^\s]+)/", $argv, $av);
-            $argv = $av[1];
-            foreach ($av[2] as $k => $a) {
-                if (empty($a)) {
-                    continue;
-                }
-                $argv[$k] = trim($a) ;
-            }
-        }
-        return Console_Getopt::getopt2($argv, $short_options, $long_options);
-    }
-
-    /**
-     * Output errors with PHP trigger_error(). You can silence the errors
-     * with prefixing a "@" sign to the function call: @System::mkdir(..);
-     *
-     * @param mixed $error a PEAR error or a string with the error message
-     * @return bool false
-     * @static
-     * @access private
-     */
-    function raiseError($error)
-    {
-        if (PEAR::isError($error)) {
-            $error = $error->getMessage();
-        }
-        trigger_error($error, E_USER_WARNING);
-        return false;
-    }
-
-    /**
-     * Creates a nested array representing the structure of a directory
-     *
-     * System::_dirToStruct('dir1', 0) =>
-     *   Array
-     *    (
-     *    [dirs] => Array
-     *        (
-     *            [0] => dir1
-     *        )
-     *
-     *    [files] => Array
-     *        (
-     *            [0] => dir1/file2
-     *            [1] => dir1/file3
-     *        )
-     *    )
-     * @param    string  $sPath      Name of the directory
-     * @param    integer $maxinst    max. deep of the lookup
-     * @param    integer $aktinst    starting deep of the lookup
-     * @param    bool    $silent     if true, do not emit errors.
-     * @return   array   the structure of the dir
-     * @static
-     * @access   private
-     */
-    function _dirToStruct($sPath, $maxinst, $aktinst = 0, $silent = false)
-    {
-        $struct = array('dirs' => array(), 'files' => array());
-        if (($dir = @opendir($sPath)) === false) {
-            if (!$silent) {
-                System::raiseError("Could not open dir $sPath");
-            }
-            return $struct; // XXX could not open error
-        }
-
-        $struct['dirs'][] = $sPath = realpath($sPath); // XXX don't add if '.' or '..' ?
-        $list = array();
-        while (false !== ($file = readdir($dir))) {
-            if ($file != '.' && $file != '..') {
-                $list[] = $file;
-            }
-        }
-
-        closedir($dir);
-        natsort($list);
-        if ($aktinst < $maxinst || $maxinst == 0) {
-            foreach ($list as $val) {
-                $path = $sPath . DIRECTORY_SEPARATOR . $val;
-                if (is_dir($path) && !is_link($path)) {
-                    $tmp    = System::_dirToStruct($path, $maxinst, $aktinst+1, $silent);
-                    $struct = array_merge_recursive($struct, $tmp);
-                } else {
-                    $struct['files'][] = $path;
-                }
-            }
-        }
-
-        return $struct;
-    }
-
-    /**
-     * Creates a nested array representing the structure of a directory and files
-     *
-     * @param    array $files Array listing files and dirs
-     * @return   array
-     * @static
-     * @see System::_dirToStruct()
-     */
-    function _multipleToStruct($files)
-    {
-        $struct = array('dirs' => array(), 'files' => array());
-        settype($files, 'array');
-        foreach ($files as $file) {
-            if (is_dir($file) && !is_link($file)) {
-                $tmp    = System::_dirToStruct($file, 0);
-                $struct = array_merge_recursive($tmp, $struct);
-            } else {
-                if (!in_array($file, $struct['files'])) {
-                    $struct['files'][] = $file;
-                }
-            }
-        }
-        return $struct;
-    }
-
-    /**
-     * The rm command for removing files.
-     * Supports multiple files and dirs and also recursive deletes
-     *
-     * @param    string  $args   the arguments for rm
-     * @return   mixed   PEAR_Error or true for success
-     * @static
-     * @access   public
-     */
-    function rm($args)
-    {
-        $opts = System::_parseArgs($args, 'rf'); // "f" does nothing but I like it :-)
-        if (PEAR::isError($opts)) {
-            return System::raiseError($opts);
-        }
-        foreach ($opts[0] as $opt) {
-            if ($opt[0] == 'r') {
-                $do_recursive = true;
-            }
-        }
-        $ret = true;
-        if (isset($do_recursive)) {
-            $struct = System::_multipleToStruct($opts[1]);
-            foreach ($struct['files'] as $file) {
-                if (!@unlink($file)) {
-                    $ret = false;
-                }
-            }
-
-            rsort($struct['dirs']);
-            foreach ($struct['dirs'] as $dir) {
-                if (!@rmdir($dir)) {
-                    $ret = false;
-                }
-            }
-        } else {
-            foreach ($opts[1] as $file) {
-                $delete = (is_dir($file)) ? 'rmdir' : 'unlink';
-                if (!@$delete($file)) {
-                    $ret = false;
-                }
-            }
-        }
-        return $ret;
-    }
-
-    /**
-     * Make directories.
-     *
-     * The -p option will create parent directories
-     * @param    string  $args    the name of the director(y|ies) to create
-     * @return   bool    True for success
-     * @static
-     * @access   public
-     */
-    function mkDir($args)
-    {
-        $opts = System::_parseArgs($args, 'pm:');
-        if (PEAR::isError($opts)) {
-            return System::raiseError($opts);
-        }
-
-        $mode = 0777; // default mode
-        foreach ($opts[0] as $opt) {
-            if ($opt[0] == 'p') {
-                $create_parents = true;
-            } elseif ($opt[0] == 'm') {
-                // if the mode is clearly an octal number (starts with 0)
-                // convert it to decimal
-                if (strlen($opt[1]) && $opt[1]{0} == '0') {
-                    $opt[1] = octdec($opt[1]);
-                } else {
-                    // convert to int
-                    $opt[1] += 0;
-                }
-                $mode = $opt[1];
-            }
-        }
-
-        $ret = true;
-        if (isset($create_parents)) {
-            foreach ($opts[1] as $dir) {
-                $dirstack = array();
-                while ((!file_exists($dir) || !is_dir($dir)) &&
-                        $dir != DIRECTORY_SEPARATOR) {
-                    array_unshift($dirstack, $dir);
-                    $dir = dirname($dir);
-                }
-
-                while ($newdir = array_shift($dirstack)) {
-                    if (!is_writeable(dirname($newdir))) {
-                        $ret = false;
-                        break;
-                    }
-
-                    if (!mkdir($newdir, $mode)) {
-                        $ret = false;
-                    }
-                }
-            }
-        } else {
-            foreach($opts[1] as $dir) {
-                if ((@file_exists($dir) || !is_dir($dir)) && !mkdir($dir, $mode)) {
-                    $ret = false;
-                }
-            }
-        }
-
-        return $ret;
-    }
-
     /**
      * Concatenate files
      *
@@ -306,14 +65,12 @@ class System
      * 2) System::cat('sample.txt test.txt > final.txt');
      * 3) System::cat('sample.txt test.txt >> final.txt');
      *
-     * Note: as the class use fopen, urls should work also (test that)
+     * Note: as the class use fopen, urls should work also
      *
-     * @param    string  $args   the arguments
+     * @param string $args the arguments
      * @return   boolean true on success
-     * @static
-     * @access   public
      */
-    function &cat($args)
+    public static function &cat($args)
     {
         $ret = null;
         $files = array();
@@ -325,11 +82,11 @@ class System
         for ($i = 0; $i < $count_args; $i++) {
             if ($args[$i] == '>') {
                 $mode = 'wb';
-                $outputfile = $args[$i+1];
+                $outputfile = $args[$i + 1];
                 break;
             } elseif ($args[$i] == '>>') {
                 $mode = 'ab+';
-                $outputfile = $args[$i+1];
+                $outputfile = $args[$i + 1];
                 break;
             } else {
                 $files[] = $args[$i];
@@ -363,6 +120,22 @@ class System
         return $ret;
     }
 
+    /**
+     * Output errors with PHP trigger_error(). You can silence the errors
+     * with prefixing a "@" sign to the function call: @System::mkdir(..);
+     *
+     * @param mixed $error a PEAR error or a string with the error message
+     * @return bool false
+     */
+    protected static function raiseError($error)
+    {
+        if (PEAR::isError($error)) {
+            $error = $error->getMessage();
+        }
+        trigger_error($error, E_USER_WARNING);
+        return false;
+    }
+
     /**
      * Creates temporary files or directories. This function will remove
      * the created files when the scripts finish its execution.
@@ -381,13 +154,11 @@ class System
      *           TMPDIR in Unix will be used. If these vars are also missing
      *           c:\windows\temp or /tmp will be used.
      *
-     * @param   string  $args  The arguments
+     * @param string $args The arguments
      * @return  mixed   the full path of the created (file|dir) or false
      * @see System::tmpdir()
-     * @static
-     * @access  public
      */
-    function mktemp($args = null)
+    public static function mktemp($args = null)
     {
         static $first_time = true;
         $opts = System::_parseArgs($args, 't:d');
@@ -408,7 +179,7 @@ class System
             $tmpdir = System::tmpdir();
         }
 
-        if (!System::mkDir(array('-p', $tmpdir))) {
+        if (!System::mkDir(['-p', $tmpdir])) {
             return false;
         }
 
@@ -421,9 +192,9 @@ class System
         }
 
         $GLOBALS['_System_temp_files'][] = $tmp;
-        if (isset($tmp_is_dir)) {
+        /*if (isset($tmp_is_dir)) {
             //$GLOBALS['_System_temp_files'][] = dirname($tmp);
-        }
+        }*/
 
         if ($first_time) {
             PEAR::registerShutdownFunc(array('System', '_removeTmpFiles'));
@@ -434,20 +205,45 @@ class System
     }
 
     /**
-     * Remove temporary files created my mkTemp. This function is executed
-     * at script shutdown time
+     * returns the commandline arguments of a function
      *
-     * @static
-     * @access private
+     * @param string $argv the commandline
+     * @param string $short_options the allowed option short-tags
+     * @param string $long_options the allowed option long-tags
+     * @return   array   the given options and there values
      */
-    function _removeTmpFiles()
+    public static function _parseArgs($argv, $short_options, $long_options = null)
     {
-        if (count($GLOBALS['_System_temp_files'])) {
-            $delete = $GLOBALS['_System_temp_files'];
-            array_unshift($delete, '-r');
-            System::rm($delete);
-            $GLOBALS['_System_temp_files'] = array();
+        if (!is_array($argv) && $argv !== null) {
+            /*
+            // Quote all items that are a short option
+            $av = preg_split('/(\A| )--?[a-z0-9]+[ =]?((?<!\\\\)((,\s*)|((?<!,)\s+))?)/i', $argv, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE);
+            $offset = 0;
+            foreach ($av as $a) {
+                $b = trim($a[0]);
+                if ($b{0} == '"' || $b{0} == "'") {
+                    continue;
+                }
+
+                $escape = escapeshellarg($b);
+                $pos = $a[1] + $offset;
+                $argv = substr_replace($argv, $escape, $pos, strlen($b));
+                $offset += 2;
+            }
+            */
+
+            // Find all items, quoted or otherwise
+            preg_match_all("/(?:[\"'])(.*?)(?:['\"])|([^\s]+)/", $argv, $av);
+            $argv = $av[1];
+            foreach ($av[2] as $k => $a) {
+                if (empty($a)) {
+                    continue;
+                }
+                $argv[$k] = trim($a);
+            }
         }
+
+        return (new Console_Getopt)->getopt2($argv, $short_options, $long_options);
     }
 
     /**
@@ -456,10 +252,9 @@ class System
      * Note: php.ini-recommended removes the "E" from the variables_order setting,
      * making unavaible the $_ENV array, that s why we do tests with _ENV
      *
-     * @static
      * @return string The temporary directory on the system
      */
-    function tmpdir()
+    public static function tmpdir()
     {
         if (OS_WINDOWS) {
             if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) {
@@ -482,17 +277,222 @@ class System
         return realpath('/tmp');
     }
 
+    /**
+     * Make directories.
+     *
+     * The -p option will create parent directories
+     * @param string $args the name of the director(y|ies) to create
+     * @return   bool    True for success
+     */
+    public static function mkDir($args)
+    {
+        $opts = System::_parseArgs($args, 'pm:');
+        if (PEAR::isError($opts)) {
+            return System::raiseError($opts);
+        }
+
+        $mode = 0777; // default mode
+        foreach ($opts[0] as $opt) {
+            if ($opt[0] == 'p') {
+                $create_parents = true;
+            } elseif ($opt[0] == 'm') {
+                // if the mode is clearly an octal number (starts with 0)
+                // convert it to decimal
+                if (strlen($opt[1]) && $opt[1]{0} == '0') {
+                    $opt[1] = octdec($opt[1]);
+                } else {
+                    // convert to int
+                    $opt[1] += 0;
+                }
+                $mode = $opt[1];
+            }
+        }
+
+        $ret = true;
+        if (isset($create_parents)) {
+            foreach ($opts[1] as $dir) {
+                $dirstack = array();
+                while ((!file_exists($dir) || !is_dir($dir)) &&
+                    $dir != DIRECTORY_SEPARATOR) {
+                    array_unshift($dirstack, $dir);
+                    $dir = dirname($dir);
+                }
+
+                while ($newdir = array_shift($dirstack)) {
+                    if (!is_writeable(dirname($newdir))) {
+                        $ret = false;
+                        break;
+                    }
+
+                    if (!mkdir($newdir, $mode)) {
+                        $ret = false;
+                    }
+                }
+            }
+        } else {
+            foreach ($opts[1] as $dir) {
+                if ((@file_exists($dir) || !is_dir($dir)) && !mkdir($dir, $mode)) {
+                    $ret = false;
+                }
+            }
+        }
+
+        return $ret;
+    }
+
+    /**
+     * Remove temporary files created my mkTemp. This function is executed
+     * at script shutdown time
+     */
+    public static function _removeTmpFiles()
+    {
+        if (count($GLOBALS['_System_temp_files'])) {
+            $delete = $GLOBALS['_System_temp_files'];
+            array_unshift($delete, '-r');
+            System::rm($delete);
+            $GLOBALS['_System_temp_files'] = array();
+        }
+    }
+
+    /**
+     * The rm command for removing files.
+     * Supports multiple files and dirs and also recursive deletes
+     *
+     * @param string $args the arguments for rm
+     * @return   mixed   PEAR_Error or true for success
+     * @static
+     * @access   public
+     */
+    public static function rm($args)
+    {
+        $opts = System::_parseArgs($args, 'rf'); // "f" does nothing but I like it :-)
+        if (PEAR::isError($opts)) {
+            return System::raiseError($opts);
+        }
+        foreach ($opts[0] as $opt) {
+            if ($opt[0] == 'r') {
+                $do_recursive = true;
+            }
+        }
+        $ret = true;
+        if (isset($do_recursive)) {
+            $struct = System::_multipleToStruct($opts[1]);
+            foreach ($struct['files'] as $file) {
+                if (!@unlink($file)) {
+                    $ret = false;
+                }
+            }
+
+            rsort($struct['dirs']);
+            foreach ($struct['dirs'] as $dir) {
+                if (!@rmdir($dir)) {
+                    $ret = false;
+                }
+            }
+        } else {
+            foreach ($opts[1] as $file) {
+                $delete = (is_dir($file)) ? 'rmdir' : 'unlink';
+                if (!@$delete($file)) {
+                    $ret = false;
+                }
+            }
+        }
+        return $ret;
+    }
+
+    /**
+     * Creates a nested array representing the structure of a directory and files
+     *
+     * @param array $files Array listing files and dirs
+     * @return   array
+     * @static
+     * @see System::_dirToStruct()
+     */
+    protected static function _multipleToStruct($files)
+    {
+        $struct = array('dirs' => array(), 'files' => array());
+        settype($files, 'array');
+        foreach ($files as $file) {
+            if (is_dir($file) && !is_link($file)) {
+                $tmp = System::_dirToStruct($file, 0);
+                $struct = array_merge_recursive($tmp, $struct);
+            } else {
+                if (!in_array($file, $struct['files'])) {
+                    $struct['files'][] = $file;
+                }
+            }
+        }
+        return $struct;
+    }
+
+    /**
+     * Creates a nested array representing the structure of a directory
+     *
+     * System::_dirToStruct('dir1', 0) =>
+     *   Array
+     *    (
+     *    [dirs] => Array
+     *        (
+     *            [0] => dir1
+     *        )
+     *
+     *    [files] => Array
+     *        (
+     *            [0] => dir1/file2
+     *            [1] => dir1/file3
+     *        )
+     *    )
+     * @param string $sPath Name of the directory
+     * @param integer $maxinst max. deep of the lookup
+     * @param integer $aktinst starting deep of the lookup
+     * @param bool $silent if true, do not emit errors.
+     * @return   array   the structure of the dir
+     */
+    protected static function _dirToStruct($sPath, $maxinst, $aktinst = 0, $silent = false)
+    {
+        $struct = array('dirs' => array(), 'files' => array());
+        if (($dir = @opendir($sPath)) === false) {
+            if (!$silent) {
+                System::raiseError("Could not open dir $sPath");
+            }
+            return $struct; // XXX could not open error
+        }
+
+        $struct['dirs'][] = $sPath = realpath($sPath); // XXX don't add if '.' or '..' ?
+        $list = array();
+        while (false !== ($file = readdir($dir))) {
+            if ($file != '.' && $file != '..') {
+                $list[] = $file;
+            }
+        }
+
+        closedir($dir);
+        natsort($list);
+        if ($aktinst < $maxinst || $maxinst == 0) {
+            foreach ($list as $val) {
+                $path = $sPath . DIRECTORY_SEPARATOR . $val;
+                if (is_dir($path) && !is_link($path)) {
+                    $tmp = System::_dirToStruct($path, $maxinst, $aktinst + 1, $silent);
+                    $struct = array_merge_recursive($struct, $tmp);
+                } else {
+                    $struct['files'][] = $path;
+                }
+            }
+        }
+
+        return $struct;
+    }
+
     /**
      * The "which" command (show the full path of a command)
      *
      * @param string $program The command to search for
-     * @param mixed  $fallback Value to return if $program is not found
+     * @param mixed $fallback Value to return if $program is not found
      *
      * @return mixed A string with the full path or false if not found
-     * @static
      * @author Stig Bakken <ssb@php.net>
      */
-    function which($program, $fallback = false)
+    public static function which($program, $fallback = false)
     {
         // enforce API
         if (!is_string($program) || '' == $program) {
@@ -504,36 +504,37 @@ class System
             $path_elements[] = dirname($program);
             $program = basename($program);
         } else {
-            // Honor safe mode
-            if (!ini_get('safe_mode') || !$path = ini_get('safe_mode_exec_dir')) {
-                $path = getenv('PATH');
-                if (!$path) {
-                    $path = getenv('Path'); // some OSes are just stupid enough to do this
-                }
+            $path = getenv('PATH');
+            if (!$path) {
+                $path = getenv('Path'); // some OSes are just stupid enough to do this
             }
+
             $path_elements = explode(PATH_SEPARATOR, $path);
         }
 
         if (OS_WINDOWS) {
             $exe_suffixes = getenv('PATHEXT')
-                                ? explode(PATH_SEPARATOR, getenv('PATHEXT'))
-                                : array('.exe','.bat','.cmd','.com');
+                ? explode(PATH_SEPARATOR, getenv('PATHEXT'))
+                : array('.exe', '.bat', '.cmd', '.com');
             // allow passing a command.exe param
             if (strpos($program, '.') !== false) {
                 array_unshift($exe_suffixes, '');
             }
-            // is_executable() is not available on windows for PHP4
-            $pear_is_executable = (function_exists('is_executable')) ? 'is_executable' : 'is_file';
         } else {
             $exe_suffixes = array('');
-            $pear_is_executable = 'is_executable';
         }
 
         foreach ($exe_suffixes as $suff) {
             foreach ($path_elements as $dir) {
                 $file = $dir . DIRECTORY_SEPARATOR . $program . $suff;
-                if (@$pear_is_executable($file)) {
+                // It's possible to run a .bat on Windows that is_executable
+                // would return false for. The is_executable check is meaningless...
+                if (OS_WINDOWS) {
                     return $file;
+                } else {
+                    if (is_executable($file)) {
+                        return $file;
+                    }
                 }
             }
         }
@@ -552,19 +553,17 @@ class System
      * System::find("$dir -name *.php -name *.htm*");
      * System::find("$dir -maxdepth 1");
      *
-     * Params implmented:
+     * Params implemented:
      * $dir            -> Start the search at this directory
      * -type d         -> return only directories
      * -type f         -> return only files
      * -maxdepth <n>   -> max depth of recursion
      * -name <pattern> -> search pattern (bash style). Multiple -name param allowed
      *
-     * @param  mixed Either array or string with the command line
+     * @param mixed Either array or string with the command line
      * @return array Array of found files
-     * @static
-     *
      */
-    function find($args)
+    public static function find($args)
     {
         if (!is_array($args)) {
             $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY);
@@ -580,8 +579,8 @@ class System
         for ($i = 0; $i < $args_count; $i++) {
             switch ($args[$i]) {
                 case '-type':
-                    if (in_array($args[$i+1], array('d', 'f'))) {
-                        if ($args[$i+1] == 'd') {
+                    if (in_array($args[$i + 1], array('d', 'f'))) {
+                        if ($args[$i + 1] == 'd') {
                             $do_files = false;
                         } else {
                             $do_dirs = false;
@@ -590,15 +589,15 @@ class System
                     $i++;
                     break;
                 case '-name':
-                    $name = preg_quote($args[$i+1], '#');
+                    $name = preg_quote($args[$i + 1], '#');
                     // our magic characters ? and * have just been escaped,
                     // so now we change the escaped versions to PCRE operators
                     $name = strtr($name, array('\?' => '.', '\*' => '.*'));
-                    $patterns[] = '('.$name.')';
+                    $patterns[] = '(' . $name . ')';
                     $i++;
                     break;
                 case '-maxdepth':
-                    $depth = $args[$i+1];
+                    $depth = $args[$i + 1];
                     break;
             }
         }
@@ -612,7 +611,7 @@ class System
         }
         if (count($patterns)) {
             $dsq = preg_quote(DIRECTORY_SEPARATOR, '#');
-            $pattern = '#(^|'.$dsq.')'.implode('|', $patterns).'($|'.$dsq.')#';
+            $pattern = '#(^|' . $dsq . ')' . implode('|', $patterns) . '($|' . $dsq . ')#';
             $ret = array();
             $files_count = count($files);
             for ($i = 0; $i < $files_count; $i++) {
@@ -626,4 +625,4 @@ class System
         }
         return $files;
     }
-}
\ No newline at end of file
+}