Преобразование метода C, который использует побитовое к PHP - PullRequest
1 голос
/ 30 января 2012

Я пытаюсь преобразовать метод 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";
}

1 Ответ

0 голосов
/ 08 июля 2013

измените две строки, это должно работать, я считаю

$ x = (ord ($ md5URL [$ i]) << 16) |(ord ($ md5URL [$ i + 1]) << 8) |ord ($ md5URL [$ i + 2]); </p>

$ x = ord ($ md5URL [15]);

Я думаю, что вы также должны изменить эту строку: $ md5URL = md5($ URL, false);

...