2009-09-30 11 views
5

Ho trovato alcuni post correlati qui ma, niente di giusto in .. Ho bisogno di servire un'immagine (humm) "correttamente" e usare il minor numero possibile di risorse. Stavo lavorando su un sotto (sotto) ma, non è troppo adatto alle risorse solo per il fatto che utilizzo CGI. Questa è solo la mia ipotesi però. Sono un principiante di Perl ma, mi piace meglio di PHP.Come posso fornire un'immagine con Perl con un po 'di sicurezza e meno risorse?

La query sarebbe generato da "somescript.pl?img=image.png"

#!/usr/bin/perl -Tw 
use strict; 
use warnings; 
use CGI; 

#I should drop warnings after all is said and done. Also name my vars generically. Right? 
#I dont know if this query method will work or is even the best method. 
$query = new CGI; 
my @img = $query->param; 
if ($_ eq "img") { my $file = $query->param($_); } 
if ($_ ne "img") { ## I will send to an error sub that serves up a error image 
} 

# Prob a one liner to take care of the above. Not within my ability though. 
# Still figuring all this out here.. Very verbose sorry... 
# I will strip everything but lowercase alpha and the "." 
# with s =~ /[something like A-Z] I will look it up //g; 
# Still.. prob all above will fit in a one liner by a PERL guru! 

# Below is related to -Taint, I was told this is important to use the -T. 
$ENV{PATH} = "bin:/usr/bin"; 
delete($ENV{qw(IFS CDPATH BASH_ENV ENV)}); 

# now I will grab the images extension. 
my $ext = ($file =~ m/[^.]+$/)[0]; 

#I was informed to use the "three" but, I am unsure what that means. 
# My attempt based on my reading many posts here. 

my $length = (stat($file))[10]; 
my $image = do { 
    local $/ = undef; 
    print "Content-type: image/$ext\n"; 
    print "Content-length: $length \n\n"; 
    binmode STDOUT; 
    open(FH, "<", $file) || die "Could not find $file: $!"; 
    my $buffer = ""; 
    while (read(FH, $buffer, 10240)) { 
     print $buffer; 
    } 
    close(FH); 
}; 

Come si può vedere, il mio tentativo qui è ovviamente un principiante.

Ho trovato un ottimo consiglio qui in overflow dello stack. Ringrazio tutti passato e presente.

+0

Si prega di inserire il codice in un blocco di codice (aggiungere 4 spazi prima di ogni riga), è completamente illeggibile al momento –

+0

Scusa, pensavo di averlo fatto. –

+0

Grazie Adam! Non so perché il blocco di codice non funzionasse per me. Il mio male è ovvio ... –

risposta

4

Avere uno sguardo al modo in cui si è fatto in Apachegallery

http://metacpan.org/pod/Apache::Gallery

che sta utilizzando Imlib2 ed è abbastanza efficiente, incluse le funzioni avanzate come il ridimensionamento e la rotazione al volo e con una cache disco condiviso.

1

penso che ti manca qualcosa qui:

my @img = $query->param; 
if ($_ eq "img") { my $file = $query->param($_); } 
if ($_ ne "img") { ## error } 

$_ è inizializzato. Credo che volevi dire:

my @img = $query->param; 
foreach (@img) { 
    if ($_ eq "img") { my $file = $query->param($_); } 
    if ($_ ne "img") { ## error } 
} 

o per una migliore leggibilità e la manutenibilità

my @img = $query->param; 
foreach my $param (@img) { 
    if ($param eq "img") { my $file = $query->param($param); } 
    if ($param ne "img") { ## error } 
} 

Per un'altra cosa, probabilmente si desidera utilizzare

(stat($file))[7]; 

e non

(stat($file))[10]; 

per ottenere la lunghezza di un file. (stat $file)[10] ti darà il tempo di cambio del file.

+0

Come su 'my $ file = $ query-> param (" img "); if (grep $ _ ne "img", $ query-> param) {errore param inaspettato} '? Correre su una collezione solo per tirare fuori un valore noto è un po 'un anti-pattern :) – hobbs

+0

Grazie ragazzi! Non so come ho perso il foreach, è nel mio codice originale. Lasciami passare sopra tutte queste risposte qui. Nessuno ha ancora commentato il mio uso di contaminazione. Immagino sia ok come si siede .. stat è qualcosa su cui leggerò di più. Grazie ancora per averlo indicato! –

+0

@hobbs bello ... Grazie! –

5
  1. Se avete intenzione di utilizzare l'estensione come un sostituto per MIME-tipo, allora è meglio nominare tutte le immagini JPEG .jpeg e non .jpg! File::MMagic o File::MimeInfo creerebbero soluzioni migliori per uso generale.
  2. (stat $file)[10] non è la lunghezza del contenuto, è il ctime, che non ha valore per voi. (stat $file)[7] funziona, ma il -s $file funziona altrettanto bene ed è ovvio per qualsiasi programmatore Perl che cosa fa senza consultare il manuale stat. (2a: utilizzare -s sul filehandle dopo averlo aperto anziché il nome file per evitare corse contro la sostituzione dei file)
  3. Posso accedere a qualsiasi file sul filesystem leggibile dall'utente che il CGI esegue come, ad es. image.pl?image=../../../../../../../etc/passwd. Suggerirei di menzionare specificamente la directory delle immagini in modo da non dipendere dallo getcwd e dall'uso di File::Spec->no_upwards e File::Spec->catfile per creare un nome di percorso che può essere solo all'interno della directory delle immagini.
  4. Non è una buona forma per una CGI a die se è evitabile. Se il file non viene trovato, restituire uno stato 404. Se la richiesta è illegale, restituire uno stato 400 o 403, ecc
  5. vostri URL sarebbe più bello se si è utilizzato path_info per consentire image.pl/foo.png invece di image.pl?img=foo.png.
  6. A meno che non aggiungiate un po 'di logica, le immagini che servite non verranno memorizzate nella cache dal client.
  7. Man, questi sono accatastati. Hai pensato di trovare un codice che è già stato scritto per lo scopo invece di scriverne uno tuo?
+0

Ho il jpe? G coperto nel mio htaccess ma non qui, presa eccellente. Ho dimenticato di inserire if ($ ext eq "jpg") {$ ext = "jpeg"} in parte il codice che ho postato qui. –

+0

Sì, l'ho soffiato sul [10] il mio male. Htaccess è il modo in cui viene chiamato lo script. Il tag immagine è normale, quindi, il mio amico può mostrare le sue immagini su siti che non consentono stringhe di query nei tag. –

+0

Ma, ho impostato il mio htaccess per colpire lo script e servire l'immagine quando c'è una condizione esistente nel percorso delle immagini. Fondamentalmente una regola di hotlinking invertita. Il fatto che non abbia nemmeno bisogno di una stringa di query è vero. GRAZIE Dovrei farlo ma, sono rimasto bloccato su come avrei afferrato quell'url così da poter dividere il/i se necessario. path_info potrebbe essere esattamente l'indizio di cui ho bisogno per risolverlo. Guarderò File :: Spec in grande tempo .. Volevo evitare i moduli ma, inutilmente. –

1

Il modo più semplice per servire un'immagine consiste nell'utilizzare la gestione dei file che è probabilmente già inclusa nel server web.

È inoltre possibile aggiungere l'autenticazione utilizzando un file .htaccess (se si utilizza Apache).

+0

Sì, grazie, sembra che tu sappia cosa sto combinando. Questo (htaccess) è come viene chiamato lo script. Il tag immagine è normale, quindi può mostrare le sue immagini su siti che non consentono stringhe di query nei tag. Ma, ho impostato il mio htaccess per colpire lo script e servire l'immagine quando c'è una condizione esistente nel percorso delle immagini. Fondamentalmente una regola di hotlinking invertita. Quindi, ora sono bloccato sullo script effettivo che servirà ... –

1

Vorrei solo cambiare alcune cose.

In primo luogo, sostituire il blocco di codice dopo il primo blocco commento a questo:

my $query = new CGI; 
my $file = $query->params('img'); 

Il codice per ottenere l'estensione del file non funziona per me. Si tratta di:

my ($ext) = $file =~ m/\.([^\.]+)$/; 

Non capisco l'uso di "my $ image = do {...". Semplicemente non sembra necessario.

Dal momento che si sta utilizzando già il modulo CGI, usarlo per fare le intestazioni per voi:

print $query->header(
    -type => 'image/' . $ext, 
    -Content_length => $length, 
    ); 

Il modo in cui si sta leggendo il file e scrivere di nuovo fuori sembra funzionalmente perfetta.

Ho diversi commenti aggiuntivi & suggerimenti. Innanzitutto, il tuo codice è estremamente insicuro. È bello che tu stia pensando alla modalità contaminazione, ma non stai facendo nulla riguardo al nome file passato dal tuo client. Cosa succede se hanno passato "/ etc/passwd", per esempio? Un altro è che si potrebbe anche aprire il file immagine (dopo aver effettuato ulteriori controlli di sicurezza) prima dello inviando le intestazioni HTTP. Ciò consentirebbe di inviare un errore ragionevole al client (404?), Piuttosto che morire. Usa il metodo "header" della CGI per renderlo facile. Puoi comunque scrivere qualcosa su STDERR, se lo desideri.

Questo è tutto quello che posso pensare solo ora. Spero che questo sia sufficiente per farti andare.

+0

Grazie! Sì, morire non doveva essere usato. Voglio pubblicare un'immagine predefinita se il file non è stato trovato. Continuo a capirlo. Il file htacces è ciò che effettivamente sta chiamando lo script dell'immagine. La regola lo invia al mio script se il percorso delle immagini soddisfa una condizione specifica. In questo modo il mio amico può usare un normale tag immagine per mostrare le sue immagini grafiche su luoghi che potrebbero non consentire le stringhe di query nei tag immagine. Ho bisogno di aiuto per la sicurezza "upgrade" che hai menzionato. Grazie ancora per la tua guida ... –

0

Non sono sicuro di cosa si sta provando a fare, ma sembra che sarebbe molto più semplice gestirlo senza Perl e CGI. Quale server stai usando? Preferirei risolvere il problema con una regola di riscrittura in Apache.

Non sono mai stato un fan degli script di gatekeeper, però. Forse se puoi dire perché stai cercando di farlo, possiamo trovare una buona soluzione (e non solo una migliore :).

Problemi correlati