0

I have a PHP function I got from the web that uses bcmath functions:

function SteamID64to32($steamId64) {
    $iServer = "1";
    if(bcmod($steamId64, "2") == "0") {
        $iServer = "0";
    }
    $steamId64 = bcsub($steamId64,$iServer);
    if(bccomp("76561197960265728",$steamId64) == -1) {
        $steamId64 = bcsub($steamId64,"76561197960265728");
    }
    $steamId64 = bcdiv($steamId64, "2");
    return ("STEAM_0:" . $iServer . ":" . $steamId64);
}

For any valid input the function will at random times add ".0000000000" to the output.

Ex:

$input = 76561198014791430;
SteamID64to32($input);

//result for each run
STEAM_0:0:27262851
STEAM_0:0:27262851.0000000000
STEAM_0:0:27262851
STEAM_0:0:27262851
STEAM_0:0:27262851.0000000000
STEAM_0:0:27262851
STEAM_0:0:27262851.0000000000
STEAM_0:0:27262851.0000000000
STEAM_0:0:27262851.0000000000

This was tested on 2 different nginx servers running php-fpm. Please help me understand what is wrong here. Thanks

bockzior
  • 199
  • 1
  • 6
  • 20
  • Your question is very different to the answer you where asking. I think you should change it, at least the title. Have you found why appears decimals if are the same code? – PhoneixS Jan 15 '15 at 11:19

2 Answers2

1

I found this: SteamProfile

/**
 *      This file is part of SteamProfile.
 *
 *      Written by Nico Bergemann <barracuda415@yahoo.de>
 *      Copyright 2009 Nico Bergemann
 *
 *      SteamProfile is free software: you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation, either version 3 of the License, or
 *      (at your option) any later version.
 *
 *      SteamProfile is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *
 *      You should have received a copy of the GNU General Public License
 *      along with SteamProfile.  If not, see <http://www.gnu.org/licenses/>.
 */

// thanks to voogru for the id transformation algorithm (http://forums.alliedmods.net/showthread.php?t=60899)

class SteamID {
        private $sSteamID = '';
        private $sSteamComID = '';

        const STEAMID64_BASE = '76561197960265728';

        public function __construct($sID) {
                // make sure the bcmath extension is loaded
                if(!extension_loaded('bcmath')) {
                        throw new RuntimeException("BCMath extension required");
                }

                if($this->isValidSteamID($sID)) {
                        $this->sSteamID = $sID;
                        $this->sSteamComID = $this->convertToSteamComID($sID);
                } elseif($this->isValidComID($sID)) {
                        $this->sSteamID = $this->convertToSteamID($sID);
                        $this->sSteamComID = $sID;
                } else {
                        $this->sSteamID = '';
                        $this->sSteamComID = '';
                }
        }

        public function getSteamID() {
                return $this->sSteamID;
        }

        public function getSteamComID() {
                return $this->sSteamComID;
        }

        public function isValid() {
                return $this->sSteamID != '';
        }

        private function isValidSteamID($sSteamID) {
                return preg_match('/^(STEAM_)?[0-5]:[0-9]:\d+$/i', $sSteamID);
        }

        private function isValidComID($sSteamComID) {
                // anything else than a number is invalid
                // (is_numeric() doesn't work for 64 bit integers)
                if(!preg_match('/^\d+$/i', $sSteamComID)) {
                        return false;
                }

                // the community id must be bigger than STEAMID64_BASE
                if(bccomp(self::STEAMID64_BASE, $sSteamComID) == 1) {
                        return false;
                }

                // TODO: Upper limit?

                return true;
        }

        private function convertToSteamComID($sSteamID) {
                $aTMP = explode(':', $sSteamID);

                $sServer = $aTMP[1];
                $sAuth = $aTMP[2];

                if((count($aTMP) == 3) && $sAuth != '0' && is_numeric($sServer) && is_numeric($sAuth)) {
                        $sComID = bcmul($sAuth, "2"); // multipy Auth-ID with 2
                        $sComID = bcadd($sComID, $sServer); // add Server-ID
                        $sComID = bcadd($sComID, self::STEAMID64_BASE); // add this odd long number

                        // It seems that PHP appends ".0000000000" at the end sometimes.
                        // I can't find a reason for this, so I'll take the dirty way...
                        $sComID = str_replace('.0000000000', '', $sComID);

                        return $sComID;
                } else {
                        throw new RuntimeException("Unable to convert Steam-ID");
                }
        }

        private function convertToSteamID($sSteamComID) {
                $sServer = bcmod($sSteamComID, '2') == '0' ? '0' : '1';
                $sCommID = bcsub($sSteamComID, $sServer);
                $sCommID = bcsub($sCommID, self::STEAMID64_BASE);
                $sAuth = bcdiv($sCommID, '2');

                return "STEAM_0:$sServer:$sAuth";
        }
}
JD Vangsness
  • 697
  • 3
  • 10
  • 27
  • What about SteamIDs of type STEAM_0:1 ? – bockzior May 10 '14 at 00:33
  • This is the accepted answer but although the user solved his problem, why some times it produces decimals and other times not if the operations and values are the same? (this was the original question that I think wasn't answered). – PhoneixS Jan 15 '15 at 11:18
1

The answer provided by JD doesn't account for all possible STEAM_ ID types, namely, anything that is in the STEAM_0:1 range. This block of code will:

<?php

function Steam64ToSteam32($Steam64ID)
{
    $offset = $Steam64ID - 76561197960265728;
    $id = ($offset / 2);
    if($offset % 2 != 0)
    {
        $Steam32ID = 'STEAM_0:1:' . bcsub($id, '0.5');
    }
    else
    {
        $Steam32ID = "STEAM_0:0:" . $id;
    }
    return $Steam32ID;
}

echo Steam64ToSteam32(76561197960435530);
echo "<br/>";
echo Steam64ToSteam32(76561197990323733);
echo "<br/>";
echo Steam64ToSteam32(76561198014791430);
?>

This outputs

STEAM_0:0:84901
STEAM_0:1:15029002
STEAM_0:0:27262851

The first one is for a Valve employee and someone who's had a Steam account since 2003 (hence the low ID), the second is a random profile I found on VACBanned which had an ID in the STEAM_0:1 range. The third is the ID you provided in your sample code.

Andy
  • 49,085
  • 60
  • 166
  • 233
  • This is the accepted answer but although the user solved his problem, why some times it produces decimals and other times not if the operations and values are the same? (this was the original question that I think wasn't answered). – PhoneixS Jan 15 '15 at 11:17