Newsgroup: it.comp.lang.perl
Titolo: CGI file upload

Ciao,
sto provando a caricare un file in una cartella, ma sembra ci sia un 
problema: invece di caricare un file miofile.doc, carica CGITemp12378.
Qui c'è il codice:
if ($q->param) {
     my $filename = $q->param("fileUpload");
     my $savePath = "c:/siti/perlbox/".$filename; #percorso
     my $ok = $q->upload($q->param("fileUpload"), $savePath);
     if ($ok) {
         print "ok";
     } else {
         print $q->cgi_error();
     }
}
E non stampa né ok, ne l'errore. 'Un capico miha.
Grazie.....
max

 }
prova cosě:
if ($q->param)
{
   my $filename = $q->param("fileUpload");
   my $savePath = "c:/siti/perlbox/" . $filename;
   my ($name) = ($filename =~ m|([^\\/]+)$|);
 
   open(LOCAL, ">$savePath");
   binmode(LOCAL);
   while(<$file>) {
      print LOCAL $_;
   }
   close(LOCAL);
 
   chmod (0644, $savePath);
}

meglio ancora sarebbe questo codice:
#!/usr/bin/perl
use strict;
use warnings;
use CGI::Carp "fatalsToBrowser";
use CGI;
my $q = new CGI();
if ($q->param)
{
   my $file = $q->param('fileUpload');
 
   my ($name) = ($file =~ m|([^\\/]+)$|);
 
   my $savePath = 'c:/siti/perlbox/' . $name;
 
   open(LOCAL, ">$savePath");
   binmode(LOCAL);
   while(<$file>) {
      print LOCAL $_;
   }
   close(LOCAL);
 
   chmod (0644, $savePath);
}
print "Content-type: text/html","\n\n";
print "ok!\n";

> print "ok!\n";
Grazie Larry,
mi chiedo come mai non funzionasse l'esempio che ho trascritto (preso 
dal perldoc di CGI)...

    open(LOCAL, ">$savePath");
Uhm, non conosco a sufficienza la shell in Windows, ma se una cosa del
genere la vedessi da qualche parte in Linux inorridirei. Nell'esempio
che segue mi limito a togliere 'c:' dal percorso, ma la sostanza non
cambia.
Prova a pensare ad un utente malizioso che ti spedisce un file con un
filename tipo "ciao | rm -rf /". L'uso della open() a due argomenti fa
sì che questa vada ad operare su ">/siti/perlbox/ciao | rm -rf /".
Questa roba viene eseguita dalla shell, che ti apre il file, e
simpaticamente ti esegue anche 'rm -rf /', provando a cancellarti
tutti i file che può. Magari non saranno molti, magari sì.
Per questo motivo, è anche sempre consigliabile usare la modalità
"taint" (perldoc perlrun, opzione -T). E' comunque singolare che nel
tuo caso subiresti danni anche con la modalità taint attiva.
Il mio consiglio è mai, *mai*, *MAI* usare la open a 2 argomenti. Usa
sempre quella a tre argomenti, tipo;
   open(LOCAL, '>', $filename);
In questo modo, perl non andrà a chiamare la shell, ma utilizzerà il
contenuto di $filename come nome di file effettivo.
Avrei qualcosa da ridire anche sull'uso di filehandle non lessicali e
sul fatto che non si controlli l'esito della open(), ma a questo punto
se ti interessa ho scritto quel che penso qui:
http://www.polettix.it/cgi-bin/wiki.pl/Programming/Dammi_una_mano

 genere la vedessi da qualche parte in Linux inorridirei.
credi che il suddetto codice sia meglio?
#!/usr/bin/perl
use strict;
use warnings;
use CGI::Carp "fatalsToBrowser";
use CGI;
my $q = new CGI();
if ($q->param)
{
   my $file = $q->param('fileUpload');
 
   my ($name) = ($file =~ m|([^\\/]+)$|);
       $name =~ s/[^ -~]+//g;
   my $savePath = 'c:/siti/perlbox/' . $name;
 
   open my $fh1, '>', $savePath;
   binmode($fh1);
   while(<$file>) {
      print $fh1 $_;
   }
   close($fh1);


 print "ok!\n";
Sicuramente meglio! Mi rendo conto che molte volte la documentazione
di Perl e dei vari moduli in realtà incoraggia certe pratiche che
potrebbero rivelarsi poi dannose.
Mi chiedo però se questo codice in realtà funziona a dovere. Leggendo
la documentazione di CGI, ho trovato quanto segue:
"However, there are problems with the dual nature of the upload
fields. If you use strict, then Perl will complain when you try to use
a string as a filehandle. You can get around this by placing the file
reading code in a block containing the no strict pragma. More
seriously, it is possible for the remote user to type garbage into the
upload field, in which case what you get from param() is not a
filehandle at all, but a string."
La soluzione proposta consiste nel prendere il filehandle attraverso
la funzione/metodo "upload":
    my $fh = upload('uploaded_file');
Altro nit-pick riguarda l'apertura del file, IMHO dovrebbe esserci un
controllo che l'apertura stessa sia andata a buon fine, ad esempio con
il classico "or die...":
    open my $fh1, '>', $savePath or die "open('$savePath'): $!";
A tutto ciò si può ovviare "una volta per tutte" utilizzando il modulo
CORE Fatal:
   use Fatal qw( open );
In questo modo, tutte le open() che non vanno a buon fine lanceranno
automaticamente un'eccezione.
Ci sono poi argomentazioni convincenti riguardo l'utilizzo della
cosiddetta "indirect notation" nella chiamata dei metodi. Quindi, al
posto di una suggestiva chiamata:
   my $q = new CGI();
preferisco qualcosa di più Perl-safe:
   my $q = CGI->new();
Come dicevo nell'altra email, inoltre, è di solito buona norma
attivare la modalità Taint nel caso di script CGI, per cui la shebang
diventa qualcosa tipo:
   #!/usr/bin/perl -T
Riguardo ai messaggi d'errore, infine, la riga:
   use CGI::Carp "fatalsToBrowser";
è molto utile in fase di debugging, ma è normalmente sconsigliata "in
produzione", perché rischia di esporre troppo del proprio script ad un
utente malintezionato che riesce in qualche modo a far crashare lo
script.
Per una trattazione sicuramente migliore e più accurata dell'argomento
puoi guardare 
http://users.easystreet.com/ovid/cgi_course/
Ciao,
    Flavio.