Avendo un’applicazione PHP che provvede un upload da un form, può essere importante settare il limite di MegaByte concessi.

Il file di configurazione in Debian risiede nei dintorni di /etc/php/apache*/php.ini e le voci da cambiare sono tre, non una, come si legge nella descrizione di post_max_size (vedi conf.ini).

Sets max size of post data allowed. This setting also affects file upload.

To upload large files, this value must be larger than upload_max_filesize.

If memory limit is enabled by your configure script, memory_limit also affects file uploading.

Generally speaking, memory_limit should be larger than post_max_size.

If the size of post data is greater than post_max_size, the $_POST and $_FILES superglobals are empty.

Quindi occhio a:

  1. upload_max_filesize
  2. post_max_size
  3. memory_limit

Ennesimo caso di fastidio…

Scrivo in php un test che dovrebbe essere semplice (nella mia testa): se esiste il primo valore passa quello, se non esiste passa il secondo, se non esiste manco quello dammi il terzo e basta.

$output = isset($a) ? $a
        : isset($b) ? $b
        :             $c;
return "$output";

Il risultato che ottengo non è quel che mi aspetto: se sono settati il secondo e il terzo (o solo il terzo) tutto ok, ma se setto il primo valore invece che restituirmi $a mi restituisce $b… orcal’oca.

La risposta è “il verso dell’associatività“.

Precedenze e associatività degli operatori in Perl e in php.

In Perl l’associatività dell’operatore ternario (? :) parte da destra, in Php da sinistra.
In soldoni servono delle parentesi sui blocchi successivi il primo per forzare php con la precedenza che voglio dare (in effetti sul manuale c’è una nota: “It is recommended that you avoid “stacking” ternary expressions. PHP’s behaviour when using more than one ternary operator within a single statement is non-obvious“).

Boh, a me viene più naturale pensare alla precedenza perlistica.

I test case in Perl (right)…

#!/usr/bin/perl
use strict;
use warnings;

sub test_ternary_without {
    my ($a,$b) = @_;
    my $c = ‘last’;
    my $output = defined($a) ? $a
               : defined($b) ? $b
               :               $c;
    return "$output";
}

sub test_ternary_with {
    my ($a,$b) = @_;
    my $c = ‘last’;
    my $output = defined($a)  ? $a
               :( defined($b) ? $b
               :                $c);
}
my @cases = (
    [ ‘primo’, ‘secondo’ ],
    [ undef  , ‘secondo’ ],
    [ undef  , undef     ]
);

foreach my $node (@cases) {
    my $values_string = ‘a="’.($node->[0] || ).‘"; b="’.($node->[1] || ).‘"; c="last";’;
    printf("Without ( %s ) : %s\n", $values_string, test_ternary_without($node->[0],$node->[1]) );
    printf("With    ( %s ) : %s\n", $values_string, test_ternary_with($node->[0],$node->[1]) );
}

exit 0;

$ perl test_ternary.pl
Without ( a="primo"; b="secondo"; c="last"; ) : primo
With    ( a="primo"; b="secondo"; c="last"; ) : primo
Without ( a=""; b="secondo"; c="last"; ) : secondo
With    ( a=""; b="secondo"; c="last"; ) : secondo
Without ( a=""; b=""; c="last"; ) : last
With    ( a=""; b=""; c="last"; ) : last

In PHP (left):

<?php

function test_ternary_without($a = NULL,$b = NULL,$c = ‘last’) {
    $output = isset($a) ? $a
            : isset($b) ? $b
            :             $c;
    return "$output";
}

function test_ternary_with($a = NULL,$b = NULL,$c = ‘last’) {
    $output =  isset($a) ? $a
            :( isset($b) ? $b
            :              $c );
    return "$output";
}
$cases = array(
    array( ‘primo’, ‘secondo’ ),
    array( NULL   , ‘secondo’ ),
    array( NULL   , NULL      )
);

foreach($cases as $node) {
    $values_string = ‘a="’.$node[0].‘"; b="’.$node[1].‘"; c="last";’;
    printf("Without ( %s ) : %s\n", $values_string, test_ternary_without($node[0],$node[1]) );
    printf("With    ( %s ) : %s\n", $values_string, test_ternary_with($node[0],$node[1]) );
}

?>

$ php test_ternary.php
Without ( a="primo"; b="secondo"; c="last"; ) : secondo
With    ( a="primo"; b="secondo"; c="last"; ) : primo
Without ( a=""; b="secondo"; c="last"; ) : secondo
With    ( a=""; b="secondo"; c="last"; ) : secondo
Without ( a=""; b=""; c="last"; ) : last
With    ( a=""; b=""; c="last"; ) : last

Che dos marones…

Lavorando in PHP, ogni tanto mi viene nostalgia di Perl.

Avendo un array canonico

$string = ‘a/1/b/2/c/3/e’;
@array = ( ‘a’, ’1′, ‘b’, ’2′, ‘c’, ’3′, ‘e’ );

in Perl, è molto semplice tramutarlo in un hash (o array associativo) con un semplice:

%hash = @array
$VAR1 = {
          ‘e’ => undef,
          ‘c’ => ’3′,
          ‘a’ => ’1′,
          ‘b’ => ’2′
        };

In PHP la soluzione (un po’ micraniosa) che m’era venuta…

<?php

$array = explode(‘/’,$string);
if( count($array) %2 !== 0 )
    $array[] = NULL;

for($i=0; $i < count($array) ;$i = $i+2) {
    $hash[$array[$i]] = $array[$i+1];
}

?>

Array
(
    [a] => 1
    [b] => 2
    [c] => 3
    [e] =>
)

Fortunatamente ho chiesto su Frenoode/##php e qualcuno ha prodotto questa…

$arr = array();
foreach (array_chunk(explode(‘/’, $string), 2) as $node)
    $arr[$node[0]] = $node[1];

Magnifica. E così ho visto anche array_chunk().

Ho trovato un articolo di Aaron Crane intitolato Experiences of Using PHP in Large Websites.

PHP ha dei grandi pregi: principalmente semplicità e rapidità.
L’articolo parla dei difetti del PHP: un sito complesso, da sviluppare in team, con molto codice embeddato nelle pagine puo’ diventare un caos allucinante.

Poiché la libreria Imagick di php NON si comporta proprio come imagemagick da cmdl, mi sono fatto una semplice funzione per thumbnailare le immagini che carico con un form.

Per qualche oscura ragione a differenza di suo padre, la funzione Imagick::thumbnailImage della libreria non riduce a partire dal lato più lungo, quindi bisogna imporre la propria volontà.

<?php
function img_resize($src,$dst,$size = 450) {
        $max_length = $size; /* Lato maggiore consentito in px */

        $img = new Imagick();
        $img->readImage($src);
        $real_width  = $img->getImageWidth();
        $real_height = $img->getImageHeight();
        if ( $real_width > $max_length || $real_height > $max_length ) {
                if ($real_width > $real_height) {
                        $img->thumbnailImage($max_length,0,false);
                } else {
                        $img->thumbnailImage(0,$max_length,false);
                }
        }
        $img->setImageFormat(‘jpeg’);
        $img->writeImage($dst);
        $img->destroy();
}
?>

Sono ancora alla ricerca di idee su “modi decenti” per uploadare immagini su di un sito.
L’idea è prendere i file con un form di upload, analizzarli e caricarli nel sistema. Poi metterli nel db, creare l’immagine delle dimensioni giuste e il thumb, poi linkarli quando vengono richiesti.
Le immagini vengono passate nel fs grazie a tempnam(), trasformate con le lib php di imagemagick in formato jpeg, e servite da apache come image/jpeg forzatamente (con ForceType sulla <Directory>).

Per ora non mi vengono idee migliori. Accetto consigli, nel caso.

Ne approfitto per linkare una paginetta semplice semplice di tutorial riguardo le lib php Imagick, visto che non hanno documentazione.

Ok, weekend nel marasma delle webapplication.

Ricapitolo un po’…
* Passaggi dati non numerici (potenzialmente massicci) in POST, ritorno in GET (per forza).
* Controllo in entrata di pagina (isset, is_numeric, blablabla, check di esistenza sul db).
* Funzioni di escape sui dati da inserire nel db. (pg_escape_string, mysql_real_escape)
* Funzioni di escape in output sul codice html (giusto per evitare scriptini e tag interpretabili): htmlentities.
* Funzioni stripslashes per togliere gli escape nel db in output.
* Check con regexp (preg_match) sulle stringhe inserite, ocio ai filename con rischio per gli header serviti.

Un po’ di storie dal php security consortium.

« Previous Articles    
SIMOTRONE WEB PAGE is based on WordPress platform, RSS tech , RSS comments design by Gx3.