Znalazłem tu kilka powiązanych postów, ale nictak jest.. Muszę wyświetlać obraz (humm) „poprawnie” i wykorzystywać jak najmniej zasobów. Pracowałem nad sub (poniżej), ale nie jest zbyt przyjazny zasobom, ponieważ używam CGI. To tylko moje przypuszczenie. Jestem nowicjuszem w Perlu, ale podoba mi się to lepiej niż php.
Zapytanie zostanie wygenerowane przez „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/$extn";
print "Content-length: $length nn";
binmode STDOUT;
open( FH, "<", $file ) || die "Could not find $file: $!";
my $buffer = "";
while ( read( FH, $buffer, 10240 ) ) {
print $buffer;
}
close(FH);
};
Jak widać, moja próba tutaj jest oczywiście dla początkujących.
Znalazłem świetne rady w przepełnieniu stosu. Dziękuję wszystkim przeszłym i obecnym.
Odpowiedzi:
5 dla odpowiedzi № 1- Jeśli zamierzasz używać rozszerzenia jako substytutu typu MIME, lepiej nazwij wszystkie swoje zdjęcia JPEG
.jpeg
i nie.jpg
!File::MMagic
lubFile::MimeInfo
uczyniłby lepsze rozwiązania ogólnego przeznaczenia. (stat $file)[10]
nie jest to długość zawartości, to jestctime
, co jest dla ciebie bezwartościowe.(stat $file)[7]
działa, ale-s $file
działa równie dobrze i dla każdego programisty Perla jest oczywiste, co robi bez konieczności sprawdzaniastat
podręcznik. (2a: użyj-s
na uchwycie pliku po jego otwarciu zamiast nazwy pliku, aby uniknąć ścigania się z zastąpieniem pliku.)- Mogę uzyskać dostęp do dowolnego pliku w systemie plików, który może być odczytany przez użytkownika, na którym działa CGI, np.
image.pl?image=../../../../../../../etc/passwd
. Sugeruję konkretnie wspomnienie katalogu obrazów, abyś nie był zależny odgetcwd
i używanieFile::Spec
->no_upwards
iFile::Spec->catfile
zbudować ścieżkę, która może znajdować się tylko w katalogu images. - To nie jest naprawdę dobra forma dla CGI
die
jeśli „da się uniknąć. Jeśli plik nie zostanie znaleziony, zwróć a404
status. Jeśli żądanie jest nielegalne, zwróć a400
lub403
status itp. - Twoje adresy URL byłyby ładniejsze, gdybyś używał
path_info
zezwolićimage.pl/foo.png
zamiastimage.pl?img=foo.png
. - Jeśli nie dodasz więcej logiki, obrazy, które serwujesz, nie będą buforowane przez klienta.
- Człowieku, to się układa. Czy zastanawiałeś się nad znalezieniem kodu, który został już napisany w tym celu, zamiast pisać własny?
4 dla odpowiedzi nr 2
Spójrz na sposób w Apachegallery
http://metacpan.org/pod/Apache::Gallery
Używa Imlib2 i jest dość wydajny, w tym zaawansowane funkcje, takie jak zmiana rozmiaru i obracanie w locie oraz korzystanie z udostępnionej pamięci podręcznej dysku.
1 dla odpowiedzi nr 3
Myślę, że coś tu brakuje:
my @img = $query->param;
if ( $_ eq "img" ) { my $file = $query->param($_); }
if ( $_ ne "img" ) { ## error }
$_
jest niezainicjowany. Myślę, że chciałeś powiedzieć:
my @img = $query->param;
foreach (@img) {
if ( $_ eq "img" ) { my $file = $query->param($_); }
if ( $_ ne "img" ) { ## error }
}
lub dla lepszej czytelności i łatwości konserwacji
my @img = $query->param;
foreach my $param (@img) {
if ( $param eq "img" ) { my $file = $query->param($param); }
if ( $param ne "img" ) { ## error }
}
Po drugie, prawdopodobnie chcesz użyć
( stat($file) )[7];
i nie
( stat($file) )[10];
aby uzyskać długość pliku. (stat $file)[10]
poda czas zmiany pliku.
1 dla odpowiedzi nr 4
Najprostszym sposobem na wyświetlenie obrazu jest użycie obsługi plików, która prawdopodobnie jest już zawarta w twoim serwerze.
Możesz także dodać uwierzytelnianie za pomocą .htaccess
plik (jeśli używasz Apache).
1 dla odpowiedzi nr 5
Zmieniłbym tylko kilka rzeczy.
Najpierw zamień blok kodu po pierwszym bloku komentarza na ten:
my $query = new CGI;
my $file = $query->params("img");
Twój kod, aby uzyskać rozszerzenie pliku, nie działa dla mnie.
my ($ext) = $file =~ m/.([^.]+)$/;
Nie rozumiem używania „my $ image = do {...”. To po prostu nie wydaje się konieczne.
Odkąd korzystasz już z modułu CGI, używaj go do wykonywania swoich nagłówków:
print $query->header(
-type => "image/" . $ext,
-Content_length => $length,
);
Sposób, w jaki czytasz plik i zapisujesz go z powrotem, wygląda funkcjonalnie idealnie.
Mam kilka dodatkowych komentarzy i sugestii. Po pierwsze, twój kod jest bardzo niepewny. To miłe, że „zastanawiasz się nad trybem taint, ale nie robisz niczego na temat nazwy pliku przekazywanego z twojego klienta. Co jeśli na przykład przekażą„ / etc / passwd ”? otwórz plik obrazu (po wykonaniu większej liczby kontroli bezpieczeństwa) przed wysyłanie nagłówków HTTP. Pozwoli to na wysłanie rozsądnego błędu z powrotem do klienta (404?), A nie tylko na śmierć. Aby to ułatwić, użyj metody „nagłówka” CGI. Jeśli chcesz, możesz napisać coś do STDERR.
To wszystko, o czym mogę teraz pomyśleć.
0 dla odpowiedzi № 6
Nie jestem pewien, co próbujesz zrobić, ale towygląda na to, że łatwiej byłoby sobie z tym poradzić bez Perla i CGI. Jakiego serwera używasz? Wolę to naprawić za pomocą reguły przepisywania w Apache.
Jednak nigdy nie byłem fanem skryptów gatekeepera. Może jeśli powiesz dlaczego próbujesz to zrobić, możemy wymyślić dobre rozwiązanie (a nie tylko lepsze :).