#!/bin/env php PHK Manager - File: /src/PHK/Tools/Util.php
Package Home

PHK Manager

PHK Home

File: /src/PHK/Tools/Util.php

Size:13303
Storage flags:

<?php
//=============================================================================
//
// Copyright Francois Laupretre <phk@tekwire.net>
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//
//=============================================================================
/**
* @copyright Francois Laupretre <phk@tekwire.net>
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, V 2.0
* @category PHK
* @package PHK
*///==========================================================================
//=============================================================================
/**
* PHK utility functions
*
* Static-only
* API status: Private
* Included in the PHK PHP runtime: Yes
* Implemented in the extension: No
*///==========================================================================

namespace PHK\Tools {

// Ensures PHP_VERSION_ID is set. If version < 5.2.7, emulate.

if (!defined('PHP_VERSION_ID'))
    {
    
$v explode('.',PHP_VERSION);
    
define('PHP_VERSION_ID', ($v[0]*10000+$v[1]*100+$v[2]));
    }

//=============================================================================

if (!class_exists('PHK\Tools\Util',false))
{
//============================================================================

class Util    // Static only
{
//-----

private static $verbose=true;

public static function 
msg($msg)
{
if (
self::$verbose) echo $msg."\n";
}

//-----

public static function varType($var)
{
return 
is_object($var) ? 'object '.get_class($var) : gettype($var);
}

//-----
// Keep in sync with \Phool\Util

public static function envIsWeb()
{
return (
php_sapi_name()!='cli');
}

//----
// Keep in sync with \Phool\Util

public static function envIsWindows()
{
return (
substr(PHP_OS03) == 'WIN');
}

//----

public static function fileSuffix($filename)
{
$dotpos=strrpos($filename,'.');
if (
$dotpos===false) return '';

return 
strtolower(substr($filename,$dotpos+1));
}

//---------
// Warning: This is not the same code as \Automap\Map::combinePath() and
// \Phool\File::combinePath(). Those were modified to support providing
// an absolute $rpath. So, the behavior is different if $rpath starts with '/'.
//
// Combines a base directory and a relative path. If the base directory is
// '.', returns the relative part without modification
// Use '/' separator on stream-wrapper URIs

public static function combinePath($dir,$rpath)
{
if (
$dir=='.' || $dir=='') return $rpath;
$rpath=trim($rpath,'/');
$rpath=trim($rpath,'\\');

$separ=(strpos($dir,':')!==false) ? '/' DIRECTORY_SEPARATOR;
if ((
$dir==='/') || ($dir==='\\')) $separ='';
else
    {
    
$c=substr($dir,-1,1);
    if ((
$c==='/') || ($c=='\\')) $dir=rtrim($dir,$c);
    }

return ((
$rpath==='.') ? $dir $dir.$separ.$rpath);
}

//---------------------------------
/**
* Adds or removes a trailing separator in a path
*
* @param string $path Input
* @param bool $flag true: add trailing sep, false: remove it
* @return bool The result path
*/

public static function trailingSepar($path$separ)
{
$path=rtrim($path,'/\\');
if (
$path=='') return '/';
if (
$separ$path=$path.'/';
return 
$path;
}

//---------------------------------
/**
* Determines if a given path is absolute or relative
*
* @param string $path The path to check
* @return bool True if the path is absolute, false if relative
*/

public static function isAbsolutePath($path)
{
return ((
strpos($path,':')!==false)
    ||(
strpos($path,'/')===0)
    ||(
strpos($path,'\\')===0));
}

//---------------------------------
/**
* Build an absolute path from a given (absolute or relative) path
*
* If the input path is relative, it is combined with the current working
* directory.
*
* @param string $path The path to make absolute
* @param bool $separ True if the resulting path must contain a trailing separator
* @return string The resulting absolute path
*/

public static function mkAbsolutePath($path,$separ=false)
{
if (!
self::isAbsolutePath($path)) $path=self::combinePath(getcwd(),$path);
return 
self::trailingSepar($path,$separ);
}

//---------
// Adapted from PEAR

public static function loadExtension($ext)
{
if (
extension_loaded($ext)) return;

if (
PHP_OS == 'AIX'$suffix 'a';
else 
$suffix PHP_SHLIB_SUFFIX;

@
dl('php_'.$ext.'.'.$suffix) || @dl($ext.'.'.$suffix);

if (!
extension_loaded($ext)) throw new \Exception("$ext: Cannot load extension");
}

//---------
// Require several extensions. Allows to list every extensions that are not
// present.

public static function loadExtensions($ext_list)
{
$failed_ext=array();
foreach(
$ext_list as $ext)
    {
    try { 
self::loadExtension($ext); }
    catch (\
Exception $e) { $failed_ext[]=$ext; }
    }
if (
count($failed_ext))
    throw new \
Exception('Cannot load the following required extension(s): '
        
.implode(' ',$failed_ext));
}

//---------
// Replacement for substr()
// Difference : returns '' instead of false (when index out of range)

public static function substr($buf,$position,$len=NULL)
{
$str=is_null($len) ? substr($buf,$position) : substr($buf,$position,$len);
if (
$str===false$str='';
return 
$str;
}

//---------
// This function must be called before every file access
// Starting with version 5.3.0, 'magic_quotes_runtimes' is deprecated and
// mustn't be used any more.

private static $mqr_exists=null;
private static 
$mqr_level=0;
private static 
$mqr_save;

public static function 
disableMQR()
{
if (
is_null(self::$mqr_exists))
    
self::$mqr_exists=((PHP_VERSION_ID 50300)
        && 
function_exists('set_magic_quotes_runtime'));

if (!
self::$mqr_exists) return;

if (
self::$mqr_level==0)
    {
    
self::$mqr_save=get_magic_quotes_runtime();
    
set_magic_quotes_runtime(0);
    }
self::$mqr_level++;
}

//---------
// This function must be called after every file access

public static function restoreMQR()
{
if (
is_null(self::$mqr_exists))
    
self::$mqr_exists=((PHP_VERSION_ID 50300)
        && 
function_exists('set_magic_quotes_runtime'));

if (!
self::$mqr_exists) return;

self::$mqr_level--;
if (
self::$mqr_level==0set_magic_quotes_runtime(self::$mqr_save);
}

//---------
// Converts a timestamp to a string
// @ to suppress warnings about system timezone

public static function timeString($time=null)
{
if (
$time=='unlimited') return $time;
if (
is_null($time)) $time=time();
return @
strftime('%d-%b-%Y %H:%M %z',$time);
}

//---------
// HTTP mode only: Compute the base URL we were called with

public static function httpBaseURL()
{
if (!
self::envIsWeb()) return '';

if (!isset(
$_SERVER['PATH_INFO'])) return $_SERVER['PHP_SELF'];

$phpself=$_SERVER['PHP_SELF'];
$slen=strlen($phpself);

$pathinfo=$_SERVER['PATH_INFO'];
$ilen=strlen($pathinfo);

// Remove PATH_INFO from PHP_SELF if it is at the end. Don't know
// which config does this, but some servers put it, some don't.

if (($slen $ilen) && (substr($phpself,$slen-$ilen)==$pathinfo))
    
$phpself=substr($phpself,0,$slen-$ilen);

return 
$phpself;
}

//---------------------------------
// Sends an HTTP 301 redirection

public static function http301Redirect($path)
{
header('Location: http://'.$_SERVER['HTTP_HOST'].self::httpBaseURL().$path);
header('HTTP/1.1 301 Moved Permanently');
exit(
0);
}

//---------------------------------
// Sends an HTTP 404 failure

public static function http404Fail()
{
header("HTTP/1.0 404 Not Found");
exit(
1);
}

//---------------------------------
// Sends an HTTP 403 failure

public static function http403Fail()
{
header("HTTP/1.0 403 Forbidden");
exit(
1);
}

//-----

public static function bool2str($cond)
{
return 
$cond 'Yes' 'No';
}

//---------

public static function readFile($path)
{
if ((
$data=@file_get_contents($path))===false)
    throw new \
Exception($path.': Cannot get file content');
return 
$data;
}

//---------
// Throws exceptions and removes '.' and '..'

public static function scandir($path)
{
if ((
$subnames=scandir($path))===false)
    throw new \
Exception($path.': Cannot read directory');

$a=array();
foreach(
$subnames as $f)
    if ((
$f!='.') && ($f!='..')) $a[]=$f;

return 
$a;
}

//---------

public static function trace($msg)
{
if ((
$tfile=getenv('PHK_TRACE_FILE')) !== false)
        {
        
// Append message to trace file
        
if (($fp=fopen($tfile,'a'))===false) throw new \Exception($tfile.': Cannot open trace file');
        
fwrite($fp,self::timeString().': '.$msg."\n");
        
fclose($fp);
        }
}

//---------
// $start=microtime() float

public static function deltaMS($start)
{
$delta=microtime(true)-$start;

return 
round($delta*1000,2).' ms';
}

//---------

public static function mkArray($data)
{
if (
is_null($data)) return array();
if (!
is_array($data)) $data=array($data);
return 
$data;
}

//---------

public static function displaySlowPath()
{
if (
getenv('PHK_DEBUG_SLOW_PATH')!==false)
    {
    
$html=self::envIsWeb();

    if (isset(
$GLOBALS['__PHK_SLOW_PATH']))
        
$data="Slow path entered at:\n".$GLOBALS['__PHK_SLOW_PATH'];
    else 
$data="Fast path OK\n";

    \
PHK::infoSection($html,'Fast path result');

    if (
$html) echo "<pre>";
    echo 
$data;
    if (
$html) echo "/<pre>";
    }
}

//---------

public static function slowPath()
{
if ((
getenv('PHK_DEBUG_SLOW_PATH')!==false)
    && (!isset(
$GLOBALS['__PHK_SLOW_PATH'])))
    {
    
$e=new \Exception();
    
$GLOBALS['__PHK_SLOW_PATH']=$e->getTraceAsString();
    }
}

//-----
/**
* Sends an \Exception with a message starting with 'Format error'
*
* @param string $msg Message to send
* @return void
* @throws \Exception
*/

public static function formatError($msg)
{
throw new \
Exception('Format error: '.$msg);
}

//---------------------------------
// Utility functions called by PHK\Mgr. When using the accelerator, this
// data is persistent. So, retrieving it to populate the cache can be done
// in PHP.

public static function getMinVersion($mnt,$caching)
{
return \
PHK\Stream\Wrapper::getFile(false,\PHK\Mgr::commandURI($mnt
    
,'magicField&name=mv'),$mnt,'magicField',array('name' => 'mv'),''
    
,$caching);
}

public static function 
getOptions($mnt,$caching)
{
return 
unserialize(\PHK\Stream\Wrapper::getFile(false,\PHK\Mgr::sectionURI($mnt
    
,'OPTIONS'),$mnt,'section',array('name' => 'OPTIONS'),'',$caching));
}

public static function 
getBuildInfo($mnt,$caching)
{
return 
unserialize(\PHK\Stream\Wrapper::getFile(false,\PHK\Mgr::sectionURI($mnt
    
,'BUILD_INFO'),$mnt,'section',array('name' => 'BUILD_INFO'),'',$caching));
}

//---------------------------------

public static function callMethod($object,$method,$args)
{
// Special care to avoid endless loops

if (!method_exists($object,$method))
    throw new \
Exception("$method: calling non existing method");

return 
call_user_func_array(array($object,$method),$args);
}

//---------------------------------

public static function runWebInfo($phk)
{
$phk->proxy()->crcCheck();    //-- check CRC before running webinfo
$phkw=new \PHK\Web\Info($phk);
$phkw->run();
}

//---------------------------------

public static function atomicWrite($path,$data)
{
$tmpf=tempnam(dirname($path),'tmp_');

if (
file_put_contents($tmpf,$data)!=strlen($data))
    throw new \
Exception($tmpf.": Cannot write");

// Windows does not support renaming to an existing file (looses atomicity)

if (self::envIsWindows()) @unlink($path);

if (!
rename($tmpf,$path))
    {
    
unlink($tmpf);
    throw new \
Exception($path.': Cannot replace file');
    }
}

//---------------------------------
/**
* Computes a string uniquely identifying a given path on this host.
*
* Mount point unicity is based on a combination of device+inode+mtime.
*
* On systems which don't supply a valid inode number (eg Windows), we
* maintain a fake inode table, whose unicity is based on the path filtered
* through realpath(). It is not perfect because I am not sure that realpath
* really returns a unique 'canonical' path, but this is best solution I
* have found so far.
*
* @param string $path The path to be mounted
* @return string the computed mount point
* @throws \Exception
*/

private static $simul_inode_array=array();
private static 
$simul_inode_index=1;

public static function 
pathUniqueID($prefix,$path,&$mtime)
{
if ((
$s=@stat($path))===false) throw new \Exception("$path: File not found");

$dev=$s[0];
$inode=$s[1];
$mtime=$s[9];

if (
$inode==0// This system does not support inodes
    
{
    
$rpath=realpath($path);
    if (
$rpath === false) throw new \Exception("$path: Cannot compute realpath");

    if (isset(
self::$simul_inode_array[$rpath]))
        
$inode=self::$simul_inode_array[$rpath];
    else
        { 
// Create a new slot
        
$inode=self::$simul_inode_index++;    
        
self::$simul_inode_array[$rpath]=$inode;
        }
    }

return 
sprintf('%s_%X_%X_%X',$prefix,$dev,$inode,$mtime);
}

//---
// End of class
//===========================================================================
// End of class_exists
//===========================================================================
// End of namespace
//===========================================================================
?>

For more information about the PHK package format: http://phk.tekwire.net