Я пытаюсь преобразовать метод APR (Apache Runtime) в PHP, но я не могу понять это.
Метод создает строку, которая представляет собой путь к каталогу и файл - таким примером будет A / B / C / [a-fA-F0-9_ @]. Он использует побитовые операции над двоичной строкой, возвращаемой из md5 ($ string, true); Когда я запускаю PHP ниже, я получаю:
array (
0 => 'A',
1 => '/',
2 => 'A',
3 => '/',
4 => 'A',
5 => '/',
6 => 'AAAAAAAAAAAAAAAAAAA',
)
Что я делаю не так? Разве это невозможно из-за того, как PHP внутренне представляет массивы символов?
Вот метод c :
static void cache_hash(const char *it, char *val, int ndepth, int nlength)
{
apr_md5_ctx_t context;
unsigned char digest[16];
char tmp[22];
int i, k, d;
unsigned int x;
static const char enc_table[64] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_@";
apr_md5_init(&context);
apr_md5_update(&context, (const unsigned char *) it, strlen(it));
apr_md5_final(digest, &context);
/* encode 128 bits as 22 characters, using a modified uuencoding
* the encoding is 3 bytes -> 4 characters* i.e. 128 bits is
* 5 x 3 bytes + 1 byte -> 5 * 4 characters + 2 characters
*/
for (i = 0, k = 0; i < 15; i += 3) {
x = (digest[i] << 16) | (digest[i + 1] << 8) | digest[i + 2];
tmp[k++] = enc_table[x >> 18];
tmp[k++] = enc_table[(x >> 12) & 0x3f];
tmp[k++] = enc_table[(x >> 6) & 0x3f];
tmp[k++] = enc_table[x & 0x3f];
}
/* one byte left */
x = digest[15];
tmp[k++] = enc_table[x >> 2]; /* use up 6 bits */
tmp[k++] = enc_table[(x << 4) & 0x3f];
/* now split into directory levels */
for (i = k = d = 0; d < ndepth; ++d) {
memcpy(&val[i], &tmp[k], nlength);
k += nlength;
val[i + nlength] = '/';
i += nlength + 1;
}
memcpy(&val[i], &tmp[k], 22 - k);
val[i + 22 - k] = '\0';
}
Вот моя попытка конвертировать в PHP:
$URL = 'thumbnail.php?u=http%3A%2F%2Fwww.google.com%2Flogos%2Fclassicplus.png&w=200';
cache_hash($URL, $theFile);
function cache_hash($URL, &$theFile, $dirlevels = 3, $dirlength = 1)
{
$enc_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_@";
$md5URL = md5($URL,true);
// echo "MD5URL: ".var_export($md5URL,true);
//$md5URL = digest
$tmp = '0000000000000000000000'; //22 chars
for ($i = 0; $i < 22; $i++) {
$tmp[$i] = 0x0;
}
var_export(unpack('S',$md5URL));
p(ord($md5URL[0]));
p(ord($md5URL[1]));
/* encode 128 bits as 22 characters, using a modified uuencoding
* the encoding is 3 bytes -> 4 characters* i.e. 128 bits is
* 5 x 3 bytes + 1 byte -> 5 * 4 characters + 2 characters
*/
for ($i = 0, $k = 0; $i < 15; $i += 3) {
// p($md5URL[$i] << 16);
// p($md5URL[$i + 1] << 8);
// p($md5URL[$i + 2]);
$x = ($md5URL[$i] << 16) | ($md5URL[$i + 1] << 8) | $md5URL[$i + 2];
// p($x);
p($x >> 18);
$tmp[$k++] = $enc_table[$x >> 18];
$tmp[$k++] = $enc_table[($x >> 12) & 0x3f];
$tmp[$k++] = $enc_table[($x >> 6) & 0x3f];
$tmp[$k++] = $enc_table[$x & 0x3f];
}
/* one byte left */
$x = $md5URL[15];
$tmp[$k++] = $enc_table[$x >> 2]; /* use up 6 bits */
$tmp[$k++] = $enc_table[($x << 4) & 0x3f];
/* now split into directory levels */
for ($i = $k = $d = 0; $d < $dirlevels; ++$d) {
var_export($tmp);
$theFile[$i] = substr($tmp,$k,$dirlength);
$k += $dirlength;
$theFile[$i + $dirlength] = '/';
$i += $dirlength + 1;
}
$theFile[$i] = substr($tmp,$k,22 - $k);
var_export($theFile);
}
function p($val) {
echo " Dec:\n";
printf(' val= %d', ord($val));
echo "\nBinary:\n";
printf(' val= %b', ord($val));
echo "\n";
}