Grundkenntnisse
Der Computer rechnet im Prinzip nur mit Zahlen, die im
Binärsystem vorliegen. Es gibt nur zwei Ziffern in diesem Zahlensystem, nämlich 0 und 1. Ein Beispiel für eine solche Zahl wäre 110100. Eine Ziffer in einer Zahl heißt
Bit. Ein Bit ist
gesetzt, wenn es den Wert 1 hat, andernfalls (also bei 0) ist es
nicht gesetzt. Die Bits werden von rechts nach links gezählt. Das rechteste Bit ist Bit 0, das links daneben Bit 1 usw.
Rechenoperationen
Für das Binärsystem gibt es spezielle Rechenarten, die meist auf Vergleichen beruhen:
AND
Der AND-Operator ('und') kombiniert zwei Zahlen so, dass im Ergebnis alle Bits gesetzt sind, die in jedem der beiden Operanden gesetzt sind. Ist nur in einem Operanden das Bit gesetzt, im anderen jedoch nicht, ist das jeweilige Bit im Ergebnis nicht gesetzt.
Beispiel:
Code:
1100
AND 1010
--------
1000
In PHP:
PHP:
$ergebnis = $operand1 & $operand2;
OR
Der OR-Operator ('oder') kombiniert zwei Zahlen so, dass im Ergebnis alle Bits gesetzt sind, die in mindestens einem der beiden Operanden gesetzt sind. Sind beide Bits gesetzt, ist auch im Ergebnis das jeweilige Bit gesetzt.
Beispiel:
Code:
1100
OR 1010
--------
1110
In PHP:
PHP:
$ergebnis = $operand1 | $operand2;
XOR
Der XOR-Operator ('exklusives oder') kombiniert zwei Zahlen so, dass im Ergebnis alle Bits gesetzt sind, die in
nur einem der beiden Operanden gesetzt sind. Sind beide Bits gesetzt, ist das jeweilige Bit im Ergebnis
nicht gesetzt! (Hier liegt der Unterschied zu OR.)
Beispiel:
Code:
1100
XOR 1010
--------
0110
In PHP:
PHP:
$ergebnis = $operand1 ^ $operand2;
Bitshifts (>>, <<)
Die Bitshift ('Bitschiebe') - Operatoren << und >> machen ihrem Namen alle Ehre: Sie schieben die Bits umher. Und zwar um die angegebene Anzahl an Stellen in die Richtung, in die die Pfeile zeigen.
Beispiele:
Code:
0011 << 2
---------
1100
1000 >> 3
---------
0001
In PHP:
PHP:
$ergebnis = $operand << $shift;
$ergebnis = $operand >> $shift;
Anwendung
Doch wie hilft und das jetzt weiter? Nun, mit dem AND-Operator können wir jetzt bequem testen, ob ein bestimmtes Bit gesetzt ist oder eben nicht. Ein Bit repräsentiert hier nämlich immer ein Recht. Ist es gesetzt, hat der User dieses Recht, ist es nicht gesetzt, hat er es nicht.
Die Rechte-Variablen definieren wir deshalb als binäre Zahl, in der nur das zugehörige Bit gesetzt ist. Das erreichen wir, indem wir die 1 nehmen, und sie um die notwendige Anzahl an Stellen nach links shiften:
PHP:
$recht[0] = 1; // 0001 (hier wird noch nicht geshiftet!)
$recht[1] = 1<<1; // 0010 (0001 um 1 nach links: 0010);
$recht[2] = 1<<2; // 0100 (0001 um 2 nach links: 0100);
$recht[3] = 1<<3; // 1000 (0001 um 3 nach links: 1000);
usw.
Um nun einem User ein Recht zu geben, setzen wir logischerweise einfach das zugehörige Bit. Und dazu brauchen wir die vorher definierten $recht Variablen und den OR-Operator.
Beispiel: Wir wollen einem User das Recht 'neuen Poll starten' geben. Nehmen wir mal an, zu diesem Recht gehört Bit 3. Die $recht Variable hat also den (binären) Wert 1000. Der User hat schon die Rechte 'News bearbeiten' (Bit 2) und 'News posten' (Bit 1). Seine Rechte belaufen sich also binär dargestellt auf 0110. Nun setzen wir Bit 3 und geben ihm somit das Recht 'neuen Poll starten':
PHP:
$user[rechte] = $user[rechte] | $recht[3];
Und das läuft dabei ab:
Code:
$user[rechte]: 0110
OR $recht[3]: 1000
------------------------
$user[rechte](neu): 1110 (durch die Zuweisung)
Voilá! Schon ist das Bit 3 gesetzt. Hätte der User nun dieses Recht schon gehabt, wäre nichts geändert worden.
Um nun zu prüfen, ob ein User ein Recht hat oder nicht, setzen wir den AND-Operator einfach auf die Variable, in der die Rechte des Users gespeichert sind, und auf die Variable des jeweiligen Rechtes an.
Beispiel: Wir wollen nun wissen, ob der User das Recht 'News bearbeiten' (Bit 2) auch tatsächlich hat. Also kombinieren wir die Rechte-Variable des Users mit der Recht-'Maske' (wie man den zweiten Operator auch meist nennt), in der das 2. Bit gesetzt ist.
PHP:
($user[rechte] & $recht[2])
Code:
$user[rechte]: 1110
AND $recht[2]: 0100
--------------------
0100
Aha! Es kommt also genau wieder die Bitfolge wie bei $recht[2] heraus. Jetzt testen wir noch, ob der User das Recht mit Bit 0 hat (PHP wie oben, nur mit $recht[0] statt $recht[2]):
Code:
$user[rechte]: 1110
AND $recht[0]: 0001
--------------------
0000
Das Ergebnis ist also 0. Daraus können wir schließen, dass bei einem AND-Vergleich Null herauskommt, wenn der User das Recht nicht hat, und eine Zahl ungleich Null, wenn er es hat. Dies können wir dann in eine if-Konstruktion einbauen:
PHP:
if (($user[rechte] & $recht[2]) != 0)
{
// User hat Recht
}
else
{
// User hat Recht nicht
}
Das Entziehen eines Rechtes geht nach einem ähnlichen Prinzip wie das Geben, nur eben mit XOR.
Beispiel: Wir entziehen dem User gleich wieder das Recht 'neuen Poll starten' (er hat wohl Mist gebaut
):
PHP:
$user[rechte] = $user[rechte] ^ $recht[3];
Code:
$user[rechte]: 1110
XOR $rechte[3]: 1000
------------------------
$user[rechte](neu): 0110
Bit 3 ist hier doppelt gesetzt, was bei einem exklusiven Oder zur Folge hat, dass dieses im Ergebnis gelöscht wird. Alle anderen schon gesetzten Bits bleiben unberührt.
Vorsicht: Das Löschen eines Bits per XOR funktioniert nur, wenn man weiß, dass es auch wirklich gesetzt ist!! Ist es nämlich
nicht gesetzt, ist es das nach dem XOR!
Code:
$user[rechte]: 0110
XOR $rechte[3]: 1000
------------------------
$user[rechte](neu): 1110 [!]
Das ist natürlich nicht erwünscht! Deshalb sollte bzw. muss man sogar vor dem XOR prüfen, ob der User das Recht auch tatsächlich hat (mit AND).
So, ich hoffe das war ausführlich und verständlich genug.
Bei Unklarheiten einfach fragen.
Ach ja, das ganze ist natürlich für PHP mit Textfiles ausgelegt. Mit mySQL macht man einfach ein Feld pro Recht in der User-Tabelle, das dann z.B. 1 oder 0 ist.