IBA verklaart Benamite

Je zult er waarschijnlijk nog nooit van gehoord hebben: Benamite. Toch gebruik je het iedere keer weer als je gebruik maakt van de A–Eskwadraatwebsite. Benamite is het virtuele filesystem van de website. Veel websites gebruiken een fysieke filesystem als structuur van de website. Dit houdt in dat er ergens op een server een mapje moet bestaan. Als je op de website naar bijvoorbeeld www.website.nl/index.html wilt gaan, betekent dat dat er in het mapje op de server een bestand index.html moet bestaan en dat de webserver ook nog de juiste rechten moet hebben om dat bestand te kunnen lezen. Je kunt wel begrijpen dat, als je website uit veel verschillende pagina’s bestaat, je dus heel veel verschillende bestanden nodig hebt, wat nogal veel overhead geeft. De A–Eskwadraatwebsite heeft op dit moment rond de 4000 verschillende unieke pagina’s waarbij de pagina’s die een variabele url hebben, zoals bijvoorbeeld a-eskwadraat.nl/Leden/5794, niet meegenomen zijn. Om de overhead te besparen is er ooit jaren geleden (in 2006 al) Benamite gemaakt.

Hoe werkt Benamite dan? Stel, je gaat naar de pagina https://www.a-eskwadraat.nl/Service/Bugweb/. We vergeten het https://www.a-eskwadraat.nl/-gedeelte want dat geeft alleen het domein aan waarmee de server gevonden kan worden en heeft voor Benamite geen verdere functie. We houden dus de uri /Service/Bugweb/ over. Deze gaan we door Benamite halen. Benamite gaat als eerste de eerste '/' bekijken, wat de root is van de site. Hij kijkt of het wel bestaat in Benamite, of het een map is en of de huidige gebruiker er wel bij mag. Als dit allemaal goed is, gaat Benamite door naar het volgende gedeelte: 'Service/'. Ook hier kijkt hij weer of het bestaat, etc, etc. Op die manier werkt Benamite de delen van de uri een voor een af. Eenmaal bij het laatste aangekomen, zijn er een aantal opties. Als het laatste element een bestand is in Benamite, dan opent hij het bestand. Als het een map betreft, probeert hij het bestand 'index.html' in die map te openen (de naamgeving is door de jaren heen niet veranderd en eigenlijk niet meer van toepassing, want we hebben nauwelijks nog html-bestanden op de website). Als dat bestand niet bestaat, stuurt hij een foutmelding naar de gebruiker.

Dan is er ook nog de speciale ‘variabele entry’. Dit zorgt ervoor dat je bijvoorbeeld elk lid kan bekijken op /Leden/*lidnr*. Een variabele entry is een map met wat extra’s: je kan eisen van de variabele entry wat het moet zijn, bijvoorbeeld een activiteit-id, een commissie-id etc en of het zichtbaar is voor de huidige gebruiker. Vervolgens accepteert de variabele entry alles wat hieraan voldoet. Wat gebeurt er dan, als je dus naar /Leden/5794/ gaat? Benamite handelt eerst /Leden/ af en als dit allemaal goed gaat, komt hij bij het gedeelte 5794/ uit. Er staat in de map /Leden/ geen map of bestand 5794, maar wel een variabele entry. Wat Benamite nu gaat doen, is: hij gaat kijken wat de variabele entry moet zijn. In dit geval moet de variabele entry een lidnummer zijn van een bestaand lid en moet degene die ingelogd is, het lid kunnen zien. Als dit allemaal goed is gegaan, stuurt Benamite het door naar het volgende gedeelte. In alle bestanden die in de map of submappen van de variabele entry staan kunnen we vervolgens met speciale php-functies alle variabele entries uit de url halen en op die manier de juiste objecten erbij halen.

Bestanden in Benamite kunnen verschillende types zijn en dus verschillende functies hebben. Het meest standaard is het normale bestand, waarmee we functies in php-bestanden kunnen aanroepen om op die manier een pagina te maken. Daarnaast hebben we geüploade bestanden, dit zijn bestanden die naar de site zijn geüpload, zoals bijvoorbeeld pdf’jes, afbeeldingen etc. Dan zijn er ook nog Publisherbestanden. Dit zijn bestanden waarvan de html wordt opgeslagen, zodat die later door gebruikers van de website aangepast kan worden en je dus niet in de code van de website hoeft te hekken om de html aan te passen. Dit wordt bijvoorbeeld gebruikt voor pagina’s zoals /Vereniging/Kamer/. Benamite heeft ook links, als een uri eindigt in een link, stuurt Benamite je meteen door naar waar de link naar toe linkt. Als laatste is er nog de php-haak. Dit is een soort midden tussen een normaal bestand en een variabele entry in. Bij een php-haak wordt de rest van de url die nog over is en niet door benamite verwerkt is, rechtstreeks aan de php-haak doorgegeven die er dan vervolgens mee kan doen wat ie wil. Php-haken werden vroeger voornamelijk gebruikt bij de menuutjes; zo werd bijvoorbeeld ‘Open de boekverkoop’, ‘Sluit de boekverkoop’ als de boekverkoop al geopend was. Tegenwoordig worden php-haken nauwelijks meer gebruikt op de A–Eskwadraatwebsite.

Al met al maakt Benamite het beheren van onze fantastische website een stuk eenvoudiger en hopelijk kijk ook jij nu weer anders tegen de website aan dan dat je voorheen deed. Lijkt het je nou leuk om nog meer over Benamite te weten te komen of wil je graag zelf knutselen aan de A–Eskwadraatwebsite, kom dan vooral een keertje langs op onze wekelijkse Werkfeestjes op de dinsdagavond in de A–Eskwadraatwerkkamer!

IBA Verklaart ssh

Al sinds de beginjaren van het internet werden er applicaties gemaakt om in te kunnen loggen op andere computers vanaf je eigen computer. Neem bijvoorbeeld programma’s zoals telnet en rsh (als deze programma’s je niks zeggen, wees gerust, we zullen ze niet behandelen). Echter, de bestaande programma’s hadden niet genoeg beveiliging en waren vatbaar voor bijvoorbeeld wachtwoordsniffers. Daarom besloot Tatu Ylönen in 1995 om een beter programma te maken voor het inloggen op andere computers en hij doopte het programma ‘ssh’ (secure shell). Al vanaf het begin bleek ssh populair en tegenwoordig is het niet meer weg te denken in de wereld van Linux en Macs en wordt het gebruikt om veilig bestanden over te sturen, applicaties op een andere computer te draaien en nog veel meer. Windowsgebruikers moeten zich nog wenden tot andere applicaties om hetzelfde doel te bereiken (denk bijvoorbeeld aan PuTTY) maar Microsoft heeft in 2015 aangekondigd dat het ssh in toekomstige generaties van Windows gaat integreren.

Hoe werkt ssh dan precies, vraag je je misschien af. Laten we eens gaan kijken wat er allemaal gebeurt als je een ssh-connectie probeert op te zetten. Het eerste wat je doet is verbinding maken met de ssh-poort op de ssh-server (meestal poort 22). Op dit moment krijgt de client (dat is de computer vanaf waar je connectie maakt) twee dingen toegestuurd: de protocolversie en de ssh-versie van de server. Als de client het protocol ondersteunt, kunnen ze verder. Op dit moment gaan zowel de client als de server over op een Binair Package Protocol, dat betekent dat de pakketjes die overgestuurd worden nu 32 bits groot zijn. De server stuurt nu zijn publieke sleutel (het publieke deel van de asymmetrische versleuteling, maar dat is weer een verhaal voor een andere keer), 8 willekeurige bits die de client moet terugsturen als antwoord en tenslotte alle soorten encryptie die ondersteund worden. Nu maakt de client een symmetrische sleutel aan en stuurt deze sleutel ook naar de server. Deze sleutel wordt gebruikt om de data die over de ssh gestuurd wordt te versleutelen. Merk natuurlijk wel op dat deze sleutel eerst versleuteld wordt met de publieke sleutel van de server. Ook geeft de client op dit moment aan welke versleutelingsmethode hij gebruikt voor het versleutelen van de data. Als laatste stap wacht de client op een bevestiging van de server. Deze bevestiging is uiteraard versleuteld met de symmetrische sleutel die de client heeft aangemaakt en is belangrijk voor de client; dit is namelijk nu de enige manier om te weten of de client met dezelfde server praat als waar hij net mee heeft gecommuniceerd, dit om zeker te zijn dat er niet iemand is die met alles loopt te rommelen om zo je geheime data te achterhalen. Als dit allemaal goed is gegaan kunnen de client en de server versleuteld en veilig met elkaar babbelen en kan je gaan inloggen op de server.

Dit is natuurlijk een hoop informatie om in 1 keer te bevatten, dus we gaan nu kijken wat er gebeurt als je vanaf thuis bij \aesnaam gaat inloggen. Je probeert dan dus vanaf thuis met poort 22 op de A-Eskwadraatserver te verbinden. Het eerste wat je tegenkomt is de router. De router zorgt voor poortforwarding. Dat houdt in dat de router een lijstje heeft staan met welke poortverbinding hij moet doorsturen naar welke poort op welke machine. Daar staat bijvoorbeeld dat als je op poort 22 probeert te verbinden, de router je doorstuurt naar poort 22 op de ssh-extern-machine van A-Eskwadraat, paul. Vervolgens maak je dus verbinding met poort 22 op paul en treedt het standaard ssh-protocol in werking. In de router staan echter nog meer regels, zo kan je bijvoorbeeld verbinding maken met poort 32022 om op de workstation dennis uit te komen. Probeer het zelf ook eens uit, Linux- en Mac-gebruikers kunnen het commando ssh gebruiken:

ssh [username]@a-eskwadraat.nl -p 32022

Windowsgebruikers kunnen als ze putty gebruiken in putty selecteren met welke poort ze verbinding willen maken.
Natuurlijk wordt de poortforwarding voor veel meer gebruikt dan alleen ssh, denk aan mail of een http-request, maar dat is een verhaal voor een andere keer!

IBA Verklaart Achievements

Zoals velen van jullie al is opgevallen heeft de A–Eskwadraatwebsite sinds kort achievements voor alle ingelogde leden. Natuurlijk is het leuk om zoveel mogelijk achievements te verzamelen maar sommigen zijn misschien wel benieuwd hoe dat nou allemaal in z’n werk gaat, al die achievements.

Achievements kunnen we opdelen in twee categorieën, eenmalige achievements en de zogenaamde ‘medaille’-achievements. Voor eenmalige achievements hoeft 1 bepaalde actie 1 keer uitgevoerd te worden en bij medaille-achievements wordt je voortgang in een teller bijgehouden en er zijn oplopende drempelwaarden voor het halen van elk level van de achievement.

Voor elke eenmalige achievement houden we in een functie bij hoe de achievement gehaald kan worden. Op het moment dat een pagina geladen wordt kijken we of er een achievement gehaald is. Al onze pagina’s op de website worden met een speciale end-functie afgesloten. Aan deze end-functie is nu toegevoegd dat voor het lid dat ingelogd is de achievements gechecked worden. Als er nieuwe achievements zijn, worden deze met javascript bovenaan de pagina weergegeven. De achievementschecker wordt pas bij het afsluiten van de pagina aangeroepen, omdat als de functie bij het begin de pagina zou staan, zou het langer duren voordat de gebruiker een pagina te zien krijgt.

De check voor de medaille-achievements werkt net iets anders. Die functie ziet er als volgt uit:

static public function checkBSGPBadge($badgeNaam, Persoon $pers, $setlast = true)
{
    global $BADGES;

    $badgesBSGP = $BADGES['bsgp'];

    if(array_key_exists($badgeNaam, $badgesBSGP)) {
        $badge = $badgesBSGP[$badgeNaam];

        if($badge['multi'] == 'long') {
            $multiplier = array(1, 2, 5, 10);
        } elseif($badge['multi'] == 'short') {
            $multiplier = array(1, 2, 3, 4);
        }

        foreach($multiplier as $multi) {
            $res = PersoonBadge::badgeBSGPCount($badgeNaam, $pers);
            if($res >= $badge['value'] * $multi) {
                $persoonBadges = $pers->getBadges();
                $persoonBadges->addBadge($badgeNaam . '_' . ($badge['value'] * $multi), $setlast);
            }
        }
    } else {
        user_error("Badge " . $badgeNaam . " bestaat niet!");
    }
}

Eerst wordt er gekeken of de achievement die je wilt controleren (variabele $badgeNaam) wel bestaat in de lijst met bestaande achievements. Dan zijn er twee soorten medailleachievements: short en long. De long-achievements hebben als vermenigvuldigingsfactor 1, 2, 5 en 10 voor brons, zilver, goud en A–Eskwadraat respectivelijk en de short hebben als vermenigvuldigingsfactor 1, 2, 3 en 4. Dan wordt er voor iedere vermenigvuldigingsfactor gekeken of het resulterende getal de drempelwaarde overschrijdt.

Om een zo breed mogelijk aanbod aan achievements te kunnen doen en makkelijk nieuwe achievements te kunnen toevoegen worden de achievements in een json-string opgeslagen. Hier kan je zien wat er gebeurt als er een nieuwe achievement wordt toegevoegd bij een gebruiker:

public function addBadge($badge, $setlast = true)
{
    $badges_json_string = $this->getBadges();
    $last_json_string = $this->getLast();
    
    $badges = json_decode($badges_json_string);
    $last = json_decode($last_json_string);
    
    if(sizeof($badges) != 0 && in_array($badge, $badges)) {
        return;
    }   
    
    $badges[] = $badge;
    
    if($setlast) {
        if(sizeof($last) == 0 || (sizeof($last) != 0 && !in_array($badge, $last))) {
            $last[] = $badge;
        }   
    }   
    
    $badges_json_string = json_encode($badges);
    $this->setBadges($badges_json_string);
    
    if(sizeof($last) != 0) {
        $last_json_string = json_encode($last);
        $this->setLast($last_json_string);
    }   
    
    $this->opslaan();
}

Je kan zien dat eerst de huidige json-string met achievements opgehaald wordt uit het $this-object. Als de achievement al bij de gebruiker staat doen we natuurlijk niets. Dan wordt aan de gedecodeerde json-string (die nu een array is) de nieuwe achievement toegevoegd. Dit wordt dan vervolgens weer als een json-string opgeslagen. Alles met $last in de bovenstaande functie wordt gebruikt om op te slaan wat de nieuwe achievements van de gebruiker zijn sinds de gebruiker voor het laatst is ingelogd.

Dit geeft je een klein beetje een idee hoe de achievements op de A–Eskwadraatsite werken. Heb je zelf nog goede ideeën voor leuke achievements, voel je vrij om ze te melden in de IBA-chat of op Bugweb!