I have been working with a piece of code for youtube style URL's but I have found a bug and I am hoping someone can show me the most efficient way to fix it.
function alphaID($in, $to_num = false, $pad_up = false, $passKey = null)
{
static $passcache;
if(empty($passcache))
$passcache = array();
$index = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$i = array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z');
if (!empty($passKey)) {
// Although this function's purpose is to just make the
// ID short - and not so much secure,
// with this patch by Simon Franz (http://blog.snaky.org/)
// you can optionally supply a password to make it harder
// to calculate the corresponding numeric ID
if(isset($passcache[$passKey]))
$index = $passcache[$passKey];
else {
if(strlen($passhash = hash('sha256',$passKey)) < strlen($index))
$passhash = hash('sha512',$passKey);
$p = str_split($passhash);
array_multisort($p, SORT_DESC, $i);
$index = implode($i);
$passcache = $index;
}
}
$base = strlen($index);
if ($to_num) {
// Digital number <<-- alphabet letter code
$in = strrev($in);
$out = 0;
$len = strlen($in) - 1;
for ($t = 0; $t <= $len; $t++) {
$bcpow = bcpow($base, $len - $t);
$out += strpos($index, $in[$t]) * $bcpow;
}
if (is_numeric($pad_up)) {
$pad_up--;
if ($pad_up > 0) {
$out -= pow($base, $pad_up);
}
}
} else {
// Digital number -->> alphabet letter code
if (is_numeric($pad_up)) {
$pad_up--;
if ($pad_up > 0) {
$in += pow($base, $pad_up);
}
}
$out = "";
for ($t = floor(log10($in) / log10($base)); $t >= 0; $t--) {
$bcp = bcpow($base, $t);
$a = floor($in / $bcp);
$out .= $index[$a];
$in -= $a * $bcp;
}
$out = strrev($out); // reverse
}
return $out;
}
The bug is only when encoding a single number 238328 as it is my base to the power of three. As a result it divides exactly and because of use of 'floor' it goes unnoticed and the script tries to add the 62nd character which does not exist and only produces a three character code rather than four... thus 'aa' is the result rather than 'aaab'.
Here is the problem part of the code:
for ($t = floor(log10($in) / log10($base)); $t >= 0; $t--) {
$bcp = bcpow($base, $t);
$a = floor($in / $bcp);
$out .= $index[$a];
$in -= $a * $bcp;
And to make it even easier here is the call to get the error
echo alphaID(238328);
credits: Orginally written by Kevin Vanzonneveld: kevin dot vanzonneveld dot net, modified by Simon Franz: blog dot snaky dot org and optimised by Stackoverflows very own mattbasta