1<?php 2/** 3 * phpfreechattools.class.php 4 * 5 * Copyright � 2006 Stephane Gully <stephane.gully@gmail.com> 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the 19 * Free Software Foundation, 51 Franklin St, Fifth Floor, 20 * Boston, MA 02110-1301 USA 21 */ 22 23/** 24 * this file contains a toolbox with misc. usefull functions 25 * 26 * @author Stephane Gully <stephane.gully@gmail.com> 27 */ 28 29// To be sure the directory separator is defined 30// I don't know if this constant can be undefined or not so maybe this code is not necessary 31if (!defined("DIRECTORY_SEPARATOR")) 32 define("DIRECTORY_SEPARATOR", "/"); 33 34 35/** 36 * Returns the absolute script filename 37 * takes care of php cgi configuration which do not support SCRIPT_FILENAME variable. 38 */ 39function pfc_GetScriptFilename() 40{ 41 $sf = ''; 42 if(function_exists('debug_backtrace')) 43 { 44 // browse the backtrace history and take the first unknown filename as the client script 45 foreach(debug_backtrace() as $db) 46 { 47 $f = $db['file']; 48 if (!preg_match('/phpfreechat.class.php/',$f) && 49 !preg_match('/pfcglobalconfig.class.php/',$f) && 50 !preg_match('/pfctools.class.php/',$f) && 51 !preg_match('/pfcinfo.class.php/',$f) 52 ) 53 { 54 $sf = $f; 55 break; 56 } 57 } 58 } 59 else if (isset($_SERVER['PATH_TRANSLATED']) && 60 file_exists($_SERVER['SCRIPT_FILENAME'])) // check for a cgi configurations 61 { 62 $sf = $_SERVER['PATH_TRANSLATED']; 63 } 64 else if (isset($_SERVER['SCRIPT_FILENAME'])&& 65 file_exists($_SERVER['SCRIPT_FILENAME'])) // for non-cgi configurations 66 { 67 $sf = $_SERVER['SCRIPT_FILENAME']; 68 } 69 else 70 { 71 echo "<pre>"; 72 echo "<span style='color:red'>Error: pfc_GetScriptFilename function returns a wrong path. Please contact the pfc team (contact@phpfreechat.net) and copy/paste these data to help debugging:</span>\n"; 73 print_r($_SERVER); 74 print_r(debug_backtrace()); 75 echo "</pre>"; 76 exit; 77 } 78 return $sf; 79} 80 81function pfc_RelativePath($p1, $p2) 82{ 83 if (is_file($p1)) $p1 = dirname($p1); 84 if (is_file($p2)) $p2 = dirname($p2); 85 // using realpath function is necessary to resolve symbolic links 86 $p1 = realpath(cleanPath($p1)); 87 $p2 = realpath(cleanPath($p2)); 88 $res = ""; 89 // echo $p1."<br>"; 90 // echo $p2."<br>"; 91 while( $p1 != "" && 92 $p1 != "/" && // for unix root dir 93 !preg_match("/^[a-z]\:\\\$/i",$p1) && // for windows rootdir 94 strpos($p2, $p1) !== 0) 95 { 96 $res .= "../"; 97 $p1 = dirname($p1); 98 } 99 if (isset($_SERVER["WINDIR"]) || isset($_SERVER["windir"])) { 100 $p2 = str_replace("\\","/",substr($p2, strlen($p1)+1, strlen($p2)-strlen($p1))); 101 } else { 102 if ($p1 === "/" || $p1 === "") { 103 $p2 = substr($p2, strlen($p1)); 104 } else { 105 $p2 = substr($p2, strlen($p1)+1); 106 } 107 } 108 $res .= $p2; 109 // remove the last "/" 110 if (preg_match("/.*\/$/", $res)) $res = preg_replace("/(.*)\//","$1",$res); 111 // if rootpath is empty replace it by "." to avoide url starting with "/" 112 if ($res == "") $res = "."; 113 // echo $res."<br>"; 114 return $res; 115} 116 117function cleanPath($path) 118{ 119 $result = array(); 120 $pathA = explode(DIRECTORY_SEPARATOR, $path); 121 if (!$pathA[0]) 122 $result[] = ''; 123 foreach ($pathA AS $key => $dir) { 124 if ($dir == '..') { 125 if (end($result) == '..') { 126 $result[] = '..'; 127 } elseif (!array_pop($result)) { 128 $result[] = '..'; 129 } 130 } elseif ($dir && $dir != '.') { 131 $result[] = $dir; 132 } 133 } 134 if (!end($pathA)) 135 $result[] = ''; 136 return implode('/', $result); 137} 138 139 140function mkdir_r($path, $modedir = 0755) 141{ 142 // This function creates the specified directory using mkdir(). Note 143 // that the recursive feature on mkdir() is broken with PHP 5.0.4 for 144 // Windows, so I have to do the recursion myself. 145 if (!file_exists($path)) 146 { 147 // The directory doesn't exist. Recurse, passing in the parent 148 // directory so that it gets created. 149 mkdir_r(dirname($path), $modedir); 150 mkdir($path, $modedir); 151 } 152} 153 154function rm_r($dir) 155{ 156 if(!$dh = @opendir($dir)) return; 157 while (($obj = readdir($dh))) 158 { 159 if($obj=='.' || $obj=='..') continue; 160 if (!@unlink($dir.'/'.$obj)) rm_r($dir.'/'.$obj); 161 } 162 closedir($dh); 163 @rmdir($dir); 164} 165 166/** 167 * Copy a file, or recursively copy a folder and its contents 168 * 169 * @author Aidan Lister <aidan@php.net> 170 * @link http://aidanlister.com/repos/v/function.copyr.php 171 * @param string $source Source path 172 * @param string $dest Destination path 173 * @return bool Returns TRUE on success, FALSE on failure 174 */ 175function copy_r($source, $dest, $modedir = 0755, $modefile = 0664) 176{ 177 // Simple copy for a file 178 if (is_file($source)) { 179 $ret = copy($source, $dest); 180 chmod($dest, $modefile); 181 return $ret; 182 } 183 184 // Make destination directory 185 if (!is_dir($dest)) { 186 mkdir($dest, $modedir); 187 } 188 189 // Take the directories entries 190 $dir = dir($source); 191 $entries = array(); 192 while (false !== $entry = $dir->read()) 193 { 194 $entries[] = $entry; 195 } 196 197 // Loop through the folder 198 foreach ($entries as $e) 199 { 200 // Skip pointers and subversion directories 201 if ($e == '.' || $e == '..' || $e == '.svn') continue; 202 // Deep copy directories 203 if ($dest !== $source . DIRECTORY_SEPARATOR . $e) 204 copy_r($source . DIRECTORY_SEPARATOR . $e, $dest . DIRECTORY_SEPARATOR . $e, $modedir, $modefile); 205 } 206 207 // Clean up 208 $dir->close(); 209 return true; 210} 211 212/** 213 * Check the functions really exists on this server 214 */ 215function check_functions_exist( $f_list ) 216{ 217 $errors = array(); 218 foreach( $f_list as $func => $err ) 219 { 220 if (!function_exists( $func )) 221 $errors[] = _pfc("%s doesn't exist: %s", $func, $err); 222 } 223 return $errors; 224} 225 226 227function test_writable_dir($dir, $name = "") 228{ 229 $errors = array(); 230 if ($dir == "") 231 $errors[] = _pfc("%s directory must be specified", ($name!="" ? $name : $dir)); 232 233 if (is_file($dir)) 234 $this->errors[] = _pfc("%s must be a directory",$dir); 235 if (!is_dir($dir)) 236 mkdir_r($dir); 237 if (!is_dir($dir)) 238 $errors[] = _pfc("%s can't be created",$dir); 239 if (!is_writeable($dir)) 240 $errors[] = _pfc("%s is not writeable",$dir); 241 if (!is_readable($dir)) 242 $errors[] = _pfc("%s is not readable",$dir); 243 244 return $errors; 245} 246 247function install_file($src_file, $dst_file) 248{ 249 $errors = array(); 250 251 $src_dir = dirname($src_file); 252 $dst_dir = dirname($dst_file); 253 254 if (!is_file($src_file)) 255 $errors[] = _pfc("%s is not a file", $src_file); 256 if (!is_readable($src_file)) 257 $errors[] = _pfc("%s is not readable", $src_file); 258 if (!is_dir($src_dir)) 259 $errors[] = _pfc("%s is not a directory", $src_dir); 260 if (!is_dir($dst_dir)) 261 mkdir_r($dst_dir); 262 263 copy( $src_file, $dst_file ); 264 265 return $errors; 266} 267 268function install_dir($src_dir, $dst_dir) 269{ 270 $errors = array(); 271 272 if (!is_dir($src_dir)) 273 $errors[] = _pfc("%s is not a directory", $src_dir); 274 if (!is_readable($src_dir)) 275 $errors[] = _pfc("%s is not readable", $src_dir); 276 277 copy_r( $src_dir, $dst_dir ); 278 279 return $errors; 280} 281 282/** 283 * file_get_contents_flock 284 * define an alternative file_get_contents when this function doesn't exists on the used php version (<4.3.0) 285 */ 286 287if (!defined('LOCK_SH')) { 288 define('LOCK_SH', 1); 289} 290 291function file_get_contents_flock($filename, $incpath = false, $resource_context = null) 292{ 293 if (false === $fh = fopen($filename, 'rb', $incpath)) { 294 user_error('file_get_contents() failed to open stream: No such file or directory ['.$filename.']', 295 E_USER_WARNING); 296 return false; 297 } 298 299 // Attempt to get a shared (read) lock 300 if (!flock($fh, LOCK_SH)) { 301 return false; 302 } 303 304 clearstatcache(); 305 if ($fsize = @filesize($filename)) { 306 $data = fread($fh, $fsize); 307 } else { 308 $data = ''; 309 while (!feof($fh)) { 310 $data .= fread($fh, 8192); 311 } 312 } 313 314 fclose($fh); 315 return $data; 316} 317 318/** 319 * file_get_contents 320 * define an alternative file_get_contents when this function doesn't exists on the used php version (<4.3.0) 321 */ 322if (!function_exists('file_get_contents')) 323{ 324 function file_get_contents($filename, $incpath = false, $resource_context = null) 325 { 326 if (false === $fh = fopen($filename, 'rb', $incpath)) 327 { 328 trigger_error('file_get_contents() failed to open stream: No such file or directory ['.$filename.']', E_USER_WARNING); 329 return false; 330 } 331 clearstatcache(); 332 if ($fsize = filesize($filename)) 333 { 334 $data = fread($fh, $fsize); 335 } 336 else 337 { 338 while (!feof($fh)) { 339 $data .= fread($fh, 8192); 340 } 341 } 342 fclose($fh); 343 return $data; 344 } 345} 346 347/** 348 * Replace file_put_contents() 349 * 350 * @category PHP 351 * @package PHP_Compat 352 * @link http://php.net/function.file_put_contents 353 * @author Aidan Lister <aidan@php.net> 354 * @internal resource_context is not supported 355 * @since PHP 5 356 * @require PHP 4.0.0 (user_error) 357 */ 358if (!defined('FILE_USE_INCLUDE_PATH')) { 359 define('FILE_USE_INCLUDE_PATH', 1); 360} 361 362if (!defined('LOCK_EX')) { 363 define('LOCK_EX', 2); 364} 365 366if (!defined('FILE_APPEND')) { 367 define('FILE_APPEND', 8); 368} 369if (!function_exists('file_put_contents')) { 370 function file_put_contents($filename, $content, $flags = null, $resource_context = null) 371 { 372 // If $content is an array, convert it to a string 373 if (is_array($content)) { 374 $content = implode('', $content); 375 } 376 377 // If we don't have a string, throw an error 378 if (!is_scalar($content)) { 379 user_error('file_put_contents() The 2nd parameter should be either a string or an array ['.$filename.']', 380 E_USER_WARNING); 381 return false; 382 } 383 384 // Get the length of data to write 385 $length = strlen($content); 386 387 // Check what mode we are using 388 $mode = ($flags & FILE_APPEND) ? 389 'a' : 390 'wb'; 391 392 // Check if we're using the include path 393 $use_inc_path = ($flags & FILE_USE_INCLUDE_PATH) ? 394 true : 395 false; 396 397 // Open the file for writing 398 if (($fh = @fopen($filename, $mode, $use_inc_path)) === false) { 399 user_error('file_put_contents() failed to open stream: Permission denied ['.$filename.']', 400 E_USER_WARNING); 401 return false; 402 } 403 404 // Attempt to get an exclusive lock 405 $use_lock = ($flags & LOCK_EX) ? true : false ; 406 if ($use_lock === true) { 407 if (!flock($fh, LOCK_EX)) { 408 return false; 409 } 410 } 411 412 // Write to the file 413 $bytes = 0; 414 if (($bytes = @fwrite($fh, $content)) === false) { 415 $errormsg = sprintf('file_put_contents() Failed to write %d bytes to %s ['.$filename.']', 416 $length, 417 $filename); 418 user_error($errormsg, E_USER_WARNING); 419 return false; 420 } 421 422 // Close the handle 423 @fclose($fh); 424 425 // Check all the data was written 426 if ($bytes != $length) { 427 $errormsg = sprintf('file_put_contents() Only %d of %d bytes written, possibly out of free disk space. ['.$filename.']', 428 $bytes, 429 $length); 430 user_error($errormsg, E_USER_WARNING); 431 return false; 432 } 433 434 // Return length 435 return $bytes; 436 } 437} 438 439 440/** 441 * iconv 442 * define an alternative iconv when this function doesn't exists on the php modules 443 */ 444if (!function_exists('iconv')) 445{ 446 if(function_exists('libiconv')) 447 { 448 // use libiconv if it exists 449 function iconv($input_encoding, $output_encoding, $string) 450 { 451 return libiconv($input_encoding, $output_encoding, $string); 452 } 453 } 454 else 455 { 456 // fallback if nothing has been found 457 function iconv($input_encoding, $output_encoding, $string) 458 { 459 return $string; 460 } 461 } 462} 463 464/** 465 * Replace html_entity_decode() 466 * 467 * @category PHP 468 * @package PHP_Compat 469 * @link http://php.net/function.html_entity_decode 470 * @author David Irvine <dave@codexweb.co.za> 471 * @author Aidan Lister <aidan@php.net> 472 * @version $Revision: 1.8 $ 473 * @since PHP 4.3.0 474 * @internal Setting the charset will not do anything 475 * @require PHP 4.0.0 (user_error) 476 */ 477 478if (!defined('ENT_NOQUOTES')) { 479 define('ENT_NOQUOTES', 0); 480} 481 482if (!defined('ENT_COMPAT')) { 483 define('ENT_COMPAT', 2); 484} 485 486if (!defined('ENT_QUOTES')) { 487 define('ENT_QUOTES', 3); 488} 489 490if (!function_exists('html_entity_decode')) { 491 function html_entity_decode($string, $quote_style = ENT_COMPAT, $charset = null) 492 { 493 if (!is_int($quote_style)) { 494 user_error('html_entity_decode() expects parameter 2 to be long, ' . 495 gettype($quote_style) . ' given', E_USER_WARNING); 496 return; 497 } 498 499 $trans_tbl = get_html_translation_table(HTML_ENTITIES); 500 $trans_tbl = array_flip($trans_tbl); 501 502 // Add single quote to translation table; 503 $trans_tbl['''] = '\''; 504 505 // Not translating double quotes 506 if ($quote_style & ENT_NOQUOTES) { 507 // Remove double quote from translation table 508 unset($trans_tbl['"']); 509 } 510 511 return strtr($string, $trans_tbl); 512 } 513} 514 515?>