In PHP what does it mean by a function being binary-safe? - php

In PHP what does it mean by a function being binary-safe ?
What makes them special and where are they typically used ?

It means the function will work correctly when you pass it arbitrary binary data (i.e. strings containing non-ASCII bytes and/or null bytes).
For example, a non-binary-safe function might be based on a C function which expects null-terminated strings, so if the string contains a null character, the function would ignore anything after it.
This is relevant because PHP does not cleanly separate string and binary data.

The other users already mentioned what binary safe means in general.
In PHP, the meaning is more specific, referring only to what Michael gives as an example.
All strings in PHP have a length associated, which are the number of bytes that compose it. When a function manipulates a string, it can either:
Rely on that length meta-data.
Rely on the string being null-terminated, i.e., that after the data that is actually part of the string, a byte with value 0 will appear.
It's also true that all string PHP variables manipulated by the engine are also null-terminated. The problem with functions that rely on 2., is that, if the string itself contains a byte with value 0, the function that's manipulating it will think the string has ended at that point and will ignore everything after that.
For instance, if PHP's strlen function worked like C standard library strlen, the result here would be wrong:
$str = "abc\x00abc";
echo strlen($str); //gives 7, not 3!

More examples:
<?php
$string1 = "Hello";
$string2 = "Hello\x00World";
// This function is NOT ! binary safe
echo strcoll($string1, $string2); // gives 0, strings are equal.
// This function is binary safe
echo strcmp($string1, $string2); // gives <0, $string1 is less than $string2.
?>
\x indicates hexadecimal notation. See: PHP strings
0x00 = NULL
0x04 = EOT (End of transmission)
ASCII table to see ASCII char list

Related

PHP can't count (binary-hex weirdness)?

In Perl I have code that is working correctly:
print unpack('B*','10071C2');
returns 00110001001100000011000000110111001100010100001100110010
The code ported to PHP using GMP:
function gmp_convert($num, $base_a, $base_b)
{
return gmp_strval ( gmp_init($num, $base_a), $base_b );
}
$test = "10071C2";
$testb=gmp_convert($test, 16, 2);
produces 10000000110110001110000101001101111110110001101110000111
I thought it might be byte order, however if I use b* instead in Perl it still produces something else:
PHP---10000000110110001110000101001101111110110001101110000111
PERL--10001100000011000000110011101100100011001100001001001100
I simply do not understand this, can anyone help?
Your Perl and PHP implementations are doing entirely separate things.
The Perl code is converting each of the characters from the input string into the binary representation of the ASCII code for that character. For instance, the first character ("1") gets converted into "00110001" which is equal to decimal 49, the ASCII code for the character 1.
Your PHP code successfully converts the hex number represented in string form into an equivalent binary representation in string form.

How to write NON ASCII data in one file with php

I must write a binary file with php, but I think that I don't use the correct method.
I use this function:
$ptr = fopen("file.txt", 'wb');
fwrite($ptr, $Str);
fclose($ptr);
I write this string (chaotic representation of 0 and 1):
$Str="00000001001110000000000100000100000000000000001000000010000000010000001100000101000000000000010000000001000000000000010100000";
I thought that opening the file with OpenOffice I would not have seen the text of zeros and ones, but instead I was sure I saw a chaotic sequence of characters.
Why I see the zeros and ones in open office? How can I do to write the raw data with php?
If you write text in a file, even when open in binary mode, you will get text in the file. Your 0 is not stored as a zero bit, but as the ASCII representation of the 0 caracter.
Use the binary format for numbers in PHP, for instance:
$var = OxFF; // equals to 1111 1111 in binary.
More in the manual
You can write any character with the chr() function.
Alternatively, you can do something like "\x0A" (that's a newline character).

Get Ruby's OpenSSL::HMAC.hexdigest() to output the same as PHP's hash_hmac()

I'm trying to use the API of a web service provider. They don't have an example in Ruby, but they do have one for PHP, and I'm trying to interpret between the two. The API examples always use "true" on PHP's hash_hmac() call, which produces a binary output. The difference seems to be that Ruby's OpenSSL::HMAC.hexdigest() function always returns text. (If I change the PHP call to "false" they return the same value.) Does anyone know of a way to "encode" the text returned from OpenSSL::HMAC.hexdigest() to get the same thing as returned from a hash_hmac('sha256', $text, $key, true)?
Use OpenSSL::HMAC.digest to get the binary output.
You'll need to convert each pair of hex digits into a byte with the same value. I don't know any Ruby, but this is similar to how it would be handled in PHP.
First, take your string of hex digits and split them into an array. Each element in the array should be two characters long. Convert each element from a string of two hex bytes to an integer. It looks like you can do this by calling the hex method on each string.
Next, call pack on the converted array using the parameter c*, to convert each integer into a one-byte character. You should get the correct string of bytes as the result.

filesize from a String

how can i get the "filesize" from a string in php?
I put the string in a mysql database as a blob and i need to store the size of the blob. My solution was to create a temp file and put the string into the temp file. now i can get the filesize from the "string". but that solution is not good...
greetings
It depends. If you have mbstring function overloading enabled, the only call that will work will be mb_strlen($string, '8bit');. If it's not enabled, strlen($string) will work fine as well.
So, you can handle both cases like this:
if (function_exists('mb_strlen')) {
$size = mb_strlen($string, '8bit');
} else {
$size = strlen($string);
}
SELECT length(field) FROM table
From the MySQL docs:
LENGTH(str)
Returns the length of the string str,
measured in bytes. A multi-byte
character counts as multiple bytes.
This means that for a string
containing five two-byte characters,
LENGTH() returns 10, whereas
CHAR_LENGTH() returns 5.
strlen()
before putting it into mysql, or in SQL:
LENGTH()
Notice that lenght can be various depending on character set. If you want to have real length in bytes use strlen(), if you want to have character count use mb_strlen() (if you have utf-8 encoding for example)
If all you are storing is the string, then the size should be the length of your string times the number of bytes in the charset. So for Unicode that would be 2*strlen($string).
strlen($string) is the best example for viewing the size(MB) of a string
strlen() doesnt actually return the number of elements in a string, but the number of bytes in it
example:
echo(strlen('a■')); will return 4, because the black square character is made of 3 bytes, and the 'a' character is made of one.
use mb_strlen() as then you can tell it what type of encoding the string uses (if any) to get the size of it in bytes.

Check for binary string length?

Is there a native or inexpensive way to check for the length of a string in bytes in PHP?
See http://bytes.com/topic/php/answers/653733-binary-string-length
Relevant part:
"In PHP, like in C, the string ends with a zero-character, '\0', (char)
0, null-terminator, null-byte or whatever you like to call it."
No, that's not the case - PHP strings are stored with both the length and the
data, unlike C strings that just has one pointer and uses a terminator. They're
"binary-safe" - NUL doesn't terminate the string.
See the definition of zvalue_value in zend.h; the string part has both a "char
*val" and "int len".
Problems would start if you're using the mbstring.func_overload, which changes
how strlen() and the other functions work, and does try and treat strings as
strings of characters in a specific encoding rather than a string of bytes.
This is not the normal PHP behaviour.
The answer is that strlen should return the number of bytes regardless of the content of the string. For multi-byte character strings, you get the wrong number of characters, but the right number of bytes. However, you need to be certain you're not using the mbstring overload, which changes how strlen behaves.
In the event that you have mbstring overload set or your are developing for the platforms where you are unsure about this setting you can do the following:
$len=strlen(bin2hex($data))/2;
The reason why this works is that in Hex you are guaranteed to get 2 characters for all bytes that come from bin2hex (it returns two chars even for the initial binary 0).
Note that it will use significantly more resources than a normal strlen (afterall, so you should definitely not do that to the large amount of data if it's not absolutely necessary.
On php.org, someone was nice enough to create this function. Just multiply by 8 and you've got however many bits were in that string, as the function returns bytes.
The length of a string (textual data) is determined by the position of the NULL character which marks the end.
In case of binary data, NULL can be and often is in the middle of data.
You don't check the length of binary data. You have to know it beforehand. In your case, the length is 16 (bytes, not bits, if it is UUID).
As far as UUID validity is concerned, any 16-byte value is a valid UUID, so you are out of luck there.

Categories