compatibility_helper.php

Go to the documentation of this file.
00001 <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
00002 /**
00003  * CodeIgniter
00004  *
00005  * An open source application development framework for PHP 4.3.2 or newer
00006  *
00007  * @package             CodeIgniter
00008  * @author              ExpressionEngine Dev Team
00009  * @copyright   Copyright (c) 2006, EllisLab, Inc.
00010  * @license             http://codeigniter.com/user_guide/license.html
00011  * @link                http://codeigniter.com
00012  * @since               Version 1.0
00013  * @filesource
00014  */
00015 
00016 // ------------------------------------------------------------------------
00017 
00018 /**
00019  * CodeIgniter Compatibility Helpers
00020  *
00021  * This helper contains some functions based on the PEAR PHP_Compat library
00022  * http://pear.php.net/package/PHP_Compat
00023  * 
00024  * The PEAR compat library is a little bloated and the code doesn't harmonize
00025  * well with CodeIgniter, so those functions have been refactored.
00026  * We cheat a little and use CI's _exception_handler() to output our own PHP errors
00027  * so that the behavior fully mimicks the PHP 5 counterparts.  -- Derek Jones
00028  * 
00029  * @package             CodeIgniter
00030  * @subpackage  Helpers
00031  * @category    Helpers
00032  * @author              ExpressionEngine Dev Team
00033  * @link                http://codeigniter.com/user_guide/helpers/compatibility_helper.html
00034  */
00035 
00036 // ------------------------------------------------------------------------
00037 
00038 if ( ! defined('PHP_EOL'))
00039 {
00040         define('PHP_EOL', (DIRECTORY_SEPARATOR == '/') ? "\n" : "\r\n");
00041 } 
00042 
00043 // ------------------------------------------------------------------------
00044 
00045 /**
00046  * file_put_contents()
00047  *
00048  * Writes a string to a file
00049  * http://us.php.net/manual/en/function.file_put_contents.php
00050  * argument 4, $context, not supported
00051  *
00052  * @access      public
00053  * @param       string          file name
00054  * @param       mixed           data to be written
00055  * @param       int                     flags
00056  * @return      int                     length of written string
00057  */
00058 if ( ! function_exists('file_put_contents'))
00059 {
00060         function file_put_contents($filename, $data, $flags = NULL)
00061         {
00062                 if (is_scalar($data))
00063                 {
00064                         settype($data, 'STRING');
00065                 }
00066 
00067                 if ( ! is_string($data) && ! is_array($data) && ! is_resource($data))
00068                 {
00069                         $backtrace = debug_backtrace();
00070                         _exception_handler(E_USER_WARNING, 'file_put_contents(): the 2nd parameter should be either a string or an array', $backtrace[0]['file'], $backtrace[0]['line']);
00071                         return FALSE;
00072                 }
00073 
00074                 // read stream if given a stream resource
00075                 if (is_resource($data))
00076                 {
00077                         if (get_resource_type($data) !== 'stream')
00078                         {
00079                                 $backtrace = debug_backtrace();
00080                                 _exception_handler(E_USER_WARNING, 'file_put_contents(): supplied resource is not a valid stream resource', $backtrace[0]['file'], $backtrace[0]['line']);
00081                                 return FALSE;
00082                         }
00083 
00084                         $text = '';
00085                         
00086                         while ( ! feof($data))
00087                         {
00088                                 $text .= fread($data, 4096);
00089                         }
00090                         
00091                         $data = $text;
00092                         unset($text);
00093                 }
00094         
00095                 // strings only please!
00096                 if (is_array($data))
00097                 {
00098                         $data = implode('', $data);
00099                 }
00100 
00101                 // Set the appropriate mode
00102                 if (($flags & 8) > 0) // 8 = FILE_APPEND flag
00103                 {
00104                         $mode = FOPEN_WRITE_CREATE;
00105                 }
00106                 else
00107                 {
00108                         $mode = FOPEN_WRITE_CREATE_DESTRUCTIVE;
00109                 }
00110         
00111                 // Check if we're using the include path
00112                 if (($flags & 1) > 0) // 1 = FILE_USE_INCLUDE_PATH flag
00113                 {
00114                         $use_include_path = TRUE;
00115                 }
00116                 else
00117                 {
00118                         $use_include_path = FALSE;
00119                 }
00120         
00121                 $fp = @fopen($filename, $mode, $use_include_path);
00122         
00123                 if ($fp === FALSE)
00124                 {
00125                         $backtrace = debug_backtrace();
00126                         _exception_handler(E_USER_WARNING, 'file_put_contents('.htmlentities($filename).') failed to open stream', $backtrace[0]['file'], $backtrace[0]['line']);
00127                         return FALSE;
00128                 }
00129         
00130                 if (($flags & LOCK_EX) > 0)
00131                 {
00132                         if ( ! flock($fp, LOCK_EX))
00133                         {
00134                                 $backtrace = debug_backtrace();
00135                                 _exception_handler(E_USER_WARNING, 'file_put_contents('.htmlentities($filename).') unable to acquire an exclusive lock on file', $backtrace[0]['file'], $backtrace[0]['line']);
00136                                 return FALSE;
00137                         }
00138                 }
00139                 
00140                 // write it
00141                 if (($written = @fwrite($fp, $data)) === FALSE)
00142                 {
00143                         $backtrace = debug_backtrace();
00144                         _exception_handler(E_USER_WARNING, 'file_put_contents('.htmlentities($filename).') failed to write to '.htmlentities($filename), $backtrace[0]['file'], $backtrace[0]['line']);
00145                 }
00146         
00147                 // Close the handle
00148                 @fclose($fp);
00149         
00150                 // Return length
00151                 return $written;
00152         }
00153 }
00154 
00155 // ------------------------------------------------------------------------
00156 
00157 /**
00158  * fputcsv()
00159  *
00160  * Format line as CSV and write to file pointer
00161  * http://us.php.net/manual/en/function.fputcsv.php
00162  *
00163  * @access      public
00164  * @param       resource        file pointer
00165  * @param       array           data to be written
00166  * @param       string          delimiter
00167  * @param       string          enclosure
00168  * @return      int                     length of written string
00169  */
00170 if ( ! function_exists('fputcsv'))
00171 {
00172         function fputcsv($handle, $fields, $delimiter = ',', $enclosure = '"')
00173         {
00174                 // Checking for a handle resource
00175                 if ( ! is_resource($handle))
00176                 {
00177                         $backtrace = debug_backtrace();
00178                         _exception_handler(E_USER_WARNING, 'fputcsv() expects parameter 1 to be stream resource, '.gettype($handle).' given', $backtrace[0]['file'], $backtrace[0]['line']);
00179                         return FALSE;
00180                 }
00181         
00182                 // OK, it is a resource, but is it a stream?
00183                 if (get_resource_type($handle) !== 'stream')
00184                 {
00185                         $backtrace = debug_backtrace();
00186                         _exception_handler(E_USER_WARNING, 'fputcsv() expects parameter 1 to be stream resource, '.get_resource_type($handle).' given', $backtrace[0]['file'], $backtrace[0]['line']);
00187                         return FALSE;
00188                 }
00189         
00190                 // Checking for an array of fields
00191                 if ( ! is_array($fields))
00192                 {
00193                         $backtrace = debug_backtrace();
00194                         _exception_handler(E_USER_WARNING, 'fputcsv() expects parameter 2 to be array, '.gettype($fields).' given', $backtrace[0]['file'], $backtrace[0]['line']);
00195                         return FALSE;
00196                 }
00197         
00198                 // validate delimiter
00199                 if (strlen($delimiter) > 1)
00200                 {
00201                         $delimiter = substr($delimiter, 0, 1);
00202                         $backtrace = debug_backtrace();
00203                         _exception_handler(E_NOTICE, 'fputcsv() delimiter must be one character long, "'.htmlentities($delimiter).'" used', $backtrace[0]['file'], $backtrace[0]['line']);
00204                 }
00205         
00206                 // validate enclosure
00207                 if (strlen($enclosure) > 1)
00208                 {
00209                         $enclosure = substr($enclosure, 0, 1);
00210                         $backtrace = debug_backtrace();
00211                         _exception_handler(E_NOTICE, 'fputcsv() enclosure must be one character long, "'.htmlentities($enclosure).'" used', $backtrace[0]['file'], $backtrace[0]['line']);
00212 
00213                 }
00214         
00215                 $out = '';
00216         
00217                 foreach ($fields as $cell)
00218                 {
00219                         $cell = str_replace($enclosure, $enclosure.$enclosure, $cell);
00220 
00221                         if (strpos($cell, $delimiter) !== FALSE OR strpos($cell, $enclosure) !== FALSE OR strpos($cell, "\n") !== FALSE)
00222                         {
00223                                 $out .= $enclosure.$cell.$enclosure.$delimiter;
00224                         }
00225                         else
00226                         {
00227                                 $out .= $cell.$delimiter;
00228                         }
00229                 }
00230         
00231                 $length = @fwrite($handle, substr($out, 0, -1)."\n");
00232         
00233                 return $length;
00234         }
00235 }
00236 
00237 // ------------------------------------------------------------------------
00238 
00239 /**
00240  * stripos()
00241  *
00242  * Find position of first occurrence of a case-insensitive string
00243  * http://us.php.net/manual/en/function.stripos.php
00244  *
00245  * @access      public
00246  * @param       string          haystack
00247  * @param       string          needle
00248  * @param       int                     offset
00249  * @return      int                     numeric position of the first occurrence of needle in the haystack
00250  */
00251 if ( ! function_exists('stripos'))
00252 {
00253         function stripos($haystack, $needle, $offset = NULL)
00254         {
00255                 // Cast non string scalar values
00256                 if (is_scalar($haystack))
00257                 {
00258                         settype($haystack, 'STRING');
00259                 }
00260         
00261                 if ( ! is_string($haystack))
00262                 {
00263                         $backtrace = debug_backtrace();
00264                         _exception_handler(E_USER_WARNING, 'stripos() expects parameter 1 to be string, '.gettype($haystack).' given', $backtrace[0]['file'], $backtrace[0]['line']);
00265                         return FALSE;
00266                 }
00267         
00268                 if ( ! is_scalar($needle))
00269                 {
00270                         $backtrace = debug_backtrace();
00271                         _exception_handler(E_USER_WARNING, 'stripos() needle is not a string or an integer in '.$backtrace[0]['file'], $backtrace[0]['line']);
00272                         return FALSE;
00273                 }
00274         
00275                 if (is_float($offset))
00276                 {
00277                         $offset = (int)$offset;
00278                 }
00279         
00280                 if ( ! is_int($offset) && ! is_bool($offset) && ! is_null($offset))
00281                 {
00282                         $backtrace = debug_backtrace();
00283                         _exception_handler(E_USER_WARNING, 'stripos() expects parameter 3 to be long, '.gettype($offset).' given', $backtrace[0]['file'], $backtrace[0]['line']);
00284                         return NULL;
00285                 }
00286         
00287                 return strpos(strtolower($haystack), strtolower($needle), $offset);
00288         }
00289 }
00290 
00291 // ------------------------------------------------------------------------
00292 
00293 /**
00294  * str_ireplace()
00295  *
00296  * Find position of first occurrence of a case-insensitive string
00297  * http://us.php.net/manual/en/function.str-ireplace.php
00298  * (parameter 4, $count, is not supported as to do so in PHP 4 would make
00299  * it a required parameter)
00300  *
00301  * @access      public
00302  * @param       mixed           search
00303  * @param       mixed           replace
00304  * @param       mixed           subject
00305  * @return      int                     numeric position of the first occurrence of needle in the haystack
00306  */
00307 if ( ! function_exists('str_ireplace'))
00308 {
00309         function str_ireplace($search, $replace, $subject)
00310         {
00311                 // Nothing to do here
00312                 if ($search === NULL OR $subject === NULL)
00313                 {
00314                         return $subject;
00315                 }
00316         
00317                 // Crazy arguments
00318                 if (is_scalar($search) && is_array($replace))
00319                 {
00320                         $backtrace = debug_backtrace();
00321 
00322                         if (is_object($replace))
00323                         {
00324                                 show_error('Object of class '.get_class($replace).' could not be converted to string in '.$backtrace[0]['file'].' on line '.$backtrace[0]['line']);
00325                         }
00326                         else
00327                         {
00328                                 _exception_handler(E_USER_NOTICE, 'Array to string conversion in '.$backtrace[0]['file'], $backtrace[0]['line']);
00329                         }
00330                 }
00331         
00332                 // Searching for an array
00333                 if (is_array($search))
00334                 {
00335                         // Replacing with an array
00336                         if (is_array($replace))
00337                         {
00338                                 $search = array_values($search);
00339                                 $replace = array_values($replace);
00340 
00341                                 if (count($search) >= count($replace))
00342                                 {
00343                                         $replace = array_pad($replace, count($search), '');
00344                                 }
00345                                 else
00346                                 {
00347                                         $replace = array_slice($replace, 0, count($search));
00348                                 }
00349                         }
00350                         else
00351                         {
00352                                 // Replacing with a string all positions
00353                                 $replace = array_fill(0, count($search), $replace);
00354                         }
00355                 }
00356                 else
00357                 {
00358                         //Searching for a string and replacing with a string.
00359                         $search  = array((string)$search);
00360                         $replace = array((string)$replace);
00361                 }
00362                 
00363                 // Prepare the search array
00364                 foreach ($search as $search_key => $search_value)
00365                 {
00366                         $search[$search_key] = '/'.preg_quote($search_value, '/').'/i';
00367                 }
00368                 
00369                 // Prepare the replace array (escape backreferences)
00370                 foreach ($replace as $k => $v)
00371                 {
00372                         $replace[$k] = str_replace(array(chr(92), '$'), array(chr(92).chr(92), '\$'), $v);
00373                 }
00374         
00375                 // do the replacement
00376                 $result = preg_replace($search, $replace, (array)$subject);
00377         
00378                 // Check if subject was initially a string and return it as a string
00379                 if ( ! is_array($subject))
00380                 {
00381                         return current($result);
00382                 }
00383         
00384                 // Otherwise, just return the array
00385                 return $result;
00386         }
00387 }
00388 
00389 // ------------------------------------------------------------------------
00390 
00391 /**
00392  * http_build_query()
00393  *
00394  * Generate URL-encoded query string
00395  * http://us.php.net/manual/en/function.http-build-query.php
00396  *
00397  * @access      public
00398  * @param       array           form data
00399  * @param       string          numeric prefix
00400  * @param       string          argument separator
00401  * @return      string          URL-encoded string
00402  */
00403 if ( ! function_exists('http_build_query'))
00404 {
00405         function http_build_query($formdata, $numeric_prefix = NULL, $separator = NULL)
00406         {
00407                 // Check the data
00408                 if ( ! is_array($formdata) && ! is_object($formdata))
00409                 {
00410                         $backtrace = debug_backtrace();
00411                         _exception_handler(E_USER_WARNING, 'http_build_query() Parameter 1 expected to be Array or Object. Incorrect value given', $backtrace[0]['file'], $backtrace[0]['line']);
00412                         return FALSE;
00413                 }
00414         
00415                 // Cast it as array
00416                 if (is_object($formdata))
00417                 {
00418                         $formdata = get_object_vars($formdata);
00419                 }
00420         
00421                 // If the array is empty, return NULL
00422                 if (empty($formdata))
00423                 {
00424                         return NULL;
00425                 }
00426         
00427                 // Argument separator
00428                 if ($separator === NULL)
00429                 {
00430                         $separator = ini_get('arg_separator.output');
00431 
00432                         if (strlen($separator) == 0)
00433                         {
00434                                 $separator = '&';
00435                         }
00436                 }
00437         
00438                 // Start building the query
00439                 $tmp = array();
00440 
00441                 foreach ($formdata as $key => $val)
00442                 {
00443                         if ($val === NULL)
00444                         {
00445                                 continue;
00446                         }
00447         
00448                         if (is_integer($key) && $numeric_prefix != NULL)
00449                         {
00450                                 $key = $numeric_prefix.$key;
00451                         }
00452         
00453                         if (is_resource($val))
00454                         {
00455                                 return NULL;
00456                         }
00457                         
00458                         // hand it off to a recursive parser
00459                         $tmp[] = _http_build_query_helper($key, $val, $separator);
00460                 }
00461         
00462                 return implode($separator, $tmp);
00463         }
00464         
00465         
00466         // Helper helper.  Remind anyone of college?
00467         // Required to handle recursion in nested arrays.
00468         // 
00469         // You could shave fractions of fractions of a second by moving where
00470         // the urlencoding takes place, but it's much less intuitive, and if
00471         // your application has 10,000 form fields, well, you have other problems ;)
00472         function _http_build_query_helper($key, $val, $separator = '&')
00473         {       
00474                 if (is_scalar($val))
00475                 {
00476                         return urlencode($key).'='.urlencode($val);                     
00477                 }
00478                 else
00479                 {
00480                         // arrays please
00481                         if (is_object($val))
00482                         {
00483                                 $val = get_object_vars($val);
00484                         }
00485                         
00486                         foreach ($val as $k => $v)
00487                         {
00488                                 $tmp[] = _http_build_query_helper($key.'['.$k.']', $v, $separator);
00489                         }
00490                 }
00491                         
00492                 return implode($separator, $tmp);
00493         }
00494 }
00495 
00496 
00497 /* End of file compatibility_helper.php */
00498 /* Location: ./system/helpers/compatibility_helper.php */