PageRenderTime 62ms CodeModel.GetById 13ms app.highlight 39ms RepoModel.GetById 1ms app.codeStats 1ms

/src/library/Framework/Framework.Functions.php

https://github.com/dinotest/vanilla-test
PHP | 1010 lines | 764 code | 93 blank | 153 comment | 268 complexity | 6b45af085488b07d0b8c3c3960d57eb6 MD5 | raw file
   1<?php
   2/**
   3 * Non-application specific helper functions
   4 * Applications utilizing this file: Vanilla; Filebrowser;
   5 *
   6 * Copyright 2003 Mark O'Sullivan
   7 * This file is part of Lussumo's Software Library.
   8 * Lussumo's Software Library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
   9 * Lussumo's Software Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
  10 * You should have received a copy of the GNU General Public License along with Vanilla; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  11 * The latest source code is available at www.lussumo.com
  12 * Contact Mark O'Sullivan at mark [at] lussumo [dot] com
  13 *
  14 * @author Mark O'Sullivan
  15 * @copyright 2003 Mark O'Sullivan
  16 * @license http://lussumo.com/community/gpl.txt GPL 2
  17 * @package Framework
  18 * @version @@FRAMEWORK-VERSION@@
  19 */
  20
  21
  22function AddConfigurationSetting(&$Context, $SettingName, $SettingValue = '1') {
  23	if (!array_key_exists($SettingName, $Context->Configuration) || $Context->Configuration[$SettingName] != $SettingValue) {
  24		$Context->Configuration[$SettingName] = '';
  25		$SettingsManager = $Context->ObjectFactory->NewContextObject($Context, 'ConfigurationManager');
  26		$SettingsFile = $Context->Configuration['APPLICATION_PATH'].'conf/settings.php';
  27		$SettingsManager->DefineSetting($SettingName, $SettingValue, 1);
  28		$SettingsManager->SaveSettingsToFile($SettingsFile);
  29	}
  30}
  31
  32function AddDaysToTimeStamp($TimeStamp, $NumberOfDaysToAdd) {
  33	if ($NumberOfDaysToAdd == 0) {
  34		return $TimeStamp;
  35	} else {
  36		return strtotime('+'.$NumberOfDaysToAdd.' day', $TimeStamp);
  37	}
  38}
  39
  40// Append a folder (or file) to an existing path (ensures the / exists)
  41function AppendFolder($RootPath, $FolderToAppend) {
  42	if (substr($RootPath, strlen($RootPath)-1, strlen($RootPath)) == '/') $RootPath = substr($RootPath, 0, strlen($RootPath) - 1);
  43	if (substr($FolderToAppend,0,1) == '/') $FolderToAppend = substr($FolderToAppend,1,strlen($FolderToAppend));
  44	return $RootPath.'/'.$FolderToAppend;
  45}
  46
  47/**
  48 * Appends code to a php file, typically used for configuration.
  49 *
  50 * The php ending tag "?>" should be either on its own line,
  51 * or be ommited all together
  52 *
  53 * @param string $File Path to configuration file.
  54 * @param string $Append Code to append.
  55 * @return boolean
  56 */
  57function AppendToConfigurationFile($File, $Append) {
  58	$Success = 0;
  59	if (file_exists($File)) {
  60		$Lines = file($File);
  61		for ($i=0, $c=count($Lines); $i < $c; $i++) {
  62			if (substr(trim($Lines[$i]), 0, 2) == '?>') {
  63				array_splice($Lines, $i);
  64				break;
  65			}
  66		}
  67		$Lines[] = rtrim($Append) . "\r\n";
  68
  69		$Handle = @fopen($File, 'wb');
  70		if ($Handle) {
  71			$Success = @fwrite($Handle, implode('', $Lines));
  72			@fclose($Handle);
  73		}
  74	}
  75	return $Success;
  76}
  77
  78/**
  79 * Makes sure that a url and some parameters are concatentated properly
  80 * (ie. an ampersand is used instead of a question mark when necessary)
  81 *
  82 * @param string $Url
  83 * @param string $Parameters
  84 * @return string
  85 */
  86function AppendUrlParameters($Url, $Parameters) {
  87	$ReturnUrl = $Url;
  88	$ReturnUrl .= (strpos($Url, '?') === false) ? '?' : '&';
  89	$ReturnUrl .= $Parameters;
  90	return $ReturnUrl;
  91}
  92
  93// Make sure objects can be cloned in PHP 4 and 5.
  94// Example: $NewObject = clone ($ObjectName);
  95// Note: Make sure the space appears between "clone" and the
  96// first parentheses so that the clone statement in 5
  97// doesn't break.
  98if (version_compare(phpversion(), '5.0') < 0) {
  99	eval('
 100		function clone($object) {
 101			return $object;
 102		}
 103	');
 104}
 105
 106// Append two paths
 107function ConcatenatePath($OriginalPath, $PathToConcatenate) {
 108	global $Configuration;
 109	if (strpos($PathToConcatenate, $Configuration['HTTP_METHOD'].'://') !== false) return $PathToConcatenate;
 110	if (substr($OriginalPath, strlen($OriginalPath)-1, strlen($OriginalPath)) != '/') $OriginalPath .= '/';
 111	if (substr($PathToConcatenate,0,1) == '/') $PathToConcatenate = substr($PathToConcatenate,1,strlen($PathToConcatenate));
 112	return $OriginalPath.$PathToConcatenate;
 113}
 114
 115// Based on the total number of items and the number of items per page,
 116// this function will calculate how many pages there are.
 117// Returns the number of pages available
 118function CalculateNumberOfPages($ItemCount, $ItemsPerPage) {
 119	$TmpCount = ($ItemCount/$ItemsPerPage);
 120	$RoundedCount = intval($TmpCount);
 121	$PageCount = 0;
 122	if ($TmpCount > 1) {
 123		if ($TmpCount > $RoundedCount) {
 124			$PageCount = $RoundedCount + 1;
 125		} else {
 126			$PageCount = $RoundedCount;
 127		}
 128	} else {
 129		$PageCount = 1;
 130	}
 131	return $PageCount;
 132}
 133
 134function CleanupString($InString) {
 135	$Code = explode(',', '&lt;,&gt;,&#039;,&amp;,&quot;,À,Á,Â,Ã,Ä,&Auml;,Å,Ā,Ą,Ă,Æ,Ç,Ć,Č,Ĉ,Ċ,Ď,Đ,Ð,È,É,Ê,Ë,Ē,Ę,Ě,Ĕ,Ė,Ĝ,Ğ,Ġ,Ģ,Ĥ,Ħ,Ì,Í,Î,Ï,Ī,Ĩ,Ĭ,Į,İ,IJ,Ĵ,Ķ,Ł,Ľ,Ĺ,Ļ,Ŀ,Ñ,Ń,Ň,Ņ,Ŋ,Ò,Ó,Ô,Õ,Ö,&Ouml;,Ø,Ō,Ő,Ŏ,Œ,Ŕ,Ř,Ŗ,Ś,Š,Ş,Ŝ,Ș,Ť,Ţ,Ŧ,Ț,Ù,Ú,Û,Ü,Ū,&Uuml;,Ů,Ű,Ŭ,Ũ,Ų,Ŵ,Ý,Ŷ,Ÿ,Ź,Ž,Ż,Þ,Þ,à,á,â,ã,ä,&auml;,å,ā,ą,ă,æ,ç,ć,č,ĉ,ċ,ď,đ,ð,è,é,ê,ë,ē,ę,ě,ĕ,ė,ƒ,ĝ,ğ,ġ,ģ,ĥ,ħ,ì,í,î,ï,ī,ĩ,ĭ,į,ı,ij,ĵ,ķ,ĸ,ł,ľ,ĺ,ļ,ŀ,ñ,ń,ň,ņ,ʼn,ŋ,ò,ó,ô,õ,ö,&ouml;,ø,ō,ő,ŏ,œ,ŕ,ř,ŗ,š,ù,ú,û,ü,ū,&uuml;,ů,ű,ŭ,ũ,ų,ŵ,ý,ÿ,ŷ,ž,ż,ź,þ,ß,ſ,А,Б,В,Г,Д,Е,Ё,Ж,З,И,Й,К,Л,М,Н,О,П,Р,С,Т,У,Ф,Х,Ц,Ч,Ш,Щ,Ъ,Ы,Э,Ю,Я,а,б,в,г,д,е,ё,ж,з,и,й,к,л,м,н,о,п,р,с,т,у,ф,х,ц,ч,ш,щ,ъ,ы,э,ю,я');
 136	$Translation = explode(',', ',,,,,A,A,A,A,Ae,A,A,A,A,A,Ae,C,C,C,C,C,D,D,D,E,E,E,E,E,E,E,E,E,G,G,G,G,H,H,I,I,I,I,I,I,I,I,I,IJ,J,K,K,K,K,K,K,N,N,N,N,N,O,O,O,O,Oe,Oe,O,O,O,O,OE,R,R,R,S,S,S,S,S,T,T,T,T,U,U,U,Ue,U,Ue,U,U,U,U,U,W,Y,Y,Y,Z,Z,Z,T,T,a,a,a,a,ae,ae,a,a,a,a,ae,c,c,c,c,c,d,d,d,e,e,e,e,e,e,e,e,e,f,g,g,g,g,h,h,i,i,i,i,i,i,i,i,i,ij,j,k,k,l,l,l,l,l,n,n,n,n,n,n,o,o,o,o,oe,oe,o,o,o,o,oe,r,r,r,s,u,u,u,ue,u,ue,u,u,u,u,u,w,y,y,y,z,z,z,t,ss,ss,A,B,V,G,D,E,YO,ZH,Z,I,Y,K,L,M,N,O,P,R,S,T,U,F,H,C,CH,SH,SCH,Y,Y,E,YU,YA,a,b,v,g,d,e,yo,zh,z,i,y,k,l,m,n,o,p,r,s,t,u,f,h,c,ch,sh,sch,y,y,e,yu,ya');
 137	$sReturn = $InString;
 138	$sReturn = str_replace($Code, $Translation, $sReturn);
 139	$sReturn = urldecode($sReturn);
 140	$sReturn = preg_replace('/[^A-Za-z0-9 ]/', '', $sReturn);
 141	$sReturn = str_replace(' ', '-', $sReturn);
 142	return strtolower(str_replace('--', '-', $sReturn));
 143}
 144
 145function CreateArrayEntry(&$Array, $Key, $Value) {
 146	if (!array_key_exists($Key, $Array)) $Array[$Key] = $Value;
 147}
 148
 149// performs the opposite of htmlentities
 150function DecodeHtmlEntities($String) {
 151	/*
 152	$TranslationTable = get_html_translation_table(HTML_ENTITIES);
 153	print_r($TranslationTable);
 154	$TranslationTable = array_flip($TranslationTable);
 155	return strtr($String, $TranslationTable);
 156
 157	return html_entity_decode(htmlentities($String, ENT_COMPAT, 'UTF-8'));
 158	*/
 159	$String= html_entity_decode($String,ENT_QUOTES,'ISO-8859-1'); #NOTE: UTF-8 does not work!
 160	$String= preg_replace('/&#(\d+);/me','chr(\\1)',$String); #decimal notation
 161	$String= preg_replace('/&#x([a-f0-9]+);/mei','chr(0x\\1)',$String);  #hex notation
 162	return $String;
 163
 164}
 165
 166// Functions
 167function DefineExtensions(&$Context) {
 168	$Extensions = array();
 169	$CurrExtensions = array();
 170	$CurrentExtensions = @file($Context->Configuration["APPLICATION_PATH"].'conf/extensions.php');
 171	if (!$CurrentExtensions) {
 172		$Context->WarningCollector->Add($Context->GetDefinition('ErrReadFileExtensions').$Context->Configuration["APPLICATION_PATH"].'conf/extensions.php');
 173	} else {
 174		foreach ($CurrentExtensions as $ExLine) {
 175			if (substr($ExLine, 0, 7) == 'include') {
 176				$CurrExtensions[] = substr(trim($ExLine), 43, -15);
 177			}
 178		}
 179	}
 180
 181	// Examine Extensions directory
 182	$FolderHandle = @opendir($Context->Configuration["EXTENSIONS_PATH"]);
 183	if (!$FolderHandle) {
 184		$Context->WarningCollector->Add(
 185			str_replace("//1", $Context->Configuration["EXTENSIONS_PATH"], $Context->GetDefinition('ErrOpenDirectoryExtensions')));
 186		return false;
 187	} else {
 188		// Loop through each Extension folder
 189		while (false !== ($Item = readdir($FolderHandle))) {
 190			$Extension = $Context->ObjectFactory->NewObject($Context, 'Extension');
 191			$RecordItem = true;
 192			// skip directories and hidden files
 193			if (
 194				strlen($Item) < 1
 195				|| !is_dir($Context->Configuration["EXTENSIONS_PATH"].$Item)
 196				|| !file_exists($Context->Configuration["EXTENSIONS_PATH"].$Item.'/default.php')
 197				) continue;
 198
 199			// Retrieve Extension properties
 200			$Lines = @file($Context->Configuration["EXTENSIONS_PATH"].$Item.'/default.php');
 201			if (!$Lines) {
 202				$Context->WarningCollector->Add($Context->GetDefinition('ErrReadExtensionDefinition')." {$Item}");
 203			} else {
 204				// We only examine the first 30 lines of the file
 205				$Header = array_slice($Lines, 0, 30);
 206				$Extension->FileName = $Item."/default.php";
 207				foreach ($Header as $CurrentLine) {
 208					@list($key, $val) = @explode(': ', trim($CurrentLine), 2);
 209					switch ($key) {
 210						case 'Extension Name':
 211							$Extension->Name = FormatStringForDisplay($val);
 212							break;
 213						case 'Extension Url':
 214							$Extension->Url = FormatStringForDisplay($val);
 215							break;
 216						case 'Description':
 217							$Extension->Description = FormatStringForDisplay($val);
 218							break;
 219						case 'Version':
 220							$Extension->Version = FormatStringForDisplay($val);
 221							break;
 222						case 'Author':
 223							$Extension->Author = FormatStringForDisplay($val);
 224							break;
 225						case 'Author Url':
 226							$Extension->AuthorUrl = FormatStringForDisplay($val);
 227							break;
 228						default:
 229							// nothing
 230					}
 231				}
 232				if ($Extension->IsValid()) {
 233					$Extension->Enabled = in_array($Item, $CurrExtensions);
 234					$Extensions[FormatExtensionKey($Extension->Name)] = $Extension;
 235				}
 236			}
 237		}
 238		ksort($Extensions);
 239		return $Extensions;
 240	}
 241}
 242
 243// This function is compliments of Entriple on the Lussumo Community
 244function DefineVerificationKey() {
 245	return md5(
 246		sprintf(
 247			'%04x%04x%04x%03x4%04x%04x%04x%04x',
 248			mt_rand(0, 65535),
 249			mt_rand(0, 65535),
 250			mt_rand(0, 4095),
 251			bindec(substr_replace(sprintf('%016b', mt_rand(0, 65535)), '01', 6, 2)),
 252			mt_rand(0, 65535),
 253			mt_rand(0, 65535),
 254			mt_rand(0, 65535),
 255			mt_rand(0, 65535)
 256		)
 257	);
 258}
 259
 260if (!function_exists('file_get_contents')) {
 261
 262	/**
 263	 * file_get_contents function for php 4.1.x and 4.2.x
 264	 *
 265	 * It is not the equivalent of the built-in php one
 266	 * since it will always read the file in binary mode.
 267	 *
 268	 * @param string $FileName
 269	 * @return unknown
 270	 */
 271	function file_get_contents($FileName) {
 272		$Fp = fopen($FileName, 'rb');
 273
 274		if ($Fp) {
 275			$Content = '';
 276			while (!feof($Fp)) {
 277				$Content .= fread($Fp, 4096);
 278			}
 279			return $Content;
 280		}
 281
 282		return false;
 283	}
 284}
 285
 286// return the opposite of the given boolean value
 287function FlipBool($Bool) {
 288	$Bool = ForceBool($Bool, 0);
 289	return $Bool?0:1;
 290}
 291
 292// Take a value and force it to be an array.
 293function ForceArray($InValue, $DefaultValue) {
 294	if(is_array($InValue)) {
 295		$aReturn = $InValue;
 296	} else {
 297		// assume it's a string
 298		$sReturn = trim($InValue);
 299		$length = strlen($sReturn);
 300		if (empty($length) && strlen($sReturn) == 0) {
 301			$aReturn = $DefaultValue;
 302		} else {
 303			$aReturn = array($sReturn);
 304		}
 305	}
 306	return $aReturn;
 307}
 308
 309// Force a boolean value
 310// Accept a default value if the input value does not represent a boolean value
 311function ForceBool($InValue, $DefaultBool) {
 312	// If the invalue doesn't exist (ie an array element that doesn't exist) use the default
 313	if (!$InValue) return $DefaultBool;
 314	$InValue = strtoupper($InValue);
 315	if ($InValue == 1) {
 316		return 1;
 317	} elseif ($InValue === 0) {
 318		return 0;
 319	} elseif ($InValue == 'Y') {
 320		return 1;
 321	} elseif ($InValue == 'N') {
 322		return 0;
 323	} elseif ($InValue == 'TRUE') {
 324		return 1;
 325	} elseif ($InValue == 'FALSE') {
 326		return 0;
 327	} else {
 328		return $DefaultBool;
 329	}
 330}
 331
 332// Take a value and force it to be a float (decimal) with a specific number of decimal places.
 333function ForceFloat($InValue, $DefaultValue, $DecimalPlaces = 2) {
 334	$fReturn = floatval($InValue);
 335	if ($fReturn == 0) $fReturn = $DefaultValue;
 336	$fReturn = number_format($fReturn, $DecimalPlaces);
 337	return $fReturn;
 338}
 339
 340// Check both the get and post incoming data for a variable
 341function ForceIncomingArray($VariableName, $DefaultValue) {
 342	// First check the querystring
 343	$aReturn = ForceSet(@$_GET[$VariableName], $DefaultValue);
 344	$aReturn = ForceArray($aReturn, $DefaultValue);
 345	// If the default value was defined, then check the post variables
 346	if ($aReturn == $DefaultValue) {
 347		$aReturn = ForceSet(@$_POST[$VariableName], $DefaultValue);
 348		$aReturn = ForceArray($aReturn, $DefaultValue);
 349	}
 350	return $aReturn;
 351}
 352
 353// Check both the get and post incoming data for a variable
 354function ForceIncomingBool($VariableName, $DefaultBool) {
 355	// First check the querystring
 356	$bReturn = ForceSet(@$_GET[$VariableName], $DefaultBool);
 357	$bReturn = ForceBool($bReturn, $DefaultBool);
 358	// If the default value was defined, then check the post variables
 359	if ($bReturn == $DefaultBool) {
 360		$bReturn = ForceSet(@$_POST[$VariableName], $DefaultBool);
 361		$bReturn = ForceBool($bReturn, $DefaultBool);
 362	}
 363	return $bReturn;
 364}
 365
 366function ForceIncomingCookieString($VariableName, $DefaultValue) {
 367	$sReturn = ForceSet(@$_COOKIE[$VariableName], $DefaultValue);
 368	$sReturn = ForceString($sReturn, $DefaultValue);
 369	return $sReturn;
 370}
 371
 372// Check both the get and post incoming data for a variable
 373// Does not allow integers to be less than 0
 374function ForceIncomingInt($VariableName, $DefaultValue) {
 375	// First check the querystring
 376	$iReturn = ForceSet(@$_GET[$VariableName], $DefaultValue);
 377	$iReturn = ForceInt($iReturn, $DefaultValue);
 378	// If the default value was defined, then check the form variables
 379	if ($iReturn == $DefaultValue) {
 380		$iReturn = ForceSet(@$_POST[$VariableName], $DefaultValue);
 381		$iReturn = ForceInt($iReturn, $DefaultValue);
 382	}
 383	// If the value found was less than 0, set it to the default value
 384	if($iReturn < 0) $iReturn = $DefaultValue;
 385
 386	return $iReturn;
 387}
 388
 389// Check both the get and post incoming data for a variable
 390function ForceIncomingString($VariableName, $DefaultValue) {
 391	if (isset($_GET[$VariableName])) {
 392		return Strip_Slashes(ForceString($_GET[$VariableName], $DefaultValue));
 393	} elseif (isset($_POST[$VariableName])) {
 394		return Strip_Slashes(ForceString($_POST[$VariableName], $DefaultValue));
 395	} else {
 396		return $DefaultValue;
 397	}
 398}
 399
 400// Take a value and force it to be an integer.
 401function ForceInt($InValue, $DefaultValue) {
 402	$iReturn = intval($InValue);
 403	return ($iReturn == 0) ? $DefaultValue : $iReturn;
 404}
 405
 406// Takes a variable and checks to see if it's set.
 407// Returns the value if set, or the default value if not set.
 408function ForceSet($InValue, $DefaultValue) {
 409	return isset($InValue) ? $InValue : $DefaultValue;
 410}
 411
 412// Take a value and force it to be a string.
 413function ForceString($InValue, $DefaultValue) {
 414	if (is_string($InValue)) {
 415		$sReturn = trim($InValue);
 416		if (empty($sReturn) && strlen($sReturn) == 0) $sReturn = $DefaultValue;
 417	} else {
 418		$sReturn = $DefaultValue;
 419	}
 420	return $sReturn;
 421}
 422
 423/**
 424 * Check if the cookie domain is valid.
 425 * @todo the Pattern is quite loose
 426 * (don't ckeck the doamin names start by a letter or a digit, allow domain)
 427 * @param $CookieDomain string
 428 * @return string
 429 */
 430function FormatCookieDomain($CookieDomain) {
 431	$Pattern = '/^[\.-_~a-zA-Z0-9]*\.?[-_~a-zA-Z0-9]+\.[-_~a-zA-Z0-9]+$/';
 432	$Match = preg_match($Pattern, $CookieDomain);
 433	if ($Match) {
 434		return $CookieDomain;
 435	} else {
 436		return '';
 437	}
 438}
 439
 440function FormatExtensionKey($Key) {
 441	return preg_replace("/[^[:alnum:]]/i", '', unhtmlspecialchars($Key));
 442}
 443
 444function FormatFileSize($FileSize) {
 445	if ($FileSize > 1048576) {
 446		return intval((($FileSize / 1048576) * 100) + 0.5) / 100 ."mb";
 447	} elseif ($FileSize > 1024) {
 448		return ceil($FileSize / 1024)."kb";
 449	} else {
 450		return $FileSize."b";
 451	}
 452}
 453
 454function FormatHyperlink($InString, $ExternalTarget = '1', $LinkText = '', $CssClass = '') {
 455	$Display = $LinkText;
 456	if (strpos($InString, 'http://') == 0 && strpos($InString, 'http://') !== false) {
 457		if ($LinkText == '') {
 458			$Display = $InString;
 459			if (substr($Display, strlen($Display)-1,1) == '/') $Display = substr($Display, 0, strlen($Display)-1);
 460			$Display = str_replace('http://', '', $Display);
 461		}
 462	} elseif (strpos($InString, 'mailto:') == 0 && strpos($InString, 'mailto:') !== false) {
 463		if ($LinkText == '') {
 464			$Display = str_replace('mailto:', '', $InString);
 465		}
 466	} elseif (strpos($InString, 'ftp://') == 0 && strpos($InString, 'ftp://') !== false) {
 467		if ($LinkText == '') {
 468			$Display = str_replace('ftp://', '', $InString);
 469		}
 470	} elseif (strpos($InString, 'aim:goim?screenname=') == 0 && strpos($InString, 'aim:goim?screenname=') !== false) {
 471		if ($LinkText == '') {
 472			$Display = str_replace('aim:goim?screenname=', '', $InString);
 473		}
 474	} else {
 475		return $LinkText == '' ? $InString : $LinkText;
 476	}
 477	return '<a href="'.$InString.'"'.($CssClass != '' ? ' class="'.$CssClass.'"' : '').'>'.$Display.'</a>';
 478}
 479
 480function FormatHtmlStringForNonDisplay($inValue) {
 481	return str_replace("\r\n", '<br />', htmlspecialchars($inValue));
 482}
 483
 484function FormatHtmlStringInline($inValue, $StripSlashes = '0', $StripTags = '0') {
 485	// $sReturn = ForceString($inValue, '');
 486	$sReturn = $inValue;
 487	if ($StripTags) $sReturn = strip_tags($sReturn);
 488	if (ForceBool($StripSlashes, 0)) $sReturn = Strip_Slashes($sReturn);
 489	return str_replace("\r\n", ' ', htmlspecialchars($sReturn));
 490}
 491
 492function FormatPlural($Number, $Singular, $Plural) {
 493	return ($Number == 1) ? $Singular : $Plural;
 494}
 495
 496// Formats a value so it's safe to insert into the database
 497function FormatStringForDatabaseInput($inValue, $bStripHtml = '0') {
 498	$bStripHtml = ForceBool($bStripHtml, 0);
 499	// $sReturn = stripslashes($inValue);
 500	$sReturn = $inValue;
 501	if ($bStripHtml) $sReturn = trim(strip_tags($sReturn));
 502	// return MAGIC_QUOTES_ON ? $sReturn : addslashes($sReturn);
 503	return addslashes($sReturn);
 504}
 505
 506// Takes a user defined string and formats it for page display.
 507// You can optionally remove html from the string.
 508function FormatStringForDisplay($inValue, $bStripHtml = true, $AllowEncodedQuotes = true) {
 509	$sReturn = trim($inValue);
 510	if ($bStripHtml) $sReturn = strip_tags($sReturn);
 511	if (!$AllowEncodedQuotes) $sReturn = preg_replace('/("|\')/', '', $sReturn);
 512	global $Configuration;
 513	$sReturn = htmlspecialchars($sReturn, ENT_QUOTES, $Configuration['CHARSET']);
 514	if ($bStripHtml) $sReturn = str_replace("\r\n", "<br />", $sReturn);
 515	return $sReturn;
 516}
 517
 518function GetBasicCheckBox($Name, $Value = 1, $Checked, $Attributes = '') {
 519	return '<input type="checkbox" name="'.$Name.'" value="'.$Value.'" '.(($Checked == 1)?' checked="checked"':'').' '.$Attributes.' />';
 520}
 521
 522function GetBool($Bool, $True = 'Yes', $False = 'No') {
 523	return ($Bool ? $True : $False);
 524}
 525
 526function GetDynamicCheckBox($Name, $Value = 1, $Checked, $OnClick, $Text, $Attributes = '', $CheckBoxID = '') {
 527	if ($CheckBoxID == '') $CheckBoxID = $Name.'ID';
 528	$Attributes .= ' id="'.$CheckBoxID.'"';
 529	if ($OnClick != '') $Attributes .= ' onclick="'.$OnClick.'"';
 530	return '<label for="'.$CheckBoxID.'">'.GetBasicCheckBox($Name, $Value, $Checked, $Attributes).' '.$Text.'</label>';
 531}
 532
 533function GetEmail($Email, $LinkText = '') {
 534	if ($Email == '') {
 535		return '&nbsp;';
 536	} else {
 537		$EmailParts = explode('@', $Email);
 538		if (count($EmailParts) == 2) {
 539			$ScriptID = 'WriteEmail_' . rand();
 540			return "<script id=\"".$ScriptID."\" type=\"text/javascript\">\r\nWriteEmail('".$EmailParts[1]."', '".$EmailParts[0]."', '".$LinkText."', '".$ScriptID."');\r\n</script>";
 541		} else {
 542			// Failsafe
 543			return '<a href="mailto:'.$Email.'">'.($LinkText==''?$Email:$LinkText).'</a>';
 544		}
 545	}
 546}
 547
 548function GetImage($ImageUrl, $Height = '', $Width = '', $TagIdentifier = '', $EmptyImageReplacement = '&nbsp;') {
 549	$sReturn = '';
 550	if (ReturnNonEmpty($ImageUrl) == '&nbsp;') {
 551		$sReturn =  $EmptyImageReplacement;
 552	} else {
 553		$sReturn = '<img src="'.$ImageUrl.'"';
 554		if ($Height != '') $sReturn .= ' height="'.$Height.'"';
 555		if ($Width != '') $sReturn .= ' width="'.$Width.'"';
 556		if ($TagIdentifier != '') $sReturn .= ' id="'.$TagIdentifier.'"';
 557		$sReturn .= ' alt="" />';
 558	}
 559	return $sReturn;
 560}
 561
 562function GetRemoteIp($FormatIpForDatabaseInput = '0') {
 563	$FormatIpForDatabaseInput = ForceBool($FormatIpForDatabaseInput, 0);
 564	$sReturn = ForceString(@$_SERVER['REMOTE_ADDR'], '');
 565	if (strlen($sReturn) > 20) $sReturn = substr($sReturn, 0, 19);
 566	if ($FormatIpForDatabaseInput) $sReturn = FormatStringForDatabaseInput($sReturn, 1);
 567	return $sReturn;
 568}
 569
 570/**
 571 * Return the request URL
 572 *
 573 * The returned URL is tainted (based on $_SERVER['QUERY_STRING']).
 574 * However, by default ($FormatUrlForDisplay == true), the url is safe for html used.
 575 *
 576 * @param boolean $FormatUrlForDisplay Set to false to return an unformatted (and tainted) URL
 577 * @return string
 578 */
 579function GetRequestUri($FormatUrlForDisplay='1') {
 580	global $Configuration;
 581	$Host = ForceString($_SERVER['HTTP_HOST'], '');
 582	if ($Host != '') $Host = PrependString($Configuration['HTTP_METHOD'].'://', $Host);
 583	$Path = @$_SERVER['REQUEST_URI'];
 584	// If the path wasn't provided in the REQUEST_URI variable, let's look elsewhere for it
 585	if ($Path == '') $Path = @$_SERVER['HTTP_X_REWRITE_URL']; // Some servers use this instead
 586	// If the path still wasn't found, let's try building it with other variables
 587	if ($Path == '') {
 588		$Path = @$_SERVER['SCRIPT_NAME'];
 589		$Path .= (@$_SERVER['QUERY_STRING'] == '' ? '' : '?' . @$_SERVER['QUERY_STRING']);
 590	}
 591	$FullPath = ConcatenatePath($Host, $Path);
 592	return $FormatUrlForDisplay ? FormatStringForDisplay($FullPath) : $FullPath;
 593}
 594
 595function GetTableName($Key, $TableCollection, $Prefix) {
 596	global $DatabasePrefixLessTables;
 597	$DatabasePrefixLessTables = ForceArray($DatabasePrefixLessTables, array('User'));
 598	if (in_array($Key, $DatabasePrefixLessTables)) {
 599		return $TableCollection[$Key];
 600	} else {
 601		return $Prefix.$TableCollection[$Key];
 602	}
 603}
 604
 605function GetUrl($Configuration, $PageName, $Divider = '', $Key = '', $Value = '', $PageNumber='', $Querystring='', $Suffix = '') {
 606	if ($Configuration['URL_BUILDING_METHOD'] == 'mod_rewrite') {
 607		if ($PageName == './') $PageName = 'index.php';
 608		return $Configuration['BASE_URL']
 609			.($PageName == 'index.php' && $Value != '' ? '' : $Configuration['REWRITE_'.$PageName])
 610			.(strlen($Value) != 0 ? $Divider : '')
 611			.(strlen($Value) != 0 ? $Value.'/' : '')
 612			.(($PageNumber != '' && $PageNumber != '0' && $PageNumber != '1') ? $PageNumber.'/' : '')
 613			.($Suffix != '' ? $Suffix : '')
 614			.($Querystring != '' && substr($Querystring, 0, 1) != '#' ? '?' : '')
 615			.($Querystring != '' ? $Querystring : '');
 616	} else {
 617		if ($PageName == './' || $PageName == 'index.php') $PageName = '';
 618		$sReturn = ($Value != '' && $Value != '0' ? $Key.'='.$Value : '');
 619		if ($PageNumber != '') {
 620			if ($sReturn != '') $sReturn .= '&amp;';
 621			$sReturn .= 'page='.$PageNumber;
 622		}
 623		if ($Querystring != '' && substr($Querystring, 0, 1) != '#') {
 624			if ($sReturn != '') $sReturn .= '&amp;';
 625			$sReturn .= $Querystring;
 626		}
 627		if ($sReturn != '') $sReturn = '?'.$sReturn;
 628		if ($Querystring != '' && substr($Querystring, 0, 1) == '#') $sReturn .= $Querystring;
 629		return $Configuration['BASE_URL'].$PageName.$sReturn;
 630	}
 631}
 632
 633// Create the html_entity_decode function for users prior to PHP 4.3.0
 634if (!function_exists('html_entity_decode')) {
 635	function html_entity_decode($String) {
 636		return strtr($String, array_flip(get_html_translation_table(HTML_ENTITIES)));
 637	}
 638}
 639
 640// allows inline if statements
 641function Iif($Condition, $True, $False) {
 642	return $Condition ? $True : $False;
 643}
 644
 645function ThemeFile(&$Context, $FileName) {
 646	$ThemeFileArray = file(ThemeFilePath($Context->Configuration, $FileName));
 647	if (is_array($ThemeFileArray)) {
 648		$ThemeFile = implode('', $ThemeFileArray);
 649		return $ThemeFile;
 650	} else {
 651		// Throw a fatal error because the theme file wasn't found
 652		$Context->ErrorManager->AddError($Context, 'Framework.Functions', 'ThemeFile', 'The requested theme file could not be found.', $FileName, 1);
 653	}
 654}
 655
 656// Checks for a custom version of the specified file
 657// Returns the path to the custom file (if it exists) or the default otherwise
 658function ThemeFilePath($Configuration, $FileName) {
 659	if (file_exists($Configuration['THEME_PATH'].$FileName)) {
 660		return $Configuration['THEME_PATH'].$FileName;
 661	} else {
 662		return $Configuration["APPLICATION_PATH"]."themes/".$FileName;
 663	}
 664}
 665
 666function MysqlDateTime($Timestamp = '') {
 667	if ($Timestamp == '') $Timestamp = mktime();
 668	return date('Y-m-d H:i:s', $Timestamp);
 669}
 670
 671function OpenURL($URL, &$Context) {
 672	$ParsedUrl = parse_url($URL);
 673	$Host = ForceString(@$ParsedUrl['host'], '');
 674	$Port = ForceInt(@$ParsedUrl['port'], 0);
 675	if ($Port == 0) $Port = 80;
 676	$Path = (array_key_exists('path', $ParsedUrl)) ? $ParsedUrl['path'] : '';
 677	if (empty($Path)) $Path = '/';
 678	if (array_key_exists('query', $ParsedUrl) && $ParsedUrl['query'] != '') {
 679		// Do some encoding and cleanup on the querystring
 680		$QueryString = urlencode($ParsedUrl['query']);
 681		$QueryString = str_replace(array('%26', '%3D'), array('&', '='), $QueryString);
 682		$Path .= '?' . $QueryString;
 683	}
 684
 685	$UrlContents = false;
 686
 687	if (empty($Host)) {
 688		$Context->WarningCollector->Add(str_replace('\\1', $URL, $Context->GetDefinition('InvalidHostName')));
 689	} else {
 690		$Headers = "GET $Path HTTP/1.0\r\nHost: $Host\r\n\r\n";
 691		// echo("<div>$Headers</div>");
 692		$ErrorNumber = '';
 693		$ErrorMessage = '';
 694		$Handle = @fsockopen($Host, $Port, $ErrorNumber, $ErrorMessage, 30);
 695		if (!$Handle) {
 696			$Context->WarningCollector->Add(str_replace('\\1', $Host, $Context->GetDefinition("ErrorFopen")).($php_errormsg ? str_replace('\\1', $php_errormsg, $Context->GetDefinition('ErrorFromPHP')) : ''));
 697		} else {
 698			fwrite($Handle, $Headers);
 699			$UrlContents = '';
 700			$HeaderFinished = false;
 701			$String = '';
 702			while (!feof($Handle)) {
 703				 $String = fgets($Handle, 128);
 704				 if ($HeaderFinished) $UrlContents .= $String;
 705				 if ($String == "\r\n") $HeaderFinished = true;
 706			}
 707			fclose($Handle);
 708		}
 709	}
 710	return $UrlContents;
 711}
 712
 713function PrefixString($string, $prefix, $length) {
 714	if (strlen($string) >= $length) {
 715		return $string;
 716	} else {
 717		return substr(($prefix.$string),strlen($prefix.$string)-$length, $length);
 718	}
 719}
 720
 721function PrependString($Prepend, $String) {
 722	if ($String == '') return '';
 723
 724	if (is_array($Prepend)){
 725		foreach ($Prepend as $str) {
 726		   	$pos = strpos(strtolower($String), strtolower($str));
 727			if ($pos !== false && $pos == 0) {
 728				$Prepend = '';
 729			}
 730		}
 731		// If the string doesn't start with any array elements, prepend the first element
 732		if ($Prepend <> '') $Prepend = $Prepend[0];
 733	} else {
 734		$pos = strpos(strtolower($String), strtolower($Prepend));
 735		if ($pos !== false && $pos == 0) $Prepend = '';
 736	}
 737
 738	return $Prepend.$String;
 739}
 740
 741/**
 742 * Redirect to an other page
 743 *
 744 * @todo Should the Location be encoded in function?
 745 * @param string $Location Absolute URL
 746 * @param string $Code Status code
 747 * @param string $Name Name of the page
 748 * @param bool $Die Should the script terminate
 749 * @return void
 750 */
 751function Redirect($Location, $Code = '302', $Name = '', $Die = 1) {
 752	// Set status
 753	$CodeList = array(
 754		'301' => 'Moved Permanently',
 755		'303' => 'See Other'
 756	);
 757
 758	if ($Code && array_key_exists($Code, $CodeList)) {
 759		 Header( 'HTTP/1.1 ' . $Code . ' ' . $CodeList[$Code] );
 760	}
 761
 762	//Strip CRLFs and replace &amp; with & (case insensitive)
 763	$Location = preg_replace(array('/\r\n/', '/&amp;/i'), array('', '&'), $Location);
 764
 765	//$Location have to be well encoded.
 766	header('Location: ' . $Location);
 767
 768	if ($Die) {
 769		@ob_end_clean();
 770		if (isset($_SERVER['REQUEST_METHOD']) &&
 771			$_SERVER['REQUEST_METHOD'] != 'HEAD')
 772		{
 773			if (!$Name) {
 774				$Name = $Location;
 775			}
 776			// display a lick in case the redirect fails
 777			echo '<a href="' . $Location . '">' . FormatStringForDisplay($Name) . '</a>';
 778		}
 779		//global $Context;
 780		//$Context->Unload();
 781		die();
 782	}
 783}
 784
 785function RemoveIllegalChars($FileName) {
 786	return preg_replace('![\s<"\']+!s', '', $FileName);
 787}
 788
 789function RenderThemeFile($Context, $ThemeFile) {
 790	echo $ThemeFile;
 791}
 792
 793function ReplaceThemeFile($Context, $Replacements, $ThemeFile) {
 794	$theme_file = $ThemeFile;
 795	// Perform standard replacements
 796	while (list($key, $replacement) = each($Replacements)) {
 797		$theme_file = str_replace('['.$key.']', $replacement, $theme_file);
 798	}
 799	// Perform dictionary replacements
 800	// Perform configuration replacements
 801	return $theme_file;
 802}
 803
 804// If a value is empty, return the non-empty value
 805function ReturnNonEmpty($InValue, $NonEmptyValue = '&nbsp;') {
 806	return trim($InValue) == '' ? $NonEmptyValue : $InValue;
 807}
 808
 809function SaveAsDialogue($FolderPath, $FileName, $DeleteFile = '0') {
 810	$DeleteFile = ForceBool($DeleteFile, 0);
 811	if ($FolderPath != '') {
 812		if (substr($FolderPath,strlen($FolderPath)-1) != '/') $FolderPath = $FolderPath.'/';
 813	}
 814	$FolderPath = $FolderPath.$FileName;
 815	header('Pragma: public');
 816	header('Expires: 0');
 817	header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
 818	header('Content-Type: application/force-download');
 819	header('Content-Type: application/octet-stream');
 820	header('Content-Type: application/download');
 821	header('Content-Disposition: attachment; filename="'.$FileName.'"');
 822	header('Content-Transfer-Encoding: binary');
 823	readfile($FolderPath);
 824	if ($DeleteFile) unlink($FolderPath);
 825	die();
 826}
 827
 828function SerializeArray($InArray) {
 829	$sReturn = '';
 830	if (is_array($InArray)) {
 831		if (count($InArray) > 0) {
 832			$sReturn = serialize($InArray);
 833			$sReturn = addslashes($sReturn);
 834		}
 835	}
 836	return $sReturn;
 837}
 838
 839// Cuts a string to the specified length.
 840// Then moves back to the previous space so words are not sliced half-way through.
 841function SliceString($InString, $Length) {
 842	$Space = ' ';
 843	$sReturn = '';
 844	if (strlen($InString) > $Length) {
 845		$sReturn = substr(trim($InString), 0, $Length);
 846		$sReturn = substr($sReturn, 0, strlen($sReturn) - strpos(strrev($sReturn), $Space));
 847		$sReturn .= '...';
 848	} else {
 849		$sReturn = $InString;
 850	}
 851	return $sReturn;
 852}
 853
 854function Strip_Slashes($InString) {
 855	return MAGIC_QUOTES_ON ? stripslashes($InString) : $InString;
 856}
 857
 858function SubtractDaysFromTimeStamp($TimeStamp, $NumberOfDaysToSubtract) {
 859	if ($NumberOfDaysToSubtract == 0) {
 860		return $TimeStamp;
 861	} else {
 862		return strtotime('-'.$NumberOfDaysToSubtract.' day', $TimeStamp);
 863	}
 864}
 865
 866function TimeDiff(&$Context, $Time, $TimeToCompare = '') {
 867	if ($TimeToCompare == '') $TimeToCompare = time();
 868	$Difference = $TimeToCompare-$Time;
 869	$Days = floor($Difference/60/60/24);
 870
 871	if ($Days > 7) {
 872		return date($Context->GetDefinition('OldPostDateFormatCode'), $Time);
 873	} elseif ($Days > 1) {
 874		return str_replace('//1', $Days, $Context->GetDefinition('XDaysAgo'));
 875	} elseif ($Days == 1) {
 876		return str_replace('//1', $Days, $Context->GetDefinition('XDayAgo'));
 877	} else {
 878
 879		$Difference -= $Days*60*60*24;
 880		$Hours = floor($Difference/60/60);
 881		if ($Hours > 1) {
 882			return str_replace('//1', $Hours, $Context->GetDefinition('XHoursAgo'));
 883		} elseif ($Hours == 1) {
 884			return str_replace('//1', $Hours, $Context->GetDefinition('XHourAgo'));
 885		} else {
 886
 887			$Difference -= $Hours*60*60;
 888			$Minutes = floor($Difference/60);
 889			if ($Minutes > 1) {
 890				return str_replace('//1', $Minutes, $Context->GetDefinition('XMinutesAgo'));
 891			} elseif ($Minutes == 1) {
 892				return str_replace('//1', $Minutes, $Context->GetDefinition('XMinuteAgo'));
 893			} else {
 894
 895				$Difference -= $Minutes*60;
 896				$Seconds = $Difference;
 897				if ($Seconds == 1) {
 898					return str_replace('//1', $Seconds, $Context->GetDefinition('XSecondAgo'));
 899				} else {
 900					return str_replace('//1', $Seconds, $Context->GetDefinition('XSecondsAgo'));
 901				}
 902			}
 903		}
 904	}
 905}
 906
 907function unhtmlspecialchars($String) {
 908	 $String = str_replace('&amp;', '&', $String);
 909	 $String = str_replace('&#039;', '\'', $String);
 910	 $String = str_replace('&quot;', '\"', $String);
 911	 $String = str_replace('&lt;', '<', $String);
 912	 $String = str_replace('&gt;', '>', $String);
 913	 return $String;
 914}
 915
 916// Convert a datetime to a timestamp
 917function UnixTimestamp($DateTime) {
 918	if (preg_match('/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/', $DateTime, $Matches)) {
 919		$Year = $Matches[1];
 920		$Month = $Matches[2];
 921		$Day = $Matches[3];
 922		$Hour = $Matches[4];
 923		$Minute = $Matches[5];
 924		$Second = $Matches[6];
 925		return mktime($Hour, $Minute, $Second, $Month, $Day, $Year);
 926
 927	} elseif (preg_match('/^(\d{4})-(\d{2})-(\d{2})$/', $DateTime, $Matches)) {
 928		$Year = $Matches[1];
 929		$Month = $Matches[2];
 930		$Day = $Matches[3];
 931		return mktime(0, 0, 0, $Month, $Day, $Year);
 932	}
 933}
 934
 935function UnserializeArray($InSerialArray) {
 936	$aReturn = array();
 937	if ($InSerialArray != '' && !is_array($InSerialArray)) {
 938		$aReturn = unserialize($InSerialArray);
 939		if (is_array($aReturn)) {
 940			$Count = count($aReturn);
 941			$i = 0;
 942			for ($i = 0; $i < $Count; $i++) {
 943				$aReturn[$i] = array_map('Strip_Slashes', $aReturn[$i]);
 944			}
 945		}
 946	}
 947	return $aReturn;
 948}
 949
 950function UnserializeAssociativeArray($InSerialArray) {
 951	$aReturn = array();
 952	if ($InSerialArray != '' && !is_array($InSerialArray)) {
 953		$aReturn = @unserialize($InSerialArray);
 954		if (!is_array($aReturn)) $aReturn = array();
 955	}
 956	return $aReturn;
 957}
 958
 959// Instantiate a simple validator
 960function Validate($InputName, $IsRequired, $Value, $MaxLength, $ValidationExpression, &$Context) {
 961	$Validator = $Context->ObjectFactory->NewContextObject($Context, 'Validator');
 962	$Validator->InputName = $InputName;
 963	$Validator->isRequired = $IsRequired;
 964	$Validator->Value = $Value;
 965	$Validator->MaxLength = $MaxLength;
 966	if ($ValidationExpression != '') {
 967		$Validator->ValidationExpression = $ValidationExpression;
 968		$Validator->ValidationExpressionErrorMessage = $Context->GetDefinition('ErrImproperFormat').' '.$InputName;
 969	}
 970	return $Validator->Validate();
 971}
 972
 973function WriteEmail($Email, $LinkText = '') {
 974	echo(GetEmail($Email, $LinkText));
 975}
 976
 977// Taken and modified from Mark's CategoryJumper extension
 978function MoveDiscussionForm(&$Context, $SessionPostBackKey, $DiscussionID) {
 979	$CategoryManager = $Context->ObjectFactory->NewContextObject($Context, 'CategoryManager');
 980	$CategoryData = $CategoryManager->GetCategories(0, 1);
 981	if (!$CategoryData) {
 982		return '';      
 983	}
 984	else {
 985		$Select = $Context->ObjectFactory->NewObject($Context, 'Select');
 986		$Select->Name = 'CategoryID';
 987		$Select->SelectedValue = ForceIncomingInt('MoveDiscussionDropdown', 0);
 988		$Select->Attributes .= " id=\"MoveDiscussionDropdown\" onchange=\"if (confirm('".$Context->GetDefinition("ConfirmMoveDiscussion")."')) DiscussionSwitch('".$Context->Configuration['WEB_ROOT']."ajax/switch.php', 'Move', '".$DiscussionID."', ''+this.options[this.selectedIndex].value+'', 'MoveDiscussion', '".$SessionPostBackKey."'); return false;\"";
 989		$Select->AddOption(0, $Context->GetDefinition('SelectCategoryToMoveTo'));         
 990		$LastBlocked = -1;
 991		$cat = $Context->ObjectFactory->NewObject($Context, 'Category');
 992		while ($Row = $Context->Database->GetRow($CategoryData)) {
 993			$cat->Clear();
 994			$cat->GetPropertiesFromDataSet($Row);
 995			if ($cat->Blocked != $LastBlocked && $LastBlocked != -1) {
 996				$Select->AddOption('-1', '---', " disabled=\"disabled\"");
 997			}
 998			$Select->AddOption($cat->CategoryID, $cat->Name);
 999			$LastBlocked = $cat->Blocked;
1000		}         
1001		return "<form id=\"frmMoveDiscussion\"
1002				name=\"frmMoveDiscussion\"
1003				method=\"post\" 
1004				action=\"".$Context->Configuration['WEB_ROOT']."post.php\">".
1005      			$Select->Get()."
1006	     		</form>";
1007	}
1008}
1009
1010?>