[php] controllo su estensione file

tunix

Nuovo Utente
7 Giu 2018
2
0
1
Ciao a tutti,

Vorrei chiedervi aiuto nel creare un controllo dell'estensione in uno script per allegare file pdf tramite un form html...
Vorrei anche valutare la possibilità di limitare la grandezza dell'allegato.

Ho già creato uno script javascript che mi esegue dei controlli sull'inserimento di un campo mail e della presenza dell'allegato.

Mentre questo script l'ho già copiato e modificato a mio piacere da un articolo di Massimiliano Bossi

Se serve altro, fornisco dettagli, grazie :)

PHP:
<?php
// Recupero il valore dei campi del form
$destinatario = '[email protected]';
$mittente = $_POST['mittente'];
$oggetto = "Mail Automatica inviata dal form" ;
$messaggio = "In allegato";

// Valorizzo le variabili relative all'allegato
$allegato = $_FILES['allegato']['tmp_name'];
$allegato_type = $_FILES['allegato']['type'];
$allegato_name = $_FILES['allegato']['name'];

// Creo altre due variabili ad uso interno
$headers = "From: " . $mittente;
$msg = "";

// Verifico se il file è stato caricato correttamente via HTTP
// In caso affermativo proseguo nel lavoro...
if (is_uploaded_file($allegato))
{
  // Apro e leggo il file allegato
  $file = fopen($allegato,'rb');
  $data = fread($file, filesize($allegato));
  fclose($file);

  // Adatto il file al formato MIME base64 usando base64_encode
  $data = chunk_split(base64_encode($data));

  // Genero il "separatore"
  // Serve per dividere, appunto, le varie parti del messaggio.
  // Nel nostro caso separerà la parte testuale dall'allegato
  $semi_rand = md5(time());
  $mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";
 
  // Aggiungo le intestazioni necessarie per l'allegato
  $headers .= "\nMIME-Version: 1.0\n";
  $headers .= "Content-Type: multipart/mixed;\n";
  $headers .= " boundary=\"{$mime_boundary}\"";

  // Definisco il tipo di messaggio (MIME/multi-part)
  $msg .= "This is a multi-part message in MIME format.\n\n";

  // Metto il separatore
  $msg .= "--{$mime_boundary}\n";

  // Questa è la parte "testuale" del messaggio
  $msg .= "Content-Type: text/plain; charset=\"iso-8859-1\"\n";
  $msg .= "Content-Transfer-Encoding: 7bit\n\n";
  $msg .= $messaggio . "\n\n";

  // Metto il separatore
  $msg .= "--{$mime_boundary}\n";

  // Aggiungo l'allegato al messaggio
  $msg .= "Content-Disposition: attachment; filename=\"{$allegato_name}\"\n";
  $msg .= "Content-Transfer-Encoding: base64\n\n";
  $msg .= $data . "\n\n";

  // chiudo con il separatore
  $msg .= "--{$mime_boundary}--\n";
}

// Invio la mail
if (mail($destinatario, $oggetto, $msg, $headers))
{
header("xxxx"); //Riapro la pag. iniziale
}else{
  echo "<p>Errore!</p>";
}
?>
 

MarcoGrazia

Utente Attivo
15 Dic 2009
793
16
18
59
Udine
www.stilisticamente.com
Devi allegare un file ad un'email inviata da un form pubblico? Non si fa! Sai lo spam e i tentativi di inviare worm tramite il tuo sito?
Tanto sei stato tu mica io :D

Ma non si fa per un motivo ben preciso, verificare il tipo di file inviato è virtualmente impossibile, ci sono dei metodi ma sono aggirabili.
Per esempio già l'HTML5 permette di inserire nell'input di file l'attributo accept a cui passare il mime type del file da caricare, ma se io utilizzo un browser datato o che comunque non riconosce l'html5 ecco aggirato l'ostacolo.
Via PHP è molto dura leggere il tipo di file; io una volta arrivato il file tramite l'array $_FILE ne leggo i primi 6 caratteri, dove c'è solitamente l'indirizzo del tipo di file alla ricerca dei caratteri che me lo identificano, ma sai che ci vuole a sovrascriverli?
 

tunix

Nuovo Utente
7 Giu 2018
2
0
1
Intanto grazie per la risposta :)

Purtroppo certe cose non le partorisce la mia testa, ma ahimè, devo cercare di eseguirle...
È già qualcosa farle arrivare ad un alias e poi ci pensa l'antivirus (non delle balle) ancor prima che arrivi al client, però mi serve quanto meno cercare di limitare il tipo di file al solo pdf.
Inserisco un captcha per aiutare..

Se non posso farla da php, posso forse in js?

Codice:
    x = document.getElementById("allegato").value;
    if (x == "")
    errore = "Non puoi inviare senza allegare."
 

macus_adi

Utente Attivo
5 Dic 2017
1.328
89
48
IT/SW
$_FILE ne leggo i primi 6 caratteri
Cosa leggi?
Esistono librerie atte a leggere preventivamente il file, vedi zend framework, oltre che analizzare l'estensione (banalmente raggirabile) ne leggi il contenuto ed il relativo type corretto....
Hai mai provato ad inviare una mail con una dll dentro, magari anche zippata? Bene... Come fa google ad impedire l'invio?
La logica è la stessa... solo che applicata all'upload...

Salut!
 

MarcoGrazia

Utente Attivo
15 Dic 2009
793
16
18
59
Udine
www.stilisticamente.com
il tipo mime, eccoti la funzione che lo legge dentro il file e ritorna il tipo mime, oppure false se non lo trova:
PHP:
function minimime($fname) {
    $fh = fopen($fname, 'rb');
    if ($fh) {
        $bytes6 = fread($fh, 6);
        fclose($fh);
        if ($bytes6 === false) return false;
        //    IMG
        if (substr($bytes6, 0, 3) == "\xff\xd8\xff") return 'image/jpeg';
        if (substr($bytes6, 0, 2) == "\x42\x4D") return 'image/x-windows-bmp';
        if ($bytes6    == "\x89PNG\x0d\x0a" || $bytes6    == "\x89\x50\x4E\x47\x0D\x0A") return 'image/png';
        if ($bytes6    == "\x47\x49\x46\x38\x37\x61" || $bytes6 == "\x47\x49\x46\x38\x39\x61") return 'image/gif';
        if ($bytes6    == "GIF87a" || $bytes6 == "GIF89a") return 'image/gif';
        if (substr($bytes6, 0, 4) == "\x49\x49\x2A\x00" || substr($bytes6, 0, 4) =="\x4D\x4D\x00\x2A") return 'image/tiff';
        //    PDF
        if ($bytes6 == "%PDF" || substr($bytes6, 0, 4) == "\x25\x50\x44\x46") return 'application/pdf';
        //    ZIP, RAR file or 7z
        if (substr($bytes6, 0, 2) == "PK" || substr($bytes6, 0, 2) == "\x50\x4B") return 'application/zip';
        if ($bytes6 == "\x52\x61\x72\x21\x1A\x07") return 'application/x-rar-compressed';
        if ($bytes6 == "\x75\x73\x74\x61\x72") return 'application/x-tar';
        if (substr($bytes6, 0, 2) == "7z" || $bytes6 == "\x37\x7A\xBC\xAF\x27\x1C") return 'application/x-7z-compressed';
        //    ELSE
        return 'application/octet-stream';    //    Generic file
    }
    return false;
}    //    minimime()
Il tipo di mime si trova sempre nei primi 6 caratteri del file, ovvio che si può sempre modificare e il file funziona lo stesso.
Una DLL porta sempre nei primi 4 caratteri il codice esadecimale 4D 5A , in ASCII: MZ.
Esistono librerie atte a leggere preventivamente il file, vedi zend framework, oltre che analizzare l'estensione (banalmente raggirabile) ne leggi il contenuto ed il relativo type corretto....
Ovvio che ne esistono, ma non sempre uso un intero framework per estrapolare un solo dato, persino PHP non ha solo la libreria che lo estrapola dall'array $_FILE, per esempio le FINFO sono molto più performanti ma non sempre sono disponibili dato che vannno abilitate.
Hai mai provato ad inviare una mail con una dll dentro, magari anche zippata? Bene... Come fa google ad impedire l'invio?
La logica è la stessa... solo che applicata all'upload...
Ovvio ma che discorso è, ognuno usa o sviluppa le librerie che ritiene necessarie; GMail è un'applicazione, come altre, che permette di inviare e ricevere email, ma a quello serve e mi aspetto che funzioni in modo egregio, ma dietro Google ci sono migliaglia di sviluppatori, se io devo realizzare un sito non ho ne il loro background ne i loro sviluppatori.
Posso solo immaginare come fanno loro e pensare a come farei io, ma tutto dipende.
Se devo sviluppare un sito in cui c'è un form per inviare email, cerco di renderlo più semplice possibile, proprio per non cacciarmi in problemi ulteriori. A meno che ovviamente per lavoro non mi chiedano di più, ma a quel punto non dovrei essere io da solo a decidere sul da farsi, ma devo spiegare quale sarà la strategia da seguire.
Inviare un file da form pubblico è sempre un pericolo ed una libreria preconfezionata non da mai la sicurezza al 100% uno se è obbligato ci prova, se usi zend framework o altro per il lavoro usi ovviamente le sue funzioni, non reinventi la ruota avendola già a disposizione, se non è questo il tuo caso ti tocca inventare qualche cosa, ne va non solo della sicurezza del sito e di chi riceve le email, ma anche della credibilità dell'azienda che l'ha ordinato e soprattutto della credibilità di chi lo ha sviluppato, capro espiatorio per ogni problema che si possa verificare.
Buonissima giornata a te.

@tunix in javascript non è che serva per la sicurezza, o meglio, se impedisci l'invio del form se non è attivo il javascript può anche andare, ma è sempre meglio utilizzare un sistema lato server per la sicurezza.
 
Ultima modifica:

macus_adi

Utente Attivo
5 Dic 2017
1.328
89
48
IT/SW
Ciao @MarcoGrazia la tua funzione che funziona egregiamente è sintetizzabile con 1 (una) linea di codice, vedi qui.
Ovvio ma che discorso è, ognuno usa o sviluppa le librerie che ritiene necessarie;
Bhè qui il discorso è uno: La ruota è stata inventata, si sviluppa per cercare di minimizzare codice, e comunque senza andare lontano e parlare di framework blasonati si potrebbe utilizzare la Classe di Codeigniter (https://www.codeigniter.com/userguide3/libraries/file_uploading.html), che fa esattamente ciò che serve...

Buona giornata, buon code editing e buono studio!
 

MarcoGrazia

Utente Attivo
15 Dic 2009
793
16
18
59
Udine
www.stilisticamente.com
Concordo con te sull'utilizzo di una classe del genere se devi controllare l'aupload, ma se ti serve il solo controllo del file è una procedura costosa in termini di risorse.
Per questo ho affrontato il problema da un punto di vista radicale; non voglio reinventare la ruota, ma nemmeno mettere una ruota da 17 pollici in una 500 ;-)
 

macus_adi

Utente Attivo
5 Dic 2017
1.328
89
48
IT/SW
@MarcoGrazia Punti di vista... un Controller che pesa poco più di 17k non credo (ed infatti non lo è) sia molto esoso di risorse. Il cerchio da 17 sarebbe da prevedere per future scalabilità dell'applicazione...
Certo il discorso prende una piega ben diversa (e concordo pienamente con te) quando si analizzano i seguenti punti:
  1. Budget
  2. Tempi
  3. Compliance
  4. Macchina di produzione
  5. Servizi
  6. etc etc...
Mi fermo, la lista è lunga!

Controllando meglio la docs di PHP, le librerie inerenti alla manipolazione dei file sono rese disponibili di default da PHP.

@tunix Affrontando il discorso a modi servizi si potrebbe prevedere la validazione del media attraverso un qualsiasi servizio atto alla verifica dello stesso.
 
Discussioni simili
Autore Titolo Forum Risposte Data
C [PHP] Controllo <select> comportamento anomalo PHP 2
A [PHP] Controllo nome utente form di registrazione PHP 4
L [PHP] controllo dimensione immagine per il resize PHP 2
P [PHP] Controllo al checkbox privacy PHP 6
M [PHP] Script per controllo disponibilitá negozio in citta PHP 4
F Controllo dati sui campi di input tramite php PHP 1
M [PHP] Dubbio controllo IF PHP 15
M [PHP] Controllo campo cap con trattino oltre ai numeri PHP 3
Fede72 Controllo registrazioni PHP Mysql PHP 5
bubino8 [PHP] Controllo Log e Modifiche Utenti PHP 5
P [PHP] Realizzare un controllo accessi cantiere, problema lettore Qrcode... PHP 0
M [PHP] Controllo inserimento in tempo reale PHP 0
M [PHP] Help: controllo valori inseriti in un campo PHP 1
M [PHP] Impedire di digitare determinati caratteri nell’input (controllo in tempo reale) PHP 4
giancadeejay [PHP] Controllo inserimento tot caratteri PHP 5
giancadeejay [PHP] Controllo su quantita' di caratteri inseriti, in colonna db PHP 5
CristianB72 [PHP] Controllo sintassi indirizzo email non funziona PHP 13
M [PHP] controllo inserimento dati un un form PHP 4
ANDREA20 [PHP] Controllo email se e valida PHP 5
P controllo browser sul server o in php? PHP 2
F controllo form php con restituzione errori nella form PHP 10
B Problemi con pannello di controllo PHP PHP 0
B Problemi con pannello di controllo PHP PHP 0
L [php] upload controllo dimensione immagine PHP 8
Z Controllo campi di un form php PHP 5
X Eseguire controllo su variabili php PHP 1
P Controllo php su checkbox PHP 2
X controllo e scrittura su db mysql con pagine php PHP 4
P controllo dati form con jquery e php PHP 8
L [PHP e FTP upload] controllo file allegato PHP 6
L [PHP] Sapere se si lavora in locale o remoto (Controllo server Database) PHP 1
max_400 Messenger HTML - PHP - Controllo script PHP 29
A Sicurezza e controllo password in PHP PHP 4
X Controllo versione minima PHP PHP 1
E campo controllo in formail php PHP 1
G Script php per invio email con controllo sintassi e record MX PHP 0
G Script php per invio email con controllo sintassi e record MX PHP 7
T fatture con voci fattura in php PHP 0
T ALTRO PROBLEMA CON ARRAY PHP PHP 1
M Collegamento tra form html e script php PHP 4
M Problemi con la stampa dei valori in php PHP 1
W [Cerco collaborazioni] Sviluppatore Web (PHP) Offerte e Richieste di Lavoro e/o Collaborazione 0
D passare valori da database sql a php PHP 1
L Ricezione dei dati su file php da modulo html PHP 6
E Inviare variabile a PHP da ciclo in JS Javascript 0
A form PHP prenotazione tramite query PHP 2
A Form php prenotazione di un azienda sanitaria locale presso studio medico PHP 1
F menù select dinamico da db in php PHP 3
L Problemi form Pagina php HTML e CSS 3
L php mysql non salva solo id PHP 21

Discussioni simili