[ Index ]

PHP Cross Reference of PHK Manager

title

Body

[close]

/PHK/Tools/ -> Util.php (source)

   1  <?php
   2  //=============================================================================
   3  //
   4  // Copyright Francois Laupretre <phk@tekwire.net>
   5  //
   6  //   Licensed under the Apache License, Version 2.0 (the "License");
   7  //   you may not use this file except in compliance with the License.
   8  //   You may obtain a copy of the License at
   9  //
  10  //       http://www.apache.org/licenses/LICENSE-2.0
  11  //
  12  //   Unless required by applicable law or agreed to in writing, software
  13  //   distributed under the License is distributed on an "AS IS" BASIS,
  14  //   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15  //   See the License for the specific language governing permissions and
  16  //   limitations under the License.
  17  //
  18  //=============================================================================
  19  /**
  20  * @copyright Francois Laupretre <phk@tekwire.net>
  21  * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, V 2.0
  22  * @category PHK
  23  * @package PHK
  24  *///==========================================================================
  25  //=============================================================================
  26  /**
  27  * PHK utility functions
  28  *
  29  * Static-only
  30  * API status: Private
  31  * Included in the PHK PHP runtime: Yes
  32  * Implemented in the extension: No
  33  *///==========================================================================
  34  
  35  namespace PHK\Tools {
  36  
  37  // Ensures PHP_VERSION_ID is set. If version < 5.2.7, emulate.
  38  
  39  if (!defined('PHP_VERSION_ID'))
  40      {
  41      $v = explode('.',PHP_VERSION);
  42      define('PHP_VERSION_ID', ($v[0]*10000+$v[1]*100+$v[2]));
  43      }
  44  
  45  //=============================================================================
  46  
  47  if (!class_exists('PHK\Tools\Util',false))
  48  {
  49  //============================================================================
  50  
  51  class Util    // Static only
  52  {
  53  //-----
  54  
  55  private static $verbose=true;
  56  
  57  public static function msg($msg)
  58  {
  59  if (self::$verbose) echo $msg."\n";
  60  }
  61  
  62  //-----
  63  
  64  public static function varType($var)
  65  {
  66  return is_object($var) ? 'object '.get_class($var) : gettype($var);
  67  }
  68  
  69  //-----
  70  // Keep in sync with \Phool\Util
  71  
  72  public static function envIsWeb()
  73  {
  74  return (php_sapi_name()!='cli');
  75  }
  76  
  77  //----
  78  // Keep in sync with \Phool\Util
  79  
  80  public static function envIsWindows()
  81  {
  82  return (substr(PHP_OS, 0, 3) == 'WIN');
  83  }
  84  
  85  //----
  86  
  87  public static function fileSuffix($filename)
  88  {
  89  $dotpos=strrpos($filename,'.');
  90  if ($dotpos===false) return '';
  91  
  92  return strtolower(substr($filename,$dotpos+1));
  93  }
  94  
  95  //---------
  96  // Warning: This is not the same code as \Automap\Map::combinePath() and
  97  // \Phool\File::combinePath(). Those were modified to support providing
  98  // an absolute $rpath. So, the behavior is different if $rpath starts with '/'.
  99  //
 100  // Combines a base directory and a relative path. If the base directory is
 101  // '.', returns the relative part without modification
 102  // Use '/' separator on stream-wrapper URIs
 103  
 104  public static function combinePath($dir,$rpath)
 105  {
 106  if ($dir=='.' || $dir=='') return $rpath;
 107  $rpath=trim($rpath,'/');
 108  $rpath=trim($rpath,'\\');
 109  
 110  $separ=(strpos($dir,':')!==false) ? '/' : DIRECTORY_SEPARATOR;
 111  if (($dir==='/') || ($dir==='\\')) $separ='';
 112  else
 113      {
 114      $c=substr($dir,-1,1);
 115      if (($c==='/') || ($c=='\\')) $dir=rtrim($dir,$c);
 116      }
 117  
 118  return (($rpath==='.') ? $dir : $dir.$separ.$rpath);
 119  }
 120  
 121  //---------------------------------
 122  /**
 123  * Adds or removes a trailing separator in a path
 124  *
 125  * @param string $path Input
 126  * @param bool $flag true: add trailing sep, false: remove it
 127  * @return bool The result path
 128  */
 129  
 130  public static function trailingSepar($path, $separ)
 131  {
 132  $path=rtrim($path,'/\\');
 133  if ($path=='') return '/';
 134  if ($separ) $path=$path.'/';
 135  return $path;
 136  }
 137  
 138  //---------------------------------
 139  /**
 140  * Determines if a given path is absolute or relative
 141  *
 142  * @param string $path The path to check
 143  * @return bool True if the path is absolute, false if relative
 144  */
 145  
 146  public static function isAbsolutePath($path)
 147  {
 148  return ((strpos($path,':')!==false)
 149      ||(strpos($path,'/')===0)
 150      ||(strpos($path,'\\')===0));
 151  }
 152  
 153  //---------------------------------
 154  /**
 155  * Build an absolute path from a given (absolute or relative) path
 156  *
 157  * If the input path is relative, it is combined with the current working
 158  * directory.
 159  *
 160  * @param string $path The path to make absolute
 161  * @param bool $separ True if the resulting path must contain a trailing separator
 162  * @return string The resulting absolute path
 163  */
 164  
 165  public static function mkAbsolutePath($path,$separ=false)
 166  {
 167  if (!self::isAbsolutePath($path)) $path=self::combinePath(getcwd(),$path);
 168  return self::trailingSepar($path,$separ);
 169  }
 170  
 171  //---------
 172  // Adapted from PEAR
 173  
 174  public static function loadExtension($ext)
 175  {
 176  if (extension_loaded($ext)) return;
 177  
 178  if (PHP_OS == 'AIX') $suffix = 'a';
 179  else $suffix = PHP_SHLIB_SUFFIX;
 180  
 181  @dl('php_'.$ext.'.'.$suffix) || @dl($ext.'.'.$suffix);
 182  
 183  if (!extension_loaded($ext)) throw new \Exception("$ext: Cannot load extension");
 184  }
 185  
 186  //---------
 187  // Require several extensions. Allows to list every extensions that are not
 188  // present.
 189  
 190  public static function loadExtensions($ext_list)
 191  {
 192  $failed_ext=array();
 193  foreach($ext_list as $ext)
 194      {
 195      try { self::loadExtension($ext); }
 196      catch (\Exception $e) { $failed_ext[]=$ext; }
 197      }
 198  if (count($failed_ext))
 199      throw new \Exception('Cannot load the following required extension(s): '
 200          .implode(' ',$failed_ext));
 201  }
 202  
 203  //---------
 204  // Replacement for substr()
 205  // Difference : returns '' instead of false (when index out of range)
 206  
 207  public static function substr($buf,$position,$len=NULL)
 208  {
 209  $str=is_null($len) ? substr($buf,$position) : substr($buf,$position,$len);
 210  if ($str===false) $str='';
 211  return $str;
 212  }
 213  
 214  //---------
 215  // This function must be called before every file access
 216  // Starting with version 5.3.0, 'magic_quotes_runtimes' is deprecated and
 217  // mustn't be used any more.
 218  
 219  private static $mqr_exists=null;
 220  private static $mqr_level=0;
 221  private static $mqr_save;
 222  
 223  public static function disableMQR()
 224  {
 225  if (is_null(self::$mqr_exists))
 226      self::$mqr_exists=((PHP_VERSION_ID < 50300)
 227          && function_exists('set_magic_quotes_runtime'));
 228  
 229  if (!self::$mqr_exists) return;
 230  
 231  if (self::$mqr_level==0)
 232      {
 233      self::$mqr_save=get_magic_quotes_runtime();
 234      set_magic_quotes_runtime(0);
 235      }
 236  self::$mqr_level++;
 237  }
 238  
 239  //---------
 240  // This function must be called after every file access
 241  
 242  public static function restoreMQR()
 243  {
 244  if (is_null(self::$mqr_exists))
 245      self::$mqr_exists=((PHP_VERSION_ID < 50300)
 246          && function_exists('set_magic_quotes_runtime'));
 247  
 248  if (!self::$mqr_exists) return;
 249  
 250  self::$mqr_level--;
 251  if (self::$mqr_level==0) set_magic_quotes_runtime(self::$mqr_save);
 252  }
 253  
 254  //---------
 255  // Converts a timestamp to a string
 256  // @ to suppress warnings about system timezone
 257  
 258  public static function timeString($time=null)
 259  {
 260  if ($time=='unlimited') return $time;
 261  if (is_null($time)) $time=time();
 262  return @strftime('%d-%b-%Y %H:%M %z',$time);
 263  }
 264  
 265  //---------
 266  // HTTP mode only: Compute the base URL we were called with
 267  
 268  public static function httpBaseURL()
 269  {
 270  if (!self::envIsWeb()) return '';
 271  
 272  if (!isset($_SERVER['PATH_INFO'])) return $_SERVER['PHP_SELF'];
 273  
 274  $phpself=$_SERVER['PHP_SELF'];
 275  $slen=strlen($phpself);
 276  
 277  $pathinfo=$_SERVER['PATH_INFO'];
 278  $ilen=strlen($pathinfo);
 279  
 280  // Remove PATH_INFO from PHP_SELF if it is at the end. Don't know
 281  // which config does this, but some servers put it, some don't.
 282  
 283  if (($slen > $ilen) && (substr($phpself,$slen-$ilen)==$pathinfo))
 284      $phpself=substr($phpself,0,$slen-$ilen);
 285  
 286  return $phpself;
 287  }
 288  
 289  //---------------------------------
 290  // Sends an HTTP 301 redirection
 291  
 292  public static function http301Redirect($path)
 293  {
 294  header('Location: http://'.$_SERVER['HTTP_HOST'].self::httpBaseURL().$path);
 295  header('HTTP/1.1 301 Moved Permanently');
 296  exit(0);
 297  }
 298  
 299  //---------------------------------
 300  // Sends an HTTP 404 failure
 301  
 302  public static function http404Fail()
 303  {
 304  header("HTTP/1.0 404 Not Found");
 305  exit(1);
 306  }
 307  
 308  //---------------------------------
 309  // Sends an HTTP 403 failure
 310  
 311  public static function http403Fail()
 312  {
 313  header("HTTP/1.0 403 Forbidden");
 314  exit(1);
 315  }
 316  
 317  //-----
 318  
 319  public static function bool2str($cond)
 320  {
 321  return $cond ? 'Yes' : 'No';
 322  }
 323  
 324  //---------
 325  
 326  public static function readFile($path)
 327  {
 328  if (($data=@file_get_contents($path))===false)
 329      throw new \Exception($path.': Cannot get file content');
 330  return $data;
 331  }
 332  
 333  //---------
 334  // Throws exceptions and removes '.' and '..'
 335  
 336  public static function scandir($path)
 337  {
 338  if (($subnames=scandir($path))===false)
 339      throw new \Exception($path.': Cannot read directory');
 340  
 341  $a=array();
 342  foreach($subnames as $f)
 343      if (($f!='.') && ($f!='..')) $a[]=$f;
 344  
 345  return $a;
 346  }
 347  
 348  //---------
 349  
 350  public static function trace($msg)
 351  {
 352  if (($tfile=getenv('PHK_TRACE_FILE')) !== false)
 353          {
 354          // Append message to trace file
 355          if (($fp=fopen($tfile,'a'))===false) throw new \Exception($tfile.': Cannot open trace file');
 356          fwrite($fp,self::timeString().': '.$msg."\n");
 357          fclose($fp);
 358          }
 359  }
 360  
 361  //---------
 362  // $start=microtime() float
 363  
 364  public static function deltaMS($start)
 365  {
 366  $delta=microtime(true)-$start;
 367  
 368  return round($delta*1000,2).' ms';
 369  }
 370  
 371  //---------
 372  
 373  public static function mkArray($data)
 374  {
 375  if (is_null($data)) return array();
 376  if (!is_array($data)) $data=array($data);
 377  return $data;
 378  }
 379  
 380  //---------
 381  
 382  public static function displaySlowPath()
 383  {
 384  if (getenv('PHK_DEBUG_SLOW_PATH')!==false)
 385      {
 386      $html=self::envIsWeb();
 387  
 388      if (isset($GLOBALS['__PHK_SLOW_PATH']))
 389          $data="Slow path entered at:\n".$GLOBALS['__PHK_SLOW_PATH'];
 390      else $data="Fast path OK\n";
 391  
 392      \PHK::infoSection($html,'Fast path result');
 393  
 394      if ($html) echo "<pre>";
 395      echo $data;
 396      if ($html) echo "/<pre>";
 397      }
 398  }
 399  
 400  //---------
 401  
 402  public static function slowPath()
 403  {
 404  if ((getenv('PHK_DEBUG_SLOW_PATH')!==false)
 405      && (!isset($GLOBALS['__PHK_SLOW_PATH'])))
 406      {
 407      $e=new \Exception();
 408      $GLOBALS['__PHK_SLOW_PATH']=$e->getTraceAsString();
 409      }
 410  }
 411  
 412  //-----
 413  /**
 414  * Sends an \Exception with a message starting with 'Format error'
 415  *
 416  * @param string $msg Message to send
 417  * @return void
 418  * @throws \Exception
 419  */
 420  
 421  public static function formatError($msg)
 422  {
 423  throw new \Exception('Format error: '.$msg);
 424  }
 425  
 426  //---------------------------------
 427  // Utility functions called by PHK\Mgr. When using the accelerator, this
 428  // data is persistent. So, retrieving it to populate the cache can be done
 429  // in PHP.
 430  
 431  public static function getMinVersion($mnt,$caching)
 432  {
 433  return \PHK\Stream\Wrapper::getFile(false,\PHK\Mgr::commandURI($mnt
 434      ,'magicField&name=mv'),$mnt,'magicField',array('name' => 'mv'),''
 435      ,$caching);
 436  }
 437  
 438  public static function getOptions($mnt,$caching)
 439  {
 440  return unserialize(\PHK\Stream\Wrapper::getFile(false,\PHK\Mgr::sectionURI($mnt
 441      ,'OPTIONS'),$mnt,'section',array('name' => 'OPTIONS'),'',$caching));
 442  }
 443  
 444  public static function getBuildInfo($mnt,$caching)
 445  {
 446  return unserialize(\PHK\Stream\Wrapper::getFile(false,\PHK\Mgr::sectionURI($mnt
 447      ,'BUILD_INFO'),$mnt,'section',array('name' => 'BUILD_INFO'),'',$caching));
 448  }
 449  
 450  //---------------------------------
 451  
 452  public static function callMethod($object,$method,$args)
 453  {
 454  // Special care to avoid endless loops
 455  
 456  if (!method_exists($object,$method))
 457      throw new \Exception("$method: calling non existing method");
 458  
 459  return call_user_func_array(array($object,$method),$args);
 460  }
 461  
 462  //---------------------------------
 463  
 464  public static function runWebInfo($phk)
 465  {
 466  $phk->proxy()->crcCheck();    //-- check CRC before running webinfo
 467  $phkw=new \PHK\Web\Info($phk);
 468  $phkw->run();
 469  }
 470  
 471  //---------------------------------
 472  
 473  public static function atomicWrite($path,$data)
 474  {
 475  $tmpf=tempnam(dirname($path),'tmp_');
 476  
 477  if (file_put_contents($tmpf,$data)!=strlen($data))
 478      throw new \Exception($tmpf.": Cannot write");
 479  
 480  // Windows does not support renaming to an existing file (looses atomicity)
 481  
 482  if (self::envIsWindows()) @unlink($path);
 483  
 484  if (!rename($tmpf,$path))
 485      {
 486      unlink($tmpf);
 487      throw new \Exception($path.': Cannot replace file');
 488      }
 489  }
 490  
 491  //---------------------------------
 492  /**
 493  * Computes a string uniquely identifying a given path on this host.
 494  *
 495  * Mount point unicity is based on a combination of device+inode+mtime.
 496  *
 497  * On systems which don't supply a valid inode number (eg Windows), we
 498  * maintain a fake inode table, whose unicity is based on the path filtered
 499  * through realpath(). It is not perfect because I am not sure that realpath
 500  * really returns a unique 'canonical' path, but this is best solution I
 501  * have found so far.
 502  *
 503  * @param string $path The path to be mounted
 504  * @return string the computed mount point
 505  * @throws \Exception
 506  */
 507  
 508  private static $simul_inode_array=array();
 509  private static $simul_inode_index=1;
 510  
 511  public static function pathUniqueID($prefix,$path,&$mtime)
 512  {
 513  if (($s=@stat($path))===false) throw new \Exception("$path: File not found");
 514  
 515  $dev=$s[0];
 516  $inode=$s[1];
 517  $mtime=$s[9];
 518  
 519  if ($inode==0) // This system does not support inodes
 520      {
 521      $rpath=realpath($path);
 522      if ($rpath === false) throw new \Exception("$path: Cannot compute realpath");
 523  
 524      if (isset(self::$simul_inode_array[$rpath]))
 525          $inode=self::$simul_inode_array[$rpath];
 526      else
 527          { // Create a new slot
 528          $inode=self::$simul_inode_index++;    
 529          self::$simul_inode_array[$rpath]=$inode;
 530          }
 531      }
 532  
 533  return sprintf('%s_%X_%X_%X',$prefix,$dev,$inode,$mtime);
 534  }
 535  
 536  //---
 537  } // End of class
 538  //===========================================================================
 539  } // End of class_exists
 540  //===========================================================================
 541  } // End of namespace
 542  //===========================================================================
 543  ?>


Generated: Thu Jun 4 18:33:15 2015 Cross-referenced by PHPXref 0.7.1