$options = IPSBWOptions::thawOptions( 18, 'user', 'forums' );
*/
static public function thaw( $bitfield, $type, $app='global' )
{
/* INIT */
$bitfield = intval($bitfield);
$array = array();
/* Generate bitwise array */
$bitArray = self::_getBitWiseArray( $type, $app );
if ( ! $bitArray OR ! count( $bitArray ) )
{
return array();
}
/* Build options */
foreach( $bitArray as $key => $bitvalue )
{
if ( $bitfield & intval( $bitvalue ) )
{
$array[ $key ] = 1;
}
else
{
$array[ $key ] = 0;
}
}
return $array;
}
/**
* Build an SQL query bit
*
* @param string Field (field name as assigned by thaw)
* @param string SQL field
* @param string Type (members, groups, etc )
* @param string App (global, forums, etc)
* @param string Type of SQL query (add/remove/has)
* @return string Formatted SQL field
*/
static public function sql( $bitField, $sqlField, $type, $app='global', $sql='has' )
{
/* Generate int sign */
switch( $sql )
{
default:
case 'has':
$_sign = '&';
break;
case 'remove':
$_sign = '-';
break;
case 'add':
$_sign = '+';
break;
}
/* Generate bitwise array */
$bitArray = self::_getBitWiseArray( $type, $app );
/* Do it.. .*/
if ( in_array( $bitField, array_keys( $bitArray ) ) )
{
return '( ' . $sqlField . ' ' . $_sign . ' ' . $bitArray[ $bitField ] . ' ) != 0';
}
else
{
return FALSE;
}
}
/**
* Freeze options
* Converts an array of options array( 'key' => 0 ... ) into an int for saving in a DB field
*
* @param array Array of key => values to save
* @param string Type of options to save
* @param string App
* @return int
*/
static public function freeze( $toSave, $type, $app='global' )
{
/* INIT */
$int = 0;
/* Generate bitwise array */
$bitArray = self::_getBitWiseArray( $type, $app );
if ( ! $bitArray OR ! count( $bitArray ) )
{
return 0;
}
foreach( $bitArray as $key => $value )
{
if ( isset( $toSave[ $key ] ) )
{
if ( $toSave[ $key ] == 1 )
{
$int += $value;
}
}
}
return intval( $int );
}
/**
* Fetch and build the bitwise array
*
* @param string Array key to return
* @return array
*/
static private function _getBitWiseArray( $type, $app )
{
$bitArray = array();
$allOptions = ipsRegistry::fetchBitWiseOptions( $app );
if ( is_array( $allOptions ) )
{
if ( isset( $allOptions[ $type ] ) AND is_array( $allOptions[ $type ] ) )
{
$n = 1;
foreach( $allOptions[ $type ] as $key )
{
$bitArray[ $key ] = $n;
$n *= 2;
}
}
}
return $bitArray;
}
}
/**
* Time Class
*
* Class for handling timestamps
*
*/
class IPSTime
{
/**
* Current timestamp
*
* @var integer
*/
private static $timestamp = IPS_UNIX_TIME_NOW;
/**
* Number of seconds in a minute
*
* @var integer
*/
private static $minute = 60;
/**
* Number of seconds in a hour
*
* @var integer
*/
private static $hour = 3600;
/**
* Number of seconds in a day
*
* @var integer
*/
private static $day = 86400;
/**
* Number of seconds in a week
*
* @var integer
*/
private static $week = 604800;
/**
* Number of seconds in a year
*
* @var integer
*/
private static $year = 220752000;
/**
* Months with 31 days
*
* @var array
*/
private static $months_31 = array( 01, 03, 05, 07, 08, 10, 12 );
/**
* Months with 30 days
*
* @var array
*/
private static $months_30 = array( 04, 06, 09, 11 );
/**
* time_class::dmy_format()
* Generates a time stamp for the day/month/year
*
* @param integer [$ts] Timestamp to format, self::$timestamp used if none specified
* @return void
*/
static public function dmy_format( $ts=0 )
{
/* Set the timestamp */
$_ts = ( $ts ) ? $ts : self::$timestamp;
/* Break it into dmy format */
$_ts = date( "m,d,Y", $_ts );
$_ts = explode( ",", $_ts );
/* Return the timestamp */
return mktime( 0, 0, 0, $_ts[0], $_ts[1], $_ts[2] );
}
/**
* time_class::time_ago()
* Returns how long ago the specified time stamp was
*
* @param integer $ts Timestamp to format
* @return void
*/
static public function time_ago( $ts )
{
if( $ts == time() )
{
return '--';
}
if( $ts < 60 )
{
$plural = ( $ts == 1 ) ? '' : 's';
return sprintf( "%0d", $ts ) . " second$plural";
}
else if( $ts < self::$hour )
{
$plural = ( sprintf("%0d", ( $ts / self::$minute ) ) == 1 ) ? '' : 's';
return sprintf("%0d", ( $ts / self::$minute ) ) . " minute$plural";
}
else if( $ts < self::$day )
{
$plural = ( sprintf("%0d", ( $ts / self::$hour ) ) == 1 ) ? '' : 's';
return sprintf("%0d", ( $ts / self::$hour ) ) . " hour$plural";
}
else
{
$plural = ( sprintf("%0d", ( $ts / self::$day ) ) == 1 ) ? '' : 's';
return sprintf("%0d", ( $ts / self::$day ) ) . " day$plural";
}
}
/**
* Set the timestamp
*
* @param int New timestamp
* @return void
*/
static public function setTimestamp( $time )
{
self::$timestamp = $time;
}
/**
* Get the timestamp
*
* @return int Timestamp
*/
static public function getTimestamp()
{
return self::$timestamp;
}
/**
* time_class::add_minutes()
* Adds the specified number of minutes to the timestamp
*
* @param integer [$num] Number of minutes to add, 1 by default
* @return void
*/
static public function add_minutes( $num=1 )
{
self::$timestamp += self::$minute * $num;
}
/**
* time_class::add_hours()
* Adds the specified number of hours to the timestamp
*
* @param integer [$num] Number of hours to add, 1 by default
* @return void
*/
static public function add_hours( $num=1 )
{
self::$timestamp += self::$hours * $num;
}
/**
* time_class::add_days()
* Adds the specified number of days to the timestamp
*
* @param integer [$num] Number of days to add, 1 by default
* @return void
*/
static public function add_days( $num=1 )
{
self::$timestamp += self::$day * $num;
}
/**
* time_class::add_weeks()
* Adds the specified number of weeks to the timestamp
*
* @param integer [$num] Number of weeks to add, 1 by default
* @return void
*/
static public function add_weeks( $num=1 )
{
self::$timestamp += self::$week * $num;
}
/**
* time_class::add_month()
* Adds a single month to the current timestamp, takes into account leap years
*
* @return void
*/
static public function add_month()
{
$daysInMonth = date( 't', self::$timestamp );
self::$timestamp += self::add_days( intval( $daysInMonth ) );
}
/**
* time_class::add_months()
* Adds the specified number of months to the timestamp
*
* @param integer $num Number of months to add, 1 by default
* @return void
*/
static public function add_months( $num=1 )
{
for( $i = 0; $i < $num; $i++ )
{
self::add_month();
}
}
/**
* time_class::add_years()
* Adds the specified number of years to the timestamp
*
* @param integer $num Number of years to add, 1 by default
* @return void
*/
static public function add_years( $num=1 )
{
for( $i = 0; $i < $num; $i++ )
{
self::add_months( 12 );
self::remove_days( 1 );
}
}
/**
* time_class::remove_days()
* Removes the specified number of days to the timestamp
*
* @param integer [$num] Number of days to remove, 1 by default
* @return void
*/
static public function remove_days( $num=1 )
{
self::$timestamp -= self::$day * $num;
}
/**
* Convert unix timestamp into: (no leading zeros)
* array( 'day' => x, 'month' => x, 'year' => x, 'hour' => x, 'minute' => x );
* Written into separate static public function to allow for timezone to be used easily
*
* @param integer [$unix] Timestamp
* @return array Date parts
*/
static public function unixstamp_to_human( $unix=0 )
{
$tmp = gmdate( 'j,n,Y,G,i', $unix );
list( $day, $month, $year, $hour, $min ) = explode( ',', $tmp );
return array( 'day' => $day,
'month' => $month,
'year' => $year,
'hour' => $hour,
'minute' => $min );
}
/**
* Convert unix timestamp into mmddyyyy
*
* @param integer [$unix] Timestamp
* @param string [$sep] Separator
* @return string mm/dd/yyyy
*/
static public function unixstamp_to_mmddyyyy( $unix=0, $sep='/' )
{
if ( ! $unix )
{
return "";
}
$date = self::unixstamp_to_human( $unix );
return sprintf("%02d{$sep}%02d{$sep}%04d", $date['month'], $date['day'], $date['year'] );
}
/**
* Convert mmddyyyy into unix timestamp
*
* @param string [$date] Date
* @param string [$sep] Separator
* @param bool [$checkdate] Whether to validate date or not
* @return integer Timestamp
*/
static public function mmddyyyy_to_unixstamp( $date='', $sep='/', $checkdate=true )
{
if ( ! $date )
{
return "";
}
list( $month, $day, $year ) = explode( $sep, $date );
if ( $checkdate )
{
if ( ! checkdate( $month, $day, $year ) )
{
return "";
}
}
return self::human_to_unixstamp( $day, $month, $year, 0, 0 );
}
/**
* Wrapper for gmmktime (separated for timezone management)
*
* @param integer $day Day
* @param integer $month Month
* @param integer $year Year
* @param integer $hour Hour
* @param integer $minute Minute
* @return integer Timestamp
*/
static public function human_to_unixstamp( $day, $month, $year, $hour, $minute )
{
return gmmktime( intval($hour), intval($minute), 0, intval($month), intval($day), intval($year) );
}
/**
* My gmmktime() - PHP func seems buggy
*
* @param integer $hour Hour
* @param integer $min Minute
* @param integer $sec Second
* @param integer $month Month
* @param integer $day Day
* @param integer $year Year
* @return integer Timestamp
* @since 2.0
*/
static public function date_gmmktime( $hour=0, $min=0, $sec=0, $month=0, $day=0, $year=0 )
{
// Calculate UTC time offset
$offset = date( 'Z' );
// Generate server based timestamp
$time = mktime( $hour, $min, $sec, $month, $day, $year );
// Calculate DST on / off
$dst = intval( date( 'I', $time ) - date( 'I' ) );
return $offset + ($dst * 3600) + $time;
}
/**
* Hand rolled GETDATE method
*
* getdate doesn't work apparently as it doesn't take into account
* the offset, even when fed a GMT timestamp.
*
* @param integer Unix date
* @return array 0, seconds, minutes, hours, mday, wday, mon, year, yday, weekday, month
* @since 2.0
*/
static public function date_getgmdate( $gmt_stamp )
{
//$tmp = gmdate( 'j,n,Y,G,i,s,w,z,l,F,W,M', $gmt_stamp );
$format = '%e,%m,%Y,%H,%M,%S,%u,%j,%A,%B,%W,%b';
//-----------------------------------------
// Some flags not available on Windows
// @see http://www.php.net/manual/en/function.strftime.php#53340
//-----------------------------------------
if( strpos( strtolower( PHP_OS ), 'win' ) === 0 )
{
$mapping = array(
'%e' => sprintf("%' 2d", date("j", $gmt_stamp)),
'%u' => ($w = date("w", $gmt_stamp)) ? $w : 7,
);
$format = str_replace( array_keys($mapping), array_values($mapping), $format );
}
$tmp = gmstrftime( $format, $gmt_stamp );
list( $day, $month, $year, $hour, $min, $seconds, $wday, $yday, $weekday, $fmon, $week, $smon ) = explode( ',', $tmp );
return array( 0 => $gmt_stamp,
"seconds" => $seconds, // Numeric representation of seconds 0 to 59
"minutes" => $min, // Numeric representation of minutes 0 to 59
"hours" => $hour, // Numeric representation of hours 0 to 23
"mday" => trim($day), // Numeric representation of the day of the month 1 to 31
"wday" => $wday, // Numeric representation of the day of the week 0 (for Sunday) through 6 (for Saturday)
"mon" => $month, // Numeric representation of a month 1 through 12
"year" => $year, // A full numeric representation of a year, 4 digits Examples: 1999 or 2003
"yday" => $yday, // Numeric representation of the day of the year 0 through 365
"weekday" => $weekday, // A full textual representation of the day of the week Sunday through Saturday
"month" => $fmon, // A full textual representation of a month, such as January or Mar
"week" => $week, // Week of the year
"smonth" => $smon,
"smon" => $smon
);
}
}
/**
* IPSLib
*
* Dumping ground for functions that don't fit anywhere else
*
*/
class IPSLib
{
/**
* FURL Templates
*
* @param array
*/
static private $_furlTemplates = array();
/**
* Search configs
*
* @param array
*/
static private $_searchConfigs = array();
/**
* Log in methods
*
* @param array
*/
static private $_lims = array();
/**
* Returns the class name to be instantiated, the class file will already be included
*
* @param string $filePath File location of the class
* @param string $className Name of the class
* @param string $app Application (defaults to 'core')
* @return string Class Name
*/
static public function loadLibrary( $filePath, $className, $app='core' )
{
/* Get the class */
require_once( $filePath );
/* Check for hooks */
$hooksCache = ipsRegistry::cache()->getCache('hooks');
if( isset( $hooksCache['libraryHooks'][ $app ][ $className ] ) AND is_array( $hooksCache['libraryHooks'][ $app ][ $className ] ) AND count( $hooksCache['libraryHooks'][ $app ][ $className ] ) )
{
foreach( $hooksCache['libraryHooks'][ $app ][ $className ] as $classOverloader )
{
/* Hooks: Do we have a hook that extends this class? */
if( file_exists( DOC_IPS_ROOT_PATH . 'hooks/' . $classOverloader['filename'] ) )
{
/* Hooks: Do we have the hook file? */
require_once( DOC_IPS_ROOT_PATH . 'hooks/' . $classOverloader['filename'] );
if( class_exists( $classOverloader['className'] ) )
{
/* Hooks: We have the hook file and the class exists - reset the classname to load */
$className = $classOverloader['className'];
}
}
}
}
/* Return Class Name */
return $className;
}
/**
* Returns the class name to be instantiated, the class file will already be included
*
* @param string $filePath File location of the class
* @param string $className Name of the class
* @return string Class Name
*/
static public function loadActionOverloader( $filePath, $className )
{
/* Get the class */
require_once( $filePath );
/* Hooks: Are we overloading this class? */
$hooksCache = ipsRegistry::cache()->getCache('hooks');
if( isset( $hooksCache['commandHooks'][ $className ] ) AND is_array( $hooksCache['commandHooks'][ $className ] ) AND count( $hooksCache['commandHooks'][ $className ] ) )
{
foreach( $hooksCache['commandHooks'][ $className ] as $classOverloader )
{
if( file_exists( DOC_IPS_ROOT_PATH . 'hooks/' . $classOverloader['filename'] ) )
{
/* Hooks: Do we have the hook file? */
require_once( DOC_IPS_ROOT_PATH . 'hooks/' . $classOverloader['filename'] );
if( class_exists( $classOverloader['className'] ) )
{
/* Hooks: We have the hook file and the class exists - reset the classname to load */
$className = $classOverloader['className'];
}
}
}
}
/* Return Class Name */
return $className;
}
/**
* Checks if there are any data hooks to run
*
* @param array $dataArray Data to be passed into the hooks
* @param string $hookLocation Location the data was sent from
* @return void
*/
static public function doDataHooks( &$dataArray, $hookLocation )
{
/* Loop through the cache */
$hooksCache = ipsRegistry::cache()->getCache( 'hooks' );
if( isset($hooksCache['dataHooks'][ $hookLocation ]) AND is_array( $hooksCache['dataHooks'][ $hookLocation ] ) AND count( $hooksCache['dataHooks'][ $hookLocation ] ) )
{
foreach( $hooksCache['dataHooks'][ $hookLocation ] as $r )
{
/* Check for hook file */
if( file_exists( DOC_IPS_ROOT_PATH . 'hooks/' . $r['filename'] ) )
{
/* Check for hook class */
require_once( DOC_IPS_ROOT_PATH . 'hooks/' . $r['filename'] );
if( class_exists( $r['className'] ) )
{
/* Create and run the hook */
$_hook = new $r['className'];
$newArray = $_hook->handleData( $dataArray );
/* Make sure the array isn't wiped out */
if( is_array( $newArray ) && count( $newArray ) )
{
$dataArray = $newArray;
}
}
}
}
}
}
/**
* Returns an array of data hook locations
*
* @return array
*/
static public function getDataHookLocations()
{
$_locations = array();
/* Loop all apps and get back our locations! */
foreach( ipsRegistry::$applications as $app_dir => $application )
{
$dataHookLocations = array();
if( file_exists( IPSLib::getAppDir( $app_dir ) . '/extensions/dataHookLocations.php' ) )
{
require_once( IPSLib::getAppDir( $app_dir ) . '/extensions/dataHookLocations.php' );
if ( count($dataHookLocations) )
{
$_locations = array_merge( $_locations, $dataHookLocations );
}
}
}
return $_locations;
}
/**
* Checks to see if there is a template hook installed at the specified location
*
*
* @param string $group
* @param array $id
* @return bool
*/
static public function locationHasHooks( $group, $ids )
{
/* Return right away if we don't have an ids to check */
if( ! is_array( $ids ) || ! count( $ids ) )
{
return false;
}
/* Reformat the cache on the first call, to save processing later */
static $formattedCache = array();
if( !isset($formattedCache[ $group ]) )
{
$formattedCache[ $group ] = array();
$hookCache = ipsRegistry::cache()->getCache( 'hooks' );
if ( isset( $hookCache['templateHooks'][ $group ] ) AND is_array($hookCache['templateHooks'][ $group ]) AND count($hookCache['templateHooks'][ $group ]) )
{
foreach( $hookCache['templateHooks'][ $group ] as $_hook )
{
$formattedCache[ $group ][] = $_hook['id'];
}
}
}
/* Use formatted cache to check */
if( count( $formattedCache[ $group ] ) )
{
foreach( $ids as $id )
{
if( in_array( $id, $formattedCache[ $group ] ) )
{
return true;
}
}
}
return false;
}
/**
* Quickly determines if we've got VK enabled and set up
*
* @access public
* @return boolean
*/
static public function vkontakte_enabled()
{
return ( ipsRegistry::$settings['vk_enabled'] AND ipsRegistry::$settings['vk_api_id'] AND ipsRegistry::$settings['vk_secret'] ) ? TRUE : FALSE;
}
/**
* Central setlocale method so we can adjust as needed
*
* @param string Locale to set
* @return void
* @link http://community.invisionpower.com/tracker/issue-16386-language-locale-gives-error/
* @link http://community.invisionpower.com/tracker/issue-18424-change-lang-locale/
*/
static public function setlocale( $locale='' )
{
if( !$locale )
{
return;
}
if ( stripos( $locale, 'tr_' ) !== FALSE )
{
setlocale( LC_COLLATE, $locale );
setlocale( LC_MONETARY, $locale );
setlocale( LC_NUMERIC, $locale );
setlocale( LC_TIME, $locale );
setlocale( LC_MESSAGES, $locale );
}
else
{
setlocale( LC_ALL, $locale );
}
}
/**
* Quickly determines if we've got FB enabled and set up
*
* @return boolean
*/
static public function fbc_enabled()
{
return ( ipsRegistry::$settings['fbc_enable'] AND ipsRegistry::$settings['fbc_api_id'] AND ipsRegistry::$settings['fbc_secret'] ) ? TRUE : FALSE;
}
/**
* Quickly determines if we've got twitter enabled and set up
*
* @return boolean
*/
static public function twitter_enabled()
{
return ( ipsRegistry::$settings['tc_enabled'] AND ipsRegistry::$settings['tc_token'] AND ipsRegistry::$settings['tc_secret'] ) ? TRUE : FALSE;
}
/**
* Quickly determines if we've got other log in enabled and set up
*
* @return boolean
*/
static public function loginMethod_enabled( $method )
{
if ( ! count( self::$_lims ) )
{
if ( is_array( ipsRegistry::cache()->getCache('login_methods') ) )
{
$cache = ipsRegistry::cache()->getCache('login_methods');
foreach( $cache as $lim )
{
self::$_lims[ $lim['login_folder_name'] ] = $lim['login_folder_name'];
}
}
}
switch( $method )
{
case 'vkontakte':
return self::vkontakte_enabled();
break;
case 'facebook':
return self::fbc_enabled();
break;
case 'twitter':
return self::twitter_enabled();
break;
default:
return in_array( $method, self::$_lims ) ? true : false;
break;
}
}
/**
* Unpack group bitwise options
*
* @param array
* @param bool Do not warn on overwrite
* @return array
*/
static public function unpackGroup( $group, $silence=false )
{
/* Unpack bitwise fields */
$_tmp = IPSBWOptions::thaw( $group['g_bitoptions'], 'groups', 'global' );
if ( count( $_tmp ) )
{
foreach( $_tmp as $k => $v )
{
/* Trigger notice if we have DB field */
if ( $silence === false AND isset( $group[ $k ] ) )
{
trigger_error( "Thawing bitwise options for GROUPS: Bitwise field '$k' has overwritten DB field '$k'", E_USER_WARNING );
}
$group[ $k ] = $v;
}
}
return $group;
}
/**
* Little function to return the version number data
*
* Handy to use when dealing with IN_DEV, etc
* Uses the constant where available
*
* @param string App ( Default 'core')
* @return array array( 'long' => x, 'human' => x )
*/
static public function fetchVersionNumber( $app='core' )
{
if ( ! defined( IPB_VERSION ) OR ! defined( IPB_LONG_VERSION ) )
{
require_once( IPS_ROOT_PATH . 'setup/sources/base/setup.php' );
$XMLVersions = IPSSetUp::fetchXmlAppVersions( $app );
$tmp = $XMLVersions;
krsort( $tmp );
foreach( $tmp as $long => $human )
{
$return = array( 'long' => $long, 'human' => $human );
break;
}
}
else
{
$return = array( 'long' => IPB_LONG_VERSION, 'human' => IPB_VERSION );
}
return $return;
}
/**
* Cheeky little function to locate group table fields from other apps
*
* @return array Array of fields from different apps
*/
static function fetchNonDefaultGroupFields()
{
$fields = array();
foreach( array( 'gallery', 'blog', 'downloads', 'ccs', 'ipchat', 'nexus', 'subscriptions' ) as $app )
{
$_file = IPSLib::getAppDir( $app ) . '/setup/versions/install/sql/' . $app . '_mysql_tables.php';
if ( file_exists( $_file ) )
{
$TABLE = array();
require( $_file );
foreach( $TABLE as $t )
{
if ( preg_match( '#^ALTER TABLE\s+?groups\s+?ADD\s+?(\S+?)\s#i', $t, $match ) )
{
$fields[] = $match[1];
}
}
}
}
return $fields;
}
/**
* Update settings
*
* @param array array('conf_key' => 'new value')
* @return true/false
* @author MarkWade
*/
static public function updateSettings($update=array())
{
$fields = array_keys($update);
ipsRegistry::DB()->build( array( 'select' => '*', 'from' => 'core_sys_conf_settings', 'where' => "conf_key IN ('" . implode( "','", $fields ) . "')" ) );
ipsRegistry::DB()->execute();
$db_fields = array();
while ( $r = ipsRegistry::DB()->fetch() )
{
$db_fields[ $r['conf_key'] ] = $r;
}
if (empty($db_fields))
{
return false;
}
foreach( $db_fields as $key => $data )
{
$value = str_replace( "'", "'", IPSText::safeslashes($update[ $key ]) );
$value = $value == '' ? "{blank}" : $value;
ipsRegistry::DB()->update( 'core_sys_conf_settings', array( 'conf_value' => $value ), 'conf_id=' . $data['conf_id'] );
}
ipsRegistry::DB()->build( array( 'select' => '*', 'from' => 'core_sys_conf_settings', 'where' => 'conf_add_cache=1' ) );
$info = ipsRegistry::DB()->execute();
while ( $r = ipsRegistry::DB()->fetch($info) )
{
$value = $r['conf_value'] != "" ? $r['conf_value'] : $r['conf_default'];
if ( $value == '{blank}' )
{
$value = '';
}
$settings[ $r['conf_key'] ] = $value;
}
ipsRegistry::cache()->setCache( 'settings', $settings, array( 'array' => 1 ) );
return true;
}
/**
* Retrieve the default language
*
* @return string Default language id (most likely a number)
*/
static public function getDefaultLanguage()
{
$cache = ipsRegistry::cache()->getCache('lang_data');
if( !count($cache) OR !is_array($cache) )
{
ipsRegistry::getClass('class_localization')->rebuildLanguagesCache();
$cache = ipsRegistry::cache()->getCache('lang_data');
}
$_default = 1;
foreach( $cache as $_lang )
{
if( $_lang['lang_default'] )
{
$_default = $_lang['lang_id'];
break;
}
}
return $_default;
}
/**
* Build furl templates from FURL extensions
*
* @return array
*/
static public function buildFurlTemplates()
{
/* INIT */
$apps = array();
$_SEOTEMPLATES = array();
static $_apps = array();
/* Done this already? */
if ( self::$_furlTemplates )
{
return self::$_furlTemplates;
}
/**
* Get app data and cache - 1 query is better than 1 per app
*/
ipsRegistry::DB()->build( array( 'select' => 'app_directory, app_public_title, app_enabled', 'from' => 'core_applications' ) );
ipsRegistry::DB()->execute();
while( $_r = ipsRegistry::DB()->fetch() )
{
$_apps[ $_r['app_directory'] ] = $_r;
}
/* Because this is called before the cache is unpacked, we need to expensively grab all app dirs */
foreach( array( 'applications', 'applications_addon/ips', 'applications_addon/other' ) as $folder )
{
try
{
foreach( new DirectoryIterator( IPS_ROOT_PATH . $folder ) as $file )
{
if ( ! $file->isDot() AND $file->isDir() )
{
$_name = $file->getFileName();
if ( substr( $_name, 0, 1 ) != '.' )
{
/* Check if this app is enabled before including the templates.. */
$_check = $_apps[ $_name ];
if ( $_check['app_public_title'] && $_check['app_enabled'] )
{
$apps[ $folder . '/' . $_name ] = $_name;
}
}
}
}
} catch ( Exception $e ) {}
}
/* First, add in core stuffs */
ipsRegistry::_loadCoreVariables();
$templates = ipsRegistry::_fetchCoreVariables('templates');
if ( is_array( $templates ) )
{
foreach( $templates as $key => $data )
{
self::$_furlTemplates[ $key ] = $data;
}
}
// FURL Pack select
$furl_templates_filename = 'furlTemplates.php';
if ( IPB_USE_ONLY_ID_FURL )
{
$furl_templates_filename = 'furlIdTemplates.php';
}
/* Loop over the applications and build */
foreach( $apps as $path => $app_dir )
{
if ( file_exists( IPS_ROOT_PATH . $path . '/extensions/' . $furl_templates_filename ) )
{
$_SEOTEMPLATES = array();
require( IPS_ROOT_PATH . $path . '/extensions/' . $furl_templates_filename );
if ( is_array( $_SEOTEMPLATES ) && count( $_SEOTEMPLATES ) )
{
foreach( $_SEOTEMPLATES as $key => $data )
{
self::$_furlTemplates[ $key ] = $data;
}
}
}
}
/* Return for anyone else */
return self::$_furlTemplates;
}
/**
* Cache templates from FURL extensions
*
* @return boolean
* @exceptions
* CANNOT_WRITE Cannot write to cache file
* NO_DATA_TO_WRITE No data to write
*/
static public function cacheFurlTemplates()
{
if ( ! count( self::$_furlTemplates ) )
{
self::buildFurlTemplates();
}
if ( count( self::$_furlTemplates ) )
{
$_date = gmdate( 'r', time() );
$_var = var_export( self::$_furlTemplates, TRUE );
$data = <<
* $a = array( 'red' => 100,
* 'green' => 200,
* 'blue' => 300,
* 'orange' => 600 );
*
* $b = array( 'red' => 101,
* 'green' => 199,
* 'blue' => 305,
* 'black' => 100 );
*
* Merge both arrays, finding the highest value in each
* print_r( array_umerge( $a, $b, create_function( '$a,$b', 'return $a < $b;' ) ) );
* Produces:
* Array
* (
* [red] => 101
* [green] => 200
* [blue] => 305
* [orange] => 600
* [black] => 100
* )
*
*
* @param array Array to merge
* @param array Array to merge
* @param string Callback function
* @return array Merged array
* @deprecated This will likely be removed in a future version
*/
static public function arrayUmerge( $array1, $array2, $callback )
{
$return = array();
if ( ! is_array( $array1 ) AND ! is_array( $array2 ) )
{
return FALSE;
}
foreach( $array1 as $_k1 => $_v1 )
{
$return[ $_k1 ] = $_v1;
/* Key exists in second array - so compare */
if ( isset( $array2[$_k1] ) )
{
if ( call_user_func( $callback, $_v1, $array2[$_k1] ) )
{
$return[ $_k1 ] = $array2[$_k1];
}
}
}
/* Now check for keys in the second array that aren't in the first */
foreach( $array2 as $_k2 => $_v2 )
{
if ( ! isset( $array1[ $_k2 ] ) )
{
$return[ $_k2 ] = $_v2;
}
}
return $return;
}
/**
* Merges arrays like array_merge_recursive but replaces indentical keys
*
*/
static public function arrayMergeRecursive()
{
$arrays = func_get_args();
$base = array_shift( $arrays );
if ( ! is_array($base) )
{
$base = empty($base) ? array() : array($base);
}
foreach( $arrays as $append )
{
if ( ! is_array( $append ) )
{
$append = array( $append );
}
foreach( $append as $key => $value)
{
if ( ! array_key_exists( $key, $base ) and ! is_numeric( $key ) )
{
$base[$key] = $append[$key];
continue;
}
if ( is_array($value) or is_array( $base[$key] ) )
{
$base[$key] = self::arrayMergeRecursive( $base[$key], $append[$key] );
}
else if ( is_numeric( $key ) )
{
if ( ! in_array( $value, $base ) )
{
$base[] = $value;
}
}
else
{
$base[$key] = $value;
}
}
}
return $base;
}
/**
* Merge two arrays. Unlike array_merge, however, duplicate keys are ignored rather than overwritten.
*
* @param array
* @param array
* @return array
*/
static public function mergeArrays( $array1, $array2 )
{
$returnArray = $array1;
foreach( $array2 as $_key => $_value )
{
if( !array_key_exists( $_key, $returnArray ) )
{
$returnArray[ $_key ] = $_value;
}
}
return $returnArray;
}
/**
* arraySearchLoose
*
* @param string "Needle"
* @param array Array of text to search
* @return mixed Key of array, or false on failure
*/
static public function arraySearchLoose( $needle, $haystack )
{
if( !is_array( $haystack ) OR !count($haystack) OR ! $needle )
{
return false;
}
foreach( $haystack as $k => $v )
{
if( $v AND stripos( $v, $needle ) !== false )
{
return $k;
}
}
return false;
}
/**
* Check to see if any applications support 'like' system
*
* @return bool True if there are any applications that support the 'like' system, otherwise false
*/
static public function haveAppsWithLike()
{
foreach( ipsRegistry::$applications as $_app => $data )
{
if( $data['_supports_likes'] )
{
return true;
}
}
return false;
}
/**
* Get the application title. Uses lang file keys if present.
*
* @param string application
* @return string Text to show for application title
*/
static public function getAppTitle( $app )
{
if ( ! $app )
{
return '';
}
return isset( ipsRegistry::getClass('class_localization')->words[ $app . '_display_title' ] ) ?
ipsRegistry::getClass('class_localization')->words[ $app . '_display_title' ] :
( IN_ACP ? ipsRegistry::$applications[ $app ]['app_title'] : ipsRegistry::$applications[ $app ]['app_public_title'] );
}
/**
* Generates the app [ -> module ] path. The module is optional, if module is not
* specified then just the app dir is returned. If this is called from the ACP and module
* is present, then it'll return modules_admin, otherwise modules_public
*
* @param string application
* @param string module (optional)
* @return mixed Directory to app or module (or false if error)
*/
static public function getAppDir( $app, $module='' )
{
$location = '';
if ( ! $app OR !is_string($app) )
{
return FALSE;
}
/* Ok, chicken and egg scenario. Applications has not been set up - most likely because
we're using this function before the caches have been loaded and unpacked.
So we guess based on folder names.... */
if ( ! is_array( ipsRegistry::$applications ) OR ! count( ipsRegistry::$applications ) OR ! isset( ipsRegistry::$applications[ $app ] ) )
{
$location = self::extractAppLocationKey( $app );
}
else
{
$location = ipsRegistry::$applications[ $app ]['app_location'];
}
$pathBit = IPS_ROOT_PATH . 'applications';
$modulesFolder = ( IPS_AREA != 'admin' ) ? 'modules_public' : 'modules_admin';
switch ( $location )
{
default:
case 'root':
$pathBit .= '/' . $app;
break;
case 'ips':
$pathBit .= '_addon/ips/' . $app;
break;
case 'other':
$pathBit .= '_addon/other/' . $app;
break;
}
if ( $module )
{
return $pathBit . "/" . $modulesFolder . "/" . $module;
}
else
{
return $pathBit;
}
}
/**
* Extracts app_location from app key
*
* @param string File path
* @return string root, ips, other
*/
static public function extractAppLocationKey( $app )
{
/* Test core apps first... */
if ( is_dir( IPS_ROOT_PATH . 'applications/' . $app ) )
{
$location = 'root';
}
else if ( is_dir( IPS_ROOT_PATH . 'applications_addon/ips/' . $app ) )
{
$location = 'ips';
}
else
{
$location = 'other';
}
return $location;
}
/**
* Generates the app folder name, either "applications" or "applications_addon"
*
* @param string application
* @return mixed Directory to app or module (or false if error)
*/
static public function getAppFolder( $app )
{
if ( ! $app OR ! isset(ipsRegistry::$applications[ $app ]) )
{
return FALSE;
}
switch ( ipsRegistry::$applications[ $app ]['app_location'] )
{
default:
case 'root':
$pathBit = 'applications';
break;
case 'ips':
$pathBit = 'applications_addon/ips';
break;
case 'other':
$pathBit = 'applications_addon/other';
break;
}
return $pathBit;
}
/**
* Determines if the application can be searched
*
* @param string $app Application key
* @return bool
*/
static public function appIsSearchable( $app, $type='search' )
{
/* Init */
$_ck = '';
/* map config */
switch( strtolower( $type ) )
{
default:
case 'search':
$_ck = 'can_search';
break;
case 'vnc':
case 'newcontent':
case 'viewnewcontent':
$_ck = 'can_viewNewContent';
break;
case 'active':
case 'activecontent':
$_ck = 'can_activeContent';
break;
case 'usercontent':
case 'users':
case 'user':
$_ck = 'can_userContent';
break;
}
/* got anything? */
if ( ! is_array( self::$_searchConfigs ) OR ! count( self::$_searchConfigs ) )
{
foreach( ipsRegistry::$applications as $_app => $data )
{
/* use the cache if we can */
if ( ! IN_DEV AND isset( ipsRegistry::$applications[$_app]['search'] ) AND is_array( ipsRegistry::$applications[$_app]['search'] ) AND count( ipsRegistry::$applications[$_app]['search'] ) )
{
self::$_searchConfigs[ $_app ] = ipsRegistry::$applications[$_app]['search'];
}
else
{
$_file = IPSLib::getAppDir( $_app ) . '/extensions/search/config.php';
if ( IPSLib::appIsInstalled( $_app ) AND file_exists( $_file ) )
{
$CONFIG = array();
require( $_file );
if ( is_array( $CONFIG ) AND count( $CONFIG ) )
{
self::$_searchConfigs[ $_app ] = $CONFIG;
unset( $CONFIG );
}
}
}
}
}
/* return */
if ( isset( self::$_searchConfigs[ $app ] ) AND is_array( self::$_searchConfigs[ $app ] ) AND count( self::$_searchConfigs[ $app ] ) )
{
return ( self::$_searchConfigs[ $app ][ $_ck ] ) ? true : false;
}
return false;
}
/**
* Checks to see if the given application is currently installed and enabled
*
* @param string $app
* @return bool
*/
static public function appIsInstalled( $app, $checkEnabled=true )
{
if ( isset( ipsRegistry::$applications[$app] ) )
{
if( $checkEnabled )
{
if( ipsRegistry::$applications[$app]['app_enabled'] )
{
return TRUE;
}
}
else
{
return TRUE;
}
}
return FALSE;
}
/**
* Check to see if the givem module is currently installed and enabled
*
* @param string $module module_key
* @param string [$app] app_key, current application by default
* @return bool
*/
static public function moduleIsEnabled( $module, $app='' )
{
$app = $app ? $app : ipsRegistry::$current_application;
foreach( ipsRegistry::$modules[$app] as $_m )
{
if ( $_m['sys_module_key'] == $module )
{
return $_m['sys_module_visible'] == 1;
}
}
return FALSE;
}
/**
* Grab max post upload
*
* @return integer Max post size
*/
static public function getMaxPostSize()
{
$max_file_size = 16777216;
$tmp = 0;
$_post = @ini_get('post_max_size');
$_upload = @ini_get('upload_max_filesize');
if ( $_upload > $_post )
{
$tmp = $_post;
}
else
{
$tmp = $_upload;
}
if ( $tmp )
{
$max_file_size = $tmp;
unset($tmp);
preg_match( '#^(\d+)(\w+)$#', strtolower($max_file_size), $match );
if( $match[2] == 'g' )
{
$max_file_size = intval( $max_file_size ) * 1024 * 1024 * 1024;
}
else if ( $match[2] == 'm' )
{
$max_file_size = intval( $max_file_size ) * 1024 * 1024;
}
else if ( $match[2] == 'k' )
{
$max_file_size = intval( $max_file_size ) * 1024;
}
else
{
$max_file_size = intval( $max_file_size );
}
}
return $max_file_size;
}
/**
* Convert strlen to bytes
*
* @param integer string length (no chars)
* @return integer Bytes
* @since 2.0
*/
static public function strlenToBytes( $strlen=0 )
{
$dh = pow(10, 0);
return round( $strlen / ( pow(1024, 0) / $dh ) ) / $dh;
}
/**
* Takes a number of bytes and formats in k or MB as required
*
* @param string Size, in bytes
* @param boolean TRUE = no language class avaiable (during start up, debug, etc)
* @return string Size, in MB, KB or bytes, whichever is closest
*/
static public function sizeFormat($bytes="", $noLang=FALSE)
{
$retval = "";
if ( $noLang === FALSE )
{
$lang['sf_gb'] = ipsRegistry::getClass('class_localization')->words['sf_gb'] ? ipsRegistry::getClass('class_localization')->words['sf_gb'] : 'gb';
$lang['sf_mb'] = ipsRegistry::getClass('class_localization')->words['sf_mb'] ? ipsRegistry::getClass('class_localization')->words['sf_mb'] : 'mb';
$lang['sf_k'] = ipsRegistry::getClass('class_localization')->words['sf_k'] ? ipsRegistry::getClass('class_localization')->words['sf_k'] : 'kb';
$lang['sf_bytes'] = ipsRegistry::getClass('class_localization')->words['sf_bytes'] ? ipsRegistry::getClass('class_localization')->words['sf_bytes'] : 'b';
}
else
{
$lang['sf_gb'] = 'gb';
$lang['sf_mb'] = 'mb';
$lang['sf_k'] = 'kb';
$lang['sf_bytes'] = 'b';
}
if ( $bytes >= 1073741824 )
{
$retval = round($bytes / 1073741824 * 100 ) / 100 . $lang['sf_gb'];
}
else if ($bytes >= 1048576)
{
$retval = round($bytes / 1048576 * 100 ) / 100 . $lang['sf_mb'];
}
else if ($bytes >= 1024)
{
$retval = round($bytes / 1024 * 100 ) / 100 . $lang['sf_k'];
}
else
{
$retval = $bytes . $lang['sf_bytes'];
}
return $retval;
}
/**
* Makes int based arrays safe
* XSS Fix: Ticket: 24360 (Problem with cookies allowing SQL code in keys)
*
* @param array Array
* @return array Array (Cleaned)
* @since 2.1.4(A)
*/
static public function cleanIntArray( $array=array() )
{
$return = array();
if ( is_array( $array ) and count( $array ) )
{
foreach( $array as $k => $v )
{
$return[ intval($k) ] = intval($v);
}
}
return $return;
}
/**
* Loads an interface. Abstracted incase we change location / method
* of loading an interface
*
* @param string File name
* @return void
* @since 3.0.0
*/
static public function loadInterface( $filename )
{
//-----------------------------------------
// Very simple, currently.
//-----------------------------------------
include_once( IPS_ROOT_PATH . 'sources/interfaces/' . $filename );
}
/**
* Create a random 15 character password
*
* @return string Password
* @since 2.0
*/
public static function makePassword()
{
$pass = "";
// Want it random you say, eh?
// (enter evil laugh)
$unique_id = uniqid( mt_rand(), TRUE );
$prefix = IPSMember::generatePasswordSalt();
$unique_id .= md5( $prefix );
usleep( mt_rand(15000,1000000) );
// Hmm, wonder how long we slept for
$new_uniqueid = uniqid( mt_rand(), TRUE );
$final_rand = md5( $unique_id . $new_uniqueid );
for ($i = 0; $i < 15; $i++)
{
$pass .= $final_rand{ mt_rand(0, 31) };
}
return $pass;
}
/**
* Scale a remote image
*
* @param string URL
* @param int Max width
* @param int Max height
* @return string width='#' height='#' string
*/
static public function getTemplateDimensions( $image, $width, $height )
{
if( empty( $width ) AND empty( $height ) )
{
return;
}
if( !$image )
{
return;
}
//-----------------------------------------
// Checking image dimensions via disk instead
// of http is faster...can we try that..?
//-----------------------------------------
if( strpos( $image, ipsRegistry::$settings['board_url'] ) === 0 )
{
$image = DOC_IPS_ROOT_PATH . str_replace( ipsRegistry::$settings['board_url'], '', $image );
}
//-----------------------------------------
// Dimensions
// If set maxwidth and no maxheight, then we want the script to
// reduce based on width only. And vice-versa.
//-----------------------------------------
$maxWidth = ( $width ) ? intval($width) : 1000000000;
$maxHeight = ( $height ) ? intval($height) : 1000000000;
//-----------------------------------------
// Existing dims
//-----------------------------------------
$_dims = @getimagesize( $image );
if( !$_dims[0] )
{
return;
}
$_newDims = IPSLib::scaleImage( array(
'cur_width' => $_dims[0],
'cur_height' => $_dims[1],
'max_width' => $maxWidth,
'max_height' => $maxHeight,
) );
//-----------------------------------------
// Process the tag and return the data
//-----------------------------------------
return " width='{$_newDims['img_width']}' height='{$_newDims['img_height']}'";
}
/**
* Given current dimensions + max dimensions, return scaled image dimensions constrained to maximums
*
* @param array Current dimensions + max dimensions
* @return array New image dimensions
* @since 2.0
* @todo [Future] We may want to consider moving this to kernel classImage.php. Method exists there, protected, already.
*/
public static function scaleImage($arg)
{
// max_width, max_height, cur_width, cur_height
$ret = array(
'img_width' => $arg['cur_width'],
'img_height' => $arg['cur_height']
);
if ( $arg['cur_width'] > $arg['max_width'] )
{
$ret['img_width'] = $arg['max_width'];
$ret['img_height'] = ceil( ( $arg['cur_height'] * ( ( $arg['max_width'] * 100 ) / $arg['cur_width'] ) ) / 100 );
$arg['cur_height'] = $ret['img_height'];
$arg['cur_width'] = $ret['img_width'];
}
if ( $arg['cur_height'] > $arg['max_height'] )
{
$ret['img_height'] = $arg['max_height'];
$ret['img_width'] = ceil( ( $arg['cur_width'] * ( ( $arg['max_height'] * 100 ) / $arg['cur_height'] ) ) / 100 );
}
return $ret;
}
/**
* Format name based on group suffix/prefix
*
* @param string User's display name
* @param integer User's group ID
* @param string Optional prefix override (uses group setting if not provided)
* @param string Optional suffix override (uses group setting if not provided)
* @return string Formatted name
* @since 2.2
*/
public static function makeNameFormatted($name='', $group_id="", $prefix="", $suffix="")
{
if ( ipsRegistry::$settings['ipb_disable_group_psformat'] )
{
return $name;
}
if ( ! $group_id )
{
$group_id = 0;
}
$groupCache = ipsRegistry::cache()->getCache('group_cache');
if ( ! $prefix )
{
if( $groupCache[ $group_id ]['prefix'] )
{
$prefix = $groupCache[ $group_id ]['prefix'];
}
}
if( ! $suffix )
{
if( $groupCache[ $group_id ]['suffix'] )
{
$suffix = $groupCache[ $group_id ]['suffix'];
}
}
if ( ! $name )
{
if( $groupCache[ $group_id ]['g_title'] )
{
$name = $groupCache[ $group_id ]['g_title'];
}
}
return $prefix.$name.$suffix;
}
/**
* Retrieve all IP addresses a user (or multiple users) have used
*
* @param string Where clause for ip address
* @param string Defaults to 'All', otherwise specify which tables to check (comma separated)
* @return array Multi-dimensional array of found IP addresses in which sections
*/
static public function findIPAddresses( $ip_where, $tables_to_check='all' )
{
//-----------------------------------------
// INIT
//-----------------------------------------
$ip_addresses = array();
$tables = array(
'admin_logs' => array( 'member_id', 'ip_address', 'ctime' ),
'dnames_change' => array( 'dname_member_id', 'dname_ip_address', 'dname_date' ),
'email_logs' => array( 'from_member_id', 'from_ip_address', 'email_date' ),
'members' => array( 'member_id', 'ip_address', 'joined' ),
'message_posts' => array( 'msg_author_id', 'msg_ip_address', 'msg_date' ),
'moderator_logs' => array( 'member_id', 'ip_address', 'ctime' ),
'posts' => array( 'author_id', 'ip_address', 'post_date' ),
'profile_comments' => array( 'comment_by_member_id', 'comment_ip_address', 'comment_date' ),
'profile_ratings' => array( 'rating_by_member_id', 'rating_ip_address', '' ),
//'sessions' => array( 'member_id', 'ip_address', 'running_time' ),
'topic_ratings' => array( 'rating_member_id', 'rating_ip_address', '' ),
'validating' => array( 'member_id', 'ip_address', 'entry_date' ),
'voters' => array( 'member_id', 'ip_address', 'vote_date' ),
'error_logs' => array( 'log_member', 'log_ip_address', 'log_date' ),
);
//-----------------------------------------
// Check apps
// @see http://forums.invisionpower.com/tracker/issue-16966-members-download-manag/
//-----------------------------------------
foreach( ipsRegistry::$applications as $app_dir => $data )
{
if( file_exists( IPSLib::getAppDir( $app_dir ) . "/extensions/coreExtensions.php") )
{
$classX = IPSLib::loadLibrary( IPSLib::getAppDir( $app_dir ) . "/extensions/coreExtensions.php", $app_dir . '_findIpAddress', $app_dir );
if( class_exists( $classX ) )
{
$ipLookup = new $classX( ipsRegistry::instance() );
if( method_exists( $ipLookup, 'getTables' ) )
{
$tables = array_merge( $tables, $ipLookup->getTables() );
}
}
}
}
//-----------------------------------------
// Got tables?
//-----------------------------------------
$_tables = explode( ',', $tables_to_check );
if( !is_array($_tables) OR !count($_tables) )
{
return array();
}
//-----------------------------------------
// Loop through them and grab the IPs
//-----------------------------------------
foreach( $tables as $tablename => $fields )
{
if( $tables_to_check == 'all' OR in_array( $tablename, $_tables ) )
{
$extra = '';
$ids = array();
if( $tablename == 'members' )
{
if( $fields[2] )
{
$extra = ',' . $fields[2] . ' as date';
}
ipsRegistry::DB()->build( array(
'select' => $fields[1] . $extra . ', member_id',
'from' => $tablename,
'where' => $fields[1] . $ip_where,
'group' => 'member_id, ip_address, joined',
'order' => 'joined DESC',
'limit' => array( 250 ),
) );
}
else
{
if( $fields[2] )
{
$extra = ', c.' . $fields[2] . ' as date';
}
$extra .= ', c.' . $fields[1] . ' as ip_address, c.' . $fields[0];
ipsRegistry::DB()->build( array(
'select' => 'c.' . $fields[1] . $extra,
'from' => array( $tablename => 'c' ),
'where' => 'c.' . $fields[1] . $ip_where,
'order' => $fields[2] ? 'c.' . $fields[2] . ' DESC' : 'c.' . $fields[0] . ' DESC',
'group' => 'c.' . $fields[0] . ', c.' . $fields[1],
'limit' => array( 250 ),
'add_join' => array(
array(
'select' => 'm.member_id, m.members_display_name, m.email, m.posts, m.joined',
'from' => array( 'members' => 'm' ),
'where' => 'm.member_id=c.' . $fields[0],
'type' => 'left',
)
)
) );
}
ipsRegistry::DB()->execute();
$i = 0;
while( $r = ipsRegistry::DB()->fetch() )
{
if ( $r[ $fields[0] ] )
{
$ids[] = $r[ $fields[0] ];
}
if( $r[ $fields[1] ] )
{
$rawData[ ++$i ] = $r;
}
}
/* Get members */
$members = IPSMember::load( $ids, 'core' );
if ( is_array( $rawData ) and count ( $rawData ) )
{
foreach( $rawData as $idx => $data )
{
if ( $data[ $fields[0] ] && is_array( $members[ $data[ $fields[0] ] ] ) )
{
$ip_addresses[ $tablename ][ $idx ] = array_merge( $data, $members[ $data[ $fields[0] ] ] );
}
}
}
}
}
//-----------------------------------------
// Here are your IPs kind sir. kthxbai
//-----------------------------------------
return $ip_addresses;
}
/**
* Display a strip of share links
*
* @param string Document title (can be left blank and it will attempt to self-discover)
* @param array Addition params: url, cssClass, group [string template group], bit [string template bit], skip [array of share_keys to skip]
* @return string HAITHTEEEMEL
*/
static public function shareLinks( $title='', $params=array() )
{
$url = ( isset( $params['url'] ) ) ? $params['url'] : '';
$cssClass = ( isset( $params['cssClass'] ) ) ? $params['cssClass'] : 'topic_share left';
$group = ( isset( $params['group'] ) ) ? $params['group'] : 'global';
$bit = ( isset( $params['bit'] ) ) ? $params['bit'] : 'shareLinks';
$skip = ( isset( $params['skip'] ) ) ? $params['skip'] : array();
/* Disabled? */
if ( ! ipsRegistry::$settings['sl_enable'] )
{
return '';
}
$canon = ipsRegistry::getClass('output')->fetchRootDocUrl();
$url = ( $url ) ? $url : ipsRegistry::$settings['this_url'];
$canon = IPSText::base64_encode_urlSafe( ( $canon ) ? $canon : $url );
$title = IPSText::base64_encode_urlSafe( $title );
$url = IPSText::base64_encode_urlSafe( $url );
$cache = ipsRegistry::cache()->getCache('sharelinks');
if ( ! $cache OR ! is_array( $cache ) )
{
ipsRegistry::cache()->rebuildCache('sharelinks', 'global' );
$cache = ipsRegistry::cache()->getCache('sharelinks');
}
/* Check for required canonical urls or not */
foreach( $cache as $key => $data )
{
if ( is_array( $skip ) AND in_array( $key, $skip ) )
{
unset( $cache[ $key ] );
}
else
{
$cache[ $key ]['_url'] = ( $data['share_canonical'] ) ? $canon : $url;
}
}
return ipsRegistry::getClass('output')->getTemplate( $group )->$bit( $cache, $title, $canon, $cssClass );
}
/**
* Checks to see if the logged in user can recieve mobile notifications
*
* @param array $memberData Optional, logged in user will be used if this is not passed in
* @return BOOL
*/
static public function canReceiveMobileNotifications( $memberData=array() )
{
/* INIT */
$memberData = ( is_array( $memberData ) && count( $memberData ) ) ? $memberData : ipsRegistry::member()->fetchMemberData();
/* Check to see if notifications are enabled */
if( ! ipsRegistry::$settings['iphone_notifications_enabled'] )
{
return false;
}
/* Check to see if the user has permission to get notifications */
if( ipsRegistry::$settings['iphone_notifications_groups'] )
{
if( ipsMember::isInGroup( $memberData, explode( ',', ipsRegistry::$settings['iphone_notifications_groups'] ) ) )
{
return true;
}
else
{
return false;
}
}
return true;
}
/**
* Quick function to see if a string is serialized
* End up using something similar throughout the code
*
* @param string String to test
* @return boolean
*/
static public function isSerialized( $string )
{
if ( ! is_string( $string ) OR ! trim( $string ) )
{
return false;
}
if ( preg_match( "#^(i|s|a|o|d):(.*)#si", $string ) !== false )
{
return true;
}
return false;
}
}
/**
* IPSDebug
*
* Only useful when developing
*/
class IPSDebug
{
/**
* Memory debug array
*
* @var array Memory debug info
*/
static public $memory_debug = array();
/**
* Messages
*
* @var array Messages
*/
static private $_messages = array();
/**
* Turn off constructor
*
* @return void
*/
private function __construct() {}
/**
* Start time
*
* @var integer Start time
*/
static private $_starttime;
/**
* Add message
*
* @param string
* @return void
*/
static public function addMessage( $message )
{
self::$_messages[] = $message;
}
/**
* Send a FirePHP message
*
* @param string $method Method to call
* @param string $vars Parameters to pass
* @return void
* @link http://www.firephp.org/HQ/
*/
static public function fireBug( $method, $parameters=array() )
{
if( IN_DEV )
{
if( !class_exists( 'FB' ) )
{
require_once( IPS_KERNEL_PATH . '/FirePHPCore/fb.php' );
}
if( $method == 'registerExceptionHandler' )
{
$firephp = FirePHP::getInstance(true);
$firephp->registerExceptionHandler();
}
if( $method == 'registerErrorHandler' )
{
$firephp = FirePHP::getInstance(true);
$firephp->registerErrorHandler();
}
if( method_exists( 'FB', $method ) )
{
$function = 'FB::' . $method;
call_user_func_array( $function, $parameters );
}
}
}
/**
* Prettify a debug backtrace
*
* @param array Data from backtrace
* @return string
*/
static public function prettifyBackTrace( $debug )
{
$_dString = '';
if ( is_array( $debug ) and count( $debug ) )
{
foreach( $debug as $idx => $data )
{
/* Remove non-essential items */
if ( $data['class'] == 'dbMain' OR $data['class'] == 'ips_DBRegistry' OR $data['class'] == 'ipsRegistry' OR $data['class'] == 'ipsController' OR $data['class'] == 'ipsCommand' OR $data['class'] == 'db_driver_mysql' )
{
continue;
}
$_dbString[ $idx ] = array( 'file' => $data['file'],
'line' => $data['line'],
'function' => $data['function'],
'class' => $data['class'] );
}
}
if ( count( $_dbString ) )
{
$_error_string .= "\n .--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------.";
$_error_string .= "\n | File | Function | Line No. |";
$_error_string .= "\n |----------------------------------------------------------------------------+-------------------------------------------------------------------------------+-------------------|";
foreach( $_dbString as $i => $data )
{
if ( defined('DOC_IPS_ROOT_PATH') )
{
$data['file'] = str_replace( DOC_IPS_ROOT_PATH, '', $data['file'] );
}
/* Reset */
$data['func'] = "[" . $data['class'] . '].' . $data['function'];
/* Pad right */
$data['file'] = str_pad( $data['file'], 75 );
$data['func'] = str_pad( $data['func'], 78 );
$data['line'] = str_pad( $data['line'], 18 );
$_error_string .= "\n | " . $data['file'] . "| " . $data['func'] . '| ' . $data['line'] . '|';
$_error_string .= "\n '----------------------------------------------------------------------------+-------------------------------------------------------------------------------+-------------------'";
}
}
return $_error_string;
}
/**
* Custom error handler
*
* @param integer Error number
* @param string Error string
* @param string Error file
* @param string Error line number
* @return void
*/
static public function errorHandler( $errno, $errstr, $errfile, $errline )
{
/* Did we turn off errors with @? */
if ( ! error_reporting() )
{
return;
}
/* Are we truly debugging? */
if ( IPS_ERROR_CAPTURE === FALSE )
{
return;
}
$errfile = str_replace( @getcwd(), "", $errfile );
$log = false;
$message = "> [$errno] $errstr\n> > Строка: $errline\n> > Файл: $errfile";
/* What do we have? */
switch ($errno)
{
case E_ERROR:
$log = true;
echo "Ошибка [$errno] $errstr (Строка: $errline в $errfile)
* # We want to replace all instances of with
* $text = IPSText::replaceRecursively( $text, "", array( 'myClass', 'replaceIt' ) );
* class myClass {
* static function replaceIt( $text, $openText, $closeText )
* {
* # $text contains the matched text between the tags, eg: "http://www.domain.com"
* # $openText contains the searched for opening, eg:
* # Remove http...
* $text = str_replace( 'http://', '', $text )
* # Remove quotes
* $text = str_replace( array( '"', "'" ), '', $text );
* return '"javascript:goLoad(\'' . $text . '\')"';
* }
* }
*
*/
public static function replaceRecursively( $text, $textOpen, $textClose, $callBackFunction )
{
//----------------------------------------
// INIT
//----------------------------------------
# Tag specifics
$foundOpenText_pointer = 0;
$foundCloseText_pointer = 0;
$foundOpenTextRecurse_pointer = 0;
//----------------------------------------
// Keep the server busy for a while
//----------------------------------------
while ( 1 == 1 )
{
# Reset pointer
$startOfTextAfterOpenText_pointer = 0;
# See if we have any 'textOpen' at all
$foundOpenText_pointer = strpos( $text, $textOpen, $foundCloseText_pointer );
# No?
if ( $foundOpenText_pointer === FALSE )
{
break;
}
# Do we have any close text?
$foundCloseText_pointer = strpos( $text, $textClose, $foundOpenText_pointer );
# No?
if ( $foundCloseText_pointer === FALSE )
{
return $text;
}
# Reset pointer for text between the open and close text
$startOfTextAfterOpenText_pointer = $foundOpenText_pointer + strlen( $textOpen );
# Check recursively
$foundOpenTextRecurse_pointer = $startOfTextAfterOpenText_pointer;
while ( 1 == 1 )
{
# Got any open text again?
$foundOpenTextRecurse_pointer = strpos( $text, $textOpen, $foundOpenTextRecurse_pointer );
# No?
if ( $foundOpenTextRecurse_pointer === FALSE OR $foundOpenTextRecurse_pointer >= $foundCloseText_pointer )
{
break;
}
# Yes! Reset recursive pointer
$foundCloseTextRecurse_pointer = $foundCloseText_pointer + strlen( $textClose );
# Yes! Reset close normal pointer to next close tag FROM the last found close point
$foundCloseText_pointer = strpos( $text, $textClose, $foundCloseTextRecurse_pointer );
# Make sure we have a closing text
if ( $foundCloseText_pointer === FALSE )
{
return $text;
}
$foundOpenTextRecurse_pointer += strlen( $textOpen );
}
# This is the text between the open text and close text
$foundText = substr( $text, $startOfTextAfterOpenText_pointer, $foundCloseText_pointer - $startOfTextAfterOpenText_pointer );
# Recurse
if ( strpos( $foundText, $textOpen ) !== FALSE )
{
$foundText = IPSText::replaceRecursively( $foundText, $textOpen, $textClose, $callBackFunction );
}
# Run the call back...
$_newText = call_user_func( $callBackFunction, $foundText, $textOpen, $textClose );
# Run the replacement
$text = substr_replace( $text, $_newText, $foundOpenText_pointer, ( $foundCloseText_pointer - $foundOpenText_pointer ) + strlen( $textClose ) );
# Reset pointer
$foundCloseText_pointer = $foundOpenText_pointer + strlen($_newText);
}
return $text;
}
/**
* Reset Text Classes
*
* @param string Classname to search for
* @return boolean True if successful, false if not
*/
static public function resetTextClass( $name )
{
if ( ! is_object( self::$_internalClasses[ $name ] ) )
{
return false;
}
switch( $name )
{
default:
case 'bbcode':
self::$_internalClasses[ $name ]->allow_cache_updates = 1;
self::$_internalClasses[ $name ]->bypass_badwords = intval( ipsRegistry::instance()->member()->getProperty('g_bypass_badwords') );
self::$_internalClasses[ $name ]->parse_smilies = 1;
self::$_internalClasses[ $name ]->parse_nl2br = 1;
self::$_internalClasses[ $name ]->parse_html = 0;
self::$_internalClasses[ $name ]->parse_bbcode = 1;
self::$_internalClasses[ $name ]->parsing_section = 'post';
self::$_internalClasses[ $name ]->error = '';
self::$_internalClasses[ $name ]->parsing_mgroup = '';
self::$_internalClasses[ $name ]->parsing_mgroup_others = '';
break;
case 'editor':
self::$_internalClasses[ $name ]->error = '';
break;
}
return true;
}
/**
* Clean _GET _POST key
*
* @param string Key name
* @return string Cleaned key name
* @since 2.1
*/
static public function parseCleanKey($key)
{
if ( $key == "" )
{
return "";
}
$key = htmlspecialchars( urldecode($key) );
$key = str_replace( ".." , "" , $key );
$key = preg_replace( "/\_\_(.+?)\_\_/" , "" , $key );
$key = preg_replace( "/^([\w\.\-\_]+)$/", "$1", $key );
return $key;
}
/**
* Clean _GET _POST value
*
* @param string Input
* @param bool Also run postParseCleanValue
* @return string Cleaned Input
* @since 2.1
*/
static public function parseCleanValue( $val, $postParse=true )
{
if ( $val == "" )
{
return "";
}
$val = str_replace( " ", " ", IPSText::stripslashes($val) );
# Convert all carriage return combos
$val = str_replace( array( "\r\n", "\n\r", "\r" ), "\n", $val );
$val = str_replace( "&" , "&" , $val );
$val = str_replace( "" , "-->" , $val );
$val = str_ireplace( "