PageRenderTime 54ms CodeModel.GetById 3ms app.highlight 40ms RepoModel.GetById 1ms app.codeStats 0ms

/plugins/lib/upgrade.php

https://bitbucket.org/DennisSchulmeister/www-wikiberd
PHP | 1594 lines | 1531 code | 18 blank | 45 comment | 19 complexity | 4fdbf75845b56f121431f32fc7efe691 MD5 | raw file
   1<?php
   2/*
   3   This include() script adds missing PHP functions to earlier interpreter
   4   versions, so you can make downwards compatible scripts without having
   5   to stick to the least common denominator. It only defines the ones that
   6   are really missing - the faster native functions will be used whenever
   7   available.
   8
   9   - many of the emulation functions are one-liners
  10   - a few features have been added that never made it into one of the
  11     official versions (CVS code and the ever-absent "gzdecode" and
  12     "file_put_contents" for example)
  13   - a few very extravagant functions (array_u?diff*_u*assoc?) and other
  14     extensions have been separated out into ext/
  15   - the advanced OO-capabilities and language syntax extensions of PHP5
  16     and ZE2 cannot seriously be emulated here, this script only takes care
  17     of procedural interfaces
  18   - with only this part loaded, you get "PHP 4.1 COMPATIBILITY"
  19   - this is PuplicDomain (no copyright, no license, no warranty) so you
  20     can melt it into anything, regardless of your preferred license (you
  21     may strip this paragraph and turn it all into GPL, BSD, GNU LGPL,
  22     Artistic, MPL, PHP license, M$ EULA, or whatever you like best)
  23   
  24   Get update notes via "http://freshmeat.net/projects/upgradephp" or
  25   google for it. Any contribution is appreciated. <milky*users新f搖et>
  26*/
  27
  28
  29
  30#------------------------------------------------------------------ CVS ---
  31// most of this appeared in 5.0
  32// ...
  33
  34
  35
  36
  37#------------------------------------------------------------------ 6.0 ---
  38// following functions were never implemented in PHP
  39
  40
  41#-- inflates a string enriched with gzip headers
  42#   (this is the logical counterpart to gzencode(), but don't tell anyone!)
  43if (!function_exists("gzdecode")) {
  44   function gzdecode($data, $maxlen=NULL) {
  45
  46      #-- decode header
  47      $len = strlen($data);
  48      if ($len < 20) {
  49         return;
  50      }
  51      $head = substr($data, 0, 10);
  52      $head = unpack("n1id/C1cm/C1flg/V1mtime/C1xfl/C1os", $head);
  53      list($ID, $CM, $FLG, $MTIME, $XFL, $OS) = array_values($head);
  54      $FTEXT = 1<<0;
  55      $FHCRC = 1<<1;
  56      $FEXTRA = 1<<2;
  57      $FNAME = 1<<3;
  58      $FCOMMENT = 1<<4;
  59      $head = unpack("V1crc/V1isize", substr($data, $len-8, 8));
  60      list($CRC32, $ISIZE) = array_values($head);
  61
  62      #-- check gzip stream identifier
  63      if ($ID != 0x1f8b) {
  64         trigger_error("gzdecode: not in gzip format", E_USER_WARNING);
  65         return;
  66      }
  67      #-- check for deflate algorithm
  68      if ($CM != 8) {
  69         trigger_error("gzdecode: cannot decode anything but deflated streams", E_USER_WARNING);
  70         return;
  71      }
  72
  73      #-- start of data, skip bonus fields
  74      $s = 10;
  75      if ($FLG & $FEXTRA) {
  76         $s += $XFL;
  77      }
  78      if ($FLG & $FNAME) {
  79         $s = strpos($data, "\000", $s) + 1;
  80      }
  81      if ($FLG & $FCOMMENT) {
  82         $s = strpos($data, "\000", $s) + 1;
  83      }
  84      if ($FLG & $FHCRC) {
  85         $s += 2;  // cannot check
  86      }
  87      
  88      #-- get data, uncompress
  89      $data = substr($data, $s, $len-$s);
  90      if ($maxlen) {
  91         $data = gzinflate($data, $maxlen);
  92         return($data);  // no checks(?!)
  93      }
  94      else {
  95         $data = gzinflate($data);
  96      }
  97      
  98      #-- check+fin
  99      $chk = crc32($data);
 100      if ($CRC32 != $chk) {
 101         trigger_error("gzdecode: checksum failed (real$chk != comp$CRC32)", E_USER_WARNING);
 102      }
 103      elseif ($ISIZE != strlen($data)) {
 104         trigger_error("gzdecode: stream size mismatch", E_USER_WARNING);
 105      }
 106      else {
 107         return($data);
 108      }
 109   }
 110}
 111
 112
 113#-- get all already made headers(),
 114#   CANNOT be emulated, because output buffering functions
 115#   already swallow up any sent http header
 116if (!function_exists("ob_get_headers")) {
 117   function ob_get_headers() {
 118      return (array)NULL;
 119   }
 120}
 121
 122
 123#-- encodes required named XML entities, like htmlentities(),
 124#   but does not re-encode numeric &#xxxx; character references
 125#   - could screw up scripts which then implement this themselves
 126#   - doesn't fix bogus or invalid numeric entities
 127if (!function_exists("xmlentities")) {
 128   function xmlentities($str) {
 129      return strtr($str, array(
 130        "&#"=>"&#", "&"=>"&amp;", "'"=>"&apos;",
 131        "<"=>"&lt;", ">"=>"&gt;", "\""=>"&quot;", 
 132      ));
 133   }
 134}
 135
 136
 137
 138#------------------------------------------------------------------ 5.0 ---
 139# set_exception_handler - unimpl.
 140# restore_exception_handler - unimpl.
 141# debug_print_backtrace - unimpl.
 142# class_implements - unimplementable
 143# proc_terminate - unimpl?
 144# proc_get_status - unimpl.
 145# --
 146# proc_nice
 147# dns_get_record
 148# date_sunrise - undoc.
 149# date_sunset - undoc.
 150
 151
 152
 153#-- constant: end of line
 154if (!defined("PHP_EOL")) {
 155   define("PHP_EOL", ( (DIRECTORY_SEPARATOR == "\\") ?"\015\012" :(strncmp(PHP_OS,"D",1)?"\012":"\015") )  ); #"
 156}
 157
 158
 159#-- case-insensitive string search function,
 160#   - finds position of first occourence of a string c-i
 161#   - parameters identical to strpos()
 162if (!function_exists("stripos")) {
 163   function stripos($haystack, $needle, $offset=NULL) {
 164   
 165      #-- simply lowercase args
 166      $haystack = strtolower($haystack);
 167      $needle = strtolower($needle);
 168      
 169      #-- search
 170      $pos = strpos($haystack, $needle, $offset);
 171      return($pos);
 172   }
 173}
 174
 175
 176#-- case-insensitive string search function
 177#   - but this one starts from the end of string (right to left)
 178#   - offset can be negative or positive
 179if (!function_exists("strripos")) {
 180   function strripos($haystack, $needle, $offset=NULL) {
 181
 182      #-- lowercase incoming strings
 183      $haystack = strtolower($haystack);
 184      $needle = strtolower($needle);
 185
 186      #-- [-]$offset tells to ignore a few string bytes,
 187      #   we simply cut a bit from the right
 188      if (isset($offset) && ($offset < 0)) {
 189         $haystack = substr($haystack, 0, strlen($haystack) - 1);
 190      }
 191
 192      #-- let PHP do it
 193      $pos = strrpos($haystack, $needle);
 194
 195      #-- [+]$offset => ignore left haystack bytes
 196      if (isset($offset) && ($offset > 0) && ($pos > $offset)) {
 197         $pos = false;
 198      }
 199
 200      #-- result      
 201      return($pos);
 202   }
 203}
 204
 205
 206#-- case-insensitive version of str_replace
 207if (!function_exists("str_ireplace")) {
 208   function str_ireplace($search, $replace, $subject, $count=NULL) {
 209
 210      #-- call ourselves recursively, if parameters are arrays/lists 
 211      if (is_array($search)) {
 212         $replace = array_values($replace);
 213         foreach (array_values($search) as $i=>$srch) {
 214            $subject = str_ireplace($srch, $replace[$i], $subject);
 215         }
 216      }
 217      
 218      #-- sluice replacement strings through the Perl-regex module
 219      #   (faster than doing it by hand)
 220      else {
 221         $replace = addcslashes($replace, "$\\");
 222         $search = "{" . preg_quote($search) . "}i";
 223         $subject = preg_replace($search, $replace, $subject);
 224      }
 225
 226      #-- result
 227      return($subject);
 228   }
 229}
 230
 231
 232#-- performs a http HEAD request
 233if (!function_exists("get_headers")) {
 234   function get_headers($url, $parse=0) {
 235   
 236      #-- extract URL parts ($host, $port, $path, ...)
 237      $c = parse_url($url);
 238      extract($c);
 239      if (!isset($port)) { 
 240         $port = 80;
 241      }
 242      
 243      #-- try to open TCP connection      
 244      $f = fsockopen($host, $port, $errno, $errstr, $timeout=15);
 245      if (!$f) {
 246         return;
 247      }
 248
 249      #-- send request header
 250      socket_set_blocking($f, true);
 251      fwrite($f, "HEAD $path HTTP/1.0\015\012"
 252               . "Host: $host\015\012"
 253               . "Connection: close\015\012"
 254               . "Accept: */*, xml/*\015\012"
 255               . "User-Agent: ".trim(ini_get("user_agent"))."\015\012"
 256               . "\015\012");
 257
 258      #-- read incoming lines
 259      $ls = array();
 260      while ( !feof($f) && ($line = trim(fgets($f, 1<<16))) ) {
 261         
 262         #-- read header names to make result an hash (names in array index)
 263         if ($parse) {
 264            if ($l = strpos($line, ":")) {
 265               $name = substr($line, 0, $l);
 266               $value = trim(substr($line, $l + 1));
 267               #-- merge headers
 268               if (isset($ls[$name])) {
 269                  $ls[$name] .= ", $value";
 270               }
 271               else {
 272                  $ls[$name] = $value;
 273               }
 274            }
 275            #-- HTTP response status header as result[0]
 276            else {
 277               $ls[] = $line;
 278            }
 279         }
 280         
 281         #-- unparsed header list (numeric indices)
 282         else {
 283            $ls[] = $line;
 284         }
 285      }
 286
 287      #-- close TCP connection and give result
 288      fclose($f);
 289      return($ls);
 290   }
 291}
 292
 293
 294#-- list of already/potentially sent HTTP responsee headers(),
 295#   CANNOT be implemented (except for Apache module maybe)
 296if (!function_exists("headers_list")) {
 297   function headers_list() {
 298      trigger_error("headers_list(): not supported by this PHP version", E_USER_WARNING);
 299      return (array)NULL;
 300   }
 301}
 302
 303
 304#-- write formatted string to stream/file,
 305#   arbitrary numer of arguments
 306if (!function_exists("fprintf")) {
 307   function fprintf(/*...*/) {
 308      $args = func_get_args();
 309      $stream = array_shift($args);
 310      return fwrite($stream, call_user_func_array("sprintf", $args));
 311   }
 312}
 313
 314
 315#-- write formatted string to stream, args array
 316if (!function_exists("vfprintf")) {
 317   function vfprintf($stream, $format, $args=NULL) {
 318      return fwrite($stream, vsprintf($format, $args));
 319   }
 320}
 321
 322
 323#-- splits a string in evenly sized chunks
 324#   and returns this as array
 325if (!function_exists("str_split")) {
 326   function str_split($str, $chunk=1) {
 327      $r = array();
 328      
 329      #-- return back as one chunk completely, if size chosen too low
 330      if ($chunk < 1) {
 331         $r[] = $str;
 332      }
 333      
 334      #-- add substrings to result array until subject strings end reached
 335      else {
 336         $len = strlen($str);
 337         for ($n=0; $n<$len; $n+=$chunk) {
 338            $r[] = substr($str, $n, $chunk);
 339         }
 340      }
 341      return($r);
 342   }
 343}
 344
 345
 346#-- constructs a QUERY_STRING (application/x-www-form-urlencoded format, non-raw)
 347#   from a nested array/hash with name=>value pairs
 348#   - only first two args are part of the original API - rest used for recursion
 349if (!function_exists("http_build_query")) {
 350   function http_build_query($data, $int_prefix="", $subarray_pfix="", $level=0) {
 351   
 352      #-- empty starting string
 353      $s = "";
 354      ($SEP = ini_get("arg_separator.output")) or ($SEP = "&");
 355      
 356      #-- traverse hash/array/list entries 
 357      foreach ($data as $index=>$value) {
 358         
 359         #-- add sub_prefix for subarrays (happens for recursed innovocation)
 360         if ($subarray_pfix) {
 361            if ($level) {
 362               $index = "[" . $index . "]";
 363            }
 364            $index =  $subarray_pfix . $index;
 365         }
 366         #-- add user-specified prefix for integer-indices
 367         elseif (is_int($index) && strlen($int_prefix)) {
 368            $index = $int_prefix . $index;
 369         }
 370         
 371         #-- recurse for sub-arrays
 372         if (is_array($value)) {
 373            $s .= http_build_query($value, "", $index, $level + 1);
 374         }
 375         else {   // or just literal URL parameter
 376            $s .= $SEP . $index . "=" . urlencode($value);
 377         }
 378      }
 379      
 380      #-- remove redundant "&" from first round (-not checked above to simplifiy loop)
 381      if (!$subarray_pfix) {
 382         $s = substr($s, strlen($SEP));
 383      }
 384
 385      #-- return result / to previous array level and iteration
 386      return($s);
 387   }
 388}
 389
 390
 391#-- transform into 3to4 uuencode
 392#   - this is the bare encoding, not the uu file format
 393if (!function_exists("convert_uuencode")) {
 394   function convert_uuencode($data) {
 395
 396      #-- init vars
 397      $out = "";
 398      $line = "";
 399      $len = strlen($data);
 400#      $data .= "\252\252\252";   // PHP and uuencode(1) use some special garbage??, looks like "\000"* and "`\n`" simply appended
 401
 402      #-- canvass source string
 403      for ($n=0; $n<$len; ) {
 404      
 405         #-- make 24-bit integer from first three bytes
 406         $x = (ord($data[$n++]) << 16)
 407            + (ord($data[$n++]) <<  8)
 408            + (ord($data[$n++]) <<  0);
 409            
 410         #-- disperse that into 4 ascii characters
 411         $line .= chr( 32 + (($x >> 18) & 0x3f) )
 412                . chr( 32 + (($x >> 12) & 0x3f) )
 413                . chr( 32 + (($x >>  6) & 0x3f) )
 414                . chr( 32 + (($x >>  0) & 0x3f) );
 415                
 416         #-- cut lines, inject count prefix before each
 417         if (($n % 45) == 0) {
 418            $out .= chr(32 + 45) . "$line\n";
 419            $line = "";
 420         }
 421      }
 422
 423      #-- throw last line, +length prefix
 424      if ($trail = ($len % 45)) {
 425         $out .= chr(32 + $trail) . "$line\n";
 426      }
 427
 428      // uuencode(5) doesn't tell so, but spaces are replaced with the ` char in most implementations
 429      $out = strtr("$out \n", " ", "`");
 430      return($out);
 431   }
 432}
 433
 434
 435#-- decodes uuencoded() data again
 436if (!function_exists("convert_uudecode")) {
 437   function convert_uudecode($data) {
 438
 439      #-- prepare
 440      $out = "";
 441      $data = strtr($data, "`", " ");
 442      
 443      #-- go through lines
 444      foreach(explode("\n", ltrim($data)) as $line) {
 445         if (!strlen($line)) {
 446            break;  // end reached
 447         }
 448         
 449         #-- current line length prefix
 450         unset($num);
 451         $num = ord($line{0}) - 32;
 452         if (($num <= 0) || ($num > 62)) {  // 62 is the maximum line length
 453            break;          // according to uuencode(5), so we stop here too
 454         }
 455         $line = substr($line, 1);
 456         
 457         #-- prepare to decode 4-char chunks
 458         $add = "";
 459         for ($n=0; strlen($add)<$num; ) {
 460         
 461            #-- merge 24 bit integer from the 4 ascii characters (6 bit each)
 462            $x = ((ord($line[$n++]) - 32) << 18)
 463               + ((ord($line[$n++]) - 32) << 12)  // were saner with "& 0x3f"
 464               + ((ord($line[$n++]) - 32) <<  6)
 465               + ((ord($line[$n++]) - 32) <<  0);
 466               
 467            #-- reconstruct the 3 original data chars
 468            $add .= chr( ($x >> 16) & 0xff )
 469                  . chr( ($x >>  8) & 0xff )
 470                  . chr( ($x >>  0) & 0xff );
 471         }
 472
 473         #-- cut any trailing garbage (last two decoded chars may be wrong)
 474         $out .= substr($add, 0, $num);
 475         $line = "";
 476      }
 477
 478      return($out);
 479   }
 480}
 481
 482
 483#-- return array of filenames in a given directory
 484#   (only works for local files)
 485if (!function_exists("scandir")) {
 486   function scandir($dirname, $desc=0) {
 487   
 488      #-- check for file:// protocol, others aren't handled
 489      if (strpos($dirname, "file://") === 0) {
 490         $dirname = substr($dirname, 7);
 491         if (strpos($dirname, "localh") === 0) {
 492            $dirname = substr($dirname, strpos($dirname, "/"));
 493         }
 494      }
 495      
 496      #-- directory reading handle
 497      if ($dh = opendir($dirname)) {
 498         $ls = array();
 499         while ($fn = readdir($dh)) {
 500            $ls[] = $fn;  // add to array
 501         }
 502         closedir($dh);
 503         
 504         #-- sort filenames
 505         if ($desc) {
 506            rsort($ls);
 507         }
 508         else {
 509            sort($ls);
 510         }
 511         return $ls;
 512      }
 513
 514      #-- failure
 515      return false;
 516   }
 517}
 518
 519
 520#-- like date(), but returns an integer for given one-letter format parameter
 521if (!function_exists("idate")) {
 522   function idate($formatchar, $timestamp=NULL) {
 523   
 524      #-- reject non-simple type parameters
 525      if (strlen($formatchar) != 1) {
 526         return false;
 527      }
 528      
 529      #-- get current time, if not given
 530      if (!isset($timestamp)) {
 531         $timestamp = time();
 532      }
 533      
 534      #-- get and turn into integer
 535      $str = date($formatchar, $timestamp);
 536      return (int)$str;
 537   }
 538}
 539
 540
 541
 542#-- combined sleep() and usleep() 
 543if (!function_exists("time_nanosleep")) {
 544   function time_nanosleep($sec, $nano) {
 545      sleep($sec);
 546      usleep($nano);
 547   }
 548}
 549
 550
 551
 552#-- search first occourence of any of the given chars, returns rest of haystack
 553#   (char_list must be a string for compatibility with the real PHP func)
 554if (!function_exists("strpbrk")) {
 555   function strpbrk($haystack, $char_list) {
 556   
 557      #-- prepare
 558      $len = strlen($char_list);
 559      $min = strlen($haystack);
 560      
 561      #-- check with every symbol from $char_list
 562      for ($n = 0; $n < $len; $n++) {
 563         $l = strpos($haystack, $char_list{$n});
 564         
 565         #-- get left-most occourence
 566         if (($l !== false) && ($l < $min)) {
 567            $min = $l;
 568         }
 569      }
 570      
 571      #-- result
 572      if ($min) {
 573         return(substr($haystack, $min));
 574      }
 575      else {
 576         return(false);
 577      }
 578   }
 579}
 580
 581
 582
 583#-- logo image activation URL query strings (gaga feature)
 584if (!function_exists("php_real_logo_guid")) {
 585   function php_real_logo_guid() { return php_logo_guid(); }
 586   function php_egg_logo_guid() { return zend_logo_guid(); }
 587}
 588
 589
 590#-- no need to implement this
 591#   (there aren't interfaces in PHP4 anyhow)
 592if (!function_exists("get_declared_interfaces")) {
 593   function get_declared_interfaces() {
 594      trigger_error("get_declared_interfaces(): Current script won't run reliably with PHP4.", E_USER_WARNING);
 595      return( (array)NULL );
 596   }
 597}
 598
 599
 600#-- creates an array from lists of $keys and $values
 601#   (both should have same number of entries)
 602if (!function_exists("array_combine")) {
 603   function array_combine($keys, $values) {
 604   
 605      #-- convert input arrays into lists
 606      $keys = array_values($keys);
 607      $values = array_values($values);
 608      $r = array();
 609      
 610      #-- one from each
 611      foreach ($values as $i=>$val) {
 612         if ($key = $keys[$i]) {
 613            $r[$key] = $val;
 614         }
 615         else {
 616            $r[] = $val;   // useless, PHP would have long aborted here
 617         }
 618      }
 619      return($r);
 620   }
 621}
 622
 623
 624#-- apply userfunction to each array element (descending recursively)
 625#   use it like:  array_walk_recursive($_POST, "stripslashes");
 626#   - $callback can be static function name or object/method, class/method
 627if (!function_exists("array_walk_recursive")) {
 628   function array_walk_recursive(&$input, $callback, $userdata=NULL) {
 629      #-- each entry
 630      foreach ($input as $key=>$value) {
 631
 632         #-- recurse for sub-arrays
 633         if (is_array($value)) {
 634            array_walk_recursive($input[$key], $callback, $userdata);
 635         }
 636
 637         #-- $callback handles scalars
 638         else {
 639            call_user_func_array($callback, array(&$input[$key], $key, $userdata) );
 640         }
 641      }
 642
 643      // no return value
 644   }
 645}
 646
 647
 648#-- complicated wrapper around substr() and and strncmp()
 649if (!function_exists("substr_compare")) {
 650   function substr_compare($haystack, $needle, $offset=0, $len=0, $ci=0) {
 651
 652      #-- check params   
 653      if ($len <= 0) {   // not well documented
 654         $len = strlen($needle);
 655         if (!$len) { return(0); }
 656      }
 657      #-- length exception
 658      if ($len + $offset >= strlen($haystack)) {
 659         trigger_error("substr_compare: given length exceeds main_str", E_USER_WARNING);
 660         return(false);
 661      }
 662
 663      #-- cut
 664      if ($offset) {
 665         $haystack = substr($haystack, $offset, $len);
 666      }
 667      #-- case-insensitivity
 668      if ($ci) {
 669         $haystack = strtolower($haystack);
 670         $needle = strtolower($needle);
 671      }
 672
 673      #-- do
 674      return(strncmp($haystack, $needle, $len));
 675   }
 676}
 677
 678
 679#-- stub, returns empty list as usual;
 680#   you must load "ext/spl.php" beforehand to get this
 681if (!function_exists("spl_classes")) {
 682   function spl_classes() {
 683      trigger_error("spl_classes(): not built into this PHP version");
 684      return (array)NULL;
 685   }
 686}
 687
 688
 689
 690#-- gets you list of class names the given objects class was derived from, slow
 691if (!function_exists("class_parents")) {
 692   function class_parents($obj) {
 693   
 694      #-- first get full list
 695      $all = get_declared_classes();
 696      $r = array();
 697      
 698      #-- filter out
 699      foreach ($all as $potential_parent) {
 700         if (is_subclass_of($obj, $potential_parent)) {
 701            $r[$potential_parent] = $potential_parent;
 702         }
 703      }
 704      return($r);
 705   }
 706}
 707
 708
 709#-- an alias
 710if (!function_exists("session_commit") && function_exists("session_write_close")) {
 711   function session_commit() {
 712      // simple
 713      session_write_close();
 714   }
 715}
 716
 717
 718#-- aliases
 719if (!function_exists("dns_check_record")) {
 720   function dns_check_record($host, $type=NULL) {
 721      // synonym to
 722      return checkdnsrr($host, $type);
 723   }
 724}
 725if (!function_exists("dns_get_mx")) {
 726   function dns_get_mx($host, $mx) {
 727      $args = func_get_args();
 728      // simple alias - except the optional, but referenced third parameter
 729      if ($args[2]) {
 730         $w = & $args[2];
 731      }
 732      else {
 733         $w = false;
 734      }
 735      return getmxrr($host, $mx, $w);
 736   }
 737}
 738
 739
 740#-- setrawcookie(),
 741#   can this be emulated 100% exactly?
 742if (!function_exists("setrawcookie")) {
 743   // we output everything directly as HTTP header(), PHP doesn't seem
 744   // to manage an internal cookie list anyhow
 745   function setrawcookie($name, $value=NULL, $expire=NULL, $path=NULL, $domain=NULL, $secure=0) {
 746      if (isset($value) && strpbrk($value, ",; \r\t\n\f\014\013")) {
 747         trigger_error("setrawcookie: value may not contain any of ',; \r\n' and some other control chars; thrown away", E_USER_WARNING);
 748      }
 749      else {
 750         $h = "Set-Cookie: $name=$value"
 751            . ($expire ? "; expires=" . gmstrftime("%a, %d-%b-%y %H:%M:%S %Z", $expire) : "")
 752            . ($path ? "; path=$path": "")
 753            . ($domain ? "; domain=$domain" : "")
 754            . ($secure ? "; secure" : "");
 755         header($h);
 756      }
 757   }
 758}
 759
 760
 761#-- write-at-once file access (counterpart to file_get_contents)
 762if (!function_exists("file_put_contents")) {
 763   function file_put_contents($filename, $data, $flags=0, $resource=NULL) {
 764
 765      #-- prepare
 766      $mode = ($flags & FILE_APPEND ? "a" : "w" ) ."b";
 767      $incl = $flags & FILE_USE_INCLUDE_PATH;
 768      $length = strlen($data);
 769
 770      #-- open for writing
 771      $f = fopen($filename, $mode, $incl);
 772      if ($f) {
 773         $written = fwrite($f, $data);
 774         fclose($f);
 775         
 776         #-- only report success, if completely saved
 777         return($length == $written);
 778      }
 779   }
 780}
 781
 782
 783#-- file-related constants
 784if (!defined("FILE_APPEND")) {
 785   define("FILE_USE_INCLUDE_PATH", 1);
 786   define("FILE_IGNORE_NEW_LINES", 2);
 787   define("FILE_SKIP_EMPTY_LINES", 4);
 788   define("FILE_APPEND", 8);
 789   define("FILE_NO_DEFAULT_CONTEXT", 16);
 790}
 791
 792
 793#-- more new constants for 5.0
 794if (!defined("E_STRICT")) {
 795   define("E_STRICT", 2048);  // _STRICT is a special case of _NOTICE (_DEBUG)
 796   # PHP_CONFIG_FILE_SCAN_DIR
 797}
 798
 799
 800#-- array count_recursive()
 801if (!defined("COUNT_RECURSIVE")) {
 802   define("COUNT_NORMAL", 0);       // count($array, 0);
 803   define("COUNT_RECURSIVE", 1);    // not supported
 804}
 805
 806
 807#-- we introduce a new function, because we cannot emulate the
 808#   newly introduced second parameter to count()
 809if (!function_exists("count_recursive")) {
 810   function count_recursive($array, $mode=1) {
 811      if (!$mode) {
 812         return(count($array));
 813      }
 814      else {
 815         $c = count($array);
 816         foreach ($array as $sub) {
 817            if (is_array($sub)) {
 818               $c += count_recursive($sub);
 819            }
 820         }
 821         return($c);
 822      }
 823   }
 824}
 825
 826
 827
 828
 829
 830
 831
 832#------------------------------------------------------------------ 4.3 ---
 833# money_format - unimpl?
 834# sha1, sha1_file - too much code to pack it into here; and this
 835#                   has already been implemented elsewhere, btw
 836
 837
 838#-- simplified file read-at-once function
 839if (!function_exists("file_get_contents")) {
 840   function file_get_contents($filename, $use_include_path=1) {
 841
 842      #-- open file, let fopen() report error
 843      $f = fopen($filename, "rb", $use_include_path);
 844      if (!$f) { return; }
 845
 846      #-- read max 2MB
 847      $content = fread($f, 1<<21);
 848      fclose($f);
 849      return($content);
 850   }
 851}
 852
 853
 854
 855#-- shell-like filename matching (* and ? globbing characters)
 856if (!function_exists("fnmatch")) {
 857
 858   #-- associated constants
 859   define("FNM_PATHNAME", 1<<0);  // no wildcard ever matches a "/"
 860   define("FNM_NOESCAPE", 1<<1);  // backslash can't escape meta chars
 861   define("FNM_PERIOD",   1<<2);  // leading dot must be given explicit
 862   define("FNM_LEADING_DIR", 1<<3);  // not in PHP
 863   define("FNM_CASEFOLD", 0x50);  // match case-insensitive
 864   define("FNM_EXTMATCH", 1<<5);  // not in PHP
 865   
 866   #-- implementation
 867   function fnmatch($pattern, $str, $flags=0x0000) {
 868      
 869      #-- 'hidden' files
 870      if ($flags & FNM_PERIOD) {
 871         if (($str[0] == ".") && ($pattern[0] != ".")) {
 872            return(false);    // abort early
 873         }
 874      }
 875
 876      #-- case-insensitivity
 877      $rxci = "";
 878      if ($flags & FNM_CASEFOLD) {
 879         $rxci = "i";
 880      }
 881      #-- handline of pathname separators (/)
 882      $wild = ".";
 883      if ($flags & FNM_PATHNAME) {
 884         $wild = "[^/".DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR."]";
 885      }
 886
 887      #-- check for cached regular expressions
 888      static $cmp = array();
 889      if (isset($cmp["$pattern+$flags"])) {
 890         $rx = $cmp["$pattern+$flags"];
 891      }
 892
 893      #-- convert filename globs into regex
 894      else {
 895         $rx = preg_quote($pattern);
 896         $rx = strtr($rx, array(
 897            "\\*"=>"$wild*?", "\\?"=>"$wild", "\\["=>"[", "\\]"=>"]",
 898         ));
 899         $rx = "{^" . $rx . "$}" . $rxci;
 900         
 901         #-- cache
 902         if (count($cmp) >= 50) {
 903            $cmp = array();   // free
 904         }
 905         $cmp["$pattern+$flags"] = $rx;
 906      }
 907      
 908      #-- compare
 909      return(preg_match($rx, $str));
 910   }
 911}
 912
 913
 914#-- file search and name matching (with shell patterns)
 915if (!function_exists("glob")) {
 916
 917   #-- introduced constants
 918   define("GLOB_MARK", 1<<0);
 919   define("GLOB_NOSORT", 1<<1);
 920   define("GLOB_NOCHECK", 1<<2);
 921   define("GLOB_NOESCAPE", 1<<3);
 922   define("GLOB_BRACE", 1<<4);
 923   define("GLOB_ONLYDIR", 1<<5);
 924   define("GLOB_NOCASE", 1<<6);
 925   define("GLOB_DOTS", 1<<7);
 926   // unlikely to work under Win(?), without replacing the explode() with
 927   // a preg_split() incorporating the native DIRECTORY_SEPARATOR as well
 928
 929   #-- implementation
 930   function glob($pattern, $flags=0x0000) {
 931      $ls = array();
 932      $rxci = ($flags & GLOB_NOCASE) ? "i" : "";
 933#echo "\n=> glob($pattern)...\n";
 934      
 935      #-- transform glob pattern into regular expression
 936      #   (similar to fnmatch() but still different enough to require a second func)
 937      if ($pattern) {
 938
 939         #-- look at each directory/fn spec part separately
 940         $parts2 = explode("/", $pattern);
 941         $pat = preg_quote($pattern);
 942         $pat = strtr($pat, array("\\*"=>".*?", "\\?"=>".?"));
 943         if ($flags ^ GLOB_NOESCAPE) {
 944            // uh, oh, ouuch - the above is unclean enough...
 945         }
 946         if ($flags ^ GLOB_BRACE) {
 947            $pat = preg_replace("/\{(.+?)\}/e", 'strtr("[$1]", ",", "")', $pat);
 948         }
 949         $parts = explode("/", $pat);
 950#echo "parts == ".implode(" // ", $parts) . "\n";
 951         $lasti = count($parts) - 1;
 952         $dn = "";
 953         foreach ($parts as $i=>$p) {
 954
 955            #-- basedir included (yet no pattern matching necessary)
 956            if (!strpos($p, "*?") && (strpos($p, ".?")===false)) {
 957               $dn .= $parts2[$i] . ($i!=$lasti ? "/" : "");
 958#echo "skip:$i, cause no pattern matching char found -> only a basedir spec\n";
 959               continue;
 960            }
 961            
 962            #-- start reading dir + match filenames against current pattern
 963            if ($dh = opendir($dn ?$dn:'.')) {
 964               $with_dot = ($p[1]==".") || ($flags & GLOB_DOTS);
 965#echo "part:$i:$p\n";
 966#echo "reading dir \"$dn\"\n";
 967               while ($fn = readdir($dh)) {
 968                  if (preg_match("\007^$p$\007$rxci", $fn)) {
 969
 970                     #-- skip over 'hidden' files
 971                     if (($fn[0] == ".") && !$with_dot) {
 972                        continue;
 973                     }
 974
 975                     #-- add filename only if last glob/pattern part
 976                     if ($i==$lasti) {
 977                        if (is_dir("$dn$fn")) {
 978                           if ($flags & GLOB_ONLYDIR) {
 979                              continue;
 980                           }
 981                           if ($flags & GLOB_MARK) {
 982                              $fn .= "/";
 983                           }
 984                        }
 985#echo "adding '$fn' for dn=$dn to list\n";
 986                        $ls[] = "$dn$fn";
 987                     }
 988
 989                     #-- initiate a subsearch, merge result list in
 990                     elseif (is_dir("$dn$fn")) {
 991                        // add reamaining search patterns to current basedir
 992                        $remaind = implode("/", array_slice($parts2, $i+1));
 993                        $ls = array_merge($ls, glob("$dn$fn/$remaind", $flags));
 994                     }
 995                  }
 996               }
 997               closedir($dh);
 998
 999               #-- prevent scanning a 2nd part/dir in same glob() instance:
1000               break;  
1001            }
1002
1003            #-- given dirname doesn't exist
1004            else {
1005               return($ls);
1006            }
1007
1008         }// foreach $parts
1009      }
1010
1011      #-- return result list
1012      if (!$ls && ($flags & GLOB_NOCHECK)) {
1013         $ls[] = $pattern;
1014      }
1015      if ($flags ^ GLOB_NOSORT) {
1016         sort($ls);
1017      }
1018#print_r($ls);
1019#echo "<=\n";
1020      return($ls);
1021   }
1022} //@FIX: fully comment, remove debugging code (- as soon as it works ;)
1023
1024
1025#-- redundant alias for isset()
1026if (!function_exists("array_key_exists")) {
1027   function array_key_exists($key, $search) {
1028      return isset($search[$key]);
1029   }
1030}
1031
1032
1033#-- who could need that?
1034if (!function_exists("array_intersect_assoc")) {
1035   function array_intersect_assoc( /*array, array, array...*/ ) {
1036
1037      #-- parameters, prepare
1038      $in = func_get_args();
1039      $cmax = count($in);
1040      $whatsleftover = array();
1041      
1042      #-- walk through each array pair
1043      #   (take first as checklist)
1044      foreach ($in[0] as $i => $v) {
1045         for ($c = 1; $c < $cmax; $c++) {
1046            #-- remove entry, as soon as it isn't present
1047            #   in one of the other arrays
1048            if (!isset($in[$c][$i]) || (@$in[$c][$i] !== $v)) {
1049               continue 2;
1050            }
1051         }
1052         #-- it was found in all other arrays
1053         $whatsleftover[$i] = $v;
1054      }
1055      return $whatsleftover;
1056   }
1057}
1058
1059
1060#-- the opposite of the above
1061if (!function_exists("array_diff_assoc")) {
1062   function array_diff_assoc( /*array, array, array...*/ ) {
1063
1064      #-- params
1065      $in = func_get_args();
1066      $diff = array();
1067      
1068      #-- compare each array with primary/first
1069      foreach ($in[0] as $i=>$v) {
1070         for ($c=1; $c<count($in); $c++) {
1071            #-- skip as soon as it matches with entry in another array
1072            if (isset($in[$c][$i]) && ($in[$c][$i] == $v)) {
1073               continue 2;
1074            }
1075         }
1076         #-- else
1077         $diff[$i] = $v;
1078      }
1079      return $diff;
1080   }
1081}
1082
1083
1084#-- opposite of htmlentities
1085if (!function_exists("html_entity_decode")) {
1086   function html_entity_decode($string, $quote_style=ENT_COMPAT, $charset="ISO-8859-1") {
1087      //@FIX: we fall short on anything other than Latin-1
1088      $y = array_flip(get_html_translation_table(HTML_ENTITIES, $quote_style));
1089      return strtr($string, $y);
1090   }
1091}
1092
1093
1094#-- extracts single words from a string
1095if (!function_exists("str_word_count")) {
1096   function str_word_count($string, $result=0) {
1097   
1098      #-- let someone else do the work
1099      preg_match_all('/([\w](?:[-\'\w]?[\w]+)*)/', $string, $uu);
1100
1101      #-- return full word list
1102      if ($result == 1) {
1103         return($uu[1]);
1104      }
1105      
1106      #-- array() of $pos=>$word entries
1107      elseif ($result >= 2) {
1108         $r = array();
1109         $l = 0;
1110         foreach ($uu[1] as $word) {
1111            $l = strpos($string, $word, $l);
1112            $r[$l] = $word;
1113            $l += strlen($word);  // speed up next search
1114         }
1115         return($r);
1116      }
1117
1118      #-- only count
1119      else {
1120         return(count($uu[1]));
1121      }
1122   }
1123}
1124
1125
1126#-- creates a permutation of the given strings characters
1127#   (let's hope the random number generator was alread initialized)
1128if (!function_exists("str_shuffle")) {
1129   function str_shuffle($str) {
1130      $r = "";
1131
1132      #-- cut string down with every iteration
1133      while (strlen($str)) {
1134         $n = strlen($str) - 1;
1135         if ($n) {
1136            $n = rand(0, $n);   // glibcs` rand is ok since 2.1 at least
1137         }
1138         
1139         #-- cut out elected char, add to result string
1140         $r .= $str{$n};
1141         $str = substr($str, 0, $n) . substr($str, $n + 1);
1142      }
1143      return($r);
1144   }
1145}
1146
1147
1148#-- simple shorthands
1149if (!function_exists("get_include_path")) {
1150   function get_include_path() {
1151      return(get_cfg_var("include_path"));
1152   }
1153   function set_include_path($new) {
1154      return ini_set("include_path", $new);
1155   }
1156   function restore_include_path() {
1157      ini_restore("include_path");
1158   }
1159}
1160
1161
1162#-- constants for 4.3
1163if (!defined("PATH_SEPARATOR")) {
1164   define("PATH_SEPARATOR", ((DIRECTORY_SEPARATOR=='\\') ? ';' :':'));
1165   define("PHP_SHLIB_SUFFIX", ((DIRECTORY_SEPARATOR=='\\') ? 'dll' :'so'));
1166}
1167if (!defined("PHP_SAPI")) {
1168   define("PHP_SAPI", php_sapi_name());
1169}
1170
1171
1172#-- not identical to what PHP reports (it seems to `which` for itself)
1173if (!defined("PHP_PREFIX") && isset($_ENV["_"])) { 
1174   define("PHP_PREFIX", substr($_ENV["_"], 0, strpos($_ENV["_"], "bin/")));
1175}
1176
1177
1178
1179
1180
1181
1182#------------------------------------------------------------------ 4.2 ---
1183# almost complete!?
1184
1185
1186#-- shy away from this one - it was broken in all real PHP4.2 versions, and
1187#   this function emulation script won't change that
1188if (!function_exists("str_rot13")) {
1189   function str_rot13($str) {
1190      static $from = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
1191      static $to = "NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm";
1192      return strtr($str, $from, $to);
1193   }
1194}
1195
1196
1197#-- well, if you need it
1198if (!function_exists("array_change_key_case")) {
1199   
1200   #-- introduced constants
1201   define("CASE_LOWER", 0);
1202   define("CASE_UPPER", 1);
1203   
1204   #-- implementation
1205   function array_change_key_case($array, $case=CASE_LOWER) {
1206   
1207      #-- loop through
1208      foreach ($array as $i=>$v) {
1209         #-- do anything for strings only
1210         if (is_string($i)) {
1211            unset($array[$i]);
1212            $i = ($case==CASE_LOWER) ? strtolower($i) : strtoupper($i);
1213            $array[$i] = $v;
1214         }
1215         // non-recursive      
1216      }
1217      return($array);
1218   }
1219}
1220
1221
1222#-- create fixed-length array made up of $value data
1223if (!function_exists("array_fill")) {
1224   function array_fill($start_index, $num, $value) {
1225
1226      #-- params
1227      $r = array();
1228      $i = $start_index;
1229      $end = $num + $start_index;
1230      
1231      #-- append
1232      for (; $i < $end; $i++)
1233      {
1234         $r[$i] = $value;
1235      }
1236      return($r);
1237   }
1238}
1239
1240
1241#-- split an array into evenly sized parts
1242if (!function_exists("array_chunk")) {
1243   function array_chunk($input, $size, $preserve_keys=false) {
1244   
1245      #-- array for chunked output
1246      $r = array();
1247      $n = -1;  // chunk index
1248      
1249      #-- enum input array blocks
1250      foreach ($input as $i=>$v) {
1251      
1252         #-- new chunk
1253         if (($n < 0) || (count($r[$n]) == $size)) {
1254            $n++;
1255            $r[$n] = array();
1256         }
1257         
1258         #-- add input value into current [$n] chunk
1259         if ($preserve_keys) {
1260            $r[$n][$i] = $v;
1261         }
1262         else {
1263            $r[$n][] = $v;
1264         }
1265      }
1266      return($r);
1267   }
1268}
1269
1270
1271#-- convenience wrapper
1272if (!function_exists("md5_file")) {
1273   function md5_file($filename, $raw_output=false) {
1274
1275      #-- read file, apply hash function
1276      $data = file_get_contents($filename, "rb");
1277      $r = md5($data);
1278      $data = NULL;
1279         
1280      #-- transform? and return
1281      if ($raw_output) {
1282         $r = pack("H*", $r);
1283      }
1284      return $r;
1285   }
1286}
1287
1288
1289#-- object type checking
1290if (!function_exists("is_a")) {
1291   function is_a($obj, $classname) {
1292   
1293      #-- lowercase everything for comparison
1294      $classnaqme = strtolower($classname);
1295      $obj_class =  strtolower(get_class($obj));
1296      
1297      #-- two possible checks
1298      return ($obj_class == $classname) or is_subclass_of($obj, $classname);
1299   }
1300}
1301
1302
1303#-- floating point modulo
1304if (!function_exists("fmod")) {
1305   function fmod($x, $y) {
1306      $r = $x / $y;
1307      $r -= (int)$r;
1308      $r *= $y;
1309      return($r);
1310   }
1311}
1312
1313
1314#-- makes float variable from string
1315if (!function_exists("floatval")) {
1316   function floatval($str) {
1317      $str = ltrim($str);
1318      return (float)$str;
1319   }
1320}
1321
1322
1323#-- floats
1324if (!function_exists("is_infinite")) {
1325
1326   #-- constants as-is
1327   define("NAN", "NAN");
1328   define("INF", "INF");   // there is also "-INF"
1329   
1330   #-- simple checks
1331   function is_infinite($f) {
1332      $s = (string)$f;
1333      return(  ($s=="INF") || ($s=="-INF")  );
1334   }
1335   function is_nan($f) {
1336      $s = (string)$f;
1337      return(  $s=="NAN"  );
1338   }
1339   function is_finite($f) {
1340      $s = (string)$f;
1341      return(  !strpos($s, "N")  );
1342   }
1343}
1344
1345
1346#-- throws value-instantiation PHP-code for given variable
1347#   (a bit different from the standard, was intentional for its orig use)
1348if (!function_exists("var_export")) {
1349   function var_export($var, $return=false, $indent="", $output="") {
1350
1351      #-- output as in-class variable definitions
1352      if (is_object($var)) {
1353         $output = "class " . get_class($var) . " {\n";
1354         foreach (((array)$var) as $id=>$var) {
1355            $output .= "  var \$$id = " . var_export($var, true) . ";\n";
1356         }
1357         $output .= "}";
1358      }
1359      
1360      #-- array constructor
1361      elseif (is_array($var)) {
1362         foreach ($var as $id=>$next) {
1363            if ($output) $output .= ",\n";
1364                    else $output = "array(\n";
1365            $output .= $indent . '  '
1366                    . (is_numeric($id) ? $id : '"'.addslashes($id).'"')
1367                    . ' => ' . var_export($next, true, "$indent  ");
1368         }
1369         if (empty($output)) $output = "array(";
1370         $output .= "\n{$indent})";
1371       #if ($indent == "") $output .= ";";
1372      }
1373      
1374      #-- literals
1375      elseif (is_numeric($var)) {
1376         $output = "$var";
1377      }
1378      elseif (is_bool($var)) {
1379         $output = $var ? "true" : "false";
1380      }
1381      else {
1382         $output = "'" . preg_replace("/([\\\\\'])/", '\\\\$1', $var) . "'";
1383      }
1384
1385      #-- done
1386      if ($return) {
1387         return($output);
1388      }
1389      else {
1390         print($output);
1391      }
1392   }
1393}
1394
1395
1396#-- strcmp() variant that respects locale setting,
1397#   existed since PHP 4.0.5, but under Win32 first since 4.3.2
1398if (!function_exists("strcoll")) {
1399   function strcoll($str1, $str2) {
1400      return strcmp($str1, $str2);
1401   }
1402}
1403
1404
1405
1406
1407
1408#------------------------------------------------------------------ 4.1 ---
1409# nl_langinfo - unimpl?
1410# getmygid
1411# version_compare
1412#
1413# See also "ext/math41.php" for some more (rarely used mathematical funcs).
1414
1415
1416
1417
1418#-- aliases (an earlier fallen attempt to unify PHP function names)
1419if (!function_exists("diskfreespace")) {
1420   function diskfreespace() {
1421      return disk_free_sapce();
1422   }
1423   function disktotalspace() {
1424      return disk_total_sapce();
1425   }
1426}
1427
1428
1429#-- variable count of arguments (in array list) printf variant
1430if (!function_exists("vprintf")) {
1431   function vprintf($format, $args=NULL) {
1432      call_user_func_array("fprintf", get_func_args());
1433   }
1434}
1435
1436
1437#-- same as above, but doesn't output directly and returns formatted string
1438if (!function_exists("vsprintf")) {
1439   function vsprintf($format, $args=NULL) {
1440      $args = array_merge(array($format), array_values((array)$args));
1441      return call_user_func_array("sprintf", $args);
1442   }
1443}
1444
1445
1446#-- can be used to simulate a register_globals=on environment
1447if (!function_exists("import_request_variables")) {
1448   function import_request_variables($types="GPC", $pfix="") {
1449      
1450      #-- associate abbreviations to global var names
1451      $alias = array(
1452         "G" => "_GET",
1453         "P" => "_POST",
1454         "C" => "_COOKIE",
1455         "S" => "_SERVER",   // non-standard
1456         "E" => "_ENV",      // non-standard
1457      );
1458      #-- alias long names (PHP < 4.0.6)
1459      if (!isset($_REQUEST)) {
1460         $_GET = & $HTTP_GET_VARS;
1461         $_POST = & $HTTP_POST_VARS;
1462         $_COOKIE = & $HTTP_COOKIE_VARS;
1463      }
1464      
1465      #-- copy
1466      for ($i=0; $i<strlen($types); $i++) {
1467         if ($FROM = $alias[strtoupper($c)]) {
1468            foreach ($$FROM as $key=>$val) {
1469               if (!isset($GLOBALS[$pfix.$key])) {
1470                  $GLOBALS[$pfix . $key] = $val;
1471               }
1472            }
1473         }
1474      }
1475      // done
1476   }
1477}
1478
1479
1480// a few mathematical functions follow
1481// (wether we should really emulate them is a different question)
1482
1483#-- me has no idea what this function means
1484if (!function_exists("hypot")) {
1485   function hypot($num1, $num2) {
1486      return sqrt($num1*$num1 + $num2*$num2);  // as per PHP manual ;)
1487   }
1488}
1489
1490#-- more accurate logarithm func, but we cannot simulate it
1491#   (too much work, too slow in PHP)
1492if (!function_exists("log1p")) {
1493   function log1p($x) {
1494      return(  log(1+$x)  );
1495   }
1496   #-- same story for:
1497   function expm1($x) {
1498      return(  exp($x)-1  );
1499   }
1500}
1501
1502#-- as per PHP manual
1503if (!function_exists("sinh")) {
1504   function sinh($f) {
1505      return(  (exp($f) - exp(-$f)) / 2  );
1506   }
1507   function cosh($f) {
1508      return(  (exp($f) + exp(-$f)) / 2  );
1509   }
1510   function tanh($f) {
1511      return(  sinh($f) / cosh($f)  );   // ok, that one makes sense again :)
1512   }
1513}
1514
1515#-- these look a bit more complicated
1516if (!function_exists("asinh")) {
1517   function asinh($x) {
1518      return(  log($x + sqrt($x*$x+1))  );
1519   }
1520   function acosh($x) {
1521      return(  log($x + sqrt($x*$x-1))  );
1522   }
1523   function atanh($x) {
1524      return(  log1p( 2*$x / (1-$x) ) / 2  );
1525   }
1526}
1527
1528
1529#-- HMAC from RFC2104, but see also PHP_Compat and Crypt_HMAC
1530if (!function_exists("mhash")) {
1531
1532   #-- constants
1533   define("MHASH_CRC32", 0);
1534   define("MHASH_MD5", 1);       // RFC1321
1535   define("MHASH_SHA1", 2);      // RFC3174
1536   define("MHASH_TIGER", 7);
1537   define("MHASH_MD4", 16);      // RFC1320
1538   define("MHASH_SHA256", 17);
1539   define("MHASH_ADLER32", 18);
1540   
1541   #-- implementation
1542   function mhash($hashtype, $text, $key) {
1543   
1544      #-- hash function
1545      static $hash_funcs = array(
1546          MHASH_CRC32 => "crc32",   // needs dechex()ing here
1547          MHASH_MD5 => "md5",
1548          MHASH_SHA1 => "sha1",
1549      );
1550      if (!($func = $hash_funcs[$hashtype]) || !function_exists($func)) {
1551         return trigger_error("mhash: cannot use hash algorithm #$hashtype/$func", E_USER_ERROR);
1552      }
1553      if (!$key) {
1554         trigger_error("mhash: called without key", E_USER_WARNING);
1555      }
1556      
1557      #-- params
1558      $bsize = 64;   // fixed size
1559
1560      #-- pad key
1561      if (strlen($key) > $bsize) {  // hash key, when it's too long
1562         $key = $func($key); 
1563         $key = pack("H*", $key);   // binarify
1564      }
1565      $key = str_pad($key, $bsize, "\0");  // fill up with NULs (1)
1566      
1567      #-- prepare inner and outer padding stream
1568      $ipad = str_pad("", $bsize, "6");   // %36
1569      $opad = str_pad("", $bsize, "\\");  // %5C
1570      
1571      #-- call hash func    // php can XOR strings for us
1572      $dgst = pack("H*",  $func(  ($key ^ $ipad)  .  $text  ));  // (2,3,4)
1573      $dgst = pack("H*",  $func(  ($key ^ $opad)  .  $dgst  ));  // (5,6,7)
1574      return($dgst);
1575   }
1576}
1577
1578
1579
1580#-- other stuff
1581/*
1582  removed funcs??
1583      [18] => leak
1584*/
1585
1586
1587
1588#-- pre-4.1 -- end
1589// no need to implement anything below that, because such old versions
1590// will be incompatbile anyhow (- none of the newer superglobals known),
1591// but see also "ext/old"
1592
1593
1594?>