Source for file kernel_lib.php
Documentation is available at kernel_lib.php
* some PHP compatability issues need to be dealt with
require_once( KERNEL_PKG_PATH. 'array_fill.func.php' );
include_once( UTIL_PKG_PATH. 'PHP_Compat/Compat/Function/str_split.php' );
/** \brief substr with a utf8 string - works only with $start and $length positive or nuls
* This function is the same as substr but works with multibyte
* In a multybyte sequence, the first byte of a multibyte sequence that represents a non-ASCII character is always in the range 0xC0 to 0xFD
* and it indicates how many bytes follow for this character.
* All further bytes in a multibyte sequence are in the range 0x80 to 0xBF.
* Check mb_substr availability
function mb_substr( $str, $start, $len = '', $encoding = "UTF-8" ) {
for( $s = 0; $start > 0;-- $start ) {
if( $str[$s] <= "\x7F" ) {
while( $str[$s] >= "\x80" && $str[$s] <= "\xBF" ) {
for( $e = $s; $len > 0; -- $len ) {
if( $str[$e] <= "\x7F" ) {
while( $str[$e] >= "\x80" && $str[$e] <= "\xBF" && $e < $limit ) {
return substr( $str, $s, $e - $s );
if( false !== $retval ) { // no readfile error
* Return system defined temporary directory.
* In Unix, this is usually /tmp
* In Windows, this is usually c:\windows\temp or c:\winnt\temp
* @return system defined temporary directory.
if( !empty( $gTempDir ) ) {
? ( $_SERVER['DOCUMENT_ROOT'] . '/temp/' )
* @return TRUE if we are on windows, FALSE otherwise
if( !isset ( $sWindows )) {
$sWindows = substr( PHP_OS, 0, 3 ) == 'WIN';
* Recursively create directories
* @param array $pTarget target directory
* @param float $pPerms octal permissions
* @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
function mkdir_p( $pTarget, $pPerms = 0755 ) {
if( empty( $pTarget ) || $pTarget == ';' || $pTarget == "/" ) {
$pTarget = preg_replace( '/^\/tmp/', $_SERVER['DOCUMENT_ROOT']. '/temp', $pTarget );
if( substr( $pTarget, 0, 1 ) != '/' ) {
bitdebug( "mkdir_p() - We don't allow '..' in path for security reasons: $pTarget" );
// make use of PHP5 recursive mkdir feature
@mkdir( $pTarget, $pPerms, TRUE );
if( @mkdir( $pTarget, $pPerms )) {
bitdebug( "mkdir_p() - creating $pTarget" );
// recursively create parents
// make the actual target!
if( @mkdir( $pTarget, $pPerms )) {
} elseif( !is_dir( $pTarget ) ) {
error_log( "mkdir() - could not create $pTarget" );
* check to see if particular directories are wroteable by bitweaver
* added check for Windows - wolff_borg - see http://bugs.php.net/bug.php?id=27609
* @param array $pPath path to file or dir
* @return TRUE on success, FALSE on failure
$writeable = @fopen( $pPath. "/". $rnd, "a" );
$writeable = @fopen( $pPath,"a" );
* clean up an array of values and remove any dangerous html - particularly useful for cleaning up $_GET and $_REQUEST.
* Turn off urldecode when detoxifying $_GET or $_REQUEST - these two are always urldecoded done by PHP itself (check docs).
* If you urldecode $_GET twice there might be unexpected consequences (like page One%2BTwo --(PHP)--> One+Two --(you)--> One Two).
* @param array $pParamHash array to be cleaned
* @param boolean $pHtml set true to escape HTML code as well
* @param boolean $pUrldecode set true to urldecode as well
function detoxify( &$pParamHash, $pHtml = FALSE, $pUrldecode = TRUE) {
if( !empty( $pParamHash ) && is_array( $pParamHash ) ) {
foreach( $pParamHash as $key => $value ) {
if( isset ( $value ) && is_array( $value ) ) {
detoxify( $value, $pHtml, $pUrldecode );
$newValue = $pUrldecode ? urldecode( $value ) : $value;
unset ( $pParamHash[$key] );
* @param string $pFileName
* @return clean file name that can be used as title
// MSIE shit file names if passthrough via gigaupload, etc.
// basename will not work - see http://us3.php.net/manual/en/function.basename.php
$defaultName = $tmp[count($tmp) - 1];
} elseif( strpos( '.', $pFileName ) ) {
list ( $defaultName, $ext ) = explode( '.', $pFileName );
$defaultName = $pFileName;
* @param string $pPath Relative path starting in the bitweaver root directory
* @return a valid url based on the given path
* simple function to include in deprecated function calls. makes the developer replace with newer code
* @param array $pReplace code that needs replacing
if( !empty( $trace[1]['class'] )) {
$function = $trace[1]['class']. "::". $trace[1]['function'];
$function = $trace[1]['function'];
$out = "Deprecated function call:\n\tfunction: $function()\n\tfile: ". $trace[1]['file']. "\n\tline: ". $trace[1]['line'];
if( !empty( $pReplace ) ) {
if( !defined( 'IS_LIVE' ) || IS_LIVE == FALSE ) {
* Check that function is enabled on server.
* @return TRUE if function is enabled on server, FALSE otherwise
if( $disabled == NULL ) {
$functions = @ini_get( 'disable_functions' );
$functions = str_replace( ' ', '', $functions );
$disabled = explode( ',', $functions );
return !( in_array( $pName, $disabled ));
} elseif( preg_match('/^[a-f0-9]{6}$/i', $pColor)) {
//Check for a hex color string without hash 'c1c2b4'
} elseif( preg_match('/^#[a-f0-9]{3}$/i', $pColor) ) {
} elseif( preg_match('/^[a-f0-9]{3}$/i', $pColor)) {
//Check for a hex color string without hash 'fff'
* html encode all characters
* taken from: http://www.bbsinc.com/iso8859.html
* @param sting $pData string that might contain an email address
* @return encoded email address
* $note email regex taken from: http://www.regular-expressions.info/regexbuddy/email.html
define( 'EMAIL_ADDRESS_REGEX', '[-a-zA-Z0-9._%+]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}' );
foreach( $addresses[0] as $address ) {
$encoded = strtr( $address, $trans );
* php include as a string
* @param $pEmail the file to include
* @return a string with the results of the file
* get_include_contents -- handy function for getting the contents of a
* php include as a string
* @param $pFile the file to include
* @return a string with the results of the file
global $gContent, $gBitSystem, $gBitSmarty, $gLibertySystem, $gBitUser;
* @param string $pString String that needs to be translated
function tra( $pString ) {
return( $gBitLanguage->translate( $pString ) );
* recursively remove files and directories
* @param string $pPath directory we want to remove
* @param boolean $pFollowLinks follow symlinks or not
* @return TRUE on success, FALSE on failure
function unlink_r( $pPath, $pFollowLinks = FALSE ) {
while( FALSE !== ( $entry = readdir( $dir ) ) ) {
if( is_file( "$pPath/$entry" ) || ( !$pFollowLinks && is_link( "$pPath/$entry" ) ) ) {
} elseif( is_dir( "$pPath/$entry" ) && $entry != '.' && $entry != '..' ) {
* recursively copy the contents of a directory to a new location akin to copy -r
* @param array $pSource source directory
* @param array $pTarget target directory
function copy_r( $pSource, $pTarget ) {
while( FALSE !== ( $entry = $d->read() )) {
if( $entry == '.' || $entry == '..' ) {
$source = $pSource. '/'. $entry;
copy_r( $source, $pTarget. '/'. $entry );
copy( $source, $pTarget. '/'. $entry );
copy( $pSource, $pTarget );
* Fetch the contents of a file on a remote host
* @param string $pUrl url to file to fetch
* @param boolean $pNoCurl skip the use of curl if this causes problems
* @return FALSE on failure, contents of file on success
// rewrite url if sloppy # added a case for https urls
if( !preg_match("/^[-_a-zA-Z0-9:\/\.\?&;%=\+]*$/", $pUrl )) {
// try using curl first as it allows the use of a proxy
curl_setopt( $curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT'] );
if( $fsock = @fsockopen( $parsed['host'], 80, $error['number'], $error['string'], 5 )) {
@fwrite( $fsock, "GET ". $parsed['path']. ( !empty( $parsed['query'] ) ? '?'. $parsed['query'] : '' ). " HTTP/1.1\r\n" );
@fwrite( $fsock, "HOST: {$parsed['host']}\r\n" );
@fwrite( $fsock, "Connection: close\r\n\r\n" );
while( !@feof( $fsock )) {
$ret .= @fread( $fsock, 1024 );
if( @fgets( $fsock, 1024 ) == "\r\n" ) {
if( !empty( $error['string'] )) {
* Parse XML Attributes and return an array
* this function has a whopper of a RegEx.
* I nabbed it from http://www.phpbuilder.com/annotate/message.php3?id=1000234 - XOXO spiderr
* @param array $pString XML type string of parameters
* @return TRUE on success, FALSE on failure
//$parameters = array( '', '' );
$regexp_str = "/([A-Za-z0-9_-]+)(?:\\s*=\\s*(?:(\"|\')((?:[\\\\].|[^\\\\]?)*?)(?:\\2)|([^=\\s]*)))?/";
while( list ( $key, $match ) = each( $matches ) ) {
$value = $match[sizeof( $match )- 1]; // The value can be at different indexes because of optional quotes, but we know it's always at the end.
$parameters[$attrib] = trim( $value, '\"' );
* XML Entity Mandatory Escape Characters
* @param array $quote_style
* @return TRUE on success, FALSE on failure
function xmlentities( $string, $quote_style= ENT_QUOTES ) {
foreach( $trans as $key => $value ) {
$trans[$key] = '&#'. ord( $key ). ';';
// dont translate the '&' in case it is part of &xxx;
// after the initial translation, _do_ map standalone '&' into '&'
return preg_replace( "/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,5};)/","&" , strtr( $string, $trans ));
* Redirect to another page or site
* @param string The url to redirect to
function bit_redirect( $pUrl, $pStatusCode= HttpStatusCodes::HTTP_FOUND ) {
// Handle non-3xx codes separately
if( $pStatusCode && isset ( $errors[$pStatusCode] ) ) {
// clean up URL before executing it
while( strstr( $pUrl, '&&' ) ) {
while( strstr( $pUrl, '&&' ) ) {
// header locates should not have the & in the address it breaks things
while( strstr( $pUrl, '&' ) ) {
header( 'Location: ' . $pUrl, TRUE, $pStatusCode );
header( 'Location: ' . $pUrl );
for( $i = 1; $i < count( $args ); $i++ ) {
foreach( $args[$i] as $key => $data ) {
$pArray[$key] = trim( $pArray[$key] );
* @param numeric $num Number to append th, st, nd, rd to - only makes sense when languages is english
if( $num >= 11 and $num <= 19 ) {
} elseif( $num % 10 == 1 ) {
} elseif( $num % 10 == 2 ) {
} elseif( $num % 10 == 3 ) {
* Cleans file path according to system we're on
* @return TRUE on success, FALSE on failure
$pPath = (!empty($_SERVER["SERVER_SOFTWARE"]) && strpos($_SERVER["SERVER_SOFTWARE"],"IIS") ? str_replace( '\/', '\\', $pPath) : $pPath);
return 'http'. ( ( isset ($_SERVER['HTTPS'] ) && ( $_SERVER['HTTPS'] == 'on' ) ) ? 's' : '' );
* If an unrecoverable error has occurred, this method should be invoked. script exist occurs
* @param string $ pMsg error message to be displayed
* @return none this function will DIE DIE DIE!!!
// here we decide where to go. if there are no db settings yet, we go the welcome page.
if( isset ( $gBitDbType )) {
* pear_check will check to see if a given PEAR module is installed
* @param string $pPearModule The name of the module in the format: Image/GraphViz.php
* @return string with error message on failure, NULL on success
if( !@include_once( "PEAR.php" )) {
return tra( "PEAR is not installed." );
} elseif( !empty( $pPearModule ) && !@include_once( $pPearModule )) {
return tra( "The PEAR plugin <strong>$module</strong> is not installed. Install it with '<strong>pear install $module</strong>' or use your distribution's package manager.");
* A set of compare functions that can be used in conjunction with usort() type functions
* @return TRUE on success, FALSE on failure
if( !empty( $ar1['title'] ) && !empty( $ar2['title'] ) ) {
return strcasecmp( $ar1['title'], $ar2['title'] );
return $ar1["links"] - $ar2["links"];
return $ar1["backlinks"] - $ar2["backlinks"];
return $ar2["links"] - $ar1["links"];
return $ar2["backlinks"] - $ar1["backlinks"];
return $ar1["images"] - $ar2["images"];
return $ar2["images"] - $ar1["images"];
return $ar1["files"] - $ar2["files"];
return $ar2["files"] - $ar1["files"];
return $ar1["versions"] - $ar2["versions"];
return $ar2["versions"] - $ar1["versions"];
return $ar1["lastChanged"] - $ar2["lastChanged"];
return $ar2["lastChanged"] - $ar1["lastChanged"];
// ======================= deprecated functions =======================
* @deprecated deprecated since version 2.1.0-beta
deprecated( 'Please use get_gd_version() instead' );
|