De mest almindelige fejl begået i PHP

PHP er et fantastisk scripting sprog til hurtig udvikling af dynamiske websites.
Det er blandt meget andet et supervenligt sprog for nybegyndere da PHP ikke kræver deklarering af variabler.
Det er dog muligheder som disse som ofte skaber sikkerhedshuller, scriptfejl eller andre uønskede effekter

I denne artikel vil vi komme til at gå gennem nogle af de mest almindelige fejl begået I PHP..

Artiklen er opdelt således:
  1. Ikke valideret input
  2. Single quotes og dobbelte qoutes
  3. Forkert brug af HTTP header relaterede funktioner: header(), session_start() og set_cookie()

Ikke valideret input

En af - hvis ikke den største - de typiske fejl er når det input du får ikke bliver valideret - en sikkerhedstrussel mod din webapplikation.

Stol aldrig på dine brugere

Så kort og kontant kan det siges; stol aldrig nogensinde på dine brugere - du skal antage at hver eneste bruger du får på dit website vil skade dit website om muligt, da det med stor sikkerhed kan siges at nogle af dem helt sikkert vil.
Ikke valideret input er roden til meget ondt hvad angår sikkerhedshuller, som vi vil kigge lidt nærmere på.

Som et eksempel, skal du forestille dig at du vil skalere et billede dynamisk med imagemagick

<?php


    $image 
$_GET["billede"];
    
$resized "resized_".$image;

    
$cmd "convert ".$image." -resize 140x140 ".$resized;

    
exec($cmd);

    ...

?>

Ovenstående kode er et gabende sikkerhedshul idet at $_GET["billede"] ikke på nogen som helst må bliver valideret.
Scriptet virker jo efter hensigten, såfremt at billedet man anmoder om eksisterer. Men - hvis en bruger nu tilføjer ;rm rf * til $_GET["billede"] ville brugeren kunne slette hele dit website! (OMG - overdrevet scenarie, men stadig...)

Den rigtige må at gøre det på ville være at validere det input du får så du er sikker på at hvad du får fra brugeren er hvad du forventer det skal være. Javascript er en mulighed for brugervalidering, man det Javascript eksekveres hos brugeren, er det ikke en sikker løsning, idet brugeren ikke nødvendigvis understøtter javascript eller har javascript slået til. Men valideringen er heldigvis løst let med lidt PHP kode.

<?php

    $image 
$_GET["billede"];
    
$resized "resized_".$image;

    if(!
file_exists($image))
    {
        echo 
"Billedet kunne ikke findes";
        exit;
    }

    
$cmd "convert ".$image." -resize 140x140 ".$resized;

    
exec($cmd);
    ...

?>

Du kan undgå mange fejl ved at tage højde for skadeligt input fra brugeren.

Single quotes og dobbelte qoutes

Selvom det virker trivielt, kan det for mange være roden til et fejlende script.

Single quotes, gnyffer, ping'er, apostrof - ja, kært barn har mange navne; men "single qoute" dækker over apostroffen ( ' ). Et "double qoute" er et anførselstegn ( " ). At skrive strenge i PHP kan gøres på forskellige måder. Typisk opstår der fejl når strenge skal indeholde enten single eller double quotes - f.eks. hvis strengen indeholder HTML.

Herunder er angivet et par eksempler på strenge der vil skabe fejl:

<?php

    $string 
"<a href="index.php" title="hjem">Hjem</a>";
    
$string '<a href='index.php' title='hjem'>Hjem</a>';
    
$string 'Der var ingen af dem tilbage i 90'erne';
?>

Ovenståede kode vil resultere i fejlen Parse error: syntax error, unexpected T_STRING in ...
Fejlen opstår fordi single quotes strenge ikke kan indeholde single quotes - og double qoutes strenge kan ikke indeholde double quotes.

For at løse det, escapes disse tegn. For at "escape" særlige tegn, benyttes backslash ( \ ).
For at få ovennævnte kode til at virke, escaper vi de tegn der er specielle i forhold til hinanden:

<?php

    $string 
"<a href=\"index.php\" title=\"hjem\">Hjem</a>";
    
$string '<a href=\'index.php\' title=\'hjem\'>Hjem</a>';
    
$string 'Der var ingen af dem tilbage i 90\'erne';
?>
"Brug single quotes i stedet for dobbelte quotes - det er hurtigere"

En af de mere brugte råd når det kommer til PHP udvikling er ovenstående.
Jovist, at bruge single quotes vil give dig et performance boost, men hvis du selv tester din performance, vil du sandsynligvis ikke opleve en forskel der er større end 0,01%.

Nogle udviklere brugere single quotes til alting, andre bruger dobbelte quotes mens en tredie gruppe veksler imellem dem. Det vigtigste er at du gør det på en måde, som er mest komfortabel for dig, idet at den hastighedsforskel du kan opnår ikke er bemærkelsesværdig.

Forkert brug af HTTP headers relaterede funktioner: header(), session_start() og set_cookie()

HTTP headers HTTP headers består af ikke synlige data, som browseren læser - headers såsom cookies, cache-control eller redirects.
HTTP headers skal altid komme før alt andet output

Hvor mange gange er du ikke stødt på fejlen warning: Cannot add header information - headers already sent ...?

Det er typisk en fejl folk oplever når de starter med at udvikle applikationer som benytter sessions. Når du starter en session indikerer du for browseren at du vil sætte eller benytte en cookie der identificerer den enkelte bruger i din applikation. For at indikere noget for browseren, bliver du nød til at fortælle browseren det via HTTP headers.

Når en funktion såsom header(), session_start() eller set_cookie() eksekveres, kontrollerer PHP om du har sendt output til browseren. Er det tilfældet, opstår førnævnte fejl.

Hvad er output? Output er HTML, billeder, mellemrum, linieskift og så videre.
Her er et eksempel på kode der vil fejle:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
</head>
<body>
    <?php
        session_start
();
        
//Resulterer i: Warning: session_start() [function.session-start]: Cannot send session cache limiter - headers already sent...
    
?>
</body>
</html>

For at få det til at virke korrekt bliver vi nød til at sørge for at funktionen startes inden outputtet:

<?php
    session_start
();
    
//Fungerer som det skal
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
</head>
<body>
    ...
</body>
</html>

Hvis du, på trods af at du er sikker på du har fået placeret dine funktioner korrekt, stadig får fejlen, kan det skyldes en BOM signatur.
BOM signaturen er kort sagt en 'usynlig' streng som anvendes til at angive tegnsæt i en fil. Den typiske BOM signatur er signaturen for UTF-8.
Denne angives med HEX værdien EF BB BF. Det er din editor der indsætter denne usynlige streng.