[php] controllo su estensione file

Discussione in 'PHP' iniziata da tunix, 7 Giugno 2018.

  1. tunix

    tunix Nuovo Utente

    Registrato:
    7 Giugno 2018
    Messaggi:
    2
    Mi Piace Ricevuti:
    0
    Punteggio:
    1
    Sesso:
    Maschio
    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 'XX@xx.xx';
    $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($filefilesize($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>";
    }
    ?>
     
  2. MarcoGrazia

    MarcoGrazia Utente Attivo

    Registrato:
    15 Dicembre 2009
    Messaggi:
    664
    Mi Piace Ricevuti:
    7
    Punteggio:
    18
    Sesso:
    Maschio
    Occupazione:
    Sviluppare web design (Studiare)
    Località:
    Udine
    Home Page:
    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?
     
  3. tunix

    tunix Nuovo Utente

    Registrato:
    7 Giugno 2018
    Messaggi:
    2
    Mi Piace Ricevuti:
    0
    Punteggio:
    1
    Sesso:
    Maschio
    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."
     
  4. macus_adi

    macus_adi Utente Attivo

    Registrato:
    5 Dicembre 2017
    Messaggi:
    966
    Mi Piace Ricevuti:
    56
    Punteggio:
    28
    Sesso:
    Maschio
    Occupazione:
    Developer
    Località:
    L'Aquila
    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!
     
  5. MarcoGrazia

    MarcoGrazia Utente Attivo

    Registrato:
    15 Dicembre 2009
    Messaggi:
    664
    Mi Piace Ricevuti:
    7
    Punteggio:
    18
    Sesso:
    Maschio
    Occupazione:
    Sviluppare web design (Studiare)
    Località:
    Udine
    Home Page:
    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($fh6);
            
    fclose($fh);
            if (
    $bytes6 === false) return false;
            
    //    IMG
            
    if (substr($bytes603) == "\xff\xd8\xff") return 'image/jpeg';
            if (
    substr($bytes602) == "\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($bytes604) == "\x49\x49\x2A\x00" || substr($bytes604) =="\x4D\x4D\x00\x2A") return 'image/tiff';
            
    //    PDF
            
    if ($bytes6 == "%PDF" || substr($bytes604) == "\x25\x50\x44\x46") return 'application/pdf';
            
    //    ZIP, RAR file or 7z
            
    if (substr($bytes602) == "PK" || substr($bytes602) == "\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($bytes602) == "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.
    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.
    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: 8 Giugno 2018
  6. macus_adi

    macus_adi Utente Attivo

    Registrato:
    5 Dicembre 2017
    Messaggi:
    966
    Mi Piace Ricevuti:
    56
    Punteggio:
    28
    Sesso:
    Maschio
    Occupazione:
    Developer
    Località:
    L'Aquila
    Ciao @MarcoGrazia la tua funzione che funziona egregiamente è sintetizzabile con 1 (una) linea di codice, vedi qui.
    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!
     
  7. MarcoGrazia

    MarcoGrazia Utente Attivo

    Registrato:
    15 Dicembre 2009
    Messaggi:
    664
    Mi Piace Ricevuti:
    7
    Punteggio:
    18
    Sesso:
    Maschio
    Occupazione:
    Sviluppare web design (Studiare)
    Località:
    Udine
    Home Page:
    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 ;-)
     
  8. macus_adi

    macus_adi Utente Attivo

    Registrato:
    5 Dicembre 2017
    Messaggi:
    966
    Mi Piace Ricevuti:
    56
    Punteggio:
    28
    Sesso:
    Maschio
    Occupazione:
    Developer
    Località:
    L'Aquila
    @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.
     
Sto caricando...

Condividi questa Pagina