Между прочим, можно подробно остановиться на этой идее очень, быстро находят два уникальные числа среди списка дубликатов.
Позволяют нам назвать уникальные числа a и b. Сначала возьмите XOR всего как предложенный Kyle. То, что мы получаем, является a^b. Мы знаем a^b! = 0, с тех пор a! = b. Выберите любой 1 бит a^b и использование что как маска - более подробно: выберите x в качестве питания 2 так, чтобы x & (a^b) является ненулевым.
Теперь разделяет список на два подсписка - один подсписок содержит все числа y с y& x == 0, и остальные входят в другой подсписок. По тому, как мы выбрали x, мы знаем, что a и b находятся в различных блоках. Мы также знаем, что каждая пара дубликатов находится все еще в том же блоке. Таким образом, мы можем теперь применить Вас olde "XOR-em-all" прием к каждому блоку независимо и обнаружить то, что a и b полностью.
Обман.
.jpeg
and not .jpg
! File::MMagic
or File::MimeInfo
would make better general-purpose solutions.(stat $file)[10]
isn't the content-length, it's the ctime
, which is worthless to you. (stat $file)[7]
works, but -s $file
works just as well and it's obvious to any Perl programmer what it does without having to consult the stat
manual. (2a: use -s
on the filehandle once you open it instead of the filename to avoid racing against file replacement.)image.pl?image=../../../../../../../etc/passwd
. I'd suggest specifically mentioning the images directory so that you're not dependent on the getcwd
, and using File::Spec
->no_upwards
and File::Spec->catfile
to build a pathname that can only be inside the images directory.die
if it's avoidable. If the file isn't found, return a 404
status. If the request is illegal, return a 400
or 403
status, etc.path_info
to allow image.pl/foo.png
instead of image.pl?img=foo.png
.Посмотрите, как это делается в Apachegallery
http://metacpan.org/pod/Apache::Gallery
Он использует Imlib2 и довольно эффективен, включая расширенные функции, такие как изменение размера и поворот на лету, а также использование общего дискового кеша.
The simplest way to serve an image is by using the file handling that is probably already included in your webserver.
You can also add authentication by using an .htaccess
file (if you're using Apache).
Я думаю, вам здесь что-то не хватает:
my @img = $query->param;
if ( $_ eq "img" ) { my $file = $query->param($_); }
if ( $_ ne "img" ) { ## error }
$ _
не инициализирован. Я думаю, вы хотели сказать:
my @img = $query->param;
foreach (@img) {
if ( $_ eq "img" ) { my $file = $query->param($_); }
if ( $_ ne "img" ) { ## error }
}
или для лучшей читаемости и удобства обслуживания
my @img = $query->param;
foreach my $param (@img) {
if ( $param eq "img" ) { my $file = $query->param($param); }
if ( $param ne "img" ) { ## error }
}
С другой стороны, вы, вероятно, захотите использовать
( stat($file) )[7];
, а не
( stat($file) )[10];
, чтобы получить длину файла. (stat $ file) [10]
даст вам время изменения файла.
Я бы изменил только несколько вещей.
Во-первых, замените блок кода после первого блока комментариев следующим:
my $query = new CGI;
my $file = $query->params('img');
Ваш код для получения расширения файла не работает для меня. Это значит:
my ($ext) = $file =~ m/\.([^\.]+)$/;
Я не понимаю использования "my $ image = do {...". Это просто не кажется необходимым.
Поскольку вы уже используете модуль CGI, используйте его для создания ваших заголовков за вас:
print $query->header(
-type => 'image/' . $ext,
-Content_length => $length,
);
То, как вы читаете файл и записываете его обратно, выглядит функционально идеально.
У меня есть несколько дополнительных комментариев и предложений. Во-первых, ваш код крайне небезопасен. Приятно, что вы думаете о режиме заражения, но вы ничего не делаете с именем файла, переданным от вашего клиента. Что, если они прошли "/ etc / passwd", например? Во-вторых, вы можете открыть файл изображения (после дополнительных проверок безопасности) перед отправкой заголовков HTTP. Это позволит вам отправить клиенту разумную ошибку (404?), А не просто умереть. Используйте метод «заголовка» CGI, чтобы упростить это. Вы все еще можете написать что-нибудь в STDERR, если хотите.
Это все, о чем я сейчас могу думать. Надеюсь, этого достаточно, чтобы вы начали.
Я не уверен, что вы пытаетесь сделать, но похоже, что с этим было бы намного проще справиться без Perl и CGI. Какой сервер вы используете? Я бы предпочел исправить это с помощью правила перезаписи в Apache.
Я никогда не был поклонником скриптов привратника. Может быть, если вы скажете, почему вы пытаетесь это сделать, мы сможем предложить хорошее решение (а не просто лучшее :).