Page 1 of 1

Bitwise Permissions

Posted: Tue Feb 21, 2006 1:08 pm
by shiznatix
Ok! I honestly think this is the most difficult way to do permissions but there is no choice right now as it is not my call.

Basically I have a array like this

Code: Select all

[1] => w
[4] => r
[8] => r
[16] => w
[32] => w
[65536] => r
[64] => r
[128] => r
[256] => r
[512] => r
[1024] => r
[2048] => r
[8192] => r
[2] => r
[4096] => r
[32768] => r
[16384] => r
And here was the expanation (i have noooooo idea)

"
when user has rperm=11 (b1011) then 11&4=0 (false)
when i want to change permission i use XOR?: 11^4=15 (1011^0100=1111) and 15^4=11 (1111^4=1011)
from adm_users.php:

Code: Select all

if($data['rperm']&(int)$item)
{
    if($data['perm']&(int)$item)
    {
        $bla="perm='".($data['perm']^(int)$item)."',rperm='".($data['rperm']^(int)$item)."'";
    }
    else
    {
        $bla="perm='".($data['perm']^(int)$item)."'";
    }
}
else 
{
    $bla="rperm='".($data['rperm']^(int)$item)."'";
}
perm && rperm = w
perm && !rperm = w
!perm && rperm = r
!perm && !rperm = n
"

Well OK! the $data['perm'] and rperm are the users current settings. the key of the array i showed is the website sections bitwise thing. I need to know what to make $item based off of the value of the array i posted to make it work. r = read, w = write, n = no permission at all.

I read some stuff on this but I am seriously at a complete loss. anyone have any help for this?

Posted: Tue Feb 21, 2006 1:15 pm
by josh
I think the easiest way to solve those is to convert it to an integer and add / subtract the appropriate amount and then re-pack the data


pack()
unpack()

I'm sure someone here knows how to do the bitwise operations though (feyd?, timvw?, d11?)

Posted: Tue Feb 21, 2006 1:18 pm
by feyd
Rearranged bits to make sense.

Code: Select all

[1] => w
[2] => r
[4] => r
[8] => r
[16] => w
[32] => w
[64] => r
[128] => r
[256] => r
[512] => r
[1024] => r
[2048] => r
[4096] => r
[8192] => r
[16384] => r
[32768] => r
[65536] => r
shiznatix wrote:I need to know what to make $item based off of the value of the array i posted to make it work.
To make what work? What needs to be the resultant $bla for each if?

Posted: Tue Feb 21, 2006 1:22 pm
by shiznatix
aye that looks alright but none of this is in binary. its all numbers like this:

rperm is 1048575 for almost everyone
perm is like 11, 257, 261, 31653

and whatnot. this stuff is confusing, but this tobasco sauce is great.

Posted: Tue Feb 21, 2006 1:50 pm
by josh
Yeah that just means its already in integer form, just add - subtract the values for each permission like this:

Code: Select all

[1]  - w
[2]  - r
[4] -  w

say it looks like that, wrw would look like:

1+2+4 or 7, to take off the r subtract 2....

7-2 = 5

1+4 = 5 ==wrw

it's basically instead of doing the bitwise operations

Posted: Tue Feb 21, 2006 2:34 pm
by shiznatix

Code: Select all

foreach ($_POST as $key => $val)
        {
            if (!is_numeric($key))
                continue;

            $i++;

            $sql="
              SELECT
                * 
              FROM
                users 
              WHERE
                user_id='$key'
            ";

            $result = mysql_query($sql) or die("Päringule ei leitud ühtegi vastet");

            $data = mysql_fetch_assoc($result);

            dump($val);//this is where the big array i posted before was generated from

            foreach ($val as $key2 => $val2)
            {
                if($data['rperm']&(int)$item)
                {
                    if($data['perm']&(int)$item)
                    {
                        $bla="perm='".($data['perm']^(int)$item)."',rperm='".($data['rperm']^(int)$item)."'";
                    }
                    else
                    {
                        $bla="perm='".($data['perm']^(int)$item)."'";
                    }
                }
                else 
                {
                    $bla="rperm='".($data['rperm']^(int)$item)."'";
                }

                $sql = "
                  UPDATE
                    users
                  SET
                    $bla
                  WHERE
                    user_id='$key'
                  LIMIT 1
                ";

                mysql_query($sql) or die("Päringule ei leitud ühtegi vastet");
            }
        }
that is the whole code that I need to make work to update the users preferences. Maybe that makes somthing clearer?

jshpro2: is there a way that i could turn that into a bitwise number? stuff sounds like it might work but i really don't know much about this stuff.

Posted: Tue Feb 21, 2006 2:36 pm
by feyd
It doesn't need to be bitwise (it already is). Your database is storing them in standard integer form it appears.

Posted: Tue Feb 21, 2006 5:10 pm
by shiznatix
sorry I am replying without definate yes worked or no didnt work answers but I want to make sure this will work before i go and destroy these people's permissions.

so feyd: if i just do what jshpro2 said then it should technically work? what should I make the $item variable set to?

Posted: Tue Feb 21, 2006 5:23 pm
by feyd
As long as the bits never mix, addition and subtraction can be performed without ill effects.

I have yet to understand what you need $item to do. What is the result you are looking for in $bla for a given input? Is $item a one time setting?

Posted: Tue Feb 21, 2006 5:31 pm
by feyd
for some further learning of bitwise math and some explanations of how bit math works
viewtopic.php?t=39199

Posted: Wed Feb 22, 2006 12:53 am
by shiznatix
1st responce:
$bla is what goes into the query to update perm, rperm, or both so like blah may end up looking like

$bla = 'perm = *number*'; or $bla = 'perm = *number1*, rperm = *number2*';

then I use the perm and rperm in the other parts of the script to check permissions to do certain things.

$item needs to be some number to take the current permission to so i come up with the new bitwise permission. I don't know how that works and thats basically my problem.

2nd responce:
I'm looking at it now, good stuff but seams to be a bit out of my league right now.

*sigh* i hate math

Posted: Wed Feb 22, 2006 1:28 am
by feyd
okay.. lets go through the basics of bit work. Feyd's school of bit math is now in session. Class, sit the frak down.

There are 4 operators that work with bits. They are & (bitwise and), | (bitwise or), ^ (bitwise exclusive-or), and ~ (bitwise negation). For demonstration purposes, I will use 13 and 10 (base 10 a.k.a. decimal) for all examples. In binary (base 2) these two numbers are 1101 and 1010 respectively.

Here's how each works in simple form.

Bitwise And is used to see what bits are set in common between two operands.

Code: Select all

1101
  & 1010
  ------
    1000
As you can see, the left most bits are in common between the two numbers. Result is 4. Here's a cheat sheet for And

Code: Select all

a & b = c
  0 & 0 = 0
  1 & 0 = 0
  0 & 1 = 0
  1 & 1 = 1
Bitwise Or is used to combine the bits together.

Code: Select all

1101
  | 1010
  ------
    1111
As you can see, all of the places had bits. Result is 15. Here's a cheat sheet for Or

Code: Select all

a | b = c
  0 | 0 = 0
  1 | 0 = 1
  0 | 1 = 1
  1 | 1 = 1
Bitwise Xor (Exclusive Or) is used flip bits where set.

Code: Select all

1101
  ^ 1010
  ------
    0111
As you can see, only the bits different between the two set. Result is 7. Here's a cheat sheet for Xor

Code: Select all

a ^ b = c
  0 ^ 0 = 0
  1 ^ 0 = 1
  0 ^ 1 = 1
  1 ^ 1 = 0
Bitwise Negation is used invert all bits. It is only used against a single operand unlike the other binary operators so far.

Code: Select all

~ 1101
  ------
    0010
As you can see, what was black is now white and white, black. Result is 2. Here's a cheat sheet for Negate

Code: Select all

~a = b
  ~0 = 1
  ~1 = 0

You can combine them in interesting ways. Here's a common one:

Code: Select all

error_reporting(E_ALL & ~E_NOTICE);
E_ALL is a bitfield, E_NOTICE is a single bit. This is used to make sure E_NOTICE is turned off in the result. Although I don't condone the code, it is a good common example.

Posted: Wed Feb 22, 2006 2:03 am
by duk
some honest opinion... i dont know nothing about bitwise but ive already see some posts about this and im trying to learn more...

but when we develope a web site or some servive online this bitwise, its realy good or will just complicate things... for example for the more experience people here you use bitwise for your applications permissions... ???

Posted: Wed Feb 22, 2006 2:17 am
by feyd
If this were a compiled application, I may use bitfields where beneficial (not many real-world situations call for it.) For the web, I normally wouldn't. This is mostly due to wanting to avoid bugs (simple math errors can wreak havoc on these), but also from ease of building the application. To really use bitfields in php, you can only have 31-32 (depending on your build) bits without breaking into binary strings or other alternates. At that point, it becomes a burdon.

So although I could do a lot of things with them, if I have to share the code with anyone else, I'll avoid them. They are confusing enough to most that the bug potential is WAY too high.

Posted: Wed Feb 22, 2006 3:00 am
by onion2k
I use bitwise permissions a lot. In general I do this sort of thing:

Code: Select all

// Define permissions .. just standard decimal numbers .. if the permissions are stored in a 32 bit INT in the database you can have up to 32 seperate permissions.
define ("PERM_READ",1);
define ("PERM_INSERT",2);
define ("PERM_UPDATE",3);
define ("PERM_DELETE",4);

// Grant permissions ..
$userLevel = 0; // No permissions set .. obviously in a real scenario you'd be getting an INT from a database here.
$userLevel = setbit($userLevel,PERM_READ); // Give read permission
$userLevel = setbit($userLevel,PERM_INSERT); // Give add permission
$userLevel = setbit($userLevel,PERM_UPDATE); // Give update permission
$userLevel = setbit($userLevel,PERM_DELETE); // Give delete permission

// Check permissions
if (readbit($userLevel,PERM_READ)) {
  // Code to read a record
}
if (readbit($userLevel,PERM_INSERT)) {
  // Code to add a record
}
if (readbit($userLevel,PERM_UPDATE)) {
  // Code to edit a record
}
if (readbit($userLevel,PERM_DELETE)) {
  // Code to delete a record
}

// Revoke permissions .. normally you'd revoke some and then update the INT in the database.
$userLevel = clearbit($userLevel,PERM_READ); // Revoke read permission
$userLevel = clearbit($userLevel,PERM_INSERT); // Revoke add permission
$userLevel = clearbit($userLevel,PERM_UPDATE); // Revoke update permission
$userLevel = clearbit($userLevel,PERM_DELETE); // Revoke delete permission

// Bitwise functions
function setbit($val, $bit) {
	if (readbit($val, $bit)) return $val;
	return $val += '0x'.dechex(1<<($bit-1));
}

function clearbit($val, $bit) {
	if (!readbit($val, $bit)) return $val;
	return $val^(0+('0x'.dechex(1<<($bit-1))));
}

function readbit($val, $bit) {
	return ($val&(0+('0x'.dechex(1<<($bit-1)))))?'1':'0';
}