Masters of CGI.Perl
 Сайт клуба знатоков CGI.Perl 
FAQ · Статьи · Конференция · Ссылки · Скрипты

Часто задаваемые Вопросы.. F.A.Q.

Дайджест от 15.11.2000

Если Вы не нашли ответ на свой вопрос в этом дайджесте, то попробуйте найти его в основной базе:

Ключевые слова

Напоминаем, Вы можете получать FAQ на свой e-mail !!! Достаточно подписаться на нашу почтовую конференцию.
 

  Название : WWW специфика 

  1. Как при генерации HTML документа вывести картинку ?
  2. Можно ли как-нибудь фиксировать хост, с которого был запущен скрипт ?
  3. Как я могу изобразить графически некоторое процентное соотношение данных в генерируемом HTML документе.
  4. Как можно определить IP адрес хоста и преобразовать его в имя (DNS) ?
  5. Как можно принять почту по протоколу POP3 ?
  6. Как можно читать и отправлять новости USENET ?
  7. Как удалить все тэги в HTML документе ?
  8. Как извлечь все URL из html документа ?
  9. Какие функции в модуле CGI.pm соответствуют каким тэгам HTML ?
  10. Как я могу отладить скрипт, получающим/отправляющим данные ?
  11. Что такое библиотека CGI.pm и что в ней особенного ?
  12. Как можно отладить скрипт, используя CGI.pm
  13. Могу ли я динамически изменять поле Last Updated ?
  14. Как получить файл по URL?
  15. Как загрузить файл на сервер?
  16. Как перенаправить клиента на другой URL?
  17. Как заставить браузеры не кешировать выдаваемый результат?
  18. Ошибки HTTP 500 и 403. Что это значит и что с ними делать?
  19. Мой CGI-скрипт не работает! Как установить причину?
  20. Что такое CGI и как с ним работать
  21. Закачка файлов на сервер и решение глюка с закачкой
  22. Как передать из одного скрипта данные другому скрипту методом GET, вроде бы понятно. А как передавать данные методом POST?
  23. Как устроить загрузку файла с удаленного сервера? Проще говоря, скачать скриптом файл с http или ftp
  24. Как послать по e-mail письмо с аттачем?
  25. Можно ли проверить, жив ли определенный e-mail адрес?
    следующие >>

 

Как при генерации HTML документа вывести картинку ?


Удобнее сделать отдельный скрипт (или написать функцию), которая будет распечатывать содержимое графического файла на STDIO. Например, если этот скрипт называется такой picshow.cgi, и для вывода графического файла этому скрипту передается имя файла, то вывод изображения в HTML документе может быть осуществлен командой
print "<IMG SRC=\"http://some.address.ru/cgi-bin/picshow.cgi?picname=image.gif\">";

Дата добавления: 7.09.2000 Прислать свои комментарии  Наверх 

Можно ли как-нибудь фиксировать хост, с которого был запущен скрипт ?


Для этого можно использовать переменные REMOTE_ADDR, REMOTE_HOST, REMOTE_USER, которые содержат IP адрес и, иногда, название и пользователя удаленного хоста, посылающего запрос скрипту.
Следует отметить, что переменная окружения $ENV{REMOTE_USER} будет иметь какое-то значение только, когда скрипт или каталог прошел базовую авторизацию (authorization) средствами апача, установленую с помощью файлов .htaccess.

Дата добавления: 5.09.2000 Прислать свои комментарии  Наверх 

Как я могу изобразить графически некоторое процентное соотношение данных в генерируемом HTML документе.


Часто программисты используют простое решение: заранее формируется графический файл 1x1 пиксель. За 100% процентов принимается некоторая ширина (например, в зависимости от разрешения экрана). И в тэге
<IMG SRC="1x1.gif" width=соответсвующая ширина height=10>
указывается ширина в пикселях, соответствующая процентам. Получаем линейчатую диаграмму, высотой каждого столбика в 10 пиксель.

Дата добавления: 5.09.2000 Прислать свои комментарии  Наверх 

Как можно определить IP адрес хоста и преобразовать его в имя (DNS) ?


Для получения IP адреса по имени хоста используется функция gethostbyname:
use Socket;
@addresses=gethostbyname($addrname) or die("Error!");
@addresses=map{ inet_ntoa($_) } @addresses[4..$#addresses];
Теперь @addresses содержит список адресов.
Для определения имени хоста по по IP адресу используется функция gethostbyaddr:
use Socket;
$name=gethostbyaddr(inet_aton($address),AF_INET) or die("Error!");

Дата добавления: 2.09.2000 Прислать свои комментарии  Наверх 

Как можно принять почту по протоколу POP3 ?


Существует специальный модуль Net::POP3 с CPAN, который заметно облегчает эту задачу.

Дата добавления: 2.09.2000 Прислать свои комментарии  Наверх 

Как можно читать и отправлять новости USENET ?


Воспользуйтесь модулем Net::NNTP с CPAN.

Дата добавления: 2.09.2000 Прислать свои комментарии  Наверх 

Как удалить все тэги в HTML документе ?


Есть два способа: быстрый, но не правильный: ($result=$html_text)=~s/<[^>]*>//gs и медленный,но правильныйиспользовать алгоритм анализа кода из LWP. См. функцию HTML::Parser.

Дата добавления: 2.09.2000 Прислать свои комментарии  Наверх 

Как извлечь все URL из html документа ?


Можно воспользоваться модулем HTML::LinkExtor из LWP.

Дата добавления: 2.09.2000 Прислать свои комментарии  Наверх 

Какие функции в модуле CGI.pm соответствуют каким тэгам HTML ?


В CGI.pm есть следующие функции для формирования html документа:

h1() - <h1></h1>
h2() - <h2></h2>
h3() - <h3></h3>
strong() - <STRONG></STRONG>
li() - <li>
p() - <p></p>
hr() - <HR>
.......
Не сложно заметить, что название функций совпадает с названиями тэгов.
Вот пример:
print p('Это параграф');
Результат:
<p>Это параграф</p>

Дата добавления: 2.09.2000 Прислать свои комментарии  Наверх 

Как я могу отладить скрипт, получающим/отправляющим данные ?


Сначала нужно убедиться в том, что скрипт исполняется интерпретатором. Для этого его нужно запустить из коммандной строки. Процесс получаемых и отправляемых данных скрипта можно просмотреть, используя telnet.

Примерно вот так : telnet 127.0.0.1 80
где 127.0.0.1 - localhost.localdomain, а 80 - номер порта, на котором "висит" HTTP демон. Далее обмен данными и получение результата можно производить посредством методов GET,POST,...

Дата добавления: 2.09.2000 Прислать свои комментарии  Наверх 

Что такое библиотека CGI.pm и что в ней особенного ?


CGI.pm - это модуль для работы с Web CGI. Он представляет собой набор удобных методов, свойств, функция для создания динамических Web страниц, форм, страниц с фрэймами, работать с Cookies и пр. Генерация HTML тэгов осуществляется посредством вызова функций. Вот небольшой пример, иллючтрирующий работу модуля:

#!/usr/bin/perl
use CGI ':standart';
print header,
start_html('Example'),
h1('Perl.mastak.com example'),
"Wow ! that is cool!",
hr,
end_html;
Как видите, вам даже не обязательно знать тэги HTML.

Дата добавления: 2.09.2000 Прислать свои комментарии  Наверх 

Как можно отладить скрипт, используя CGI.pm


Для того, чтобы передать скрипту параметры, необходимые для работы, их следует указать в командной строке после имени скрипта:% do_it.pl name=Sergey language=perl или просто запустить % do_it.pl, программа будет ожидать ввода параметров с STDIN. Если параметры скрипту указывать не нужно, то можно запустить так: % do_it.pl '' или перенаправить с /dev/null: % do_it.pl </dev/null

Дата добавления: 2.09.2000 Прислать свои комментарии  Наверх 

Могу ли я динамически изменять поле Last Updated ?


при создании документа, используя CGI, легко задать поле "Last Updated". Вот пример (Perl 5),


$last_updated=localtime(time);
print "Last Updated: $last_updated\n";
или можно так

require "ctime.pl";
$last_updated=&ctime(time);
print "Last Updated: $last_updated\n";

Дата добавления: 2.09.2000 Прислать свои комментарии  Наверх 

Как получить файл по URL?


Возьмите на CPAN библиотеку libwww-perl и смотрите lwpcook(3), там написаны основы использования библиотеки и есть примеры.

Автор: Павел Аммосов

Дата добавления: 31.08.2000 Прислать свои комментарии  Наверх 

Как загрузить файл на сервер?


В поставку CGI.pm входит пример file_upload.cgi.
Подробности CGI(3)

Автор: Павел Аммосов

Дата добавления: 31.08.2000 Прислать свои комментарии  Наверх 

Как перенаправить клиента на другой URL?


В заголовке напишите:
print "Status: 302\n";
# Или 301. Разница состоит в том, что по стандарту 301 значит "перемещён
# навсегда", а 302 - "перемещён временно"
print "Location: ВАШ Новый URL\n";
# URL должен быть указан абсолютный
print "URI: ВАШ новый URL\n\n"; # Для http/1.0
Подробности: см. rfc1945(http/1.0), rfc2068(http/1.1)

Автор: Павел Аммосов

Дата добавления: 31.08.2000 Прислать свои комментарии  Наверх 

Как заставить браузеры не кешировать выдаваемый результат?


Выдавайте заголовки в таком виде:
print "Content-Type: type/sub-type\n"; # Подставьте Ваш тип/подтип
print "Pragma: no-cache\n"; # Для HTTP/1.0 клиентов
print "Cache-Control: no-cache\n"; # Для HTTP/1.1
print "Expires: Thu Jan 1 00:00:00 1970\n\n"; # Это уже любой браузер должен понять
Автор: Павел Аммосов

Дата добавления: 31.08.2000 Прислать свои комментарии  Наверх 

Ошибки HTTP 500 и 403. Что это значит и что с ними делать?


error_log для того и служит, чтобы туда смотреть :-)

Основные причины:
Ошибка 403 "Forbidden"
Возникает, если сервер не может отдать вам содержимое по причине отсутствия полномочий.
Проверьте:
    Может ли user (для apache под Unix это обычно nobody), под которым работает, сервер исполнять файл?
    В частности, может ли сервер исполнять интерпретатор (в случае скриптовых языков)?
    Можно ли для этого каталога исполнять CGI? (Options ExecCGI для apache)

Ошибка 500 "Internal Server Error"
Возникает в случае внутренней ошибки.
Проверьте:
    Выводите ли вы строку "Content-Type:"?
    Правильно ли вы ее выводите? (Content-type, Content_Type - неправильно)
    Заканчиваете ли вы хедеры пустой строкой? (Нельзя написать
    print "Content-Type: text/html\n";
    print "<HTML>\n";
    Надо писать:
    print "Content-Type: text/html\n\n"; # Два "\n"
    print "<HTML>\n";)
Также, эта ошибка возникает, если CGI-программа завершилась с ненулевым кодом возврата, что часто встречается в случае некомпилируемости вашего скрипта perl'ом.

Совет: делайте
use CGI::Carp qw(fatalsToBrowser)
во время отладки, тогда вам выдадут сообщение об ошибке perl.

Автор: Павел Аммосов

Дата добавления: 31.08.2000 Прислать свои комментарии  Наверх 

Мой CGI-скрипт не работает! Как установить причину?


Прежде чем читать дальше, убедитесь в том, что:
  1. Вы запустили скрипт с командной строки (не через CGI!!!) и он работает, а не говорит 'compilation stopped due to errors'
  2. Скрипт не только работает, но и выдает нужный заголовок с пустой строкой после него
  3. (Для многопользовательских систем) Вы сделали тоже под пользователем, под которым работает сервер (su -m имя_пользователя -c script в Unix) и он столь же благополучно работает

Автор: Павел Аммосов

Дата добавления: 31.08.2000 Прислать свои комментарии  Наверх 

Что такое CGI и как с ним работать


CGI - Common Gateway Interface.
Cтандарт интерфейса внешних программ с http-сервером.

Как работать:
HTTP - клиент-серверный протокол (HipperText Transfer Protocol), следовательно со стороны CGI, как серверного процесса, все взаимодействие выглядит следующим образом:

  1. Получение данных от клиента
  2. Обработка данных
  3. Выдача ответа клиенту.

Пункты 1 и 3 я в кратце опишу здесь, а 2, надеюсь, сделате сами.
Начнем с п.3 как наиболее простого.

3. Выдача данных клиенту:
Обычно клиенту выдают текст в формате HTML (ничто не мешает Вам отправить ему и картинку/видео/etc). Для того, чтобы сервер и клиент вас поняли, необходимо сказать, что вы выдаете, c помощью заголовка Content-Type: mime-type/mime-subtype. Обатите внимание на регистр и последовательность - если вы скажите нечто типа Content_type, то сервер вас скорее всего не поймет. (Сообщение типа "500 Internal Server Error" будет симптомом).

Пример:
print "Content-Type: text/html\n"; # Мы выдаем текст в формате HTML. Также
# можно: text/plain - простой текст, в
# брузере отобразится аналогично тексту,
# заключённому между тегами <pre></pre>.
# image/gif - Картинка, формат gif
# video/mpeg - mpeg-видео
# И целая куча других форматов, см.
# файл mime.types из apache
print "\n"; # <-- еще одна пустая строка, обозначает конец вывода наших
# заголовков. ВАЖНО!

# Теперь мы можем написать свой текст клиенту
print "
<html>
<head>
<title>Моя первая CGI программа</title>
</head>
<body>
<h1>Моя первая CGI программа</h1>
</body>
</head>
";
## Все.

1. Прием данных от клиента
Взаимодействие с клиентом обеспечивается так: Он заполняет форму своими значениями, нажимает на кнопку "submit", броузер кодирует данные соответствующим образом и отправляет их серверу.

Определение форм
Производится тегами <form> и </form>. Тег определения форм имеет следующие аттрибуты
  • action - скрипт на сервере, который будет запущен на сервере для обработки данных формы.
  • method - тип взаимодействия с сервером. Может иметь значения GET и POST.
  • + еще некоторые специальные, которые вы можете посмотреть в учебнике

Формы не могут быть вложенными.

Элементы ввода
Определяются тегами <input>, <textarea> и <select>
тег <input>:
    <input type=checkbox> - Элемент ввода "Опция"
    <input type=hidden> - Элемент ввода, который не виден пользователю
    <input type=file> - в Netscape Navigator позволяет загрузить файл на сервер
    <input type=image> - Изображение. Если по нему шелкнуть, это вызовет submit формы и серверу будут выданы две переменные вида name.x и name.y, где name - то, что вы пропишете в name=... тега <input>
    <input type=password> - Элемент ввода Пароль. Позволяет ввести строку, которая на экране отображается звездочками. Никаких методов защиты при передаче на сервер не применяется
    <input type=radio> - Радиокнопки
    <input type=reset> - Кнопка сброса значений формы на начальные
    <input type=submit> - Кнопка отправки формы на сервер
    <input type=text> - строка ввода
Все теги <input> имеют аттрибут name - Наименование элемента. Служит для идентификации при передаче на сервер, а также другие типа value, width, etc, название и назначение которых можно опять-таки посмотреть в настоящем руководстве.

Тег <textarea> - Поле многострочного ввода.
Тег <select> - списочный выбор

Пример:
  <form action=/cgi-bin/myscript.pl method=GET>
Имя: <input type=string name=name><p>
Пол: <input type=radio name=gender value=male>Мужской
<input type=radio name=gender value=female>Женский
<input type=submit><input type=reset>
</form>
Как это будет видно в моей программе?
Это определяется методом формы, GET или POST. В случае GET сервер установит переменную окружения QUERY_STRING в виде name1=vaue1&name2=value2&..&nameN=vauleN. В случае POST аналогичная строка будет записана на стандартный ввод. Ее длину можно получить через переменную окружения CONTENT_LENGTH.
В обоих случаях данные будут закодированы по следующему алгоритму:

    Eсли ASCII код символа больше 32 и меньше 128, то он будет выдан без изменения.
    если символ - пробел, то он заменится на "+" (плюсик, без кавычек) все остальное преабразуется в вид %xx, где xx - шестнадцатеричный код сивола. Если вам повезло и у вас "Русский apache", то он преобразует его в нормальную кодировку.
    Декодирование на perl
      tr/+/ /;
    s/%([0-9a-fA-F]{2})/pack("c",hex($1))/ge;
    (списано из CGI.pm)

На самом деле, можно не возится со всем этим, а использовать модуль CGI.pm (Имеется в поставке Perl 5.004 и более поздних. Если у вас perl версии 4 или 1, нужно срочно взять на CPAN новую версию perl)

Самый большой и последний пример
Предположим мы делаем поисковую систему, тогда у нас должен быть HTML с формой и программа, которая будет выполнять поиск.

<html>
<head>
<title>Поиск</title>
</head>
<body>
<h1>Чего искать?</h1>
<form action=/cgi-bin/search.pl method=get>
Строка для поиска: <input type=text name=string width=70><p>
Искать в <input type=checkbox name=searchin value=internet>Интернет
<input type=checkbox name=searchin value=intranet>Интранет
<input type=checkbox name=searchin value=extranet>Экстранет<p>
<input type=submit value=Давай!><input type=reset value="Нет, не надо">
</form>
</body>
</html>


Программа:

#!/usr/bin/perl - поменяйте, как надо
use CGI;

print "Content-Type: text/html\n\n"; # Не забудьте про два "\n"

$string = param("string");
@searchin = param("searchin"); # searchin это checkbox и его значения
# возвращаются списком

# Искать мы сегодня ничего не будем
print "<html>
<body>
<h1>Мы сегодня ничего не ищем</h1>
Но, если бы искали, то: <br>
Искали бы строку <b>$string</b><br>\n";
print "В <b>" . join(" ", @searchin) . "</b>\n";
print "
</body>
</html>
";


Да, кстати, если вы собираетесь писать в файлы с помощью CGI-программ, не забывайте про file locking.

Автор: Павел Аммосов

Дата добавления: 31.08.2000 Прислать свои комментарии  Наверх 

Закачка файлов на сервер и решение глюка с закачкой


#!/usr/bin/perl                              # используйте -T для CGI-скриптов

$SIG{ALRM} = sub { die "$0 timed out" }; # эти 2 строки не работают под
alarm 900; # Windows, но они необязательны

use strict; # спасает от глупых ошибок
use Fcntl; # O_EXCL, O_CREAT и O_WRONLY
use CGI qw (:standard); # читайте "perldoc CGI"
use CGI::Carp qw (fatalsToBrowser); # вывод ошибок к browser-у

$CGI::POST_MAX = 131072; # максимальный ввод = 128 KB

my $foto = param ('foto'); # имя файла и одноврем. handle
my $DIR = '/home/alex/pics'; # не забудьте "chmod 777 pics"
my $JS = " // JavaScript-функция для пред-
// варительной проверки формы
function check (form)
{
if (form.elements['foto'].value.length < 4)// foto должно быть заполнено
{
alert ('A gde zhe foto?'); // показать JavaScript-окошко
form.elements['foto'].select (); // выделить текст в поле foto
form.elements['foto'].focus (); // и прыгнуть туда курсором

return false; // false запретит browser-у
} // отправлять данные к серверу

return true; // все OK - можно отправлять
}";

print header (-type => 'text/html; charset=koi8-r'),
start_html (-title => 'МИСС ИHТЕРHЕТ', # напечатать заголовок и $JS
-script => $JS);

# regex внизу проверяет, есть ли .gif или .jp(e)g в конце и кладет имя
# файла в $1

if ($foto !~ /([\w-]+ \. (?: gif | jpe?g ))$/ix) #только имя,путь выкидывается
{
print h1 ('Отправьте нам фото!'), #start_form работать не будет
start_multipart_form (-onsubmit => 'return check (this)'),
filefield (-name => 'foto'),
submit (-value => 'Go baby go!'), # напечатать форму с кнопкой
end_form; # напечатать </FORM>
}

# Этот скрипт никому не мешает вводить мусор (например xxxx.gif) в поле foto,
# что приведет к созданию пустых файлов; если это Вас беспокоит, установите
# новую версию CGI.pm и прочтите
# http://stein.cshl.org/WWW/software/CGI/#upload

elsif (not sysopen FILE, "$DIR/$1", O_EXCL | O_CREAT | O_WRONLY, 0444)
{
print h1 ("Hе могу создать $DIR/$1: $!"); # ошибка или такой файл уже есть
}

# Портятся файлы при посылке? См. ниже!

else # все в порядке - файл создан
{
binmode FILE; # включить binmode для Windows
print FILE while (<$foto>); # и скопировать данные в файл
close FILE;

print h1 ('Сердечное Вам спасибо!'); # воспитывать как собак Павлова
}

print end_html; # напечатать </BODY></HTML>

Если закачка некоторых файлов происходит с глюками - видимо, файл перекодируется на лету русским апачем.

Варианты решения:
  1. запретите все перекодировки для скрипта, который разбирает FileUpload, например таким способом:
      <Location /path/to/upload.cgi>
    CharsetDisable On
    </Location>
    и делайте перекодировку сами.
  2. Используйте директиву CharsetRecodeMultipartForms, которая появилась в PL23, но при этом вам все равно придется перекодировать вручную текстовые части запросов. Для этого можно использовать Russian Apache API, доступное в других модулях или Russian Apache Perl API, доступное из mod_perl.

Источник: FIDO - RU.CGI.PERL (FAQ created by SLY Golovanov, 2:5020/794.13)

Дата добавления: 31.08.2000 Прислать свои комментарии  Наверх 

Как передать из одного скрипта данные другому скрипту методом GET, вроде бы понятно. А как передавать данные методом POST?


Внимательно почитать документацию о LWP::UserAgent и HTTP::Request

Источник: FIDO - RU.CGI.PERL (FAQ created by SLY Golovanov, 2:5020/794.13)

Еще ответ:

Вот пример использования

Дата добавления: 31.08.2000 Прислать свои комментарии  Наверх 

Как устроить загрузку файла с удаленного сервера? Проще говоря, скачать скриптом файл с http или ftp


LWP
Источник: FIDO - RU.CGI.PERL (FAQ created by SLY Golovanov, 2:5020/794.13)

Еще ответ:

Вот пример использования LWP

Дата добавления: 31.08.2000 Прислать свои комментарии  Наверх 

Как послать по e-mail письмо с аттачем?


Mime::Lite
Источник: FIDO - RU.CGI.PERL (FAQ created by SLY Golovanov, 2:5020/794.13)

Дата добавления: 31.08.2000 Прислать свои комментарии  Наверх 

Можно ли проверить, жив ли определенный e-mail адрес?


В общем случае - нельзя. Проверка существования и функционирования домена, в котором этот email прописан, в сущности ничего не дает. Остается отталкиваться от конкретных требований. Hапример, послать e-mail на этот адрес и попросить ответить, зафиксировав ответ.

Источник: FIDO - RU.CGI.PERL (FAQ created by SLY Golovanov, 2:5020/794.13)

Дата добавления: 31.08.2000 Прислать свои комментарии  Наверх 

  следующие >>

Сайт клуба знатоков CGI.Perl - Masters of CGI.Perl
Designed by MoveR Studio © 2000  - | -  Вопросы? Предложения? пишите