I suspect this might be a duplicate but lord if I can find it.
I need to convert a 'mostly' hex value passed in the _GET[] array from string to an actual hex integer. I say 'mostly' because the hex number passed in is not prepended with the "0x"
The most promising thing I tried and then raised the white flag on this problem was this -- 'azk' is the name of the GET[] parameter passed in:
$timeStamp = filter_input(INPUT_GET, 'azk', FILTER_SANITIZE_STRING);
//FAILS FOR HEX --> $test = (int)$timeStamp;
//FAILS FOR HEX --> $test = 0 + $timeStamp;
$retval = sscanf($timeStamp, '%x', $test);
var_dump(gettype($test));
var_dump($test);
Here's what happens: the user passes in an 'azk' value of 531cb6d6, which is in fact a hex value but not prepended with the '0x'.
Despite my instructions to sscanf() above -- note that I specifically instruct sscanf() to convert the value of 'timeStamp' into a hex value by way of the '%x' flag --
-- the $test value is shown, via the var_dump's above, as this:
string(7) "integer" int(1394390742)
The '1394390742' is not hex. I'm not seeing why, I specifically instruct sscanf to convert to %x hex value, but this '1394390742' is the base-10 (decimal) version of the base-16 (hexadecimal) value that got passed in, the 531cb6d6 value. In other words, using "%x" is converting hex to decimal. Not sure if that is a bug, a setting in the web server ini files somewhere, or a lack of my understanding of "%x".
The sscanf() is not all I've tried, this is not exhaustive but I tried things like this, to me the most obvious choice:
// BOTH OF THESE FAIL TO PASS HEX CHARS, BOTH RETURN THIS: 53166
$timeStamp = filter_input(INPUT_GET, 'azk', FILTER_SANITIZE_NUMBER_INT,
FILTER_FLAG_ALLOW_HEX);
$timeStamp = filter_input(INPUT_GET, 'azk', FILTER_VALIDATE_INT,
FILTER_FLAG_ALLOW_HEX);
I've looked at a bunch of SO posts, I can't believe this isn't covered, but I can't find it. If someone knows how to pull this off -- convert a hex value passed by the _GET as a string, then convert to a hex value -- I would be in your debt.
As var_dump shows, the variable $test contains an integer.
PHP is converting the integer back to a decimal string just so it can show it, but the integer itself is not intrinsically decimal, nor hex. Those are just two possible representations of the same value.
If you want to output the value back as an hex string, you can use one of these:
echo dechex($test);
printf("%x", $test);
Edit: I saw your comments, you don't need to cast as int:
1) hexdec takes the string and returns an integer
2) ...do the math using integers...
3) dechex takes the result as integer an returns a string
You can use the hexdec() function:
$timeStamp = hexdec('531cb6d6'); // 1394390742
If you want to sanitize the string before using it then you can create your own filter using a callback:
$hexTimestamp = filter_input(INPUT_GET, 'azk', FILTER_CALLBACK, array(
'options' => function($str) {
return ctype_xdigit($str) ? $str : 0;
}
));
$timeStamp = hexdec('531cb6d6');
If you not going to use the HEX value then you could also convert it to an integer as part of the sanitizing:
$timestamp = filter_input(INPUT_GET, 'azk', FILTER_CALLBACK, array(
'options' => function($str) {
return ctype_xdigit($str) ? hexdec($str) : false;
}
));
Edit:
Okay, I am getting confused, I think. You have a HEX input and you want to turn it into a "HEX number". I am not sure I understand what you mean.
If you want the input HEX value to become a "real" PHP HEX value, like 0x531cb6d6, then you are mistaken about how PHP works. When PHP sees a HEX constant, like 0x531cb6d6, then it immediately converts it to an integer. PHP does not use HEX numbers; HEX notation is just a way of representing a number, and it not actually a type of number distinct from integers.
If you want the input HEX value, "531cb6d6", to look like a HEX value with the 0x prefix then you can just add it: '0x'.$timeStamp.
Not sure if I answered your question.
Related
I need to convert string like 0x2fe84e3113d7b to the float type. This string comes from infura.io API as balance of the account. I've tried to use https://github.com/mbezhanov/ethereum-converter, but it makes no sense in this case (it always returns 0.00000 in any way). How to convert this string to 0.000842796652117371 with php?
use Bezhanov\Ethereum\Converter;
...
$this->converter = new Converter();
$weiValue = '0x1e1e83d93bb6ebb88bbaf';
dump($this->converter->fromWei($weiValue)); // returns 0.00000000000000000000000000000000000
$hexValue = hexdec($weiValue); // returns 2.2757423599815E+24
dump($this->converter->fromWei($hexValue)); // returns the same
I guess it caused by too long value on $hexValue (I mean converter can't convert long integers as it). But how to get the ether value from this hex?
https://www.investopedia.com/terms/w/wei.asp
1 Ether = 1,000,000,000,000,000,000 Wei (10^18)
and since this is currency, storing it as a floating point would be asinine, so it's got to be a 64-bit integer there.
Deleted my overwrought answer for a simple:
var_dump(
$wei = hexdec("0x2fe84e3113d7b"),
$wei / pow(10, 18)
);
Output:
int(842796652117371)
float(0.000842796652117370993)
Which, coincidentally, also illustrates why you don't want to use floats for currency. Also, WFM.
Still doesn't explain why you have:
$hexValue = hexdec($weiValue); // returns 2.2757423599815E+24
Quoted in your example as that's several orders of magnitude wrong for the supposed input.
So I'm doing some CTF and one of the challenge is about php type juggling. The code looks something like this
if($_GET['var1'] == hash('md4', $_GET['var1']))
{
//print flag
}
So I was 80% sure that I need to pass in an integer so it'll be true but all I can manipulate is the url. I tried using python request to do it but still failed.
import requests
url = 'http://example.com'
params = dict(var1=0)
r = requests.get(url=url, params=params)
Is there any special case where php will treat the variable pass into GET array as int? Or there is other way to do so?
The answer to this CTF can be found here https://medium.com/#Asm0d3us/part-1-php-tricks-in-web-ctf-challenges-e1981475b3e4
The general idea is to find a value which starts with 0e and its hash also starts with 0e. The page gives an example of 0e001233333333333334557778889 which produces a hash of 0e434041524824285414215559233446
This notation is called scientific notation. To understand why this kind of type juggling works you need to understand what both numbers are. If we convert from scientific notation to decimal it becomes obvious.
0e001233333333333334557778889 = 0×101233333333333334557778889
0e434041524824285414215559233446 = 0×10434041524824285414215559233446
From primary school maths we know that anything multiplied by 0 is 0, which means both numbers are 0.
All input provided in the $_GET or $_POST superglobals is of type string.
Thanks to PHP's type juggling system both strings are treated as floating point numbers written in scientific notation and when cast to float they both equal 0.
Suppose we have a string $str = "a"; and number $num = 2;
$str = 'a';
$num = 2;
echo $str*$num;
Output:
0
When performing arithmetic operations on a string operand, PHP will try to convert the string to a number.
It does this by looking for digits at the beginning of the string and will try to convert them into a value. If there are no digits, the value will be zero.
(There's an edge case for strings containing e or E (scientific notation), but that's not relevant here.)
Good Question.
Same i did ask to my teacher when i was in collage,
The answer is.
String * int= infinity; //According to scientific calculator answer is infinity.
but we need to continue our so program it provide 0.
it is made by code by default answer.
Simply said the string will be converted to an integer with a value of 0. This will include most of the cases when only alphabetic values are used. If you try to add a integer value at the beginning of the string it would in theory become a integer of that value.
I would recommend to read Why PHP Strings Equal Zero or Comparison Operators
Maybe you are looking for str_repeat, instead doing looping for that, its a default value that php serve to you, or you need to cast A into integer . When you try to do calculation for data that is not in Integer/float data type. Usually PHP auto-typecast the variables. In some cases it wont. Then we have to type cast it manually
A select field on my HTML form may yield 1 to 5 (integers). Using is_int rejects it every time, because the $_POST['rating'] is viewed as a string.
After consulting the PHP Manual, it seems is_numeric() && !is_float() is the proper way to validate for an integer in this case.
But I want to be certain, so please confirm or fire away at my logic.
I would probably use something like this:
$value = filter_var(
$_POST['rating'],
FILTER_VALIDATE_INT,
array('options' => array('min_range' => 1, 'max_range' => 5)));
filter_var() will return either boolean false if the value is non-integer or out-of-range, or the valid value itself (as an integer.)
I would use is_numeric(), because user input always comes in as a string (as far as I know).
Another way to guarantee something is an integer is to cast it...
$id = (int) $id;
You could use the following regular expression:
preg_match('/^[0-9]{1,}$/', $value);
I does validate digits with leading zeros though...
if you want to know if $_POST['rating'] is an int before you even try to cast do use is_numeric() && !is_float() as you have. This will tell you if the string is an int or not. If you just cast to an int and there is a non numeric all the numbers before the first letter in the string is turned into an int.
x = 457h
print (int)x
outputs 457
x = h56
print (int)x
outputs 0
is_int requires the input content is a integer.
is_numeric requires the input content is a integer or a string including just 0-9.
but I am wondering the result if I put a number that is bigger than PHP_INT_MAX as the parameter into the above 2 functions.
You can always cast it as an int.
$rating = (int)$_POST['rating'];
This will remove the need to validate it (even though you should always validate form data).
It may reduce your steps is what I'm getting at.
If you're testing for digits only (what an integer usually is ;)), I tend to use ctype_digit instead of is_int. That way, you won't lose data through casting, and you can just use a string:
<?php
$_POST['foo'] = '42';
echo ctype_digit( (string) $_POST['foo'] ) ? 'yep' : 'nope';
That'll output "yep".
My $_POST value contains css friendly hex color value, for example: #ffffff. In order to make it friendly towards the ColorJizz library, I should have it in hexadecimal integer value. The code below doesn't work. If I replace the $color_hex variable with a hard coded value for example: 0xffffff, it works.
include('colorjizz.php');
$color_hex = '0x' . substr($_POST['color'], 1);
$color = new Hex($color_hex);
This is most likely a very noob level problem, but after hitting my head to the wall for a quite few hours, I'd be grateful for any advice. Thank you.
"Hexadecimal integer value" doesn't make much sense. Hex is a representation of a number (thus a string), while integer value speaks of the machine format of a number.
If you want the number, a quick Google search found hexdec
$color = hexdec(substr($_POST['color'], 1));
It appears to ignore leading "junk", so you could even use
$color = hexdec($_POST['color']);
If you have a string containing a hexadecimal representation of a number and you want to have it as a integer you have to convert from hex to dec. If I get your question right.
$dec = hexdec("ff0000");
http://php.net/hexdec
In PHP, the data type for a hexadecimal integer and a decimal integer is the same; being able to type 0xDEAD in your source code is just syntactic sugar. Thus, you can use intval() to convert the form input to a normal PHP integer from a string:
$color_hex = intval(substr($_POST['color'], 1), 16);
The final parameter, 16, specifies that the input string is in hexadecimal.