How to convert binary to integer in mysql? - php

To put my question into perspective:
I have a PHP app, which stores IP's of users in a MySQL table.
The column type is VARBINARY(16), and the app uses PHP's inet_pton to form a binary string.
That is the string has 4 bytes for a typical IP4 address.
How to retrieve these IPs from the table, displaying them in a human readable form?
My current solution is:
select INET_NTOA(CONV(HEX(ip),16,10)) from operation_ip;
Is there a more direct way to do that?
In particular is CONV(HEX(x),16,10) the easiest way to change 4 bytes into an integer (actually I believe it is not even an integer, but a string which looks like integer).
(I use VARBINARY(16), as PHP's inet_pton can return 16-bytes for IPv6 addresses. AFAIK MySQL's INET_NTOA does not support IPv6, but at the moment this is not my biggest concern).

MySQL has nice built-in functions to handle this case:
INSERT INTO t(ip) VALUE (INET_ATON('1.2.3.4')); -- stores integer 16909060
SELECT INET_NTOA(ip) FROM t; -- returns string '1.2.3.4'
Or the PHP way:
$sql = 'INSERT INTO t(ip) VALUE (' . ip2long('1.2.3.4') . '))';
// ip2long('1.2.3.4') = 16909060
// reverse conversion: long2ip(16909060) returns '1.2.3.4'

Related

PHP MySqli how to get blob as 0x00000 string?

I have a table for things properties.
Such as id, amount, owner, attributes.
The attributes is stores as blob, and could be any small information about the thing itself,.
Like, the thing may have text on it, or it may has something about it that makes it more unique.
When you export a table/row in PhpMyAdmin, I get these really nice values
INSERT INTO `user_things` (`owner_id`, `id`, `thingId`, `count`, `attributes`) VALUES
(1, 6, 101, 1, 0x10c8431200);
And what I'm trying to do, is being able get information from the blob in PHP that displays the blob the same way PhpMyAdmin displayed it, so I can with PHP build a string of query there the blob value stays at a 0x00000 value.
I've tried to use this code: (mysqlQuery is a simplified function I created for mysqli queries, and that one works perfect so don't worry about that part)
$thing = mysqlQuery("SELECT * FROM `user_things` LIMIT 1;");
$blob = $thing["attributes"];
but it doesn't work very well, and I've tried base64_encode and that doesn't give me the 0x000 either.
I would highly appreciate any help on this, how I can get the blob to the same type of value that PhpMyAdmin displays it as.
0x is just a convention for expressing hexadecimal values.
The 0x10c8431200 hexadecimal value is the same like 72079315456 decimal value.
You can try to convert binary data to hex with the bin2hex function.
Example:
$thing = mysqlQuery("SELECT * FROM `user_things` LIMIT 1;");
$blob = $thing["attributes"];
echo bin2hex($blog);

Getting value from a key type TimeUUID in Cassandra-PHP

I'm new in cassandra and I wanna get the values from a column family, where the key is a TimeUUIDType.
I'm using PHP with PHPCassa, and I can insert(set) correctly in the column family, generating uuid with the function:
$key = CassandraUtil::uuid1();
The problem happen when I try to do a get in the column family, because i have and uuid in String format( something like that):
$uuidString= "e2658820-69f2-11e1-af9a-95dd4f324d9";
I would like to know if is possible cast or transform an String form to a valid uuid for cassandra in php or phpcassa, because my purpose is in another page create the correct uuid from the $uuuidString.
Thanks.
CassandraUtil::import($uuidString) will handle that.
Edit
As of phpcassa 1.0+, \phpcassa\UUID::import() is the proper method.

How to change decimal separator cleanly in outputs in mysql - php combo

I was trying to export database query to CSV and the need arised to use different decimal comma. It seems impossible to change the decimal comma in MySQL, so I tried in PHP:
setlocale(LC_NUMERIC, "cs_CZ");
But it seems that all the database functions like mysql_fetch_row and mysql_fetch_assoc are retrieving data of type string instead of double:
$res = mysql_query("select 50/3");
$row = mysql_fetch_row($res);
var_dump($row); // $row[0] is of type "string"
So in general PHP already doesn't have data of type double, but only strings!
So is there some general, clean way to specify output of the decimal point?
I ended up converting the strings using str_replace('.', ',', $row[0]) but this is ugly for two reasons:
you have to know which field is of type double
it's a dirty string job.
I don't know which database client/driver you're using but there is something like mysql_field_type­Docs which gives you the type based on it's offset, like 0.
This should do the job to find out if a certain column needs re-formatting or not.
To reformat, there is number_format­Docs.
With these you can do the conversion automatically.
Edit: Regarding your comments:
If you want to get PHP datatypes mapped, consider using the MySQL Native Driver­Docs. Use it together with PDO:
Advantages of using mysqlnd for PDO
mysqlnd returns native data types when using Server-side Prepared Statements, for example an INT column is returned as an integer variable not as a string. That means fewer data conversions internally. Source
So depending of what you try to achieve, use the right tool.
See as well the multiple options you have when fetching data from a PDO Statement­Docs.
// French notation
$nombre_format_francais = number_format($number, 2, ',', ' ');
Try
number_format($row[0], 2, ",", ".");
That should change the format of the number. (german format)

PHP: Converting big integer from string to int with overflow

PHP does not support unsigned ints. Is there a way to convert a string representation of an unsigned integer into a signed integer with overflow?
Example:
On a 32 bit system, PHP can store int values <= 2147483647. I want a way to convert the string "2147483648" to integer, causing it to overflow to -2147483648 instead of being reduced to 2147483647.
Why do I want to do this?
I store IPv4 addresses in a database as unsigned int (32 bits). I want to do binary operations on the addresses in PHP to check for subnets. This needs to be done on every request, so it needs to be quick. Therefore it seems better to store the IP address as an unsigned int rather than storing a string which will have to be converted back and forth.
here is the workaround.
<?php
$unsignedString = "3000000000";
echo "unsigned string: ".$unsignedString."<br />";
$signedInt = intval(doubleval($unsignedString));
echo "signed int: ".$signedInt."<br />";
?>
The fastest and easiest way to do this is to get your RDBMS to do it somehow.
You can find out what the size of an integer is in PHP by checking the value of the predefined constant PHP_INT_SIZE. This will be 4 if running on a 32-bit system, 8 if running on a 64-bit system.
I suggest that you populate a variable with for example
$smallIntegers = intval(PHP_INT_SIZE == 4);
and then in your query use something like this:
SELECT
...,
CASE
WHEN :smallIntegers: = 1 AND IPAddress > 2147483647 THEN IPAddress - 4294967296
ELSE IPAddress
END AS IPAddress,
...
...
Could you store the IP address in an integer array, one segment of the IP to each part of the array so the max value would end up as 255 stored in anyone one integer:
$ipAddress = array(127, 0, 0, 1);

MD5 Hashes not matching

I am trying to match a md5 has (generated through php) to its original value in a SQLExpress database.
I am using the following function in my SQL query
master.sys.fn_varbintohexsubstring(0, HASHBYTES('MD5', 'ID'), 1, 0)
Where 'ID' is the field in the database.
However they both seem to return different values for the md5 hash. I have been using '12290' as a static value to test this.
php md5() returns: 0bd81786a8ec6ae9b22cbb3cb4d88179
The following SQL Statement returns the same output:
DECLARE #password VARCHAR(255)
SET #password = master.sys.fn_varbintohexsubstring(0, HASHBYTES('MD5', '12290'), 1, 0)
SELECT #password
Yet when I run the following statement from the table:
SELECT ID, master.sys.fn_varbintohexsubstring(0, HASHBYTES('MD5', CONVERT(NVARCHAR(255), ID)), 1, 0) AS temp
FROM Clients
ORDER BY ID ASC
The 'temp' value matching to the 'ID' value of 12290 returns: 1867dce5f1ee1ddb46ff0ccd1fc58e03
Any help on the matter would be much appreciated!
Thanks
Python helped me to help you.
>>> from hashlib import md5
>>> md5('1\x002\x002\x009\x000\x00').digest().encode('hex')
'1867dce5f1ee1ddb46ff0ccd1fc58e03'
NVARCHAR is Unicode type and it seems from the above experiment that '12990' is stored as UTF-16LE in your database: '1\02\09\09\00\0'.
Assuming that the data encoding in the PHP is UTF-8 data and you don't want to change the existing data in the database, this is how you can fix your PHP script:
<?php
$password = '12290';
$hash = md5(mb_convert_encoding($password, 'UTF-16LE', 'UTF-8')) . "\n";
echo $hash;
?>
Output:
susam#swift:~$ php utf16le-hash.php
1867dce5f1ee1ddb46ff0ccd1fc58e03
In case the data in PHP is in some other encoding such as ASCII, ISO-8859-1, etc. you can change the third argument to mb_convert_encoding accordingly. The list of all supported encodings is available at: http://www.php.net/manual/en/mbstring.supported-encodings.php
Also, see http://www.php.net/manual/en/function.mb-convert-encoding.php
I don't have SQL server to test this on, but the CONVERT command might be creating the NVARCHAR with 240-odd trailing blanks (as you have specified NVARCHAR(255))
Try setting the NVARCHAR to the length of the ID to test:
ARE #password VARCHAR(255)
SET #password = master.sys.fn_varbintohexsubstring(0, HASHBYTES('MD5', CONVERT(NVARCHAR(5), '12290')), 1, 0)
SELECT #password
Try with different lengths in the CONVERT - is there any difference?
One of two things is most likely the problem:
Either the ID column in that row has a value not exactly equal to '12290' (e.g. extra whitespace)
Or the CONVERT function produces such a value
In any case, a standard debugging approach would be to use an SQL query to SELECT the string lengths of that ID field and the return value of CONVERT; if either is not equal to 5, you found the error.
Alternatively you can perform a dump of the table in question including data, and look at the generated INSERT statement to see what the database says the value in that column is.

Categories