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