Your presentation of your problem indicates that you want to emulate the permission system as used by POSIX like systems (Unix). The three sets (user, group, and world), and three permissions (read, write, execute) are from that. Your actual implementation though is very different....
What you have will work, but is wasteful of bits, and is only a partial bitwise solution.
Consider the permissions 0777
(by the way, the 0
there is supposed to indicate that the value is Octal - did you know that? - see PHP's documentation on Integers)
The 7 permission is the read permission (4), the write permission (2), and the execute permission (1). The important thing is to look at it in binary though:
read 00000100
write 00000010
exec 00000001
If we 'OR' all those permissions, we get:
rwx 00000111
Now, the way things are supposed to work, is that the right-most 3 bits represent the permissions of the world users, the next are the group users, and then the actual user:
user rwx 00000001 11000000
group rwx 00000000 00111000
world rwx 00000000 00000111
The left-most 7 bits are also used on most systems to represent other properties about the file. For example, in Linux, the details of the bits are described in the stat
system function (remember, the leading 0 on the numbers means the number is in Octal...!!!):
S_IRWXU 00700 mask for file owner permissions
S_IRUSR 00400 owner has read permission
S_IWUSR 00200 owner has write permission
S_IXUSR 00100 owner has execute permission
S_IRWXG 00070 mask for group permissions
S_IRGRP 00040 group has read permission
S_IWGRP 00020 group has write permission
S_IXGRP 00010 group has execute permission
S_IRWXO 00007 mask for permissions for others
(not in group)
S_IROTH 00004 others have read permission
S_IWOTH 00002 others have write permission
S_IXOTH 00001 others have execute permission
The second reminder about the Octal numbers is important. Note that octal numbers go from 0 to 7. This is conveniently 3-bits in binary (and hexadecimal is conveniently 4 binary bits per hex digit).
OK, so, that's how it's normally done. Setting read-write-execute permissions for user, group, and world results in the binary:
00000001 11111111
which is 511 in decimal. Note, if I want to test whether the user has execute permission, it is a simple case of testing with:
00000000 01000000
If the permission is $perm = 0777
(octal) and the test is $userexec = 0100
(execute for user in octal), then we can do:
if (userexec & perm != 0) {
// user has execute permission
....
But, what does your code do? It does:
7 * 100 + 7 * 10 + 7
which is 777 in decimal, and, unfortunately, in binary it is
00000011 00001001
Now, if I want to determine if the user has write-permissions, I have to do divisions and bit-tests to get there (which is what you do, but it's not the way it is supposed to be).
So, with all that background, what should your code look like? First, let's talk about bit shifting...
If I have the bits (in binary):
00000000 00000111
and I then shift them all 3 positions to the left, I will have:
00000000 00111000
I can left-shift bits with the left-shift operator <<
. So, the first value there is 0007
(octal), and I can do:
$threebits = 0007;
$threebits = $threebits << 3;
After that shift, $threebits
will have the (octal) value 0070
.
Note that we need to shift permission bits 0 times for the world permissions, 3 times for group, and 6 times for user.....
$read = 4;
$write = 2;
$exec = 1;
$world = 0;
$group = 3;
$user = 6;
function check($requestedPerm, $level, $permInt){
return ($requestedPerm << $level) & $permInt != 0;
}
Note that using the above logic we expect the $permInt
to be in a different format to what you had.... so, your current code is:
$bool = check($read,$group,754);
But, that will need to change (to add the 0 to make it octal...):
$bool = check($read, $group, 0754);