See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 39 and 401]
1 <?php 2 /** 3 * The Horde_Util:: class provides generally useful methods. 4 * 5 * Copyright 1999-2017 Horde LLC (http://www.horde.org/) 6 * 7 * See the enclosed file LICENSE for license information (LGPL). If you 8 * did not receive this file, see http://www.horde.org/licenses/lgpl21. 9 * 10 * @author Chuck Hagenbuch <chuck@horde.org> 11 * @author Jon Parise <jon@horde.org> 12 * @category Horde 13 * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1 14 * @package Util 15 */ 16 class Horde_Util 17 { 18 /** 19 * A list of random patterns to use for overwriting purposes. 20 * See http://www.cs.auckland.ac.nz/~pgut001/pubs/secure_del.html. 21 * We save the random overwrites for efficiency reasons. 22 * 23 * @var array 24 */ 25 public static $patterns = array( 26 "\x55", "\xaa", "\x92\x49\x24", "\x49\x24\x92", "\x24\x92\x49", 27 "\x00", "\x11", "\x22", "\x33", "\x44", "\x55", "\x66", "\x77", 28 "\x88", "\x99", "\xaa", "\xbb", "\xcc", "\xdd", "\xee", "\xff", 29 "\x92\x49\x24", "\x49\x24\x92", "\x24\x92\x49", "\x6d\xb6\xdb", 30 "\xb6\xdb\x6d", "\xdb\x6d\xb6" 31 ); 32 33 /** 34 * Are magic quotes in use? 35 * 36 * @var boolean 37 */ 38 protected static $_magicquotes = null; 39 40 /** 41 * Data used to determine shutdown deletion. 42 * 43 * @var array 44 */ 45 protected static $_shutdowndata = array( 46 'paths' => array(), 47 'secure' => array() 48 ); 49 50 /** 51 * Has the shutdown method been registered? 52 * 53 * @var boolean 54 */ 55 protected static $_shutdownreg = false; 56 57 /** 58 * Cache for extensionExists(). 59 * 60 * @var array 61 */ 62 protected static $_cache = array(); 63 64 /** 65 * Checks to see if a value has been set by the script and not by GET, 66 * POST, or cookie input. The value being checked MUST be in the global 67 * scope. 68 * 69 * @param string $varname The variable name to check. 70 * @param mixed $default Default value if the variable isn't present 71 * or was specified by the user. Defaults to null. 72 * 73 * @return mixed $default if the var is in user input or not present, 74 * the variable value otherwise. 75 */ 76 public static function nonInputVar($varname, $default = null) 77 { 78 return (isset($_GET[$varname]) || isset($_POST[$varname]) || isset($_COOKIE[$varname])) 79 ? $default 80 : (isset($GLOBALS[$varname]) ? $GLOBALS[$varname] : $default); 81 } 82 83 /** 84 * Returns a hidden form input containing the session name and id. 85 * 86 * @param boolean $append_session 0 = only if needed, 1 = always. 87 * 88 * @return string The hidden form input, if needed/requested. 89 */ 90 public static function formInput($append_session = 0) 91 { 92 return (($append_session == 1) || !isset($_COOKIE[session_name()])) 93 ? '<input type="hidden" name="' . htmlspecialchars(session_name()) . '" value="' . htmlspecialchars(session_id()) . "\" />\n" 94 : ''; 95 } 96 97 /** 98 * Prints a hidden form input containing the session name and id. 99 * 100 * @param boolean $append_session 0 = only if needed, 1 = always. 101 */ 102 public static function pformInput($append_session = 0) 103 { 104 echo self::formInput($append_session); 105 } 106 107 /** 108 * If magic_quotes_gpc is in use, run stripslashes() on $var. 109 * 110 * @param mixed $var The string, or an array of strings, to un-quote. 111 * 112 * @return mixed $var, minus any magic quotes. 113 */ 114 public static function dispelMagicQuotes($var) 115 { 116 if (is_null(self::$_magicquotes)) { 117 self::$_magicquotes = function_exists('get_magic_quotes_gpc') && @get_magic_quotes_gpc(); 118 } 119 120 if (self::$_magicquotes) { 121 $var = is_array($var) 122 ? array_map(array(__CLASS__, 'dispelMagicQuotes'), $var) 123 : stripslashes($var); 124 } 125 126 return $var; 127 } 128 129 /** 130 * Gets a form variable from GET or POST data, stripped of magic quotes if 131 * necessary. If the variable is somehow set in both the GET data and the 132 * POST data, the value from the POST data will be returned and the GET 133 * value will be ignored. 134 * 135 * @param string $var The name of the form variable to look for. 136 * @param string $default The value to return if the variable is not 137 * there. 138 * 139 * @return string The cleaned form variable, or $default. 140 */ 141 public static function getFormData($var, $default = null) 142 { 143 return (($val = self::getPost($var)) !== null) 144 ? $val 145 : self::getGet($var, $default); 146 } 147 148 /** 149 * Gets a form variable from GET data, stripped of magic quotes if 150 * necessary. This function will NOT return a POST variable. 151 * 152 * @param string $var The name of the form variable to look for. 153 * @param string $default The value to return if the variable is not 154 * there. 155 * 156 * @return string The cleaned form variable, or $default. 157 */ 158 public static function getGet($var, $default = null) 159 { 160 return (isset($_GET[$var])) 161 ? self::dispelMagicQuotes($_GET[$var]) 162 : $default; 163 } 164 165 /** 166 * Gets a form variable from POST data, stripped of magic quotes if 167 * necessary. This function will NOT return a GET variable. 168 * 169 * @param string $var The name of the form variable to look for. 170 * @param string $default The value to return if the variable is not 171 * there. 172 * 173 * @return string The cleaned form variable, or $default. 174 */ 175 public static function getPost($var, $default = null) 176 { 177 return (isset($_POST[$var])) 178 ? self::dispelMagicQuotes($_POST[$var]) 179 : $default; 180 } 181 182 /** 183 * Creates a temporary filename for the lifetime of the script, and 184 * (optionally) registers it to be deleted at request shutdown. 185 * 186 * @param string $prefix Prefix to make the temporary name more 187 * recognizable. 188 * @param boolean $delete Delete the file at the end of the request? 189 * @param string $dir Directory to create the temporary file in. 190 * @param boolean $secure If deleting the file, should we securely delete 191 * the file by overwriting it with random data? 192 * 193 * @return string Returns the full path-name to the temporary file. 194 * Returns false if a temp file could not be created. 195 */ 196 public static function getTempFile($prefix = '', $delete = true, $dir = '', 197 $secure = false) 198 { 199 $tempDir = (empty($dir) || !is_dir($dir)) 200 ? sys_get_temp_dir() 201 : $dir; 202 203 $tempFile = tempnam($tempDir, $prefix); 204 205 // If the file was created, then register it for deletion and return. 206 if (empty($tempFile)) { 207 return false; 208 } 209 210 if ($delete) { 211 self::deleteAtShutdown($tempFile, true, $secure); 212 } 213 214 return $tempFile; 215 } 216 217 /** 218 * Creates a temporary filename with a specific extension for the lifetime 219 * of the script, and (optionally) registers it to be deleted at request 220 * shutdown. 221 * 222 * @param string $extension The file extension to use. 223 * @param string $prefix Prefix to make the temporary name more 224 * recognizable. 225 * @param boolean $delete Delete the file at the end of the request? 226 * @param string $dir Directory to create the temporary file in. 227 * @param boolean $secure If deleting file, should we securely delete 228 * the file by overwriting it with random data? 229 * 230 * @return string Returns the full path-name to the temporary file. 231 * Returns false if a temporary file could not be created. 232 */ 233 public static function getTempFileWithExtension($extension = '.tmp', 234 $prefix = '', 235 $delete = true, $dir = '', 236 $secure = false) 237 { 238 $tempDir = (empty($dir) || !is_dir($dir)) 239 ? sys_get_temp_dir() 240 : $dir; 241 242 if (empty($tempDir)) { 243 return false; 244 } 245 246 $windows = substr(PHP_OS, 0, 3) == 'WIN'; 247 $tries = 1; 248 do { 249 // Get a known, unique temporary file name. 250 $sysFileName = tempnam($tempDir, $prefix); 251 if ($sysFileName === false) { 252 return false; 253 } 254 255 // tack on the extension 256 $tmpFileName = $sysFileName . $extension; 257 if ($sysFileName == $tmpFileName) { 258 return $sysFileName; 259 } 260 261 // Move or point the created temporary file to the full filename 262 // with extension. These calls fail if the new name already 263 // exists. 264 $fileCreated = ($windows ? @rename($sysFileName, $tmpFileName) : @link($sysFileName, $tmpFileName)); 265 if ($fileCreated) { 266 if (!$windows) { 267 unlink($sysFileName); 268 } 269 270 if ($delete) { 271 self::deleteAtShutdown($tmpFileName, true, $secure); 272 } 273 274 return $tmpFileName; 275 } 276 277 unlink($sysFileName); 278 } while (++$tries <= 5); 279 280 return false; 281 } 282 283 /** 284 * Creates a temporary directory in the system's temporary directory. 285 * 286 * @param boolean $delete Delete the temporary directory at the end of 287 * the request? 288 * @param string $temp_dir Use this temporary directory as the directory 289 * where the temporary directory will be created. 290 * 291 * @return string The pathname to the new temporary directory. 292 * Returns false if directory not created. 293 */ 294 public static function createTempDir($delete = true, $temp_dir = null) 295 { 296 if (is_null($temp_dir)) { 297 $temp_dir = sys_get_temp_dir(); 298 } 299 300 if (empty($temp_dir)) { 301 return false; 302 } 303 304 /* Get the first 8 characters of a random string to use as a temporary 305 directory name. */ 306 do { 307 $new_dir = $temp_dir . '/' . substr(base_convert(uniqid(mt_rand()), 16, 36), 0, 8); 308 } while (file_exists($new_dir)); 309 310 $old_umask = umask(0000); 311 if (!mkdir($new_dir, 0700)) { 312 $new_dir = false; 313 } elseif ($delete) { 314 self::deleteAtShutdown($new_dir); 315 } 316 umask($old_umask); 317 318 return $new_dir; 319 } 320 321 /** 322 * Returns the canonical path of the string. Like PHP's built-in 323 * realpath() except the directory need not exist on the local server. 324 * 325 * Algorithim loosely based on code from the Perl File::Spec::Unix module 326 * (version 1.5). 327 * 328 * @param string $path A file path. 329 * 330 * @return string The canonicalized file path. 331 */ 332 public static function realPath($path) 333 { 334 /* Standardize on UNIX directory separators. */ 335 if (!strncasecmp(PHP_OS, 'WIN', 3)) { 336 $path = str_replace('\\', '/', $path); 337 } 338 339 /* xx////xx -> xx/xx 340 * xx/././xx -> xx/xx */ 341 $path = preg_replace(array("|/+|", "@(/\.)+(/|\Z(?!\n))@"), array('/', '/'), $path); 342 343 /* ./xx -> xx */ 344 if ($path != './') { 345 $path = preg_replace("|^(\./)+|", '', $path); 346 } 347 348 /* /../../xx -> xx */ 349 $path = preg_replace("|^/(\.\./?)+|", '/', $path); 350 351 /* xx/ -> xx */ 352 if ($path != '/') { 353 $path = preg_replace("|/\Z(?!\n)|", '', $path); 354 } 355 356 /* /xx/.. -> / */ 357 while (strpos($path, '/..') !== false) { 358 $path = preg_replace("|/[^/]+/\.\.|", '', $path); 359 } 360 361 return empty($path) ? '/' : $path; 362 } 363 364 /** 365 * Removes given elements at request shutdown. 366 * 367 * If called with a filename will delete that file at request shutdown; if 368 * called with a directory will remove that directory and all files in that 369 * directory at request shutdown. 370 * 371 * If called with no arguments, return all elements to be deleted (this 372 * should only be done by Horde_Util::_deleteAtShutdown()). 373 * 374 * The first time it is called, it initializes the array and registers 375 * Horde_Util::_deleteAtShutdown() as a shutdown function - no need to do 376 * so manually. 377 * 378 * The second parameter allows the unregistering of previously registered 379 * elements. 380 * 381 * @param string $filename The filename to be deleted at the end of the 382 * request. 383 * @param boolean $register If true, then register the element for 384 * deletion, otherwise, unregister it. 385 * @param boolean $secure If deleting file, should we securely delete 386 * the file? 387 */ 388 public static function deleteAtShutdown($filename, $register = true, 389 $secure = false) 390 { 391 /* Initialization of variables and shutdown functions. */ 392 if (!self::$_shutdownreg) { 393 register_shutdown_function(array(__CLASS__, 'shutdown')); 394 self::$_shutdownreg = true; 395 } 396 397 $ptr = &self::$_shutdowndata; 398 if ($register) { 399 $ptr['paths'][$filename] = true; 400 if ($secure) { 401 $ptr['secure'][$filename] = true; 402 } 403 } else { 404 unset($ptr['paths'][$filename], $ptr['secure'][$filename]); 405 } 406 } 407 408 /** 409 * Deletes registered files at request shutdown. 410 * 411 * This function should never be called manually; it is registered as a 412 * shutdown function by Horde_Util::deleteAtShutdown() and called 413 * automatically at the end of the request. 414 * 415 * Contains code from gpg_functions.php. 416 * Copyright 2002-2003 Braverock Ventures 417 */ 418 public static function shutdown() 419 { 420 $ptr = &self::$_shutdowndata; 421 422 foreach (array_keys($ptr['paths']) as $val) { 423 if (@is_file($val)) { 424 self::_secureDelete($val); 425 continue; 426 } 427 428 try { 429 $it = new RecursiveIteratorIterator( 430 new RecursiveDirectoryIterator($val), 431 RecursiveIteratorIterator::CHILD_FIRST 432 ); 433 } catch (UnexpectedValueException $e) { 434 continue; 435 } 436 437 while ($it->valid()) { 438 if (!$it->isDot()) { 439 if ($it->isDir()) { 440 @rmdir($it->key()); 441 } elseif ($it->isFile()) { 442 self::_secureDelete($it->key()); 443 } else { 444 @unlink($it->key()); 445 } 446 } 447 $it->next(); 448 } 449 450 @rmdir($val); 451 } 452 } 453 454 /** 455 * Securely delete the file by overwriting the data with a random 456 * string. 457 * 458 * @param string $file Filename. 459 */ 460 protected static function _secureDelete($file) 461 { 462 if (isset($ptr['secure'][$file])) { 463 $filesize = filesize($file); 464 $fp = fopen($file, 'r+'); 465 foreach (self::$patterns as $pattern) { 466 $pattern = substr(str_repeat($pattern, floor($filesize / strlen($pattern)) + 1), 0, $filesize); 467 fwrite($fp, $pattern); 468 fseek($fp, 0); 469 } 470 fclose($fp); 471 } 472 473 @unlink($file); 474 } 475 476 /** 477 * Caches the result of extension_loaded() calls. 478 * 479 * @param string $ext The extension name. 480 * 481 * @return boolean Is the extension loaded? 482 */ 483 public static function extensionExists($ext) 484 { 485 if (!isset(self::$_cache[$ext])) { 486 self::$_cache[$ext] = extension_loaded($ext); 487 } 488 489 return self::$_cache[$ext]; 490 } 491 492 /** 493 * Tries to load a PHP extension, behaving correctly for all operating 494 * systems. 495 * 496 * @param string $ext The extension to load. 497 * 498 * @return boolean True if the extension is now loaded, false if not. 499 * True can mean that the extension was already loaded, 500 * OR was loaded dynamically. 501 */ 502 public static function loadExtension($ext) 503 { 504 /* If $ext is already loaded, our work is done. */ 505 if (self::extensionExists($ext)) { 506 return true; 507 } 508 509 /* See if we can call dl() at all, by the current ini settings. 510 * dl() has been removed in some PHP 5.3 SAPIs. */ 511 if ((ini_get('enable_dl') != 1) || 512 (ini_get('safe_mode') == 1) || 513 !function_exists('dl')) { 514 return false; 515 } 516 517 if (!strncasecmp(PHP_OS, 'WIN', 3)) { 518 $suffix = 'dll'; 519 } else { 520 switch (PHP_OS) { 521 case 'HP-UX': 522 $suffix = 'sl'; 523 break; 524 525 case 'AIX': 526 $suffix = 'a'; 527 break; 528 529 case 'OSX': 530 $suffix = 'bundle'; 531 break; 532 533 default: 534 $suffix = 'so'; 535 } 536 } 537 538 return dl($ext . '.' . $suffix) || dl('php_' . $ext . '.' . $suffix); 539 } 540 541 /** 542 * Utility function to obtain PATH_INFO information. 543 * 544 * @return string The PATH_INFO string. 545 */ 546 public static function getPathInfo() 547 { 548 if (isset($_SERVER['PATH_INFO']) && 549 (strpos($_SERVER['SERVER_SOFTWARE'], 'lighttpd') === false)) { 550 return $_SERVER['PATH_INFO']; 551 } elseif (isset($_SERVER['REQUEST_URI']) && 552 isset($_SERVER['SCRIPT_NAME'])) { 553 $search = Horde_String::common($_SERVER['SCRIPT_NAME'], $_SERVER['REQUEST_URI']); 554 if (substr($search, -1) == '/') { 555 $search = substr($search, 0, -1); 556 } 557 $search = array($search); 558 if (!empty($_SERVER['QUERY_STRING'])) { 559 // We can't use QUERY_STRING directly because URL rewriting 560 // might add more parameters to the query string than those 561 // from the request URI. 562 $url = parse_url($_SERVER['REQUEST_URI']); 563 if (!empty($url['query'])) { 564 $search[] = '?' . $url['query']; 565 } 566 } 567 $path = str_replace($search, '', $_SERVER['REQUEST_URI']); 568 if ($path == '/') { 569 $path = ''; 570 } 571 return $path; 572 } 573 574 return ''; 575 } 576 577 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body