#!/usr/bin/env php 36 || $destBase < 2 || $destBase > 36 || $pad < 1 || $sourceBase != intval( $sourceBase ) || $destBase != intval( $destBase ) || $pad != intval( $pad ) || !is_string( $input ) || $input == '' ) { return false; } $digitChars = ( $lowercase ) ? '0123456789abcdefghijklmnopqrstuvwxyz' : '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; $inDigits = array(); $outChars = ''; // Decode and validate input string $input = strtolower( $input ); for( $i = 0; $i < strlen( $input ); $i++ ) { $n = strpos( $digitChars, $input[$i] ); if( $n === false || $n > $sourceBase ) { return false; } $inDigits[] = $n; } // Iterate over the input, modulo-ing out an output digit // at a time until input is gone. while( count( $inDigits ) ) { $work = 0; $workDigits = array(); // Long division... foreach( $inDigits as $digit ) { $work *= $sourceBase; $work += $digit; if( $work < $destBase ) { // Gonna need to pull another digit. if( count( $workDigits ) ) { // Avoid zero-padding; this lets us find // the end of the input very easily when // length drops to zero. $workDigits[] = 0; } } else { // Finally! Actual division! $workDigits[] = intval( $work / $destBase ); // Isn't it annoying that most programming languages // don't have a single divide-and-remainder operator, // even though the CPU implements it that way? $work = $work % $destBase; } } // All that division leaves us with a remainder, // which is conveniently our next output digit. $outChars .= $digitChars[$work]; // And we continue! $inDigits = $workDigits; } while( strlen( $outChars ) < $pad ) { $outChars .= '0'; } return strrev( $outChars ); } function base36Sha1( $text ) { return wfBaseConvert( sha1( $text ), 16, 36, 31 ); } if ($argc > 1) { $inf = fopen($argv[1], "rb"); if ($inf === FALSE) exit(1); $close = TRUE; } else { $inf = STDIN; $close = FALSE; } $data = stream_get_contents($inf); fwrite(STDOUT, base36Sha1($data)); fwrite(STDOUT, "\n"); if ($close) fclose($inf);