Go Back   vb.org Archive > vBulletin Article Depository > Read An Article > Programming Articles
A Closer Look at Bitfields
Guest190829
Posts: n/a

 

Show Printable Version Email this Page Subscription
Guest190829 01-03-2008, 10:00 PM

This article is helpful if you are curious about the internals of vBulletin permission checking. Sorry about the small thumbnails in advanced! Just click on them to enlarge.

Introduction

Do you find yourself copying and pasting the following code and not knowing the true internals of what it means?

PHP Code:
if(!($permissions['myhackpermissions'] & $vbulletin->bf_ugp['myhackpermissions']['canaddsomething'])) 
From the looks of it, you could probably identify that it involves permissions and if you read some of the great articles on vBulletin.org already regarding permissions, you probably know that this code is checking if a user has permissions for a certain custom modification action.

But what exactly is this code doing; what is the if condition truly evaluating?

Playing Detective

First let us echo out these two variables as if they actual existed:

PHP Code:

echo $permissions[?myhackpermissions?];
// prints out 4
 
echo $vbulletin->bf_ugp['myhackpermissions']['canaddsomething'];
//prints out 1 
Seeing that both the variable are numbers, you may assume that the ampersand (&) in the if condition is performing some sort of arithmetic to the two numbers, and you would be correct.

The & in PHP (and other programming languages) is called a Bitwise Operator , and it returns the bits that are both set in the two numbers. If you are confused, don't worry!

What is a Bit and Bitfield?
  • A bit is simply a binary digit and since binary is a base 2 numerical system, the only possible values of a bit is either 0 and 1.
  • A bitfield is simple just a field of bits such as: 1001, more importantly, a bitfield in programming represents a field of yes/no options that can be checked and manipulated.
Going back to the original code and the values of variables, what does bits and bit fields have to do with the numbers 4 ($permissions[?myhackpermissions?]) and 1 ($vbulletin->bf_ugp['myhackpermissions']['candosomething']) ?

Integers as binary values


Any integer can be represented as a binary digit. The two values above are all divisible by 2, and so they can both be easily represented as a binary numeral, however, even larger and odd numbers can be defined as binary numbers.

Let us convert the two values into binary:

1 = 001
4 = 100

Now, I am not going to go in depth into the conversion of base 10 numerals to base 2, but the basics can be achieved with a table. Since binary is base 2, each bit is a multiple of two starting from 1.

Attachment 74187

Enough with the math, how does this relate to Permissions?!

When creating an bitfield xml for your modification, you increase the number in between the <bitfield> </bitfield> by a multiple of two. Why? Because it can be represented as a bitfield!

Let?s take a look at a sample xml snippet:

Code:
<group name="myhackpermissions">
                <bitfield name="candosomething" group="my_hack_permissions"  phrase="canaddsomething?>1</bitfield>
                <bitfield name="candeletesomething" group="my_hack_permissions"  phrase="candeletesomething">2</bitfield>
                <bitfield name="canviewsomething" group="my_hack_permissions"  >4</bitfield>
</group>
The addition of all the values between the <bitfield></bitfield> tags is 7 (1 +2 + 4):

Using the attached table above, we see that 7 represented in binary is:

1 1 1

Now, imagine that as some sort of toggling board to enable each permission. If it is set to 1 then the user has permission to do that action. Conversely, if it is set to 0 then the user does not have permission to do that action.

So let us say that the if condition being evaluated above is for a guest and the guest is trying to add something to the database.

The administrator has selected that guest can only viewsomething. If we go back to the binary representing of group of permissions:

Attachment 74185

The binary representation of the usergroup Guest?s permissions visually are:

Attachment 74186

Recall the ampersand (&) returns the bits that set in both values:

PHP Code:
$permissions['myhackpermissions'] & $vbulletin->bf_ugp['myhackpermissions']['canaddsomething']) 
  • $permissions['myhackpermissions'] is the integer representation of all the ?yes? permissions that the user has for the specific modification. If this user were an Admin and had permissions to do everything, the value in this variable would be 7 (4 + 2 + 1), however, as we saw when we played detective earlier, the value of this variables is only 4.
  • $vbulletin->bf_ugp['myhackpermissions']['canaddsomething'] is pointing to a specific key in the array of each individual bitfield. This array is just the XML you create in bitfield_myhack.xml parsed in array.
With the example XML data given earlier, the array would look something like:

PHP Code:

/**
   *This is just a visual representation. 
   *vBulletin parses the bitfield xml file via the bitfield_builder classes 
   *and determines the user's permissions with the function 
   *cache_permissions() in   functions.php
 */

$permissions['myhackpermissions'] = array(
     
'canaddsomething' => 1,
     
'candeletesomething' => 2,
     
'canviewsomething' => 4
); 
So $vbulletin->bf_ugp['myhackpermissions']['canaddsomething'] is pointing to the bitfield 1.

The if condition is basically checking if the canaddsomething bit is set to yes in the users permissions.

We can easily perform the bitwise AND operation (&) by vertically aligning the two values in binary form. If any equal bits are both set to 1 that bit is set to 1 in the result, otherwise it is set to 0.

4 = 1 0 0
1 = 0 0 1
====
0 0 0

The result is 0, which converted to a boolean means false, and therefore means that the current user does not have permission to ?addsomething?.

Why Bitfields are Optimal

Think of using bitfields as a pseudo database table. Instead of having to add individual columns to the user table for every possible permission, an integer such as 131072 can represent a table of yes/no (1/0) options by converting it a binary number.

Using bitfields saves space and memory and is very popular method in handling permission systems across many programming languages because computers are very efficient in handling binary data.

Other articles on adding custom Permissions with Bitfields

Now go, go use the magic of bitfields in your next modification with the help of the following great articles!

[How-To] Create User Options (via Bitfields)
[How-To] Create Multiple Options Per Forum (via Bitfields)
[How-To] Create Usergroup Permissions (via Bitfields)

By: Danny Cassidy
Reply With Quote
  #2  
Old 01-04-2008, 06:43 PM
bobster65's Avatar
bobster65 bobster65 is offline
 
Join Date: Mar 2006
Location: Montana
Posts: 1,169
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Thanks Danny ... look forward to your next article
Reply With Quote
  #3  
Old 01-12-2008, 08:09 AM
Omranic's Avatar
Omranic Omranic is offline
 
Join Date: Jan 2005
Location: Egypt
Posts: 536
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

excellent article.

Q: Is there a way to update certain bitfield in the database using MySQL command (I know the value of that bitfield, lets say '128')?
Reply With Quote
  #4  
Old 01-12-2008, 10:17 AM
Opserty Opserty is offline
 
Join Date: Apr 2007
Posts: 4,103
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Great article, if only it was written 2 months earlier when I hadn't a clue about bitfields.

Still, will be very helpful to some people.
Reply With Quote
  #5  
Old 01-12-2008, 10:37 AM
-=Sniper=- -=Sniper=- is offline
 
Join Date: May 2002
Posts: 605
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Quote:
Originally Posted by SolidSnake@GTI View Post
excellent article.

Q: Is there a way to update certain bitfield in the database using MySQL command (I know the value of that bitfield, lets say '128')?
look at http://www.vbulletin.com/forum/showthread.php?t=213135 it might help
Reply With Quote
  #6  
Old 01-12-2008, 04:51 PM
Omranic's Avatar
Omranic Omranic is offline
 
Join Date: Jan 2005
Location: Egypt
Posts: 536
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Quote:
Originally Posted by -=Sniper=- View Post
That's it.
I appreciate your swift reply .
Reply With Quote
  #7  
Old 05-02-2008, 12:49 PM
Jasem's Avatar
Jasem Jasem is offline
 
Join Date: Feb 2006
Location: www.menokia.com
Posts: 594
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Thank you very much
Reply With Quote
  #8  
Old 05-12-2008, 04:39 AM
Ryan Ashbrook's Avatar
Ryan Ashbrook Ryan Ashbrook is offline
 
Join Date: Dec 2002
Location: Cincinnati, Ohio
Posts: 422
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

This article helped me out a lot.

Can't say I fully understand bits now (still gotta reference) but through trial and error I believe I will get there.

Great article Danny.
Reply With Quote
  #9  
Old 06-02-2008, 12:07 AM
consolegaming consolegaming is offline
 
Join Date: Jan 2007
Posts: 168
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Great guide, found it a couple of days ago and it helped immensely on the product I was developing .
Reply With Quote
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT. The time now is 02:36 PM.


Powered by vBulletin® Version 3.8.12 by vBS
Copyright ©2000 - 2024, vBulletin Solutions Inc.
X vBulletin 3.8.12 by vBS Debug Information
  • Page Generation 0.07834 seconds
  • Memory Usage 2,307KB
  • Queries Executed 23 (?)
More Information
Template Usage:
  • (1)SHOWTHREAD
  • (1)ad_footer_end
  • (1)ad_footer_start
  • (1)ad_header_end
  • (1)ad_header_logo
  • (1)ad_navbar_below
  • (1)ad_showthread_beforeqr
  • (1)bbcode_code
  • (4)bbcode_php
  • (2)bbcode_quote
  • (1)footer
  • (1)forumjump
  • (1)forumrules
  • (1)gobutton
  • (1)header
  • (1)headinclude
  • (1)modsystem_article
  • (1)navbar
  • (4)navbar_link
  • (120)option
  • (9)post_thanks_box
  • (9)post_thanks_button
  • (1)post_thanks_javascript
  • (1)post_thanks_navbar_search
  • (9)post_thanks_postbit_info
  • (8)postbit
  • (8)postbit_onlinestatus
  • (9)postbit_wrapper
  • (1)spacer_close
  • (1)spacer_open
  • (1)tagbit_wrapper 

Phrase Groups Available:
  • global
  • inlinemod
  • postbit
  • posting
  • reputationlevel
  • showthread
Included Files:
  • ./showthread.php
  • ./global.php
  • ./includes/init.php
  • ./includes/class_core.php
  • ./includes/config.php
  • ./includes/functions.php
  • ./includes/class_hook.php
  • ./includes/modsystem_functions.php
  • ./includes/functions_bigthree.php
  • ./includes/class_postbit.php
  • ./includes/class_bbcode.php
  • ./includes/functions_reputation.php
  • ./includes/functions_post_thanks.php 

Hooks Called:
  • init_startup
  • init_startup_session_setup_start
  • init_startup_session_setup_complete
  • cache_permissions
  • fetch_threadinfo_query
  • fetch_threadinfo
  • fetch_foruminfo
  • style_fetch
  • cache_templates
  • global_start
  • parse_templates
  • global_setup_complete
  • showthread_start
  • showthread_getinfo
  • forumjump
  • showthread_post_start
  • showthread_query_postids
  • showthread_query
  • bbcode_fetch_tags
  • bbcode_create
  • showthread_postbit_create
  • postbit_factory
  • postbit_display_start
  • post_thanks_function_post_thanks_off_start
  • post_thanks_function_post_thanks_off_end
  • post_thanks_function_fetch_thanks_start
  • post_thanks_function_fetch_thanks_end
  • post_thanks_function_thanked_already_start
  • post_thanks_function_thanked_already_end
  • fetch_musername
  • bbcode_parse_start
  • bbcode_parse_complete_precache
  • bbcode_parse_complete
  • postbit_display_complete
  • post_thanks_function_can_thank_this_post_start
  • postbit_imicons
  • tag_fetchbit_complete
  • forumrules
  • navbits
  • navbits_complete
  • showthread_complete