Posts by FangorN

    In deze opzet is het wss niet duidelijk wanneer een herhalend event plaatsvindt.


    Een alternatief is wellicht het volgende: maak een tweede tabel recurring_events oid, en zet daarin een start- en einddatum en een interval in tijd (maak je het ook nog flexibeler dan enkel wekelijks). Als je zo'n terugkerend event vervolgens wegschrijft wordt berekend wanneer dit event plaatsvindt en deze events worden dan weggeschreven als "gewone" events in de eventtabel. Of je maakt een crontab die dat voor de komende week / maand uitrekent ofzo.


    Vervolgens kun je alle events op dezelfde manier behandelen en voorkom je de rare spagaat waarin je je nu bevindt.

    @D.Oomens: jij hebt het waarschijnlijk meer over het gebruik van MySQL, wat niet altijd veilig zou zijn.


    Het potentiële veiligheidsprobleem wat je noemt (SQL-injectie) komt voort uit een onjuist gebruik van MySQL bij het opbouwen van je (dynamische) queries in de code waarmee je communiceert met je MySQL-database.


    PHP heeft voorzieningen om SQL-injectie tegen te gaan, het is de verantwoordelijkheid van de programmeur dat hij/zij vertrouwd is met de regels van het spel om queries (en op grotere schaal, de gehele applicatie) veilig te maken.


    Een handgranaat is niet onveilig als je weet wat je doet. Als je dit niet weet... Tsja.

    Ik heb die code nog eens bekeken, en die is toch wel heel wollig om enkel een connectie te maken... en regelt verder helemaal niets. Je zou je ook af kunnen vragen waarom je je login credentials zou willen onthouden binnen een object van de klasse? Wat is het nut / de toegevoegde waarde daarvan?


    Over try-catch vs die(): als je connectie mislukt omdat je login gegevens verkeerd zijn of de database op een of andere manier onbereikbaar is dan zou ik verdere uitvoer van het script gewoon staken met die(). Dit omdat er op dat moment waarschijnlijk iets grondig mis is in de (server)configuratie. Garanties ten aanzien van het (verder) correct werken van je applicatie kun je dan niet echt meer geven. Het is waarschijnlijk ook geen fout waar je snel (vanzelf) van zult "herstellen".


    Soms moet je de boel gewoon laten ontploffen in plaats van dingen tegen beter weten in draaiende proberen te houden. In dat laatste geval kun je er mogelijk pas in een heel laat stadium (of na heel veel onderzoek) achter komen dat iets gewoon niet werkt.


    Combinaties van fouten kunnen ook nieuwe fouten opleveren. Dat gaat je op den duur problemen opleveren die je niet meer uit de weg kunt gaan. En dan moet je dus dingen gaan repareren en dan is de kans heel erg groot dat je ineens een heleboel moet repareren als je daarvoor een strategie hanteerde waarbij je alle fouten onder het tapijt veegt.


    Om een heel andere reden is het bij PDO wel weer verstandig om je connectie te regelen binnen een try-catch blok. Dit vanwege het feit dat als de connectie (om wat voor reden dan ook) mislukt, er een exception ge-throwd wordt. Een exception die je niet catcht levert een fatal error op. En laten de lichten die bij de ontwikkeling van PDO actief zijn geweest nu bedacht hebben dat je login-gegevens afgedrukt worden in deze exception/fatal error... die liggen dan dus waarschijnlijk op straat als je dit zelf niet netjes afhandelt.


    Nadat je connectie "up and running" is (en ook andere objecten die je in je applicatie gebruikt succesvol zijn aangemaakt) zou je natuurlijk altijd een try-catch blok om de rest van je applicatie -en daarmee ook rond de uitvoer van queries- kunnen zetten. Het kan natuurlijk altijd voorkomen dat de uiteindelijke vorm van een query die dynamisch wordt opgebouwd niet goed is. Het is dan wel zo netjes dat eindgebruikers een nette foutpagina zien in plaats van een "or die(mysql_error())" boodschap. In je catch-blok kun je de fout ook ergens loggen zodat je later terug kunt lezen wat er fout ging.


    Ik zou zelf voor een wat andere aanpak kiezen als ik een "wrapper" zou schrijven voor mysqli. Eentje met toegevoegde waarde en een zeker gebruikersgemak. Indien gewenst kan ik een vereenvoudigde vorm posten voor wie interesse heeft.

    En, for the love of all that is good and holy, stel alsjeblieft een character encoding in, bijvoorbeeld utf8 (dit is geen typo, zo heet de UTF-8 character encoding in MySQL).


    Dit doe je middels een _set_charset() aanroep, bij voorkeur direct na het maken van een verbinding met je database.


    Wanneer je geen of de verkeerde character encoding instelt is er geen garantie dat je _real_escape_string() functionaliteit (waarmee je je queries beveiligt tegen SQL injectie) correct werkt.


    Daarnaast kan dit resulteren in het verkeerd encoden van data die je wegschrijft naar je database (lees: de data in je database is dan in feite dus CORRUPT). Hier heb je normaal geen last van (omdat MySQL veel voor je regelt onder de motorkap) totdat je je character encoding goed instelt, en dan heb je stront.


    Vervolgens is het het makkelijkste om in je hele applicatie je character encoding gelijk te schakelen. Gebruik daartoe een PHP header() aanroep, of stel het desnoods in in een meta-tag.


    Ik kan dit wel op een pamflet stempelen en elke keer uitdelen, want dit wordt keer op keer gewoon vergeten.


    Elke developer zou http://www.joelonsoftware.com/articles /Unicode.html eens moeten lezen...

    Ik vond een soortgelijk resultaat (eerste Google resultaat): internet explorer - Detect IE version (prior to v9) in Javascript - Stack Overflow


    Alternatieven te over, maar dat is niet zijn vraag. Zijn vraag is waarom bovenstaande code niet werkt.


    De syntax op regel 4 is mij onbekend (ben deze vorm niet eerder tegengekomen).


    Weet je zeker dat je geen JavaScript syntaxfouten krijgt in oudere IE versies? Misschien breekt een library die je gebruikt iets? Heb je geprobeerd je regex / navigator.userAgent te debuggen / af te drukken?


    Probeer te pinpointen waar (welke regel) het misgaat en gebruik anders een alternatieve oplossing. In zowel de link van Ferhat als die van mij staan enkele alternatieven.


    EDIT: misschien gaan oudere browsers anders om met (typecasting in) JavaScript? De retour-waarde van je regex is waarschijnlijk een string? Heb je geprobeerd parseInt() op je versienummer toe te passen zodat je twee integers vergelijkt in je if-statement?

    Ooit een internetbureau geprobeerd? Deze helpen meestal ook met conceptvorming en weten doorgaans wat wel en niet gaat werken.


    Informeer naar de (voorwaarden en) mogelijkheden van offertes, designs en/of proof-of-concepts.


    Als andere manieren niet bleken te werken, blijft dit zo'n beetje over. Of je bouwt het toch zelf waarbij je gebruik maakt van een framework of een CMS (Content Management Systeem).


    Ik ben er zelf geen fan van, maar misschien is Drupal iets voor jou. Dat is een pakket met "bouwstenen" voor het in elkaar klikken van een site (heeft natuurlijk wel wat meer voeten in de aarde dan dat). Ook dat heeft een (stijle) leercurve.


    Los van dit alles kan het geen kwaad als je je verdiept / blijft verdiepen in wat meer technische materie. Zo krijg je zelf ook een beter gevoel wat er allemaal (niet) kan. Tenzij je dit echt niet ligt, natuurlijk.

    Je $home moet $1 zijn


    Als je mijn eerste reactie had gelezen, had je geweten dat dit alleen niet genoeg is.


    Daarnaast kan wat extra uitleg ook geen kwaad. Ik geef mensen liever een hengel dan een vis want je zult op een gegeven moment wel inzien dat iedereen altijd honger heeft :). Ik heb liever dat ze op den duur zelf kunnen vissen.

    Hier is een voorbeeld van een .htaccess bestand dat alles doorstuurt naar index.php.


    De .htaccess:


    index.php:


    Vervolgens kun je allerlei URL's aanroepen, deze worden allemaal doorgestuurd naar index.php. Vervolgens kun je met behulp van $path nagaan welke specifieke pagina's iemand op wilde vragen.

    Iets wat je sowieso kunt doen is het toevoegen van een base-tag in je HTML head, anders kloppen je relatieve verwijzingen van je stylesheets niet meer. Deze regel moet je uiteraard VOOR enige verwijzing naar een stylesheet zetten.


    Bijvoorbeeld:

    Code
    <head>
    ...
    <base href="http://www.futurehousemusic.net/">
    ...
    </head>


    Je browser denkt namelijk dat je in een subfolder zit. Als je een relatieve verwijzing maakt naar je stylesheet, zal je browser deze proberen op te vragen in je subfolder, terwijl deze ergens anders staat...


    Nu zal een aanroep naar /tracks/ er wat beter uitzien :).


    Een alternatief is dat je alle URL's absoluut maakt.

    Dat weet ik niet? Ontwikkel je op een eigen machine? Daarnaast zul je ook met de PHP-versie van je hosting rekening moeten houden als je dit ooit online gaat zetten.


    Zoals ik het zie (heb er verder nog niet mee gewerkt) zijn password_hash() en password_verify() gemaksfuncties. Wat je zou kunnen doen is implementaties maken voor de algoritmes die je gebruikt voor het hashen van je wachtwoord / salt. Hier gebruik je dan dezelfde (functie)namen voor. Wanneer je PHP-versie dan op den duur (al dan niet automatisch) plaatsvindt schakel je -als het goed is :)- vlekkeloos over naar de standaard implementaties van PHP. Op deze manier maak je je software forwards compatible.


    Normaal gesproken biedt PHP.net in de user comments wel eens een implementatie voor functies die vrij nieuwe PHP-versies nodig hebben, maar in dit geval helaas niet. Je zult daarom even rond moeten kijken (Use the Google, Luke!), of, wanneer je toch gebruik maakt van een enkele hash-methode, zou je kunnen overwegen om die dan maar te gebruiken in plaats van password_hash / password_verify.

    Waarschijnlijk is je PHP-versie niet nieuw genoeg. password_verify is een functie die pas beschikbaar is vanaf PHP 5.5.0.


    Je kunt je PHP-versie controleren door (tijdelijk) een apart script te maken (bijvoorbeeld info.php) met hierin de code:


    PHP
    <?php
    phpinfo();
    ?>

    Twee dingen die ik direct zie:
    - er staat een slash aan het einde van het eerste deel van je RewriteRule (het patroon) wat gematcht moet worden, dus tenzij je /home/ gebruikt in plaats van /home zal er waarschijnlijk inderdaad niet zoveel gebeuren (EDIT: hmm, misschien maakt dit niet eens zoveel uit, het wordt immers niet gematcht; EDIT: zonder eindslash lijkt het toch niet te werken :))
    - in het tweede deel van je RewriteRule staat $home, maar wat hiervoor in de plaats zou moeten komen is een zogenaamde back reference naar onderdelen in je patroon tussen ( ronde haken ). Je kunt naar je eerste paar haken (gezien van links naar rechts in je patroon) aanspreken via $1, het tweede paar via $2 et cetera


    Daarnaast zou je ook even na moeten gaan of mod_rewrite is geladen en je .htaccess bestanden overal mag declareren.


    Persoonlijk zou ik voor een andere aanpak kiezen. Zo zou je gewoon al je requests kunnen laten verwijzen naar index.php (EDIT: er vanuitgaande dat je PHP gebruikt, haha). Zo heeft je applicatie een single point of entry (lees: één voordeur). In je index.php zou je $_SERVER['REQUEST_URI'] kunnen controleren en ontleden om te bepalen of en welke pagina er geladen moet worden.


    Als de pagina niet bestaat, zou je bijvoorbeeld een 404 header terug kunnen geven (pagina niet gevonden). Dat is wel zo vriendelijk naar zoekmachines. Ik zal even kijken of ik een simpel voorbeeld in elkaar kan zetten.

    Aangezien het topic nog niet gelocked is, mag ik hier op reageren? ^^


    @M.Beers, maar welke functie gebruik je dan om een URL te bouwen (om deze geschikt te maken om af te drukken)?


    Hopelijk niet sanitize_url()? De omschrijving van deze functie is mij niet helemaal duidelijk? Deze functie is waarschijnlijk bedoeld om je input ($string) geschikt te maken om opgenomen te worden in een URL, bijvoorbeeld als querystring-parameter of -parameter-waarde. Maar dan lijkt het mij vreemd dat je die standaard lowercase maakt, omdat deze mogelijk case-sensitive behandeld wordt.


    Wat je dus hierboven "hebt" zijn een aantal bouwstenen om een URL te maken, maar wat je wellicht nog liever wilt hebben is een soort van link-functie: een eenduidige manier om een URL te bouwen binnen je applicatie.


    Wat Starohosting en K.Rens hierboven doen is in principe niet verkeerd, maar het is toch in zekere zin hardcoding van je interne links. Hier is niets mis mee... totdat je besluit dat je een pagina anders wilt noemen of wilt verplaatsen binnen je website-structuur. Het is veel flexibeler om een (aparte) site-structuur op te zetten en hier aan te refereren via één functie.


    Kijk, het hangt natuurlijk in sterk af van hoe je hele applicatie is gestructureerd maar hoe groter je systeem wordt, hoe meer (potentieel) werk je creëert als je iets wilt wijzigen. Als je een aantal standalone PHP scripts hebt is zo'n generieke oplossing een beetje overkill.


    Maar laten we deze train-of-thought eens verder verkennen.


    Dan .htaccess. Wat je hier in feite doet is het maken van een mapping van externe URL naar een interne URL / intern script via RewriteRules. Dit is in zekere zin ook hardcoding. Ik weet niet hoe het bij jullie zit maar ik had vroeger altijd ruzie met RewriteRules. Daarnaast, als dat ding over tijd groeit wordt het een nachtmerrie om te onderhouden en als je een foutje maakt krijg je een Internal Server Error. Dat wil je ook niet op een productie-omgeving.


    Hoe vet zou het zijn om het beheer van deze mappings te verplaatsen naar een structuur binnen je applicatie, geen gekloot meer met RewriteRules en je .htaccess bestand is en blijft klein en overzichtelijk. Vervolgens maak je één link-functie die van deze site-structuur gebruik maakt. Voordeel daarvan is dat je geen interne links meer hardcode en het gevolg hiervan is dat je code herbruikbaar(der) wordt.


    Dan de link-functie zelf. Hoe zou deze er uit moeten zien? En hoe bouw ik vervolgens een URL, en wat zijn de regels voor het opstellen van deze URL? Dit hangt weer sterk samen met je site-structuur.


    Stel je hebt bijvoorbeeld een nieuws-onderdeel, te bereiken via /news. Hier zou je een overzicht kunnen tonen van de meest recente nieuwsitems (via interne links via je link-functie). De nieuws-pagina is een "node" in je sitestrucuur. Aan deze node koppel je een pagina-type "news" die op zijn beurt weer gekoppeld is aan een News class (die dynamisch via een autoloader wordt geladen) die uitgevoerd wordt als je de /news pagina aanroept. Deze (relatieve) URL (news) sla je op als "slug" in je sitestructuur. En wanneer je een pagina binnen deze sitestructuur aanroept dan rijg je de slugs van deze nodes aan elkaar, gescheiden door een forward slash. Het eerste argument van je linkfunctie is dus bijvoorbeeld een sitestructuur-id of een (intern) pad (maar dat is eigenlijk wederom hardcoding). En voor het tweede argument zou je een array van querystring-argumenten kunnen gebruiken.


    Nu kun je in je code een (interne) link-functie aanroepen die een URL construeert op grond van je site-structuur, die je vrij kunt aanpassen. Als je code enkel gebruik maakt van deze link-functie verandert deze mee als je een pagina verplaatst of van naam wijzigt - en hier hoef je verder niets voor te doen!


    Dan resten er nog twee dingen: hoe maak ik de slugs en hoe verzorg ik vervolgens de afhandeling van de aanroep van een link?


    Hierboven wordt al een voorbeeld gegeven van hoe je je slugs kunt "bakken": je stript alles wat niet voldoet aan een bepaald patroon. Een alternatief wat misschien de moeite waard is om te bekijken is een variant die probeert exotische karakters om te zetten naar standaard letters uit het alfabet. Ik heb hiervoor als inspiratie de volgende site gebruikt: The perfect PHP clean url generator.


    En dan nog de routing. Kort door de bocht stuur je alle requests via je .htaccess door naar /index.php die het verzoek verder afhandelt.


    Als je het netjes wilt doen dan kost dit redelijk wat werk, maar dit is, als dit alles achter de rug is, de moeite waard.


    Een ander voordeel van de gebruikmaking van een aparte sitestructuur is dat je hier ook een rechtenbeheer in onder kunt brengen.


    Wat je dan uiteindelijk gebouwd hebt is een website... om websites mee te bouwen :). Of je hebt in ieder geval een goed begin gemaakt.


    Waar je nog wel aan moet denken is het volgende: als je een link afdrukt in een HTML-document moet je deze escapen om deze te ontdoen van enige speciale betekenis binnen deze context (net zoals je binnen de context van een url onderdelen escaped met urlencode()). Hier kun je het beste htmlspecialchars voor gebruiken.


    Een voorbeeld van een aanroep van een linkfunctie die ik gebruik:

    PHP
    <?php
    // eerste parameter is het pad, false wil zeggen: het script zelf
    $action = $this->link(false, array(
        $this->cfg->actionVariable => 'addNodeProcess',
        $this->cfg->redirVariable => true,
    ));
    ?><form action="<?php echo $this->escape($action) ?>" method="post" accept-charset="UTF-8">


    En de output:

    Code
    <form action="http://mijn.website.com/pad/naar/pagina?action=addNodeProcess&amp;redir=1" method="post" accept-charset="UTF-8">


    De linkfunctie zet alles ook om naar absolute URL's, inclusief domein. Daarnaast zijn de namen van de action- en redirect-parameters ook vrij instelbaar via configuratie.


    Om je maar een idee te geven :).

    Vergeet ook vooral niet een character encoding in te stellen. Dat voorkomt echt een hele hoop problemen met in het ergste geval corrupte data in je database.


    Vanaf PHP versie 5.3.6 kun je deze meegeven aan je Data Source Name (DSN - je "connectie string") via de charset-parameter. Oudere PHP-versies negeren deze parameter. In die gevallen zou je de character encoding via de (connectie)optie PDO::MYSQL_ATTR_INIT_COMMAND moeten instellen.


    Tevens:
    * Persistente connecties... Ik weet niet of dat enige meerwaarde heeft.
    * Daarnaast kan het iets sneller zijn om voor de host altijd een IP op te geven, dat scheelt je weer een lookup.


    Citaat

    Je roept hier ook tot 2x error reporting. Tegenwoordig kan je alleen al door je ini aante roepen de fouten laten weergeven.

    Nope. Met display_errors geef je aan of je fouten wilt weergeven. Dit is een PHP_INI_ALL instelling en mag je dus overal neerzetten. Met error_reporting() geef je aan welke fouten worden weergegeven. Dit zijn twee verschillende dingen.

    En als $naam niet beveiligd is tegen SQL-injectie kun je met


    (EDIT: vorige voorbeeld werkte waarschijnlijk niet)
    ' OR 'A' = 'A


    alsnog alledrie de tabellen leegkieperen :).

    Het idee is natuurlijk aardig, maar ik denk niet dat .htaccess de plaats is waar je dit soort zaken moet oplossen.


    Daarnaast is het voorbeeld .htaccess-bestand die in de link van matistop333 beschreven staat... één grote blacklist.


    Het probleem van beveiligingen met blacklists is (ten minste :)) tweeledig:
    - de gevallen die niet in de blacklist staan... worden doorgelaten, dus vergeet je een geval, dan ben je de sjaak
    - het kan "false positives" opleveren, oftewel, een URL aanroep kan ten onrechte gemarkeerd worden als zijnde een "hackpoging"


    Een "whitelist" is altijd beter: beschrijf enkel die gevallen die zijn toegestaan. En niet alle gevallen die niet zijn toegestaan (om eerder genoemde redenen).


    Verder moet er altijd een zekere alertheid zijn bij het schrijven van code en queries, het lijkt mij onverstandig om er vanuit te gaan dat (in dit geval) .htaccess alle gevaarlijke gevallen eruitvist (te meer omdat het een blacklist betreft).


    Als je PHP gebruikt om met een MySQL-database te communiceren zou je met MySQLi kunnen werken of met PDO.


    Daarnaast zou je je invoer moeten filteren / valideren, en je uitvoer moeten escapen. Als je deze stelregel altijd in je achterhoofd houdt (filter input, escape output) dan kom je al een heel eind.


    Je moet het zo zien: een query is meestal opgebouwd uit vaste stukken SQL en variabele stukken DATA (user input, die je nooit moet vertrouwen).


    Iemand kan SQL injecteren als het variabele DATA-deel geinterpreteerd kan worden als SQL, je kunt in dat geval namelijk de werking van een query aanpassen.


    Dit kun je enerzijds tegengaan door je input te filteren. Als je in $_GET['id'] een auto-increment id verwacht (EDIT: waarmee je een query bouwt) - controleer hier dan op! Als $_GET['id'] geen positief geheel getal bevat
    hoef (en zou je) de query niet eens uit (moeten) voeren.


    Daarnaast zou je je DATA in je query moeten ontdoen van haar speciale betekenis binnen SQL. Dit kan in MySQLi via de real_escape_string() functie en in PDO gebruik je prepared statements.


    filter input, escape output beperkt zich trouwens niet tot MySQL alleen, maar is ook van toepassing op HTML (en zaken die je via PHP afdrukt in een HTML-document).


    Citaat

    Er is niemand die meer verstand van jouw software heeft dan jij zelf. Dus als je genoeg kennis in huis hebt of haalt, waarom zou dan iemand een lek vinden in je software?


    Omdat je vaak vastgeroest bent in je eigen denkpatroon, is het juist verstandiger om iemand anders je software te laten testen. Een buitenstaander verzint mogelijk sneller dingen waar je nooit aan hebt gedacht. Ik neem ook aan dat je dit moment wilt voor zijn :).