Well, to clarify, pawn is a language that is pretty similar to C++. I'm programming an Admin Control Panel that requires bit mask permissions (in php) and I actually don't know if I converted the permissions properly (since it's something I have never done) to PHP. I used define() to define permissions. Here's how it originally is (in pawn):
//Pawn
enum EAdminFlags (<<= 1) {
EAdminFlags_None = 0,
EAdminFlags_BasicAdmin = 1, //kick, fine, etc 0
EAdminFlags_CanGiveGuns, //1
EAdminFlags_HouseAdmin, //2
EAdminFlags_IRCAdmin, //3
EAdminFlags_BusinessAdmin, //4
EAdminFlags_AdminManage, //5 can see invisible admins/manipulate admin flags
EAdminFlags_Scripter, //getpvars, reloadcmds, stuff only scripters should need 6
EAdminFlags_HelperManage, // 7 manage helpers/teachers
EAdminFlags_Unbannable, //unbanable under ANY circumstances 8
EAdminFlags_CanRefundSelf, //can refund himself
EAdminFlags_VehicleAdmin, //10 can manipulate player vehicles
EAdminFlags_AntiCheat, //immune to the anticheat 11
EAdminFlags_BigEars, //can /bigears, /bigfamilyears, /bigmouth
EAdminFlags_SetName, //13
EAdminFlags_CanHide, //can toggle/untoggle hidden on themselves 14
EAdminFlags_Invisible, //Invisible on admins list(like 9999s before) 15
EAdminFlags_GiveDrugs, //server manager, can restart the server/do rcon cmds, create job cars 16
EAdminFlags_Unban, //can unban, oban, oprison people 17
EAdminFlags_WeatherManage, //can manage weather/time 18
EAdminFlags_GiveRestrictedGun, //can give restircted guns 19
EAdminFlags_TeleportOthers, //can teleport other people 20
EAdminFlags_CanBanAdmins, //can ban other admins(or any punishments) 21
EAdminFlags_GiveMats, //can give materials 22
EAdminFlags_StatsManage, //23 /setstat, /sethp, /setarmor
EAdminFlags_FamilyAdmin, //24
EAdminFlags_FactionAdmin, //25
EAdminFlags_MassCmds, //26 can do /masstphere, /massmoney, /masskick, /massnuke
EAdminFlags_Nuke, //27 can do things like /nuke, sparta, rangeban
EAdminFlags_RangeBan, //28 can range ban
EAdminFlags_GiveMoney, //29 can /givemoney /money
EAdminFlags_Donations, //30 can give DPS/set donate rank
EAdminFlags_ServerManager, //can restart the server, etc, use /noooc, /nopms, /nonewb
EAdminFlags_All = -1,
};
Now this is how I defined it in PHP:
define("EAdminFlags_None",0);
define("EAdminFlags_BasicAdmin",1);
define("EAdminFlags_CanGiveGuns",1 << 0);
define("EAdminFlags_HouseAdmin",1 << 1);
define("EAdminFlags_IRCAdmin",1 << 2);
define("EAdminFlags_BusinessAdmin",1 << 3);
define("EAdminFlags_AdminManage",1 << 4);
define("EAdminFlags_Scripter",1 << 5);
define("EAdminFlags_HelperManage",1 << 6);
define("EAdminFlags_Unbannable",1 << 7);
define("EAdminFlags_CanRefundSelf",1 << 8);
define("EAdminFlags_VehicleAdmin",1 << 9);
define("EAdminFlags_AntiCheat",1 << 10);
define("EAdminFlags_BigEars",1 << 11);
define("EAdminFlags_SetName",1 << 12);
define("EAdminFlags_CanHide",1 << 13);
define("EAdminFlags_Invisible",1 << 14);
define("EAdminFlags_GiveDrugs",1 << 15);
define("EAdminFlags_Unban",1 << 16);
define("EAdminFlags_WeatherManage",1 << 17);
define("EAdminFlags_GiveRestrictedGun",1 << 18);
define("EAdminFlags_TeleportOthers",1 << 19);
define("EAdminFlags_CanBanAdmins",1 << 20);
define("EAdminFlags_GiveMats",1 << 21);
define("EAdminFlags_StatsManage",1 << 22);
define("EAdminFlags_FamilyAdmin",1 << 23);
define("EAdminFlags_FactionAdmin",1 << 24);
define("EAdminFlags_MassCmds",1 << 25);
define("EAdminFlags_Nuke",1 << 26);
define("EAdminFlags_RangeBan",1 << 27);
define("EAdminFlags_GiveMoney",1 << 28);
define("EAdminFlags_Donations",1 << 29);
define("EAdminFlags_ServerManager",1 << 30);
define("EAdminFlags_All",-1);
I compared the bitflags and most of the time it just recognizes the EAdminFlags_All permission along with EAdminFlags_None and EAdminFlags_BasicAdmin. So there is probably an issue with how I defined this in PHP.
The permissions are stored in a database and they are saved as a raw integer value for example: 51531777
Then it's loaded into PHP and compared like so:
$account = new Account(Auth::getUserID());
echo "Welcome ".$account->getUsername()."<br>";
if($account->getAdminPerms(EAdminFlags_FamilyAdmin)) {
echo "You are a family admin."; //testing purposes
//If the person has those permissions set then display he / she is a family admin but even if the permissions are set to EAdminFlags_BasicAdmin, it will still display it wrong
}
public function getAdminLevel() {
return $this->adminlevel; //This holds the integer value "51531777"
}
public function getAdminPerms($n) {
return ($this->adminlevel & (1 << $n)) != 0;
}
Thank you for your help beforehand, I really appreciate it.
Assuming that your shift operations on the constants are right, there is an error in your detection of a particular rights flag:
public function getAdminPerms($n) {
return ($this->adminlevel & (1 << $n)) != 0;
}
Input is the flag value, which is only a 1 bit set at the correct position. You incorrectly shift again, but all you need to do is AND the integer value with the one read from the database:
public function getAdminPerms($n) {
return ($this->adminlevel & $n)) != 0;
}
The way back works the same. Starting from a zero value, you can add all admin rights flags with bit-OR-ing all the constant values without shifting:
$newAdmin = EAdminFlags_AntiCheat | EAdminFlags_CanGiveGuns;
define("EAdminFlags_BasicAdmin",1);
define("EAdminFlags_CanGiveGuns",1 << 0);
these two are equivalent... shifting by 0 is basically a null operation, so "cangiveguns" has the same value as basicadmin
I basically need to port this piece of code to php
for (i = 0; i < 128/4; i++)
data32[i] = bswap_32(data32[i]);
But, there is no bswap function in php.
Would someone be kind enough to provide me with something that could solve the problem?
This should do it (untested):
function bswap_32($j)
{
return (($j & 255) << 24) | (($j & 0xff00) << 8) |
(($j & 0xff0000) >> 8) | (($j & 0xff000000) >> 24);
}
Or, if there is a sign extension problem, this should resolve it:
function bswap_32($j)
{
return (($j & 255) << 24) | (($j & 0xff00) << 8) |
(($j & 0xff0000) >> 8) | (255 & (($j & 0xff000000) >> 24));
}
It sounds like bswap_32 is swapping endianness of your 32-bit quantities.
I could just give you some code, but I'd prefer not to do people's work for them, so I'll explain the principle instead:
You can achieve that with bit-shifts and masks (so for instance, you need to mask out the 8 lowest bits, and shift them into the highest 8 bit positions of the result).
Shifting can be done with the << and >> operators. Masking can be done with the & operator. See the PHP manual page on operators for more details.
http://www-graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
v = v - ((v >> 1) & (T)~(T)0/3); // temp
v = (v & (T)~(T)0/15*3) + ((v >> 2) & (T)~(T)0/15*3); // temp
v = (v + (v >> 4)) & (T)~(T)0/255*15; // temp
c = (T)(v * ((T)~(T)0/255)) >> (sizeof(v) - 1) * CHAR_BIT; // count
This is the same problem in Python: Python equivalent of C code from Bit Twiddling Hacks?
I need to use this code in PHP, independently from integer size (the above code works up to 128-bit integers, which will do fine for me). Here's what I tried:
function countSetBits($int) {
$mask = (1 << PHP_INT_SIZE*8) - 1;
$int = $int - (($int >> 1) & (int) $mask/3);
$int = ($int & ((int) $mask/15)*3) + (($int >> 2) & ((int) $mask/15)*3);
$int = ($int + ($int >> 4)) & ((int) $mask/255)*15;
return ($mask & $int * ((int) $mask/255)) >> ((int) PHP_INT_SIZE - 1) * 8;
}
The reason this doesn't work (on a 64-bit machine with 64-bit PHP - Debian Squeeze) is that PHP doesn't seem to support 64-bit unsigned integers (how to have 64 bit integer on PHP?). I'm afraid I will have to use an arbitrary-precision math library. Or is there another way?
For now, this is what I used:
function countSetBits($int) {
return substr_count(base_convert($int, 10, 2), '1');
}
Try to use the following in your php script before 64-bit operations:
ini_set('precision', 20);
How can I convert from bytes to float in php? Like in Java
int i = (byte3 & 0xff) << 24 | (byte2 & 0xff) << 16 | (byte1 & 0xff) << 8 | byte0 & 0xff;
Float.intBitsToFloat(i);
There may be a more direct way, but here you go:
<?php
var_dump(unpack('f', pack('i', 1059760811)));
?>
This is, of course, machine dependent, but I don't know of any machine running PHP that doesn't use IEEE 754 floats.
I don't think php has bytes, does it?
When you assign a number to a variable you'll get an variable with a number type
$a = 10; // integer
$f = 1.0; // double
$b = $a + $f; // $b is double
If I'm understanding you correctly, you want to take a raw 32- or 64-bit "integer" value, and force that set of bits to treated as a floating point number instead?
Try the 'pack' and 'unpack' functions
I have an array:
$arr[0] = 95
$arr[1] = 8
$arr[2] = 0
$arr[3] = 0
That are bytes. I need a DWORD.
I tried:
$dword = $arr[0]+$arr[1]*265+$arr[2]*265*265+$arr[3]*265*265*265;
Is that right or am I doing it wrong?
Try:
$dword = (($arr[3] & 0xFF) << 24) | (($arr[2] & 0xFF) << 16) | (($arr[1] & 0xFF) << 8) | ($arr[0] & 0xFF);
It can also be done your way with some corrections:
$dword = $arr[0] + $arr[1]*0x100 + $arr[2]*0x10000 + $arr[3]*0x1000000;
Or using pack/unpack:
$dword = array_shift(unpack("L", pack("CCCC", $arr[0], $arr[1], $arr[2], $arr[3])));
Or try<?php
$arr = array(95,8,0,0);
$bindata = join('', array_map('chr', $arr));
var_dump(unpack('L', $bindata));both (Emil H's and my code) give you 2143 as the result.
Or at the very least use 256 rather than 265.
Your code should work correctly, but you should multiply with 256, not 265. (in 8 bits, there are 2^8 = 256 unique values). It works, because multiplying with 256 is the same as shifting the bits 8 places to the left.
Perhaps you should consider using the bitwise operators instead, to better convey the intent. See http://theopensourcery.com/phplogic.htm