Archivio della categoria 'PHP'

RoundCube: aumentare le dimensioni degli allegati

Open Source, PHP, Principianti, Tips & tricks Nessun commento »

Chi utilizza RoundCube come applicazione webmail – noi ne utilizziamo una versione nostra con alcuni miglioramenti interessanti – si sarà accorto che la gestione degli allegati avviene in una maniera piuttosto anomala. Per motivi incomprensibili, l’applicazione è stata disegnata ignorando completamente alcuni importanti settaggi del php.ini e di Postfix relativi alle dimensioni dei file allegabili ad un messaggio email:

  • vengono completamente ignorati i valori dei parametri upload_max_filesize (=maximum allowed size for uploaded files), post_max_size (=maximum size of POST data that PHP will accept) e memory_limit (=maximum amount of memory a script may consume)  indicati nel file php.ini
  • viene completamente ignorato il valore di message_size_limit nel file main.cf di Postfix

Ovviare a questa mancanza però è davvero semplice, è sufficente editare il file /usr/share/roundcube/.htaccess e cambiare a piacimento i valori dei rispettivi parametri:

php_value       upload_max_filesize     20M
php_value       post_max_size           21M
php_value       memory_limit            64M

Tutto qui.

PHP 5.2 su Debian Squeeze

PHP, Sistema, Tips & tricks Nessun commento »

Questo ve lo devo assolutamente segnalare:

http://blog.davejamesmiller.com/2011/03/how-to-install-php-5-2-fastcgi-on-debian-6-0-squeeze

(copia HTML zippata: PHP52_on_Squeeze.zip)

Ci trovate istruzioni chiare e semplici per installare PHP 5.2 su Debian Squeeze senza effettuare il downgrade globale di PHP5! In altre parole in questo modo fate convivere tranquillamente sullo stesso server entrambe le versioni – la 5.3 con la 5.2 – ovviando i numerosi problemi introdotti dal cambio di versione per applicazioni web fondamentali, come Drupal 5.* che su Squeeze non vuole saperne di girare, come sanno ormai in molti – a proprie spese ;-)

 

Debian Squeeze: modificare il parametro memory_limit in /etc/php5/cli/php.ini

Apache, Debian, PHP, Tips & tricks Nessun commento »

Su tutte le Debian Squeeze c’è una correzione al volo da fare al php.ini dedicato agli script eseguiti lato server (a.k.a. command line). La correzione è di vitale importanza, ma solo se avete messo in cron script php e non volete che il server si rifiuti di eseguirli perché richiedono più memoria di quella allocabile. Il problema è dovuto al parametro:

memory_limit = -1

Visto così sembrerebbe un flag disabilitato e ci aspetteremmo quindi che non ci sia alcun limite nella memoria allocabile, invece il comportamento è tutt’altro:

PHP Fatal error:  Allowed memory size of 33554432 bytes exhausted (tried to allocate 64 bytes) in /var/www/clients/client21/web54/web/XXXXXX.php on line 212

Per ovviare al problema, è bene specificare quale effettivamente è il limite di memoria che intendiamo imporre ad uno script php eseguito da linea di comando. Il parametro si trova nel file:

/etc/php5/cli/php.ini

E la modifica da effettuare è la seguente:

; Maximum amount of memory a script may consume (128MB)
; http://php.net/memory-limit
;memory_limit = -1
memory_limit = 128M

Also sprach Zio Vania ;-)

Abilitare l’accesso a directory extra in Drupal

Apache, Open Source, PHP, Principianti, Tips & tricks Nessun commento »

Quelli che hanno la cattiva abitudine di installare le applicazioni web nella document root si trovano  spesso a dover affrontare un fastidioso problema: l’impossibilità di gestire directory e sub-directory estranee all’applicazione a causa delle restrizioni di accesso imposte dal file .htaccess.

L’esempio più tipico è quello del CMS Drupal. Supponiamo di averlo installato e reso completamente accessibile all’URL:

http://www.miodominio.xx/

Il file .htaccess di Drupal controllerà tutto quello che può o non può essere accessibile al di sotto della propria document root, che in questo caso coincide esattamente con la document root del virtual host. Infatti il file .htaccess si trova nella radice del filesystem dedicato a questa applicazione:

http://www.miodominio.xx/.htaccess

In questo modo, se decidiamo di creare una qualsiasi nuova directory, questa subirà le medesime restrizioni scritte nel file .htaccess durante l’installazione di Drupal, come ad esempio l’impossibilità di navigare liberamente tra i suoi file e le subdirectory che essa contiene:

http://www.miodominio.xx/test/

Questa directory non è accessibile in questo modo, ma solo richiamando il nome del file in essa contenuto a cui vogliamo accedere, ad esempio:

http://www.miodominio.xx/test/pippo.html
http://www.miodominio.xx/test/imago.jpg

Se non viene indicato alcun file, viene cercato e mostrato il solo file index.php:

http://www.miodominio.xx/test/index.php

Se il file index.php non esiste, non viene mostrato il contenuto della directory – come molti si aspetterebbero – ma al contrario viene generato un bell’errore 404  (File Not Found).

Per ovviare a questo problema è sufficiente agire sul file .htacces, aggiungendo le istruzioni che rendono la directory /test/ immune da queste regole, immediatamente dopo l’inizializzazione del RewriteEngine:

<IfModule mod_rewrite.c>
RewriteEngine on
#
# ECCO LE DUE RIGHE DI ISTRUZIONI:
RewriteCond %{REQUEST_URI} "/test/"
RewriteRule (.*) $1 [L]
#

Provare per credere.

Scansione ricorsiva di una directory con PHP

Open Source, PHP, Tips & tricks Nessun commento »

Ci sono script che dovresti sempre avere a portata di mano, perché finisce che ne hai bisogno nei momenti e nelle occasioni più impensabili. Questa function in PHP, ad esempio, mi ha risparmiato in molti casi un’inutile perdita di tempo: passandole come argomento una stringa che corrisponde al percorso completo da scandire, la function scan_directory_recursively restituisce un array contenente la struttura completa della directory specificata.

È possibile indicare, come secondo argomento opzionale, una estensione o una porzione di testo che non dovrà necessariamente comparire nel nome del file. Si tratta in pratica di un filtro per escludere una certa classe di risultati.

Ad esempio:

$dirs=scan_directory_recursively('/home/ivan/Tempo');

restituisce un array di tutte le directory e i file contenuti in /home/ivan/Tempo, mentre:

$dirs=scan_directory_recursively('/home/ivan/Tempo','.php');

restituisce un array di tutte le directory e i file contenuti in /home/ivan/Tempo ad eccezione dei file con estensione .php!

Non è opera mia, per questo motivo chiedo a chiunque ne faccia uso nei propri progetti di non rimuovere i riferimenti a lixlpixel, il sito Internet da cui provengono.

Ecco la function:

< ?php
// ------------ lixlpixel recursive PHP functions -------------
// scan_directory_recursively( directory to scan, filter )
// expects path to directory and optional an extension to filter
// of course PHP has to have the permissions to read the directory
// you specify and all files and folders inside this directory
// ------------------------------------------------------------
 
// to use this function to get all files and directories in an array, write:
// $filestructure = scan_directory_recursively('path/to/directory');
 
// to use this function to scan a directory and filter the results, write:
// $fileselection = scan_directory_recursively('directory', 'extension');
 
function scan_directory_recursively($directory, $filter=FALSE)
{
    // if the path has a slash at the end we remove it here
    if(substr($directory,-1) == '/')
    {
        $directory = substr($directory,0,-1);
    }
 
    // if the path is not valid or is not a directory ...
    if(!file_exists($directory) || !is_dir($directory))
    {
        // ... we return false and exit the function
        return FALSE;
 
    // ... else if the path is readable
    }elseif(is_readable($directory))
    {
        // we open the directory
        $directory_list = opendir($directory);
 
        // and scan through the items inside
        while (FALSE !== ($file = readdir($directory_list)))
        {
            // if the filepointer is not the current directory
            // or the parent directory
            if($file != '.' && $file != '..')
            {
                // we build the new path to scan
                $path = $directory.'/'.$file;
 
                // if the path is readable
                if(is_readable($path))
                {
                    // we split the new path by directories
                    $subdirectories = explode('/',$path);
 
                    // if the new path is a directory
                    if(is_dir($path))
                    {
                        // add the directory details to the file list
                        $directory_tree[] = array(
                            'path'    => $path,
                            'name'    => end($subdirectories),
                            'kind'    => 'directory',
 
                            // we scan the new path by calling this function
                            'content' => scan_directory_recursively($path, $filter));
 
                    // if the new path is a file
                    }elseif(is_file($path))
                    {
                        // get the file extension by taking everything after the last dot
                        $extension = end(explode('.',end($subdirectories)));
 
                        // if there is no filter set or the filter is set and matches
                        if($filter === FALSE || $filter == $extension)
                        {
                            // add the file details to the file list
                            $directory_tree[] = array(
                                'path'      => $path,
                                'name'      => end($subdirectories),
                                'extension' => $extension,
                                'size'      => filesize($path),
                                'kind'      => 'file');
                        }
                    }
                }
            }
        }
        // close the directory
        closedir($directory_list); 
 
        // return file list
        return $directory_tree;
 
    // if the path is not readable ...
    }else{
        // ... we return false
        return FALSE;    
    }
}
// ------------------------------------------------------------
 
?>

Per comodità vostra, ma anche mia, aggiungo qui una versione priva di commenti e pronta per il download:

Funzioni anonime in PHP

Open Source, PHP, Tips & tricks 2 commenti »

PHP è un buon linguaggio di programmazione, se lo si giudica con i parametri abbastanza empirici del grado di diffusione e della mole di function che integra. Si dimostra però spesso sorprendentemente flessibile anche per affrontare scenari di programmazione molto più complessi del semplice embedding di script in una pagina web.

Durante un recente scambio di opinioni con un matematico appassionato di Open Source si è presentato il problema di creare funzioni anonime e – qui sta il punto – di farlo all’interno di una classe PHP. Tralascio lo sproloquio teorico che mi sono dovuto sorbire sul lambda calcolo e le funzioni anonime e mi limito a riportare qui un passaggio della definizione che ne dà WikiPedia. Cito testualmente:

Il lambda calcolo è un sistema di riscrittura definito formalmente dal matematico Alonzo Church. È stato sviluppato per analizzare formalmente le definizioni di funzioni, le loro applicazioni ed è uno strumento interessante per studiare anche fenomeni di ricorsione. In quanto sistema di riscrittura, esso dà una descrizione dei termini ben formati, che sono le sequenze di simboli riconosciute dal sistema e in grado di essere riscritti da esso. Il lambda calcolo, infatti, definisce un insieme di regole di riscrittura che determinano in maniera precisa come i termini stessi possano essere riscritti. In questo modo, il processo di riscrittura diventa un vero e proprio calcolo.

E ancora (disponibile solo in inglese):

Anonymous functions can be used to contain functionality that need not be named and possibly for short-term use. Some notable examples include closures and currying. [...]
Closures are functions evaluated in an environment containing bound variables. The following example binds the variable “threshold” in an anonymous function that compares the input to the threshold. [...]
Currying is transforming a function from multiple inputs to fewer inputs (in this case integer division).

Anche se ufficialmente non esiste in PHP un vero e proprio metodo per gestire le funzioni anonime, si può facilmente ottenere qualcosa di simile in almeno due modi:

  1. chiamando una variabile col nome di una funzione:
    $foo = "phpinfo";
    $foo();
  2. inizializzando una variabile con l’istruzione `create_function`:
    $sum = create_function('$a, $b','return $a + $b;');
    echo $sum(1,2);

Nel primo caso stiamo creando soltanto un link alla funzione. Nel secondo, invece, assegniamo la funzione alla variabile proprio mentre la creiamo. Provare per credere: si tratta di un aspetto insolito e per certi versi divertente del PHP, ma scoraggio chiunque ad adottare una soluzione simile in ambienti di produzione in cui non si vogliano perdere di vista praticità e facilità di lettura del codice.

Convertire un testo in array di righe con la costante PHP_EOL

Open Source, PHP, Tips & tricks Nessun commento »

Quando si scrivono applicazioni per il web in PHP capita spessissimo di dovere trattare i dati contenuti in un file di testo. Il metodo migliore per acquisire dati di questo tipo è senz’altro la funzione `file`, che restituisce appunto un array contenente tutte le righe del file di testo.

Capita però altrettanto spesso di avere a che fare con script PHP datati o realizzati per girare in situazioni anomale, come ad esempio server embedded che mettono a disposizione un range limitato di funzioni PHP, oppure ancora di script che elaborano le righe del testo nel momento stesso in cui lo generano.

In questi casi si può ricorrere a una sintassi meno immediata ma altrettanto efficace, ricorrendo alla funzione `explode` e alla costante di sistema PHP_EOL.

Ecco un semplice esempio:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
< ?php
 
$txtMessage = <<<EOD
RIGA #1
RIGA #2
RIGA #3
RIGA #4
EOD;
 
$aLines = explode(PHP_EOL, $txtMessage);
 
echo "<table border=\"1\">\n" .PHP_EOL;
 
foreach ($aLines as $strLine)
{
  echo "<tr>\n".PHP_EOL."<td>\n".$strLine."</td>\n".PHP_EOL."</tr>\n".PHP_EOL;
}
 
echo "\n" .PHP_EOL;
 
?>

Il risultato sarà il seguente:

RIGA #1
RIGA #2
RIGA #3
RIGA #4

 

La costante PHP_EOL equivale al carattere di end of line del sistema operativo su cui stiamo elaborando lo script: ricorrere a questa costante non migliora soltanto la leggibilità del nostro programma, ma anche la sua portabilità.

Differenza fra date con PHP

PHP, Tips & tricks Nessun commento »

Calcolare la differenza fra due date in termini di giorni è molto, molto semplice con PHP. Ecco la function che restituisce il calcolo:

function days_diff( $giornoA, $meseA, $annoA, $giornoB, $meseB, $annoB )
{
$timestampA = mktime(0, 0, 0, $meseA, $giornoA, $annoA);
$timestampB = mktime(0, 0, 0, $meseB, $giornoB, $annoB);
$diff = floor(($timestampB - $timestampA) / (3600 * 24));
return $diff;
}
I valori da passare alla function sono i seguenti:

  • $giornoA, $meseA, $annoA: giorno, mese ed anno (int) della data minore
  • $giornoB, $meseB, $annoB: giorno, mese ed anno (int) della data maggiore