Back to index

awl  0.53
AWLUtilities.php
Go to the documentation of this file.
00001 <?php
00013 if ( !function_exists('dbg_error_log') ) {
00027   function dbg_error_log() {
00028     global $c;
00029     $args = func_get_args();
00030     $type = "DBG";
00031     $component = array_shift($args);
00032     if ( substr( $component, 0, 3) == "LOG" ) {
00033       // Special escape case for stuff that always gets logged.
00034       $type = 'LOG';
00035       $component = substr($component,4);
00036     }
00037     else if ( $component == "ERROR" ) {
00038       $type = "***";
00039     }
00040     else if ( isset($c->dbg["ALL"]) ) {
00041       $type = "ALL";
00042     }
00043     else if ( !isset($c->dbg[strtolower($component)]) ) return;
00044 
00045     $argc = func_num_args();
00046     if ( 2 <= $argc ) {
00047       $format = array_shift($args);
00048     }
00049     else {
00050       $format = "%s";
00051     }
00052     @error_log( $c->sysabbr.": $type: $component:". vsprintf( $format, $args ) );
00053   }
00054 }
00055 
00056 
00057 if ( !function_exists('fatal') ) {
00058   function fatal() {
00059     global $c;
00060     $args = func_get_args();
00061     $argc = func_num_args();
00062     if ( 2 <= $argc ) {
00063       $format = array_shift($args);
00064     }
00065     else {
00066       $format = "%s";
00067     }
00068     @error_log( $c->sysabbr.": FATAL: $component:". vsprintf( $format, $args ) );
00069     
00070     @error_log( "================= Stack Trace ===================" );
00071        
00072        $trace = array_reverse(debug_backtrace());
00073     array_pop($trace);
00074     foreach( $trace AS $k => $v ) {
00075          @error_log( sprintf(" ===>  %s[%d] calls %s%s%s()",
00076                       $v['file'],
00077                       $v['line'],
00078                       (isset($v['class'])?$v['class']:''),
00079                       (isset($v['type'])?$v['type']:''),
00080                       (isset($v['function'])?$v['function']:'')
00081              ));
00082     }
00083     echo "Fatal Error";
00084     exit();
00085   }
00086 }
00087 
00088 
00089 if ( !function_exists('trace_bug') ) {
00093   function trace_bug() {
00094     global $c;
00095     $args = func_get_args();
00096     $argc = func_num_args();
00097     if ( 2 <= $argc ) {
00098       $format = array_shift($args);
00099     }
00100     else {
00101       $format = "%s";
00102     }
00103     @error_log( $c->sysabbr.": BUG: $component:". vsprintf( $format, $args ) );
00104     
00105     @error_log( "================= Stack Trace ===================" );
00106        
00107        $trace = array_reverse(debug_backtrace());
00108     array_pop($trace);
00109     foreach( $trace AS $k => $v ) {
00110          @error_log( sprintf(" ===>  %s[%d] calls %s%s%s()",
00111                       $v['file'],
00112                       $v['line'],
00113                       (isset($v['class'])?$v['class']:''),
00114                       (isset($v['type'])?$v['type']:''),
00115                       (isset($v['function'])?$v['function']:'')
00116              ));
00117     }
00118   }
00119 }
00120 
00121 
00122 if ( !function_exists('apache_request_headers') ) {
00127   eval('
00128     function apache_request_headers() {
00129         foreach($_SERVER as $key=>$value) {
00130             if (substr($key,0,5)=="HTTP_") {
00131                 $key=str_replace(" ","-",ucwords(strtolower(str_replace("_"," ",substr($key,5)))));
00132                 $out[$key]=$value;
00133             }
00134         }
00135         return $out;
00136     }
00137   ');
00138 }
00139 
00140 
00141 
00142 if ( !function_exists('dbg_log_array') ) {
00151   function dbg_log_array( $component, $name, $arr, $recursive = false ) {
00152     if ( !isset($arr) || (gettype($arr) != 'array' && gettype($arr) != 'object') ) {
00153       dbg_error_log( $component, "%s: array is not set, or is not an array!", $name);
00154       return;
00155     }
00156     foreach ($arr as $key => $value) {
00157       dbg_error_log( $component, "%s: >>%s<< = >>%s<<", $name, $key,
00158                       (gettype($value) == 'array' || gettype($value) == 'object' ? gettype($value) : $value) );
00159       if ( $recursive && (gettype($value) == 'array' || (gettype($value) == 'object' && "$key" != 'self' && "$key" != 'parent') ) ) {
00160         dbg_log_array( $component, "$name"."[$key]", $value, $recursive );
00161       }
00162     }
00163   }
00164 }
00165 
00166 
00167 
00168 if ( !function_exists("session_simple_md5") ) {
00175   function session_simple_md5( $instr ) {
00176     global $c;
00177     if ( isset($c->dbg['password']) ) dbg_error_log( "Login", "Making plain MD5: instr=$instr, md5($instr)=".md5($instr) );
00178     return ( '*MD5*'. md5($instr) );
00179   }
00180 }
00181 
00182 
00183 
00184 if ( !function_exists("session_salted_md5") ) {
00194   function session_salted_md5( $instr, $salt = "" ) {
00195     if ( $salt == "" ) $salt = substr( md5(rand(100000,999999)), 2, 8);
00196     global $c;
00197     if ( isset($c->dbg['password']) ) dbg_error_log( "Login", "Making salted MD5: salt=$salt, instr=$instr, md5($salt$instr)=".md5($salt . $instr) );
00198     return ( sprintf("*%s*%s", $salt, md5($salt . $instr) ) );
00199   }
00200 }
00201 
00202 
00203 
00204 if ( !function_exists("session_salted_sha1") ) {
00218   function session_salted_sha1( $instr, $salt = "" ) {
00219     if ( $salt == "" ) $salt = substr( str_replace('*','',base64_encode(sha1(rand(100000,9999999),true))), 2, 9);
00220     global $c;
00221     if ( isset($c->dbg['password']) ) dbg_error_log( "Login", "Making salted SHA1: salt=$salt, instr=$instr, encoded($instr$salt)=".base64_encode(sha1($instr . $salt, true).$salt) );
00222     return ( sprintf("*%s*{SSHA}%s", $salt, base64_encode(sha1($instr.$salt, true) . $salt ) ) );
00223   }
00224 }
00225 
00226 
00227 if ( !function_exists("session_validate_password") ) {
00234   function session_validate_password( $they_sent, $we_have ) {
00235     if ( preg_match('/^\*\*.+$/', $we_have ) ) {
00236       //  The "forced" style of "**plaintext" to allow easier admin setting
00237       return ( "**$they_sent" == $we_have );
00238     }
00239 
00240     if ( preg_match('/^\*(.+)\*{[A-Z]+}.+$/', $we_have, $regs ) ) {
00241       if ( function_exists("session_salted_sha1") ) {
00242         // A nicely salted sha1sum like "*<salt>*{SSHA}<salted_sha1>"
00243         $salt = $regs[1];
00244         $sha1_sent = session_salted_sha1( $they_sent, $salt ) ;
00245         return ( $sha1_sent == $we_have );
00246       }
00247       else {
00248         dbg_error_log( "ERROR", "Password is salted SHA-1 but you are using PHP4!" );
00249         echo <<<EOERRMSG
00250 <html>
00251 <head>
00252 <title>Salted SHA1 Password format not supported with PHP4</title>
00253 </head>
00254 <body>
00255 <h1>Salted SHA1 Password format not supported with PHP4</h1>
00256 <p>At some point you have used PHP5 to set the password for this user and now you are
00257    using PHP4.  You will need to assign a new password to this user using PHP4, or ensure
00258    you use PHP5 everywhere (recommended).</p>
00259 <p>AWL has now switched to using salted SHA-1 passwords by preference in a format
00260    compatible with OpenLDAP.</p>
00261 </body>
00262 </html>
00263 EOERRMSG;
00264         exit;
00265       }
00266     }
00267 
00268     if ( preg_match('/^\*MD5\*.+$/', $we_have, $regs ) ) {
00269       // A crappy unsalted md5sum like "*MD5*<md5>"
00270       $md5_sent = session_simple_md5( $they_sent ) ;
00271       return ( $md5_sent == $we_have );
00272     }
00273     else if ( preg_match('/^\*(.+)\*.+$/', $we_have, $regs ) ) {
00274       // A nicely salted md5sum like "*<salt>*<salted_md5>"
00275       $salt = $regs[1];
00276       $md5_sent = session_salted_md5( $they_sent, $salt ) ;
00277       return ( $md5_sent == $we_have );
00278     }
00279 
00280     // Anything else is bad
00281     return false;
00282 
00283   }
00284 }
00285 
00286 
00287 
00288 if ( !function_exists("replace_uri_params") ) {
00296   function replace_uri_params( $uri, $replacements ) {
00297     $replaced = $uri;
00298     foreach( $replacements AS $param => $new_value ) {
00299       $rxp = preg_replace( '/([\[\]])/', '\\\\$1', $param );  // Some parameters may be arrays.
00300       $regex = "/([&?])($rxp)=([^&]+)/";
00301       dbg_error_log("core", "Looking for [%s] to replace with [%s] regex is %s and searching [%s]", $param, $new_value, $regex, $replaced );
00302       if ( preg_match( $regex, $replaced ) )
00303         $replaced = preg_replace( $regex, "\$1$param=$new_value", $replaced);
00304       else
00305         $replaced .= "&$param=$new_value";
00306     }
00307     if ( ! preg_match( '/\?/', $replaced  ) ) {
00308       $replaced = preg_replace("/&(.+)$/", "?\$1", $replaced);
00309     }
00310     $replaced = str_replace("&amp;", "--AmPeRsAnD--", $replaced);
00311     $replaced = str_replace("&", "&amp;", $replaced);
00312     $replaced = str_replace("--AmPeRsAnD--", "&amp;", $replaced);
00313     dbg_error_log("core", "URI <<$uri>> morphed to <<$replaced>>");
00314     return $replaced;
00315   }
00316 }
00317 
00318 
00319 if ( !function_exists("uuid") ) {
00349   function uuid() {
00350 
00351     // The field names refer to RFC 4122 section 4.1.2
00352 
00353     return sprintf('%04x%04x-%04x-%03x4-%04x-%04x%04x%04x',
00354         mt_rand(0, 65535), mt_rand(0, 65535), // 32 bits for "time_low"
00355         mt_rand(0, 65535), // 16 bits for "time_mid"
00356         mt_rand(0, 4095),  // 12 bits before the 0100 of (version) 4 for "time_hi_and_version"
00357         bindec(substr_replace(sprintf('%016b', mt_rand(0, 65535)), '01', 6, 2)),
00358             // 8 bits, the last two of which (positions 6 and 7) are 01, for "clk_seq_hi_res"
00359             // (hence, the 2nd hex digit after the 3rd hyphen can only be 1, 5, 9 or d)
00360             // 8 bits for "clk_seq_low"
00361         mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535) // 48 bits for "node"
00362     );
00363   }
00364 }
00365 
00366 if ( !function_exists("translate") ) {
00367   require("Translation.php");
00368 }
00369 
00370  if ( !function_exists("clone") && version_compare(phpversion(), '5.0') < 0) {
00376   eval( 'function clone($object) { return $object; }' );
00377 }
00378 
00379 if ( !function_exists("quoted_printable_encode") ) {
00385   function quoted_printable_encode($string) {
00386     return preg_replace('/[^\r\n]{73}[^=\r\n]{2}/', "$0=\r\n", str_replace("%","=",str_replace("%20"," ",rawurlencode($string))));
00387   }
00388 }
00389 
00390 
00391 if ( !function_exists("check_by_regex") ) {
00397   function check_by_regex( $val, $regex ) {
00398     if ( is_null($val) ) return null;
00399     switch( $regex ) {
00400       case 'int':     $regex = '#^\d+$#';     break;
00401     }
00402     if ( is_array($val) ) {
00403       foreach( $val AS $k => $v ) {
00404         $val[$k] = check_by_regex($v,$regex);
00405       }
00406     }
00407     else if ( ! is_object($val) ) {
00408       if ( preg_match( $regex, $val, $matches) ) {
00409         $val = $matches[0];
00410       }
00411       else {
00412         $val = '';
00413       }
00414     }
00415     return $val;
00416   }
00417 }
00418 
00419 
00420 if ( !function_exists("param_to_global") ) {
00431   function param_to_global( ) {
00432     $args = func_get_args();
00433 
00434     $varname = array_shift($args);
00435     $GLOBALS[$varname] = null;
00436 
00437     $match_regex = null;
00438     $argc = func_num_args();
00439     if ( $argc > 1 ) {
00440       $match_regex = array_shift($args);
00441     }
00442 
00443     $args[] = $varname;
00444     foreach( $args AS $k => $name ) {
00445       if ( isset($_POST[$name]) ) {
00446         $result = $_POST[$name];
00447         break;
00448       }
00449       else if ( isset($_GET[$name]) ) {
00450         $result = $_GET[$name];
00451         break;
00452       }
00453     }
00454     if ( !isset($result) ) return null;
00455 
00456     if ( isset($match_regex) ) {
00457       $result = check_by_regex( $result, $match_regex );
00458     }
00459 
00460     $GLOBALS[$varname] = $result;
00461     return $result;
00462   }
00463 }
00464 
00465 
00466 if ( !function_exists("get_fields") ) {
00470   $_AWL_field_cache = array();
00471   
00477   function get_fields( $tablename ) {
00478     global $_AWL_field_cache;
00479 
00480     if ( !isset($_AWL_field_cache[$tablename]) ) {
00481       dbg_error_log( "core", ":get_fields: Loading fields for table '$tablename'" );
00482       $qry = new AwlQuery();
00483       $db = $qry->GetConnection();
00484       $qry->SetSQL($db->GetFields($tablename));
00485       $qry->Exec("core");
00486       $fields = array();
00487       while( $row = $qry->Fetch() ) {
00488         $fields[$row->fieldname] = $row->typename . ($row->precision >= 0 ? sprintf('(%d)',$row->precision) : '');
00489       }
00490       $_AWL_field_cache[$tablename] = $fields;
00491     }
00492     return $_AWL_field_cache[$tablename];
00493   }
00494 }
00495 
00496 
00497 if ( !function_exists("force_utf8") ) {
00498   function define_byte_mappings() {
00499     global $byte_map, $nibble_good_chars;
00500 
00501     # Needed for using Grant McLean's byte mappings code
00502     $ascii_char = '[\x00-\x7F]';
00503     $cont_byte  = '[\x80-\xBF]';
00504 
00505     $utf8_2     = '[\xC0-\xDF]' . $cont_byte;
00506     $utf8_3     = '[\xE0-\xEF]' . $cont_byte . '{2}';
00507     $utf8_4     = '[\xF0-\xF7]' . $cont_byte . '{3}';
00508     $utf8_5     = '[\xF8-\xFB]' . $cont_byte . '{4}';
00509 
00510     $nibble_good_chars = "/^($ascii_char+|$utf8_2|$utf8_3|$utf8_4|$utf8_5)(.*)$/s";
00511 
00512     # From http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT
00513     $byte_map = array(
00514         "\x80" => "\xE2\x82\xAC",  # EURO SIGN
00515         "\x82" => "\xE2\x80\x9A",  # SINGLE LOW-9 QUOTATION MARK
00516         "\x83" => "\xC6\x92",      # LATIN SMALL LETTER F WITH HOOK
00517         "\x84" => "\xE2\x80\x9E",  # DOUBLE LOW-9 QUOTATION MARK
00518         "\x85" => "\xE2\x80\xA6",  # HORIZONTAL ELLIPSIS
00519         "\x86" => "\xE2\x80\xA0",  # DAGGER
00520         "\x87" => "\xE2\x80\xA1",  # DOUBLE DAGGER
00521         "\x88" => "\xCB\x86",      # MODIFIER LETTER CIRCUMFLEX ACCENT
00522         "\x89" => "\xE2\x80\xB0",  # PER MILLE SIGN
00523         "\x8A" => "\xC5\xA0",      # LATIN CAPITAL LETTER S WITH CARON
00524         "\x8B" => "\xE2\x80\xB9",  # SINGLE LEFT-POINTING ANGLE QUOTATION MARK
00525         "\x8C" => "\xC5\x92",      # LATIN CAPITAL LIGATURE OE
00526         "\x8E" => "\xC5\xBD",      # LATIN CAPITAL LETTER Z WITH CARON
00527         "\x91" => "\xE2\x80\x98",  # LEFT SINGLE QUOTATION MARK
00528         "\x92" => "\xE2\x80\x99",  # RIGHT SINGLE QUOTATION MARK
00529         "\x93" => "\xE2\x80\x9C",  # LEFT DOUBLE QUOTATION MARK
00530         "\x94" => "\xE2\x80\x9D",  # RIGHT DOUBLE QUOTATION MARK
00531         "\x95" => "\xE2\x80\xA2",  # BULLET
00532         "\x96" => "\xE2\x80\x93",  # EN DASH
00533         "\x97" => "\xE2\x80\x94",  # EM DASH
00534         "\x98" => "\xCB\x9C",      # SMALL TILDE
00535         "\x99" => "\xE2\x84\xA2",  # TRADE MARK SIGN
00536         "\x9A" => "\xC5\xA1",      # LATIN SMALL LETTER S WITH CARON
00537         "\x9B" => "\xE2\x80\xBA",  # SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
00538         "\x9C" => "\xC5\x93",      # LATIN SMALL LIGATURE OE
00539         "\x9E" => "\xC5\xBE",      # LATIN SMALL LETTER Z WITH CARON
00540         "\x9F" => "\xC5\xB8",      # LATIN CAPITAL LETTER Y WITH DIAERESIS
00541     );
00542 
00543     for( $i=160; $i < 256; $i++ ) {
00544       $ch = chr($i);
00545       $byte_map[$ch] = iconv('ISO-8859-1', 'UTF-8', $ch);
00546     }
00547   }
00548   define_byte_mappings();
00549 
00550   function force_utf8( $input ) {
00551     global $byte_map, $nibble_good_chars;
00552 
00553     $output = '';
00554     $char   = '';
00555     $rest   = '';
00556     while( $input != '' ) {
00557       if ( preg_match( $nibble_good_chars, $input, $matches ) ) {
00558         $output .= $matches[1];
00559         $rest = $matches[2];
00560       }
00561       else {
00562         preg_match( '/^(.)(.*)$/s', $input, $matches );
00563         $char = $matches[1];
00564         $rest = $matches[2];
00565         if ( isset($byte_map[$char]) ) {
00566           $output .= $byte_map[$char];
00567         }
00568         else {
00569           # Must be valid UTF8 already
00570           $output .= $char;
00571         }
00572       }
00573       $input = $rest;
00574     }
00575     return $output;
00576   }
00577 
00578 }
00579 
00580 
00584 function olson_from_tzstring( $tzstring ) {
00585   global $c;
00586   
00587   if ( function_exists('timezone_identifiers_list') && in_array($tzstring,timezone_identifiers_list()) ) return $tzstring;
00588   if ( preg_match( '{((Antarctica|America|Africa|Atlantic|Asia|Australia|Indian|Europe|Pacific)/(([^/]+)/)?[^/]+)$}', $tzstring, $matches ) ) {
00589 //    dbg_error_log( 'INFO', 'Found timezone "%s" from string "%s"', $matches[1], $tzstring );
00590     return $matches[1];
00591   }
00592   switch( $tzstring ) {
00593     case 'New Zealand Standard Time': case 'New Zealand Daylight Time':
00594          return 'Pacific/Auckland';
00595          break;
00596     case 'Central Standard Time':     case 'Central Daylight Time':     case 'US/Central':
00597          return 'America/Chicago';
00598          break;
00599     case 'Eastern Standard Time':     case 'Eastern Daylight Time':     case 'US/Eastern':
00600     case '(UTC-05:00) Eastern Time (US & Canada)':
00601          return 'America/New_York';
00602          break;
00603     case 'Pacific Standard Time':     case 'Pacific Daylight Time':     case 'US/Pacific':
00604          return 'America/Los_Angeles';
00605          break;
00606     case 'Mountain Standard Time':    case 'Mountain Daylight Time':    case 'US/Mountain':    case 'Mountain Time':
00607          return 'America/Denver';
00608          // The US 'Mountain Time' can in fact be America/(Denver|Boise|Phoenix|Shiprock) which
00609          // all vary to some extent due to differing DST rules.
00610          break;
00611     case '(GMT-07.00) Arizona':
00612          return 'America/Phoenix';
00613          break;
00614     default:
00615          if ( isset($c->timezone_translations) && is_array($c->timezone_translations) 
00616                       && !empty($c->timezone_translations[$tzstring]) )
00617            return $c->timezone_translations[$tzstring];      
00618   }
00619   return null;
00620 }
00621 
00622 if ( !function_exists("deprecated") ) {
00623   function deprecated( $method ) {
00624     global $c;
00625     if ( isset($c->dbg['ALL']) || isset($c->dbg['deprecated']) ) {
00626       $stack = debug_backtrace();
00627       array_shift($stack);
00628       if ( preg_match( '{/inc/iCalendar.php$}', $stack[0]['file'] ) && $stack[0]['line'] > __LINE__ ) return;
00629       @error_log( sprintf( $c->sysabbr.':DEPRECATED: Call to deprecated method "%s"', $method));
00630       foreach( $stack AS $k => $v ) {
00631         @error_log( sprintf( $c->sysabbr.':  ==>  called from line %4d of %s', $v['line'], $v['file']));
00632       }
00633     }
00634   }
00635 }
00636 
00637 
00638 if ( !function_exists("gzdecode") ) {
00639   function gzdecode( $instring ) {
00640     global $c;
00641     if ( !isset($c->use_pipe_gunzip) || $c->use_pipe_gunzip ) {
00642       $descriptorspec = array(
00643          0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
00644          1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
00645          2 => array("file", "/dev/null", "a") // stderr is discarded
00646       );
00647       $process = proc_open('gunzip',$descriptorspec, $pipes);
00648       if ( is_resource($process) ) {
00649         fwrite($pipes[0],$instring);
00650         fclose($pipes[0]);
00651         
00652         $outstring = stream_get_contents($pipes[1]);
00653         fclose($pipes[1]);
00654         
00655         proc_close($process);
00656         return $outstring;
00657       }
00658       return '';
00659     }
00660     else {
00661       $g=tempnam('./','gz');
00662       file_put_contents($g,$instring);
00663       ob_start();
00664       readgzfile($g);
00665       $d=ob_get_clean();
00666       unlink($g);
00667       return $d;
00668     }
00669   }
00670 }
00671 
00675 function awl_version() {
00676   global $c;
00677 $c->awl_library_version = 0.53;
00678   return $c->awl_library_version;
00679 }