IBA verklaart Antiquiteiten van Bookweb en andere hilariteiten

Volgens de website bestaat de WebCie al sinds 1 januari 1970, dat is zo’n 25 jaar voor het uitvinden van het concept “website”! Volgens Git, ons versiebeheersysteem (wat vroeger SVN was (wat vroeger CVS was)), bestaat de code van de website al vanaf 1 juli 2000. Bookweb is het antiekste deel van de website en als je dit leest, is het nog steeds niet vervangen met een modern en superfancy nieuw boekenweb! Allemaal veranderingen in de vereniging kunnen we als jaarringen terugvinden in de code.

De huidige grote revisie van onze websitecode heet WhosWho4 omdat het de vierde editie is van ons ledenzoeksysteem. In het begin was WhosWho nog gewoon een collectie programmaatjes geschreven in de programmeertaal C, om de ledenadministratie bij te houden, maar ook al in code uit oktober 2000 wordt code geïntroduceerd die we nog altijd gebruiken. Hierbij zit bijvoorbeeld de functie tryPar, om parameters uit webrequests te lezen.

We hebben een overlevingsgrafiekje gemaakt, van welk percentage van de code gecommit op een bepaalde datum nog terug te vinden is in de huidige code.
survival_plot
Om eerlijk te zijn hebben we geen idee hoe al die plotselinge verspringingen zijn gebeurd, maar vermoedelijk hangt het samen met werken met branches (die in SVN neerkomen op alle code copy-pasten naar een andere map) en/of gegenereerde code. Je kunt ook interessante patronen ontdekken in de totale hoeveelheid regels code waar de website op gegeven momenten uit bestond. In deze grafiek zijn ook allemaal rare verspringingen te zien, die vermoedelijk met de verspringingen in de andere grafiek te maken hebben.
stack_plot

We hebben nog een paar interessante statistieken te geven over de Git-repository die we gebruiken bij de WebCie. Op het moment van schrijven (25 oktober 2017) bestaat de repository uit 15962 commits wat neerkomt op een gemiddelde van 2.5 per dag, of 4.9 per dag als je alleen de dagen meerekent waarop een commit gedaan is. De repository is 6324 dagen oud, waarvan op 3252 dagen een commit heeft plaatsgevonden. Over de gehele geschiedenis zijn er 1950084 regels toegevoegd en zijn er 1285980 regels verwijderd, waarmee je een huidig aantal van 664104 regels in de repo hebt. Niet geheel tegen de verwachtingen in zijn de maanden juli en augustus de minst actieve maanden; het aantal commits in deze maanden is samen goed voor slechts 8% van de totale commits.

In zulke oude code kom je nog wel eens “interessante” constructies tegen, zoals de onbegrijpelijke amalgamatie aan if-statements die in Bookweb draait als de boekencommissaris een rapport van de verkopen wil hebben en op de knop “Poep CSV-bestand uit” drukt. Leveranciers verwijder je niet, die worden “Weggeflikkerd”. Gaat er iets mis in deze brij, dan verschijnen er ook mooie foutmeldingen zoals “Whaa, het ging mis met $error, schop meteen een technisch persoon in zijn ballen!!!!” (waarbij $error staat voor dingen als 'WAAROM HEB IK GEEN TYPE?'). Inconsistenties in de administratie worden vermeld in de variabele $hedzerregels, vermoedelijk als belediging aan het adres van een zekere Hedzer die in het bestuur en WebCie zat. Als je de juiste rechten hebt, wordt de link naar deze pagina in het menu toegevoegd door de “Financieelmaaktnietuitmenucontenthook”. Als je als commissielid leden wilt inschrijven voor je activiteit maar je hebt geen leden geselecteerd wordt je door website op je vingers getikt met de melding “Je moet wel iemand selecteren Willem!”.

Groetjes, De ldap-check, de ldap-check, Kentucky Fried Chicken en de ldap-check

Ook gebruikers kunnen er wat van, met behulp van de doe-het-zelf sitebouwer de Publisher. Zo zit er in een mapje met verscheidene HTML-pagina’s uit 2006 ook de pagina kim, met als enige inhoud “Je bent lief!”, gemaakt door de toenmalige boekencommissaris, die naar verluidt een oogje had op de toenmalige commissaris intern. Verder zijn hier de pagina bedankt!, prachtige ouderwetse screenshots screenshots en archeologisch bewijs voor ledenpassen te vinden.

Toch kunnen we de mooiste lelijke constructies vinden in interne data. Het systeem dat voor Nederlandse tekst (waar beschikbaar) een Engelse tekst opzoekt, verwerkt opmerkingen die beginnen met VOC:, vernoemd naar de Vertaal- en Onderhoudscommissie van vier jaar terug, inmiddels vervangen door de Webredactie, die inmiddels is opgegaan in de PromoCie. Dit vertaalsysteem geeft soms de melding “FOUT: draai _(‘verfris’) in de wortel van je (mineraal?)bronnen”, als het wil dat je het scriptje “update” uitvoert in de map waar de source code te vinden is, ook wel “root” genoemd.

if(!$ster->checkUrl($entry->getName())) //Als dit fout gaat is er echt stront aan de knikker!

Mails correct versturen blijkt overigens ook niet zo makkelijk: omdat een mailprogramma anders omgaat met witregels dan een browser, dacht iemand slim te zijn en overbodige witruimte als volgt aan te pakken: neem alle juiste witruimte en vervang dat met de string “#SOEPMES#”, gooi alle andere witregels weg en vervang alle SOEPMESsen met de juiste witregels. En nu maar hopen dat niemand SOEPMES in zijn activiteitomschrijving vermeldt, zo zegt het bijbehorende commentaar.

Omdat er veel WebCieërs zijn die graag debuggen met de PHP-functie var_dump (een functie waarmee je meteen de inhoud van een variabele op het scherm weergeeft) wil het nog wel eens voor komen dat er een var_dump blijft staan in de code die gecommit wordt. Omdat er in het verleden kennelijk iemand was die nogal de neiging had dit erg vaak te doen zijn er maatregels genomen; iedere keer als je een var_dump probeert te committen krijg je de vriendelijke foutmelding “Eerst je debug code verwijderen, loeki.”.

Ben je dus een fan van oude code uitspitten om te snappen hoe het ooit had moeten werken, of juist iemand die in een avondje zulke fantastiche constructies uitdenkt, ook voor jou is het bij de WebCie altijd een feestje!

Ork ork ork, soep eet je met een…

#SOEPMES#.

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 POST Requests

Zo rond het begin van de jaren negentig kwam Tim Berners-Lee op het idee van het WereldWijde Web. Alle informatie op de wereld wordt daarmee aan elkaar gekoppeld met behulp van pagina’s die links bevatten naar andere pagina’s. Met een browserprogramma dat HTTP (Hypertext Transfer Protocol) spreekt, kan iedereen deze pagina’s ophalen van servercomputers die over de hele wereld verspreid zijn. Meer dan twintig jaar later is het principe van het web nog ongeveer hetzelfde gebleven, maar dan compleet anders opgevat. Pagina’s zijn geen statische documenten meer die ergens op een harde schijf staan, maar interactieve programma’s die doen alsof ze statische documenten zijn die ergens op een harde schijf staan. Daarbij komt nog aardig wat kijken.

Lees verder IBA Verklaart POST Requests

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!