How to write this php code in c++ - php

$x = pack("N", $num1).pack("N", $num2).$data;
I am trying to do it with
union unionchal {
struct ast{
unsigned long a;
unsigned long b;
char c[8];
} chal;
unsigned char response[16];
};
ast being the input and response being the output
It is meant to output yp¶ ‚¬þÖHpö€ì_± but gives ¶pyßêÈ)ÖHpöì_
I think it's got something to do with it being big endian byte order

Try using htonl on your integers before placing them into the structure. It will convert them into big-endian order. If you need 64-bit longs, see the discussion about it on SE.

I think it's got something to do with
it being big endian byte order
I also think so. You may use htonl() for example, to change the byte order on little-endian machines, or write your own byte-swapping function (but then you'll have to test yourself what the byte order of the host machine is).

Try using Boost Variant library.

Related

Pack Convert byte array into UINT64

I want to convert byte array to UINT64 using PHP.
I can do this easily in C# but I want to do this in PHP.
Here is C# code.
bytes = Encoding.UTF8.GetBytes(hashed);
BitConverter.ToUInt64(bytes, 0);
I want to convert this to PHP.
I tried to use pack() function but this does not works.
Let's say this is a byte array.
$bytes = [101,102,54,55,99,55,56,49];
pack("J*","101","102","54","55","99","55","56","49");
This shows a warning.
epack(): 7 arguments unused on line
How can I fix this?
The major issue here (if I understand it correctly) is you're using PHP numbers to represent a byte array however unpack requires an input string. If you keep the array as is then PHP seems to just convert the numbers to strings meaning a 101 will be '101' which in turn is 3 bytes, which breaks the whole thing down.
You need to first convert the numbers to bytes. A byte is essentially as an unsigned char so you could first pack your array into unsigned chars and then unpack them:
$bytes = [101,102,54,55,99,55,56,49];
$unpacked = unpack("J", pack('C*', ...$bytes));
echo current($unpacked);
Explanation:
C is the pack code for unsigned char and * indicates that you need to use all array entries. This will generate a string of characters based on the array. You can then unpack this string using J (if you know for a fact that the bytes were generated in a big endian byte order) or P if you know the bytes were generated in little endian order or Q if you want to use the machine order. If the bytes were generated in the same machine then Q would probably be a better choice than J otherwise you need to know the endianess.
Example: http://sandbox.onlinephpfunctions.com/code/5cba2c29522f7b9f9a0748b99fac768012e759ce
Note: This is my personal understanding of what is happening so anyone with better pack/unpack knowledge can let me know if I got things wrong.

PHP equivalent to Python's struct format

I am trying to write Python code to PHP. But I couldn't PHP pack format equivalent to Python pack format
Python:
format = "!LLLLQ"
mystr = struct.unpack(format, str)
I am using like this
$mystr = unpack("!LLLLQ", $str); // But its not working
Because there is no ! or Q in PHP pack.
Is there anyway to achieve that?
Format codes for Python: https://docs.python.org/2/library/struct.html
Format codes for PHP: http://www.php.net/manual/en/function.pack.php
Thanks!
The following sequence:
!LLLL
represents 4 unsigned longs (32 bit) in big endian format. In PHP this would be:
NNNN
However, the Q at the end is problematic. It represents an unsigned long long (64 bit). PHP's pack function doesn't offer unsigned long longs ( Correct me if I'm wrong).
If you unpack the 8-byte unsigned long long using two 4-byte unsigned longs (NN format in PHP), then you can bit-shift the first long 32 bits and add that to the second long to recover the 8-byte unsigned long long. In Python,
In [49]: import struct
In [50]: c = 12345678912345678912
In [51]: struct.pack('!Q', c) # this is the packed string
Out[51]: '\xabT\xa9\x8f\x81e$#'
# unpack the string using `NN` in PHP
In [52]: a, b = struct.unpack('!LL', struct.pack('!Q', c))
In [53]: a, b
Out[53]: (2874452367L, 2170889280L)
This bit-shifts the first number by 32-bits then adds it to the second number.
In [54]: (a<<32)+b
Out[54]: 12345678912345678912L
And this shows that the original number c is recovered:
In [55]: assert (a<<32)+b == c

Same algorithm , different result

Good day, I am making my hashing algorthm, so I am rewriting it to C++ from PHP.
But result in C++ is different than php result. PHP result contains more than 10 characters, C++ result only 6 - 8 characters. But those last 8 characters of PHP result are same as C++ result.
So here is PHP code:
<?php function JL1($text) {
$text.="XQ";
$length=strlen($text);
$hash=0;
for($j=0;$j<$length;$j++) {
$p=$text[$j];
$s=ord($p);
if($s%2==0) $s+=9999;
$hash+=$s*($j+1)*0x40ACEF*0xFF;
}
$hash+=33*0x40ACEF*0xFF;
$hash=sprintf("%x",$hash);
return $hash; } ?>
And here C++ code:
char * JL1(char * str){
int size=(strlen(str)+3),s=0; //Edit here (+2 replaced with +3)
if(size<=6) //Edit here (<9 replaced with <=6)
size=9;
char *final=new char[size],temp;
strcpy(final,str);
strcat(final,"XQ");
long length=strlen(final),hash=0L;
for(int i=0;i<length;i++){
temp=final[i];
s=(int)temp;
if(s%2==0)s+=9999;
hash+=((s)*(i+1)*(0x40ACEF)*(0xFF));
}
hash+=33*(0x40ACEF)*(0xFF);
sprintf(final,"%x",hash); //to hex string
final[8]='\0';
return final; }
Example of C++ result for word: "Hi!" : 053c81be
And PHP result for this word: 324c053c81be
Does anyone know,where is that mistake and how to fix that, whether in php or in cpp code?
By the way, when I cut those first letters in php result I get C++ result, but it wont help, because C++ result have not to be 8 characters long, it can be just 6 characters long in some cases.
Where to begin...
Data types do not have fixed guaranteed sizes in C or C++. As such, hash may overflow every iteration, or it may never do so.
chars can be either signed or unsigned, therefore converting one to an integer may result in negative and positive values on different implementations, for the same character.
You may be writing past the end of final when printing the value of hash into it. You may also be cutting the string off prematurely when setting the 9th character to 0.
strcat will write past the end of final if str is at least 7 characters long.
s, a relatively short-lived temporary variable, is declared way too soon. Same with temp.
Your code looks very crowded with almost no whitespace, and is very hard to read.
The expression "33*(0x40ACEF)*(0xFF)" overflows; did you mean 0x4DF48431L?
Consider using std::string instead of char arrays when dealing with strings in C++.
long hash in C++ is most likely limited to 32 bits on your platform. PHP's number isn't.
sprintf(final, "%x", hash) produces a possibly incorrect result. %x interprets the argument as an unsigned int, which is 32 bits on both Windows and Linux x64. So it's interpreting a long as an unsigned int, if your long is more than 32 bits, your result will get truncated.
See all the issues raised by aib. Especially the premature termination of the result.
You will need to deal with the 3rd point yourself, but I can answer the first two. You need to clamp the result to 32 bits: $hash &= 0xFFFFFFFF;.
If you clamp the final value, the php code will produce the same results as the C++ code would on x64 Linux (that means 64 bit integers for intermediate results).
If you clamp it after every computation, you should get the same results as the C++ code would on 32 bit platforms or Windows x64 (32 bit integers for intermediate results).
There seems to be a bug here...
int size=(strlen(str)+2),s=0;
if(size<9)
size=9;
char *final=new char[size],temp;
strcpy(final,str);
strcat(final,"XQ");
If strlen was say 10, then size will be 12 and 12 chars will be allocated.
You then copy in the original 10 characters, and add XQ, but the final terminating \0 will be outside of the allocated memory.
Not sure if that's your bug or not but it doesn;t look right

PHP's lack of unsigned ints and MySQL's CRC32 function

I told Sphinx to index some strings in their CRC32 forms as attributes, like so:
sql_query = SELECT [...], CRC32(LOWER(color)) AS color, [...], FROM table
sql_attr_uint = color
I'm trying to get some faceted search going in PHP, where users can click on a link with one of the above colors and Sphinx would get another search request going with narrowed down results, something like:
Previous page:
<h3>Narrow down results:</h3>
<p>Red (11)</p>
<p>Yellow (5)</p>
<?php
if (isset($_GET[$name]))
{
$sphinx->SetFilter('color', intval($_GET['color'])); // <-- Uh-oh
}
[...]
$sphinx->Query($query, 'table');
?>
Things goes wrong here because MySQL's CRC32() returns an unsigned 32-bit integer, which PHP very helpfully does not support and caps at 2^31-1. The above link for the color Yellow exposes my problem.
StackOverflow, what may be an acceptable workaround for this? I suppose doing some math on the SQL query side is possible, but I'm wary of making the worrying chance of collision even worse.
Thanks in advance.
Quoting from PHP's crc32() manual page:
Because PHP's integer type is signed, and many crc32 checksums will
result in negative integers, you need to use the "%u" formatter of
sprintf() or printf() to get the string representation of the unsigned
crc32 checksum.
In other words, PHP cannot handle large integers but in this precise case you can emulate unsigned integers to double precision. You can get the real value when casting to string.
This should be enough since you don't need to do mathematical operations, such as addition or multiplication.
Update: I guess I've just ignored the vital part of your question. Rather than this:
intval($_GET['color'])
... you can validate or filter with a regular expression:
preg_match('/^\d+$/', $_GET['color'])
preg_replace('[^\d]', '', $_GET['color'])
... and handle the CRC value as string.

How can you parse a Java 64-bit long from a binary file into a PHP string?

I've used unpack to convert most of the data types I have in a binary file that I'm parsing with little problems. I have no idea how to work with a big endian 64-bit signed long. I think this data type is stored using 2's complement. The application of the data file I'm reading is a java app so I assume it's 2's complement. I don't need to work with it as a number but simply work with it as a string.
Java 64-bit integers are indeed stored natively as "network-order" (big endian, i.e. start with the most significant byte) 8-byte 2's complement format. So typically you take byte at a time, shift left by 8, repeat. Byte values can be thought of as unsigned (while result is signed), but with left-shifting this should not matter.
So: first you just created equivalent 64-bit int from bytes, and display from there. No point in using short cuts; while it is possible, you just end up with more complicated and less efficient code.
32-bit PHP will only have signed 32-bit integers, thus as far as I know, there's no way to natively unpack the data.
The following code should be able to read a big endian, two's complement 64-bit integer:
<?php
function read_int64($fp)
{
$hex = unpack('H16a', fread($fp, 8));
$hex = '0x'.$hex['a'];
$n = gmp_init($hex);
if (gmp_testbit($n, 63))
{
$n = gmp_xor($n, '0xffffffffffffffff'); // flip the bits
$n = gmp_neg(gmp_add($n, 1)); // add one and negate
}
return gmp_strval($n);
}
?>
It returns the integer as a string. It can be used like:
$fp = fopen('test.bin', 'rb');
echo read_int64($fp)."\n";
fclose($fp);
(Edit: Updated code to call fewer GMP functions.)

Categories