95 lines
2.4 KiB
PHP
Executable File
95 lines
2.4 KiB
PHP
Executable File
#!/usr/bin/env php
|
|
<?php # -*- coding: utf-8 mode: php -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
|
|
|
function wfBaseConvert( $input, $sourceBase, $destBase, $pad = 1, $lowercase = true ) {
|
|
$input = strval( $input );
|
|
if( $sourceBase < 2 ||
|
|
$sourceBase > 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);
|