IZONE - http://www.izcity.com/ - бесплатный софт, вэб-сервисы, ресурсы для раскрутки, свежие номера журнала "Internet Zone".

 IZONE 


Perl для веб-мастера-2

Евгений ГРИВАСТОВ (tw@tv-gent.net)

(Продолжение, Начало в IZone-84)

Несколько счетчиков на одном скрипте.
Итак, мы создали простейший счетчик, который обсчитывает количество заходов на страницу. Теперь давайте научим его считать заходы на разные страницы. Для этого каждой странице присвоим свой идентификатор и укажем его в качестве параметра при вызове скрипта. Т. е. если, например, идентификатор страницы будет "first", то URL вызова скрипта будет выглядеть следующим образом:
<!--#exec cgi="/cgi-bin/count.cgi?first" -->
Чтобы получить значение переданного в скрипт параметра, добавим строку:
$pageid=$ENV{'QUERY_STRING'};
в начало скрипта (например, второй строкой). Таким образом в переменной $pageid у нас окажется значение first. В нашей директории mystat давайте создадим два пустых файла: first.txt и firstip.txt - в первом будем хранить значение счетчика, а во втором - IP-адрес последнего засчитанного посетителя (не забудьте назначить обоим файлам права доступа 666). Теперь осталось научить наш счетчик записывать данные в нужные файлы. Для этого изменим значение двух переменных:
$namefile="/home2/your_domen/public_html/mystat/" . $pageid . ".txt";
$nameipfile="/home2/your_domen/public_html/mystat/" . $pageid . "ip.txt";
Знак "." (точка) означает соединение строк. Т. е. при значении переменной $pageid="first", в переменной $namefile получим значение "/home2/your_domen/public_html/mystat/first.txt", а в переменной $nameipfile - значение "/home2/your_domen/public_html/mystat/firstip.txt". Таким образом, если теперь мы захотим для другой нашей страницы создать счетчик с идентификатором second, достаточно будет создать в директории mystat два файла - second.txt и secondip.txt - и вставить в страницу код вызова скрипта с значением second в качестве параметра:
<!--#exec cgi="/cgi-bin/count.cgi?second"-->

Повышение безопасности и автоматизация добавления новых счетчиков
Настало время подумать немного и о секьюрити нашего скрипта. Давайте для начала научим его хотя бы проверять, с какой страницы он вызван. И если вызов пришел не с родной страницы - просто завершать работу программы.
Прежде всего нам понадобиться еще один файл, в котором будем хранить идентификаторы счетчиков, URL'ы страниц, на которых счетчики расположены, и имена файлов, имеющих отношение к счетчикам. Назовем его counters.txt, поместим в директорию mystat и присвоим права доступа 666. Формат хранимых данных будет следующий:
идентификатор_счетчика|url_страницы|имя_файла _счетчика|имя_файла_последнего_IP
В одной строке - данные по одному счетчику, разделенные символом "|".
Давайте для начала создадим скрипт, который поможет нам легко через веб-форму добавлять новые счетчики. Создаем файл addcount.cgi со следующим кодом:

#!/usr/bin/perl

$namefile="/home2/your_domen/public_html/mystat/counters.txt";

&GetFormInput;

$countid=$field{"countid"};
$url=$field{"url"};
$countfile=$field{"countfile"};
$countipfile=$field{"countipfile"};

open(FILE, ">>$namefile");
print FILE $countid.'|'.$url.'|'.$countfile.'|'.$countipfile."\n";
close(FILE);

exit;

sub GetFormInput {

(*fval) = @_ if @_ ;

local ($buf);
if ($ENV{'REQUEST_METHOD'} eq 'POST') {
read(STDIN,$buf,$ENV{'CONTENT_LENGTH'});
}
else {
$buf=$ENV{'QUERY_STRING'};
}
if ($buf eq "") {
return 0 ;
}
else {
  @fval=split(/&/,$buf);
foreach $i (0 .. $#fval){
($name,$val)=split (/=/,$fval[$i],2);
$val=~tr/+/ /;
$val=~ s/%(..)/pack("c",hex($1))/ge;
$name=~tr/+/ /;
$name=~ s/%(..)/pack("c",hex($1))/ge;

if (!defined($field{$name})) {
$field{$name}=$val;
}
else {
$field{$name} .= ",$val";
}


   }
}
return 1;
}

Здесь мы столкнулись с новым понятием - подпрограмма. Это то же самое, что в других языках программирования именуется "функцией" или "процедурой". Объявляется подпрограмма с помощью ключевого слова sub. В нашем случае это объявление выглядит как sub GetFormInput. Далее в фигурных скобках идет собственно тело подпрограммы. Используемая в этом скрипте подпрограмма разбирает значения полей запроса, полученных от HTML-формы. Вы можете использовать ее в других своих скриптах, взаимодействующих с HTML-формами. Вызывается эта подпрограмма в нашем скрипте с помощью строки:
&GetFormInput;
В результате ее работы создается хэш %field. Хэш - это своеобразный список, в данном случае содержащий значения полученных из HTML-формы полей, связанные с их именами по принципу "имя = значение". Доступ к элементам хэша осуществляется таким образом: $hash{$key}=$value (в этом примере мы ассоциируем с ключом $key значение $value). Имя хэш-переменной начинается со знака "%" (процент) - %hash. Такое обращение к хэшу используется, когда надо обратится ко всему хэшу целиком. Чтобы получить значение, ассоциированное с ключом $key, надо обратиться к хэшу следующим образом - $hash{$key}.
Что делается внутри подпрограммы GetFormInput, мы пока разбирать не будем, чтобы не удаляться от темы нашего разговора.
Итак, что делает наш скрипт. Прежде всего, помещается в переменную $namefile путь к файлу counters.txt. Далее идет вызов подпрограммы GetFormInput, в результате которой у нас появляется хэш %field, содержащий названия и значения полей, полученных от HTML-формы. Поместим эти значения в соответствующие переменные ($countid, $url, $countfile, $countipfile). После этого мы открываем файл counters.txt для добавления в него записей (символы ">>") и записываем туда новую строку, содержащую нужные нам значения. Завершаем работу скрипта.
Для работы с вновь созданным скриптом сделаем небольшую HTML-форму. Код ее будет выглядеть так:

<form action="http://your_domen.com/cgi-bin/addcount.cgi" method="post">
ID счетчика: <input type="text" name="countid" size="20"><br>
URL страницы: <input type="text" name="url" size="20"><br>
Название файла счетчика: <input type="text" name="countfile" size="20"><br>
Название файла с последним IP: <input type="text" name="countipfile" size="20"><br>
<input type="submit"  value="Создать счетчик">
</form>

Здесь значение http://your_domen.com/cgi-bin/addcount.cgi - это URL вызова скрипта. Осталось научить наш скрипт самостоятельно создавать файлы нового счетчика. Для этого добавим в скрипт (перед строкой exit;) следующие строки:
$dir="/home2/your_domen/public_html/mystat/";
open(FILE, ">$dir$countfile");
close(FILE);
open(FILE, ">$dir$countipfile");
close(FILE);
chmod (0666, $dir$countfile, $dir$countipfile);
В переменную $dir помещаем путь к директории, где будут лежать файлы. После этого создаем оба файла (если они уже существуют, то будут очищены) и устанавливаем для них права доступа 666 (возможность чтения и записи).
Осталось научить наш счетчик использовать информацию, помещенную в файл counters.txt. Модернизируем его следующим образом:

          #!/usr/bin/perl

$pageid=$ENV{'QUERY_STRING'};
$ip=$ENV{"REMOTE_ADDR"};
$ref=$ENV{"HTTP_REFERER"};
$countersfile="/home2/your_domen/public_html/mystat/counters.txt";

open (IPFILE, "$countersfile");
METKA: while ($stroka= ) {
chomp($stroka);
($countid, $url, $countfile, $countipfile)=split(/|/,$stroka);
last METKA if ($countid eq $pageid);
}
close(IPFILE);

exit if ($url ne $ref);

$namefile="/home2/your_domen/public_html/mystat/".$countfile;
$nameipfile="/home2/your_domen/public_html/mystat/".$countipfile;

open (IPFILE, "$nameipfile");
$ipold = ;
close(IPFILE);
chomp ($ipold);

if ($ipold eq $ip) {
exit;
}

open (IPFILE, "$nameipfile");
print IPFILE "$ip";
close(IPFILE);

open (COUNTFILE, "+<$namefile");
flock (COUNTFILE,2);
$count =readline(*COUNTFILE);
chomp ($count);
$count=$count+1;
seek (COUNTFILE,0,0);
truncate(COUNTFILE,0);
print COUNTFILE "$count";
close(COUNTFILE);

print "Content-Type: text/html\n\n";
print "$count";

exit;

Примечание: в слове "METKA" использованы только английские символы!
Фактически изменению подверглась только первая половина скрипта. Получив из запроса значение ID счетчика, URL страницы, с которой счетчик был вызван, и IP-адрес посетителя, мы перебираем строки в файле counters.txt, пока не найдем строку с данными ID нашего счетчика. Для этого сначала у прочитанной из файла строки удаляется конечный символ перевода строки (команда chomp($stroka)), потом строка разбивается на четыре значения с помощью команды split (указав в качестве разделителя символ "|"). Как только мы находим строку со значением ID, совпадающим с полученным в качестве параметра, цикл завершается командой last. Далее проверяем: если URL страницы, вызвавшей счетчик, не совпадает с URL'ом, закрепленным за счетчиком - просто завершаем работу скрипта. После этого работа продолжается так же, как и ранее.
Теперь мы можем создавать новые счетчики через web-форму, вести обсчет нескольких страниц нашего сервера. Прекрасная возможность сделать что-то вроде рейтинга страниц своего сайта. Почему только своего? Это связано с тем, что вызов счетчика и вставка результата его работы в страницу происходит с использованием SSI. Несколько позже мы научим его работать и с другими серверами. А пока - займемся страницами собственного сервера. Сделаем это с помощью простого скрипта:

#!/usr/bin/perl

$countersfile="/home2/your_domen/public_html/mystat/counters.txt";

open (IPFILE, "$countersfile");
while ($stroka= ) {
chomp($stroka);
($countid, $url, $countfile, $countipfile)=split(/|/,$stroka);
$namefile="/home2/your_domen/public_html/mystat/".$countfile;
open (COUNTFILE, "$namefile");
$reiting{$url}=readline(*COUNTFILE);
close(COUNTFILE);
}
close(IPFILE);

print "Content-Type: text/html\n\n";

foreach $url (sort keys %reiting) {
print "$url => $reiting{$url}
";
}

exit;

В этом скрипте, по сравнению с описанным ранее, не используется практически ничего нового. Разве что способ перебора хэша и сортировки его элементов. В качестве ключей в хэше используем URL'ы страниц. Функция keys выделяет ключи хэша в отдельный массив, который мы сортируем с помощью функции sort и перебираем по очереди его элементы в цикле foreach, присваивая значения переменной $url.
Поместите этот скрипт в директорию cgi-bin сервера (не забудьте - в режиме ASCII!!!), назначим ему права 755, и вызовем через браузер (набрав URL скрипта). В результате, если у вас уже заведено несколько счетчиков для нескольких страниц - вы увидите список страниц со значениями счетчика для каждой из них.

Соберем статистику
При вызове скрипта браузер передает ему, кроме явно заданных нами параметров, еще кое-какую служебную информацию. Кое-что из этих данных мы уже использовали ($ENV{'QUERY_STRING'}, $ENV{"REMOTE_ADDR"}, $ENV{"HTTP_REFERER"}). Разберем, что все это означает.
QUERY_STRING - строка параметров, передаваемых в составе URL
REMOTE_ADDR - IP-адрес агента, выполнившего запрос. Это может быть как адрес клиента, так и адрес proxy или любого другого промежуточного объекта соединения.
HTTP_REFERER - содержит значение поля "Referer:" заголовка запроса.
а вот эти значения мы еще не трогали, но они могут нам пригодиться для статистики посещений:
REMOTE_HOST - доменное имя агента, выполнившего запрос (если такого имени нет, то переменная содержит то же значение, что и REMOTE_ADDR).
HTTP_USER_AGENT - информация о браузере, обычно содержит его название и версию.
Давайте будем собирать статистику по каждому счетчику в отдельных файлах. Для начала добавим еще одно поле в HTML-форму нового счетчика, включив в нее следующую строку:
Название файла статистики: <input type="text" name="countstatfile" size="20"><br>
Теперь немного изменим скрипт, создающий новый счетчик (addcount.cgi), следующим образом:
после строки
$countipfile=$field{"countipfile"};
добавим строку
$countstatfile=$field{"countstatfile"};
Теперь после строк
open(FILE, ">$dir$countipfile");
close(FILE);
добавим строки
open(FILE, ">$dir$countstatfile");
close(FILE);
и изменим строку
chmod (0666, $dir$countfile, $dir$countipfile);
следующим образом
chmod (0666, $dir$countfile, $dir$countipfile, $dir$countstatfile);
Строка же
print FILE $countid.'|'.$url.'|'.$countfile.'|'.$countipfile."\n";
теперь будет выглядеть так
print FILE $countid.'|'.$url.'|'.$countfile.'|'.$countipfile.'|'.$countstatfile."\n";
Осталось модифицировать собственно скрипт счетчика, чтобы он заполнял файлы статистики соответственной информацией:
строку
($countid, $url, $countfile, $countipfile)=split(/|/,$stroka);
сделаем такой
($countid, $url, $countfile, $countipfile, $countstatfile)=split(/|/,$stroka);
и после строк
open (IPFILE, "$nameipfile");
print IPFILE "$ip";
close(IPFILE);
добавим следующие строки:
$namestatfile="/home2/your_domen/public_html/mystat/".$countstatfile;
open (STATFILE, ">>$namestatfile");
print STATFILE "$ENV{'REMOTE_HOST'}|$ENV{'HTTP_USER_AGENT'}";
close(STATFILE);

Теперь наш скрипт будет не только считать заходы, но и по каждому учтенному заходу записывать в файл статистики хост или IP-адрес посетителя и тип его броузера.
Как просмотреть собранную статистику, мы рассмотрим в следующий раз. Так же разберем процесс создания не менее (а возможно, даже и более) нужных серверу гостевых книг и коференций. К счетчикам и статистике мы еще вернемся, но попозже, чтобы рассмотреть более защищенные варианты, а заодно и способы сбора максимального количества статистической информации, отображения счетчика в виде картинки и организации собственного рейтинга сайтов.
(...продолжение следует...)

Источник: http://www.mycomp.com.ua/

 


Copyright © "Internet Zone"info@izcity.com
Копирование и использование данных материалов разрешается только в случае указания на журнал "Internet Zone", как на источник получения информации. При этом во всех ссылках обязательно явное указание адреса вэб-сайта http://www.izcity.com/. При наличии у копируемого материала авторов и источника информации - их также нужно указывать, наряду со ссылкой на нас.