Kodi Community Forum
PHP version of thumbnail hash calculation needed - Printable Version

+- Kodi Community Forum (https://forum.kodi.tv)
+-- Forum: Development (https://forum.kodi.tv/forumdisplay.php?fid=32)
+--- Forum: Kodi Application (https://forum.kodi.tv/forumdisplay.php?fid=93)
+--- Thread: PHP version of thumbnail hash calculation needed (/showthread.php?tid=85445)



PHP version of thumbnail hash calculation needed - Klojum - 2010-11-15

I'm looking for a bit of help in translating a C# script into a PHP script/function. I am working on a PHP-tool for enhancing my remote XBMC collection for my standalone mediastreamer.

The big problem is, my limited knowledge of C# is making me unable to translate the C# hashscript into a PHP-function.

This is the code according to one of the XBMC-Wikipages. Unfortunately I'm unable to get past the XOR and other math thingies.

Code:
public string Hash(string input)
{
   char[] chars = input.ToCharArray();
   for (int index = 0; index < chars.Length; index++)
   {
       if (chars[index] <= 127)
       {
          chars[index] = System.Char.ToLowerInvariant(chars[index]);
       }
   }
   input = new string(chars);
   uint m_crc = 0xffffffff;
   byte[] bytes = System.Text.Encoding.UTF8.GetBytes(input);
   foreach (byte myByte in bytes)
   {
       m_crc ^= ((uint)(myByte) << 24);
       for (int i = 0; i < 8; i++)
       {
           if ((System.Convert.ToUInt32(m_crc) & 0x80000000) == 0x80000000)
           {
               m_crc = (m_crc << 1) ^ 0x04C11DB7;
           }
           else
           {
               m_crc <<= 1;
           }
       }
   }
   return String.Format("{0:x8}", m_crc);
}

These are two supposed examples of text strings that should work with this code:
* 123456789 returns 0376e6e7
* F:\Videos\Nosferatu.avi returns 2a6ec78d

Hope anyone can help me out with a "translation" to PHP of this C# routine. Thanks in advance Eek


- spiff - 2010-11-15

it's not really doing anything fancy. it lowercases ascii values, inits the crc at 0xFFFFFFF and runs the loop. finally it returns the hex string of the result. i don't really write php so you'll spit that out faster than me.


- Nick8888 - 2010-11-15

I assume you have read this javascript example. http://forum.xbmc.org/showthread.php?tid=58389

Post your code if you achieve this as I wouldn't mind adding it to the mediafrontpage project in the future.


- opdenkamp - 2010-11-15

it should be something like this:
Code:
function calculate_hash($input)
{
    $chars = strtolower($input);
    $crc = 0xffffffff;
    
    for ($ptr = 0; $ptr < strlen($chars); $ptr++)
    {
        $chr = ord($chars[$ptr]);
        $crc ^= $chr << 24;
        
        for (int $i = 0; $i < 8; $i++)
        {
            if ($crc & 0x80000000 == 0x80000000)
            {
                $crc = ($crc << 1) ^ 0x04C11DB7;
            }
            else
            {
                $crc <<= 1;
            }
        }
    }
    
    return $crc;
}
just typed this in a text editor without testing anything, so you'll probably have to change a couple of things, but this should give you a start.


- rhormaza - 2011-01-19

I can confirm that the php function works!
the only change I had to do was the following line:

-if ($crc & 0x80000000 == 0x80000000)
+if ($crc & 0x80000000)

Thanks, it was very helpful Wink


- MakuraRyu - 2011-02-12

Here's the same PHP function but has the benefit that it's properly formatted. Please note it does use the GNU Multiple Precision for formatting (negative) numbers. Otherwise all negatives (PHP doesn't have unsigned integers natively) will hash incorrectly.
Code:
function thumbnailHash($input) {
    $chars = strtolower($input);
    $crc = 0xffffffff;
    for ($ptr = 0; $ptr < strlen($chars); $ptr++) {
        $chr = ord($chars[$ptr]);
        $crc ^= $chr << 24;
        for ($i=0; $i<8; $i++){
            if ($crc & 0x80000000) {
                $crc = ($crc << 1) ^ 0x04C11DB7;
            } else {
                $crc <<= 1;
            }
        }
    }
    //Formatting the output in a 8 character hex
    if ($crc>=0){
        //positive results will hash properly without any issues
        return sprintf("%08s",sprintf("%x",sprintf("%u",$crc)));
    } else {
        /*
         * negative values will need to be properly converted to
         * unsigned integers before the value can be determined.
         */
        return sprintf("%08s",gmp_strval(gmp_init(sprintf("%u",$crc)),16));
    }
}



- DKreeK - 2011-02-19

Hi,

I have an Apache/PHP server but without the GMP extension. There is an equivalent function to gmp_init and gmp_strval ??

Thank you


- narfight - 2011-10-12

DKreeK Wrote:Hi,

I have an Apache/PHP server but without the GMP extension. There is an equivalent function to gmp_init and gmp_strval ??

Thank you

Of course, sorry for the delay Rolleyes

Code:
function thumbnailHash($input)
{
    $chars = strtolower($input);
    $crc = 0xffffffff;
    for ($ptr = 0; $ptr < strlen($chars); $ptr++)
    {
        $chr = ord($chars[$ptr]);
        $crc ^= $chr << 24;
        for ($i=0; $i<8; $i++)
        {
            if ($crc & 0x80000000)
            {
                $crc = ($crc << 1) ^ 0x04C11DB7;
            }
            else
            {
                $crc <<= 1;
            }
        }
    }
    //Formatting the output in a 8 character hex
    if ($crc>=0)
    {
        return sprintf("%08s",sprintf("%x",sprintf("%u",$crc)));
    }
    else
    {
        $Source = sprintf('%b', $crc);
        $StrConvert = "";
        while ($Source <> "")
        {
            $Digit = substr($Source, -4, 4);
            $Source = substr($Source, 0, -4);
            $StrConvert = base_convert($Digit, 2, 16) . $StrConvert;
        }
        
        return $StrConvert;
    }
}



- tamplan - 2012-01-07

Hi,

I have trouble with the previous code and made the following updated with system in 32bits and 64bits :
Code:
private function _get_hash($file_path)
  {
    $chars = strtolower($file_path);
    $crc = 0xffffffff;

    for ($ptr = 0; $ptr < strlen($chars); $ptr++)
    {
      $chr = ord($chars[$ptr]);
      $crc ^= $chr << 24;

      for ((int) $i = 0; $i < 8; $i++)
      {
        if ($crc & 0x80000000)
        {
          $crc = ($crc << 1) ^ 0x04C11DB7;
        }
        else
        {
          $crc <<= 1;
        }
      }
    }

    // Système d'exploitation en 64 bits ?
    if (strpos(php_uname('m'), '_64') !== false)
    {

            //Formatting the output in a 8 character hex
            if ($crc>=0)
            {
                $hash = sprintf("%16s",sprintf("%x",sprintf("%u",$crc)));
            }
            else
            {
                $source = sprintf('%b', $crc);

                $hash = "";
                while ($source <> "")
                {
                    $digit = substr($source, -4);
                    $hash = dechex(bindec($digit)) . $hash;
                    $source = substr($source, 0, -4);
                }
            }
            $hash = substr($hash, 8);
    }
    else
    {
            //Formatting the output in a 8 character hex
            if ($crc>=0)
            {
                $hash = sprintf("%08s",sprintf("%x",sprintf("%u",$crc)));
            }
            else
            {
                $source = sprintf('%b', $crc);

                $hash = "";
                while ($source <> "")
                {
                    $digit = substr($source, -4);
                    $hash = dechex(bindec($digit)) . $hash;
                    $source = substr($source, 0, -4);
                }
            }
    }

    return $hash;
  }

Hope this helps and thanks to narfight.


- baderj - 2012-02-27

I added Perl and Python versions of the XBMC CRC code to the WIKI:
http://wiki.xbmc.org/index.php?title=Thumbnails#Sample_Code

Thanks to dushmaniac for providing the PHP version.