nutools/lib/b36sha1.php

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);