Афиширование inurl c board cgi cmd. CGI-программирование на ассемблере?!? – Легко! Не выкладывайте важные данные на WEB сервер

Благодаря Всемирной паутине, почти любой может дать информацию в Интернете в приятном для глаз и пригодном для широкого распространения виде. Вы несомненно путешествовали по Интернету и видели другие сайты, и теперь вероятно знаете, что пугающие сокращения типа "HTTP" и "HTML" - просто своеобразные сокращения для "Веб" и "способ выражения информацим в Интернете". Возможно у Вас уже есть некоторый опыт представления информации в Интернете.

Интернет доказал, что является идеальной средой для распределения информации, как видно по его огромной популярности и масштабного развития. Хотя кое-кто подвергает сомнению полезность Интернета и приписывают ее широкое развитие и популярность главным образом навязчивой рекламе, Интернет бесспорно является важным средством представления всевозможных видов информации. Мало того, что существует множество услуг по предоставлению самой свежей информации (новости, погода, спортивные события в реальном времени) и материалов справочного характера в электронном виде, предлагаются также значительные объемы данных другого рода. Налоговое управление США, которое распространило все свои бланки налоговых деклараций в 1995 году и другую информацию через Всемирную паутину, недавно призналось о получении писем от поклонников своего Веб-сайта. Кто бы мог подумать, что Налоговое управление когда-нибудь будет получать письма от поклонников? Это произошло не от того, что его сайт был хорошо оформлен, а потому что он оказался по-настоящему полезным инструментом для тысяч, а возможно и миллионов людей.

Что делает Веб уникальным и таким привлекательным информационным сервисом? Прежде всего тем, что он предоставляет интерфейс гиперсреды для данных. Вспомните дисковод жесткого диска своего компьютера. Как правило, данные выражаются в линейном виде, аналогично файловой системе. Например, Вы имеете ряд папок, а внутри каждой папки находятся либо документы либо другие папки. Веб использует разную парадигму для выражения информации называемой гиперсредой. Гипертекстовый интерфейс состоит из документа и связей. Связи - это слова, на которые кликают, чтобы увидеть другие документы или отыскать другие виды информации. Веб расширяет концепцию гипертекста, включив другие типы носителей, например графику, звуки, видео (отсюда имя "гиперсреда"). Выделение текста или графики на документе позволяет увидеть связанную информацию о выделенном элементе в любом количестве форм.

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

Хотя Веб предоставляет для информации уникальный интерфейс гиперсреды, имеется много других эффективных способов распределения данных. Например, сетевые услуги типа Протокола передачи файлов (FTP) и группа новостей "Gopher" существовали намного раньше появления Всемирной паутины. Электронная почта была первичной средой для связи и обмена информацией по Интернету и большинством других сетей почти с самого начала функционирования этих сетей. Почему Интернет стал таким популярным способом распределения информации? Мультимедийный аспект Интернета внес ощутимый вклад в его небывалый успех, но для того, чтобы Интернет стал наиболее эффективным он должен быть интерактивным.

Без способности получать ввод от пользователей и давать информацию, Веб был бы полностью статической средой. Информация была бы доступна только в формате, определенном автором. Это подорвало бы одну из вычислительных возможностей вообще: интерактивную информацию. Например, вместо того, чтобы принуждать пользователя к просмотру нескольких документов, как если бы он или она просматривали книгу или словарь, будет лучше позволить пользователю определить ключевые слова по интересующей их тематике. Пользователи могут настраивать представление данных, а не полагаться на жесткую структуру, определенную поставщиком содержимого.

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

Хотя серверы могут посылать и получать данные, у самого сервера функциональные возможности ограничены. Например, наиболее примитивный сервер может только отослать требуемый файл на браузер. Сервер обычно не знает, что делать с тем или иным дополнительным вводом. Если Интернет-провайдер не сообщает серверу, как обработать такую дополнительную информацию, вероятнее всего сервер проигнорирует ввод.

Для того, чтобы сервер смог выполнять и другие операции, помимо поиска и пересылки файлов на Интернет-браузер, нужно знать, как расширить функциональные возможности сервера. Например, сервер Веб не может производить поиск в базе данных, на основе ключевого слова, введенного пользователем, и возвращать несколько документов соответствия, если такая способность не была каким-то образом запрограммирована для сервера.

Что такое CGI?

Общешлюзовой интерфейс (CGI) является интерфейсом к серверу, который позволяет расширить функциональные возможности сервера. Используя CGI, можно работать в диалоговом режиме с пользователями, которые обращаются к вашему сайту. На теоретическом уровне, CGI позволяет расширить возможности сервера в отношении анализа (интерпретации) ввода, поступающего от браузера, и возвращать информацию, основанную на введенной информации пользователя. На практическом уровне, CGI - это интерфейс, позволяющий программисту записать программы, которые легко связываются с сервером.

Обычно, для расширения возможностей сервера, Вам пришлось бы самому модифицировать сервер. Такое решение нежелательно, потому что это требует понимания нижнего уровня сетевого программирования по протоколу Интернета. Это также требовало бы редактирования и перекомпиляции исходного кода сервера или записи пользовательского сервера для каждой задачи. Допустим, нужно расширить возможности сервера так, чтобы он действовал как шлюз Web-to-e-mail (от Веб к эл.почте), отбирая информацию, введенную пользователем, из браузера и посылая ее по электронной почте другому пользователю. В сервер пришлось бы вставить код для анализа ввода от браузера, пересылки бы его по электронной почте другому пользователю, и пересылке ответа назад в браузер через сетевое соединение.

Во-первых, такая задача требует наличия доступа к коду сервера, что не всегда возможно.

Во-вторых, это трудно и требует обширных технических знаний.

В-третьих, это применимо только для конкретного сервера. Если нужно переместить ваш сервер на другую платформу, придется запустить или по крайней мере потратить много времени, занимаясь переносом кода на эту платформу.

Почему CGI?

CGI предлагает переносимое и простое решение этих проблем. Протокол CGI определяет стандартный способ для программ, чтобы связаться с сервером Веб. Без каких-либо специальных знаний, можно записать программу на любом машинном языке, который сопрягается и связывается с сервером Веб. Эта программа будет работать со всеми серверами Веб, которые понимают протокол CGI.

Связь CGI осуществляется стандартным вводом и выводом, что означает, что, если Вы знаете, как печатать и читать данные, используя свой язык программирования, можно написать приложение сервера Веб. Помимо анализа ввода и вывода, программирование приложений CGI почти эквивалентно программированию любого другого приложения. Например, для программирования программы "Hello, World!", используются функции печати вашего языка и формат, определенный для программ CGI, чтобы напечатать соответствующее сообщение.

Выбор языка програмирования

Поскольку CGI - универсальный интерфейс, Вы не ограничены каким-либо определенным машинным языком. Часто задают важный вопрос: какие языки программирования можно использовать для программирования CGI? Вы можете использовать любой язык, который позволяет делать следующее:

  • Печатать в стандартном выводе
  • Читать со стандартного ввода
  • Читать с переменных режимов

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

Языки подпадают под один из следующих двух классов: транслируемый и интерпретируемый. Транслируемый язык -например, C или C++ обычно меньше и быстрее, в то время как интерпретируемые языки, такие как Perl или Rexx, иногда требуют загрузки большого интерпретатора после запуска. Дополнительно, Вы можете распределять двоичные коды (код, транслируемый в машинный язык) без исходного кода, если ваш язык транслируемый. Распределение интерпретируемых сценариев обычно означает распределение исходнго кода.

Перед тем, как выбрать язык, сначала нужно рассмотреть свои приоритеты. Нужно оценить выгоды от скорости и эффективности одного языка программирования с легкостью программирования другого. Если у Вас есть желание изучить другой язык, вместо использования того, который Вы уже знаете, тщательно взвести преимущества и недостатки обоих языков.

Два наиболее часто используемых языка для программирования CGI - это C и Perl (оба из которых рассматриваются в настоящей книге). У обоих имеются четкие преимущества и недостатки. Perl - язык очень высокого уровня, и в то же время мощный язык, особенно пригодный для синтаксического анализа текста. Хотя легкость использования, гибкость, и мощность делает его языком, привлекательным для программирования CGI, его относительно большой размер и более медленная работа иногда делает его неподходящим для некоторых приложений. Программы C меньше по размеру, более эффективны и обеспечивают контроль за системой более низкого уровня, но более сложны для программирования, не имеют легких встроенных подпрограмм обработки текста, и их труднее отладить.

Какой язык является наиболее подходящим для программирования CGI? Тот, который Вы считаете для себя более удобным с точки зрения программирования. Оба одинаково эффективны для программирования приложений CGI, и с надлежащими библиотеками, оба имеют схожие возможности. Однако, если Вы имеете труднодоступный сервер, можно использовать меньшие транслируемые программы C. Если Вы должны быстро написать приложение, которое требует значительной работы по обработке текста, можно вместо него использовать Perl.

Предостережения

Имеются некоторые важные альтернативы к приложениям CGI. Много серверов теперь включают API-программирование, которое облегчает программирование прямых расширений сервера в противоположность отдельным приложениям CGI. Серверы API обычно более эффективны, чем программы CGI. Другие серверы включают встроенные функциональные возможности, которые могут обрабатывать специальные элементы без CGI, например, сопряжение баз данных. И наконец, некоторые приложения могут быть обработаны некоторыми новыми клиентскими (а не серверными) технологиями типа Java. Быстро ли устареет CGI в условиях таких быстрых изменений в технологии,?

Вряд ли. CGI имеет несколько преимуществ перед более новыми технологиями.

  • Он универсален и переносим. Вы можете написать приложение CGI, используя практически любой язык программирования на любой платформе. Некоторые из альтернатив, такие как API сервера, ограничивают Вас некоторыми языками и намного сложны для изучения.
  • Маловероятно что, клиентские технологии типа Java, заменят CGI, потому что имеются некоторые приложения, для которых серверные приложения намного лучше подходят для выполнения.
  • Многие из ограничений CGI - это ограничения HTML или HTTP. По мере развития стандартов Интернета в целом, развиваются и возможности CGI.

Резюме

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

Глава 2. Основы

Несколько лет назад, я создавал для колледжа в Гарварде страницу, куда бы можно было представлить свои комментарии о них. В то время, Интернет был молод, а документации было мало. Я, подобно многим другим, опирался на краткую документацию и систему программирования, созданную другими, чтобы научиться программированию CGI. Хотя этот метод изучения потребовал определенного поиска, множества экспериментов, и создавал много вопросов, он был очень эффективным. Настоящая глава - плод моей работы с CGI на ранних этапах (с несколькими уточнениями, разумеется).

Хотя для того, чтобы, полностью понять общешлюзовой интерфейс и достичь мастерства при работе с ним требуется некоторое время, сам протокол довольно прост. Любой человек, у которого есть некоторые основные навыки программирования, и который знаком с Веб, может быстро научиться программированию довольно сложных приложений CGI так же как я и другие научились этому несколько лет назад.

Цель этой главы состоит в том, чтобы представить основы CGI в комплексном, хотя и сжатом виде. Каждая концепция, рассматриваемая здесь, подробно представлена в последующих главах. Однако, после изучения этой главы, можно сразу же начать программирование приложений CGI. Как только Вы достигнете этого уровня, можно изучить тонкости CGI, либо прочитав остальную часть этой книги, либо просто экспериментируя самостоятельно.

Вы можете свести программирование CGI к двум задачам: к получению информации от браузера Веб и отсылке информации назад на браузер. Это делается достаточно интуитивно, как только Вы усвоите обычное использование приложений CGI. Часто пользователю предлагают заполнить какую-либо форму, например, вставить свое имя. Как только пользователь заполняет форму и нажимает Enter, эта информация посылается программе CGI. Программа CGI должна затем преобразовать эту информацию в то, что она понимает, соответственно обработать ее, и затем послать назад браузеру, будь то простое подтверждение или результат поиска в многоцелевой базе данных.

Другими словами, для программирования CGI требуется понять, как получить ввод от Интернет-браузера и как отослать вывод назад. Что происходит между стадиями ввода и вывода программы CGI, зависит от цели разработчика. Вы обнаружете, что главная сложность программирования CGI заключается в этой промежуточной стадии; после того, как Вы узнаете, как работать с вводом и выводом, этого будет, по существу, достасточно, чтобы стать разработчиком CGI.

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

  • Традиционная программа " Hello, World!";
  • Вывод CGI: отсылка информации назад для отображения в Интернет-браузере;
  • Конфигурирование, установка, и выполнение приложения. Вы узнаете о различных платформах и серверах Веб;
  • Ввод CGI: интерпретация информации, посланной браузером Веб. Ознакомление с некоторыми полезными библиотеками программирования для анализа такого ввода;
  • Простой пример: он охватывает все уроки данной главы;
  • Стратегия программирования.

Из-за характера данной главы, я только слегка касаюсь некоторых тем. Не волнуйтесь; все эти темы рассматриваются гораздо глубже в других главах.

Hello, World!

Вы начинаете с традиционной вводной задачи программирования. Вы напишете программу, которая отобразит "Hello, World!" на вашем браузере Веб. Прежде, чем написать эту программу, Вы должны понять, какую информацию браузер Веб ожидает получить от программ CGI. Вы также должны знать, как выполнить эту программу, так чтобы увидеть ее в действии.

CGI независит от языка, так что Вы можете реализовать эту программу на любом языке. Здесь используется несколько различных языков, чтобы продемонстрировать независимость каждого языка. В языке Perl, программа " Hello,World!" показана в листинге 2.1.

Листинг 2.1. Hello, World! в Perl. #!/usr/local/bin/perl # Hello.cgi - Моя первая программа CGI print "Content-Type: text/html\n\n"; print " \n"; print "Hello, World!"; print "\n"; print "\n"; print "

Hello, World!

\n"; print " \n";

Сохраните эту программу как hello.cgi, и установите ее в соответствующем месте. (Если Вы не уверены, где оно находится, не беспокойтесь; Вы узнаете это в разделе "Установка и выполнение программы CGI " ниже в данной главе.) Для большинства серверов нужный каталог называется cgi-bin. Теперь, вызовите программу из вашего браузера Веб. Для большинства, это означает открыть следующий универсальный указатель ресурса (URL):

http://hostname/directoryname/hello.cgi

Hostname - имя вашего сервера Веб, и directoryname - каталог, в который Вы помещаете hello.cgi (вероятно cgi-bin).

Разбиение hello.cgi

Следует отметить несколько моментов относительно hello.cgi.

Во-первых, вы используете простые команды печати. Программы CGI не требуют никаких специальных дескрипторов файла или описателей вывода. Чтобы послать вывод браузеру, просто печатают на stdout.

Во-вторых, обратите внимание на то, что содержание первого оператора печати (Content-Type: text/html) не появляется на вашем браузере Веб. Вы можете отослать любую информацию, по Вашему усмотрению, назад на браузер (страницу HTML, графику или звук), но сначала, нужно сообщить браузеру какого вида данные вы ему посылаете. Эта строка сообщает браузеру какой вид информации ожидать - в данном случае, страницу HTML.

В-третьих, программа называется hello.cgi. Не всегда нужно использовать расширение.cgi с именем вашей программы CGI. Хотя исходный код для многих языков также использует расширение.cgi, оно не используется для обозначения типа языка, а является для сервера способом идентификации файла как исполняемого файла, а не графического файла, файла HTML или текстового файла. Серверы часто конфигурируются так, чтобы только попытаться выполнить те файлы, которые имеют это расширение, отображая содержание всех других. Хотя использование расширения.cgi не обязательно, это все еще считается хорошей практикой.

В общем, hello.cgi состоит из двух основных частей:

  • сообщает браузеру какую информацию ожидать (Content-Type: text/html)
  • сообщает браузеру, что отобразить (Hello, World!)

Hello, World! в C

Чтобы показать независимость программ CGI от языков, в листинг 2.2 показан эквивалент программы hello.cgi , написанной в C.

Листинг 2.2. Hello, World! в C. /* hello.cgi.c - Hello, World CGI */ #include int main() { printf("Content-Type: text/html\r\n\r\n"); printf(" \n"); printf("Hello, World!\n"); printf("\n"); printf("\n"); printf("

Hello, World!

\n"); printf(" \n"); }

Примечание

Обратите внимание на то, что версия Perl hello.cgi использует Content-Type print ": text/html\n\n "; В то время как версия C использует Printf (" Content-Type: text/html\r\n\r\n ");

Почему Perl печатает операторный конец с двумя символами новой строки (\n), в то время как C printf заканчивается двумя символами возврата каретки и новой строки(\r\n)?

Формально, заголовки (весь вывод перед пустой строкой) как предполагается, будут отделены символом возрата каретки и новой строки. К сожалению, на машинах DOS и Windows, Perl транслирует \r как другую новую строку, а не как перевод каретки.

Хотя исключение \rs в Perl технически неправильно, она будет работать почти во всех протоколах и так же переноситься всеми платформами. Поэтому, во всех примерах Perl в этой книге я использую новую строку, отделяющие заголовки, а не символы возврата каретки и новой строки.

Соответствующее решение этой проблемы представлено в Главе 4, "Вывод".

Ни серверу Веб, ни браузеру не важно, какой язык используется для записи программы. Хотя каждый язык имеет преимущества и недостатки в качестве языка программирования CGI, лучше использовать язык, с которым Вам удобнее всего работать. (Более детально выбор языка программирования обсуждается в Главе 1 "Общешлюзовой интерфейс (CGI) ").

Выведение CGI

Теперь можно внимательнее изучить вопрос отправки информации на браузер Веб. Из примера " Hello, World!", видно, что браузеры Веб ожидают два набора данных: заголовок, который содержит информацию, например какую информацию отобразить (например Content-Type: line) и фактическую информацию (что отображается на браузере Веб). Эти два блока информации отделены пустой строкой.

Заголовок называется заголовком HTTP. Он дает важные сведения об информации, которую браузер собирается получать. Имеются несколько различных типов заголовков HTTP, и наиболее универсальным является тот, который Вы использовали раньше: Content-Type: заголовок. Вы можете использовать различные комбинации заголовков HTTP, отделяя их символами возврата каретки и новой линии (\r\n). Пустая строка, отделяющая заголовок от данных, также состоит из возврата каретки и новой строки (почему нужны оба, кратко описано в предшествующем примечании и подробно в Главе 4). Вы узнаете о других заголовках HTTP в Главе 4; в данный момент Вы занимаетесь Content-Type: заголовок.

Content-Type: заголовок описывает тип данных, которые возвращает CGI. Соответствующим форматом для этого заголовка является:

Content-Type: subtype/type

Где subtype/type - правильный тип многоцелевых расширений почты Интернета (MIME). Наиболее распространенным типом MIME является тип HTML: text/html. В таблице 2.1 приведено еще несколько распространненых типов MIME, которые будут рассмотрены; более полный перечень и анализ типов MIME приводится в Главе 4.

Примечание

MIME было первоначально изобретено для описания содержания тел сообщений почты. Оно стало довольно распространненым способом представления информации о Content-Type . Вы можете узнать больше о MIME в RFC1521. RFCs в Интернете обозначают "Просьбы о комментариях", которые представляют собой резюме решений, принятых группами в Интернете, пытающимися установить стандарты. Можно посмотреть результаты RFC1521 на следующем адресе: http://andrew2.andrew.cmu.edu/rfc/rfc1521.html

Таблица 2.1. Некоторые общие типы MIME. Тип MIME Описание Text/html Язык разметки гипертекста (HTML) Text/plain Простые текстовые файлы Image/gif Графические файлы GIF Image/jpeg Сжатые графические файлы JPEG Audio/basic Аудио - файлы Sun *.au Audio/x-wav Файлы Windows *.wav

После заголовка и пустой строки, Вы просто печатаете данные в нужном для Вас виде. Если Вы посылаете HTML, то печатайте теги HTML и данные к stdout после заголовка. Вы можете послать также графику, звук и другие двоичные файлы, просто печатая содержимое файла в stdout. Несколько примеров этого приведено в Главе 4.

Установка и выполнение программы CGI

Данный раздел несколько отклоняется от программирования CGI и рассказывает о конфигурирования вашего сервера Веб для использования CGI, об установке и выполнении программ. Вы ознакомитесь с различными серверами для различных платформ более или менее подробно, но Вам придется глубже изучить документацию своего сервера с целью нахождения оптимального варианта.

Все серверы требуют пространства для файлов сервера и пространства для документов HTML. В настоящей книге, область сервера называется ServerRoot, а область документа - DocumentRoot. На машинах UNIX ServerRoot - обычно в /usr/local/etc/httpd/, а DocumentRoot - обычно в /usr/local/etc/httpd/htdocs/. Однако, это не имеет никакого значения для вашей системы, поэтому замените все ссылки на ServerRoot и DocumentRoot на ваши собственные ServerRoot и DocumentRoot.

Когда Вы обращаетесь к файлам, используя ваш браузер Веб, Вы определяете файл в URL относительно DocumentRoot. Например, если адрес вашего сервера mymachine.org, то Вы обращаетесь к этому файлу со следующим URL: http://mymachine.org/index.html

Конфигурирование сервера для CGI

Большинство серверов Веб имеет такую предварительную конфигурацию, которая позволяет использовать программы CGI. Обычно два параметра указывают серверу о том, является ли файл приложением CGI или нет:

  • Обозначенный каталог. Некоторые серверы позволяют определить, что все файлы в обозначенном каталоге (обычно, по умолчанию, называемый cgi-bin) являются CGI.
  • Расширения имени файла. Много серверов имеют такую предварительную конфигурацию, которая позволяет определять все файлы заканчивающиеся на.cgi, как CGI.

Метод обозначенного каталога - это своего рода пережиток прошлого (самые первые серверы использовали его как единственный метод для определения того, какие файлы были программами CGI), но он имеет несколько преимуществ.

  • Он сохраняет программы CGI в централизованном виде, препятствуя загромождению других каталогов.
  • Вы не ограничены каким-либо определенным расширением имени файла, так что можете называть файлы так, как хотите. Некоторые серверы позволяют обозначить несколько различных каталогов в качестве каталогов CGI.
  • Он также дает больше возможностей в отношении контроля над теми, кто может записывать CGI. Например, если Вы имеете сервер и поддерживаете систему с несколькими пользователями и не хотите, чтобы они использовали свои собственные сценарии CGI без предварительной ревизии программы из соображений безопасности, можно обозначить только эти файлы в ограниченном,централизованном каталоге как CGI. Пользователи тогда должны будут предоставить Вам программы CGI для установки и Вы сможете сначала провести ревизию кода, чтобы удостовериться, что у программы нет каких-либо крупных проблем с защитой.

Обозначение CGI через расширение имени файла может быть полезно благодаря его гибкости. Вы не ограничены одним единственным каталогом для программ CGI. Большинство серверов может быть конфигурировано, чтобы распознать CGI через расширение имени файла, хотя по умолчанию не все из них конфигурированы таким образом.

Предостережение

Помните о важности вопросов защиты, когда Вы конфигурируете ваш сервер для CGI. Некоторые подсказки будут рассмотрены здесь, а в Главе 9 "Защита CGI" эти аспекты рассматриваются более подробно.

Установка CGI на серверах UNIX

Независимо от того, как конфигурирован ваш сервер UNIX, нужно предпринять несколько шагов, чтобы удостовериться в том, что ваши приложения CGI выполняются должным образом. Ваш сервер Веб обычно будет работать как несуществующий пользователь (то есть пользователь UNIX nobody - учетная запись, которая не имеет прав доступа к файлу и не может быть зарегистрирована). Сценарии CGI (написанные на Perl, оболочке Bourne или на другом языке описания сценария) должны быть, выполнимы и читаемы по всему миру.

Подсказка

Чтобы сделать ваши файлы читаемыми и выполнимым по всему миру, используйте следующую команду UNIX права доступа: chmod 755 имени файла.

Если Вы используете язык описания сценария типа Perl или Tcl, укажите полный путь вашего интерпретатора в первой строке вашего сценария. Например, сценарий Perl, использующий perl в каталоге /usr/local/bin должен начинаться со следующей строки:

#!/usr/local/bin/perl

Предостережение

Никогда не помещайте интерпретатор (perl, или двоичный код Tcl Wish в каталог /cgi-bin. Это создает опасность для защиты в Вашей системе. Более подробно это описано в Главе 9.

Некоторые универсальные cерверы UNIX

Серверы NCSA и Apache имеют файлы со сходной конфигурацией, потому что сервер Apache был первоначально основан на коде NCSA. По умолчанию, они конфигурированы таким образом, чтобы любой файл в каталоге cgi-bin (расположенный по умолчанию в ServerRoot) являлся программой CGI. Чтобы изменить местоположение каталога cgi-bin, можно отредактировать файл конфигурации conf/srm.conf. Форматом для конфигурирования этого каталога является

ScriptAlias fakedirectoryname realdirectoryname

где fakedirectoryname - псевдо-имя каталога (/cgi-bin), и realdirectoryname - полный путь, где программы CGI фактически сохранены. Вы можете конфигурировать более одного ScriptAlias, добавляя еще строки ScriptAlias.

Заданная по умолчанию конфигурация достаточна для потребностей большинства пользователей. Нужно отредактировать строку в файле srm.conf в любом случае, чтобы определить правильное realdirectoryname. Если, например, Ваши программы CGI расположены в /usr/local/etc/httpd/cgi-bin, строка ScriptAlias в вашем файле srm.conf должна походить на следующую:

ScriptAlias /cgi-bin/ /usr/local/etc/httpd/cgi-bin/

Чтобы обращаться или ссылаться на программы CGI, расположенные в этом каталоге, используется следующий URL:

Http://hostname/cgi-bin/programname

Где hostname - имя хозяина вашего сервера Веб, и programname - имя Вашего CGI.

Например, допустим, что Вы скопировали программу hello.cgi в Ваш каталог cgi-bin (например, /usr/local/etc/httpd/cgi-bin) на Вашем сервере Веб, называемом www.company.com. Чтобы обратиться к вашему CGI, используйте следующий URL: http://www.company.com/cgi-bin/hello.cgi

Если нужно конфигурировать сервер NCSA или Apache так, чтобы распознавать любой файл с расширением.cgi как CGI, нужно отредактировать два файла конфигурации. Сначала, в файле srm.conf, не комментируйте следующую строку:

AddType application/x-httpd-cgi .cgi

Это свяжет CGI типа MIME с расширением.cgi. Теперь, нужно изменить файл access.conf, чтобы можно было выполнить CGI в любом каталоге. Для этого, добавьте опцию ExecCGI к строке Option. Это будет выглядеть примерно как следующая строка:

Option Indexes FollowSymLinks ExecCGI

Теперь, любой файл с расширением.cgi считается CGI; обращайтесь к нему, как обращались бы к любому файлу на вашем сервере.

Сервер CERN конфигурирован так же, как и серверы Apache и NCSA. Вместо ScriptAlias, сервер CERN использует команду Exec. Например, в файле httpd.conf, Вы увидете следующую строку:

Exec /cgi-bin/* /usr/local/etc/httpd/cgi-bin/*

Другие серверы UNIX можно конфигурировать таким же способом; более подробно об этом описано в документации сервера.

Установка CGI на Windows

Большинство серверов, доступных для Windows 3.1, Windows 95 и Windows NT конфигурировано с помощью метода "расширение имени файла" для распознавания CGI. Вообще, изменение конфигурации сервера на базе Windows просто требует выполнения программы конфигурации сервера и внесения соответствующих изменений.

Иногда конфигурирование сервера для правильного выполнения сценарий (типа Perl) представляется сложным делом. В DOS или Windows, Вы не сможете определить интерпретатор на первой строке сценария, как это происходит при работе с UNIX. Некоторые серверы имеют заранее заданную конфигурацию, чтобы связать некоторые расширения имени файла с интерпретатором. Например, многие Веб-серверы Windows предполагают, что файлы, оканчивающиеся на.pl, являются сценариями Perl.

Если сервер не выполняет такой тип ассоциации файла, можно определить пакетный файл упаковщика, который вызывает как иинтерпретатор, так и сценарий. Как и с сервером UNIX, не устанавливайте интерпретатор ни в каталоге cgi-bin ни в каком-либо Веб-доступном каталоге.

Установка CGI на Macintosh

Две наиболее известные опции сервера для Macintosh - это WebStar StarNine и его предшественник MacHTTP. Оба распознают CGI по расширению имени файла.

MacHTTP понимает два различных расширения: .cgi и.acgi, который обозначает асинхронный CGI. Регулярные программы CGI, установленные на Macintosh (с расширением.cgi), будут поддерживать Веб-сервер в состоянии занятости, пока не закончится выполнение CGI, вынуждая сервер приостановить выполнение всех других запросов. Асинхронный CGI, с другой стороны, позволяет серверу принимать запросы даже во время своей работы.

Разработчик CGI Macintosh, использующий любой из этих Веб-серверов, должен, по возможности, использовать просто расширение.acgi, а не расширение.cgi. Оно должно работать с большинством программ CGI; если оно не работает, переименуйте программу на.cgi.

Выполнение CGI

После того, как вы установили CGI, имеются несколько способов выполнить его. Если ваш CGI -программа, работающая только с выводом, типа программы Hello,World!, тогда Вы может выполнять ее, просто обращаясь к ее URL.

Большинство программ выполняется как серверное приложение к форме HTML. Прежде, чем научиться, как получать информацию от этих форм, сначала прочтите краткое введение о создании таких форм.

Быстрая обучающая программа по формам HTML

Два наиболее важных тега в форме HTML - это теги

и . Можно создавать большинство форм HTML, используя только эти два тега. В данной главе, Вы изучите эти теги и небольшое подмножество возможных типов или атрибутов . Полное руководство и ссылка на формы HTML находятся в Главе 3 " HTML и формы" .

Тег

Тег используется для определения того, какая часть файла HTML должна быть использована для информации, введенной пользователем. Здесь имеется в виду, как большинство страниц HTML вызывает программу CGI. Атрибуты тега определяют имя программы и местоположение - либо локально, либо как полный URL, тип используемого кодирования, и метод перемещения данных, используемых программой.

Следующая строка показывает спецификации для тега :

< ACTION FORM = "url" METHOD = ENCTYPE = "..." >

Атрибут ENCTYPE не играет особой роли и обычно не включается с тегом . Подробная информация относительно тега ENCTYPE дана в Главе 3. Один из способов использования ENCTYPE, показан в Главе 14 "Фирменные расширения. "

Атрибут ACTION ссылается на URL программы CGI. После того, как пользователь заполнит форму и предоставит информацию, вся информация кодируется и передается программе CGI. Программа CGI решает сама вопрос о декодировании и обработке информации; этот аспект рассматривается в "Принятие ввода от браузера, " ниже в настоящей главе.

Наконец, атрибут METHOD описывает, как программа CGI должна получать ввод. Эти два методы - GET и POST - отличаются в отношении того, как передавать информацию программе CGI. Оба обсуждены в "Принятие ввода от браузера. "

Чтобы браузер смог позволить введение информации пользователем, все теги форм и информация должны быть окружены тегом . Не забудьте заключительный тег

для обозначения конца формы. Нельзя иметь форму внутри формы, хотя Вы можете установить форму, которая позволяет представлять части информации в различные местах; этот аспект широко рассматривается в Главе 3.

Тег

Вы можете создавать полоски ввода текста, кнопки "radio", окна флажков, и другие средства принятия ввода, используя тег. В данном разделе рассматриваются только поля текстового ввода. Для реализации этого поля, используйте тег со следующими атрибутами:

< INPUT TYPE=text NAME = "... " VALUE = "... " SIZE = MAXLENGTH = >

NAME - символическое имя переменной, которая содержит значение, введенное пользователем. Если Вы включаете текст в атрибут VALUE, этот текст будет помещен как заданный по умолчанию в поле текстового ввода. Атрибут SIZE позволяет Вам определить горизонтальную длину поля ввода, поскольку он будет появляться в окне браузера. И наконец, MAXLENGTH определяет максимальное число символов которые, пользователь может ввести в поле. Обратите внимание, что атрибуты VALUE, SIZE, MAXLENGTH являются необязательными.

Представление формы

Если Вы имеете только одно текстовое поле в пределах формы, пользователь может представить форму, просто набирая информацию на клавиатуре и нажимая Enter. В противном случае, должен быть какой-то другой способ представления информации пользователем. Пользователь представляет информацию, используя кнопку для представления со следующим тегом:

< Input type=submit >

Этот тег создает внутри вашей формы кнопку Submit. Когда пользователь закончивает заполнение формы, он или она может отправить ее содержание по адресу URL, указанному атрибутом ACTION формы, кликая кнопку Submit.

Принятие ввода от браузера

Выше были даны примеры записи программы CGI, которая посылает информацию с сервера на браузер. В действительности, программа CGI, которая лишь выводит данные, не имеет много приложений (некоторые примеры даны в Главе 4). Более важной способностью CGI является получение информации от браузера - особенность, которая придает Веб интерактивный характер.

Программа CGI получает два вида информации от браузера.

  • Во-первых, она получает различные части информации о браузере (его тип, что он может просматривать, хост хозяина, и так далее), сервера (его имя и версия, порт его выполнения, и так далее), и непосредственно о программе CGI (имя программы и где она расположена). Сервер дает всю эту информацию программе CGI через переменные среды.
  • Во-вторых, программа CGI может получать информацию, введенную пользователем. Эта информация, после кодирования браузером, посылается либо через переменную среду (метод GET), либо через стандартный ввод (stdin- метод POST).

Переменные среды

Полезно знать, какие переменные среды являются доступными для программы CGI, как в процессе обучения, так и для отладки. В таблице 2.2 приведены некоторые из доступных переменных среды CGI. Можно также записать программу CGI, которая выводит переменные среды и их значения на браузер Веб.

Таблица 2.2. Некоторые важные переменные среды CGI Переменная среды Цель REMOTE_ADDR Адрес IP машины клиента. REMOTE_HOST Хост хозяина машины клиента. HTTP _ACCEPT Перечисляет типы MIME данных, которые браузер умеет интерпретировать. HTTP _USER_AGENT Информация браузера (тип браузера, номер версии, операционная система, и т.д.). REQUEST_METHOD GET или POST. CONTENT_LENGTH Размер ввода, если он послан через POST. Если не имеется никакого ввода или если используется метод GET, этот параметр не определен. QUERY_STRING Содержит вводимую информацию, когда она передается с помощью метода GET. PATH_INFO Позволяет пользователю определить путь от командной строки CGI (например, http://hostname/cgi-bin/programname/path). PATH_TRANSLATED Транслирует относительный путь в PATH_INFO в фактический путь в системе.

Чтобы записать приложение CGI, которое отображает переменные среды, нужно знать, как выполнить две вещи:

  • Определить все переменные среды и их соответствующие значения.
  • Вывести результаты для браузера.

Вы уже знаете, как выполнять последнюю операцию. В Perl переменные среды сохраняются в ассоциативном массиве %ENV, который вводится именем переменной среды. Листинг 2.3 содержит env.cgi, программу Perl, которая служит для достижения нашей цели.

Листинг 2.3. Программа Perl, env.cgi, которая выводит все переменные среды CGI.

#!/usr/local/bin/perl print "Content-type: text/html\n\n"; print " \n"; print "CGI Environment\n"; print "\n"; print "\n"; print "

CGI Environment

\n"; foreach $env_var (keys %ENV) { print "$env_var = $ENV{$env_var}
\n"; } print " \n";

Подобная программа может быть написана в C; полный код находится в Листинге 2.4.

Листинг 2.4. Env.cgi.c в C. /* env.cgi.c */ #include extern char **environ; int main() { char **p = environ; printf("Content-Type: text/html\r\n\r\n"); printf(" \n"); printf("CGI Environment\n"); printf("\n"); printf("\n"); printf("

CGI Environment

\n"); while(*p != NULL) printf("%s
\n",*p++); printf(" \n"); }

GET или POST ?

Какая разница между методами GET и POST? GET передает закодированную входную строку через переменную среды QUERY_STRING, а POST передает ее через stdin. POST - более предпочтительный метод, особенно для форм с большим количеством данных, потому-что здесь нет каких-либо ограничений в отношении объема посылаемой информации, а при методе GET объем пространства среды ограничен. GET имеет однако определенное полезное свойство; это подробно рассматривается в Главе 5 "Ввод".

Чтобы определить, который метод используется, программа CGI проверяет переменную среду REQUEST_METHOD, которая будет установлена либо в GET, либо в POST. Если она установлена в POST, длина закодированной информации сохранена в переменной среды CONTENT_LENGTH.

Закодированный Ввод

Когда пользователь передает форму, браузер сначала кодирует информацию перед посылкой ее на сервер, а затем на приложение CGI. Когда Вы используете тег , каждому полю присваивают символическое имя. Значение, введенное пользователем, представляется как значение переменной.

Чтобы определить это, браузер использует кодирующую спецификацию URL, которая может быть описана следующим образом:

  • Отделяет различные поля амперсандом (&).
  • Отделяет имя и значения знаками равенства (=), с именем слева и значением справа.
  • Заменяет пробелы знаками "плюс" (+).
  • Заменяет все "ненормальные" символы знаком процента (%), за которым следует двузначный шестнадцатеричный код символа.

Ваша конечная закодированная строка будет похожа на следующую:

Name1=value1&name2=value2&name3=value3 ...

Примечание: Спецификации для кодирования URL находятся в RFC1738.

Например, предположим, что у вас была форма, которая запросила имя и возраст. Код HTML, который использовался для отображения этой формы, представлен в листинге 2.5.

Листинг 2.5. Код HTML для отображения формы имени и возраста.

Name and Age

Enter your name:

Enter your age:

Предположим, что пользователь вводит Joe Schmoe в поле имени, и 20 - в поле возраста. Ввод будет закодирован во входной строке.

Name=Joe+Schmoe&age=20

Синтаксический анализ ввода

Для того чтобы эта информация была полезной, нужно использовать информацию на что-то такое, что может быть использовано вашими программами CGI. Стратегии синтаксического анализа ввода рассматриваются в Главе 5. Практически, Вам никогда не придется думать о том, как анализировать ввод, потому что несколько специалистов уже написали доступные для всех библиотеки, которые производят синтаксический анализ. Две такие библиотеки представлены в настоящей главе в следующих разделах: cgi -lib.pl для Perl (написаны Стивом Бреннером) и cgihtml для C (написаны мной).

Общая цель большинства библиотек, написанных на различных языках, состоит в том, чтобы анализировать закодированную строку и помещать пары имен и значений в структуру данных. Имеется очевидное преимущество в использовании языка, который имеет встроенные структуры данных типа Perl; однако, большинство библиотек для языков низшего уровня типа C и C++ включает выполнение структуры данных и подпрограммы.

Не обязательно добиваться полного понимания библиотек; гораздо важнее научиться использовать их как инструментальные средства, чтобы упростить работу программиста CGI.

Cgi -lib.pl

Cgi -lib.pl использует ассоциативные массивы Perl. Функция &ReadParse анализирует входную строку и вводит каждую пару "имя / значение" по имени. Например, соответствующими строками Perl, необходимыми для декодирования только что представленной вводной строки "имя / возраст", были бы

&ReadParse(*input);

Теперь, чтобы увидеть значение, введенное для "имени", можно обращаться к ассоциативному массиву $input {"имя"}. Точно так же, чтобы обратиться к значению "возраста", нужно посмотреть на переменную $input {"возраст"}.

Cgihtml

C не имеет никаких встроенных структур данных, так что cgihtml осуществляет свой собственный список связей для использования со своими анализирующими подпрограммами CGI. Это определяет структуру entrytype следующим образом:

Typedef struct { Char *name; Char *value; } Entrytype;

Чтобы проанализировать вводную строку "name / age" ("имя / возраст") в C, используя cgihtml, используется следующее:

/* объявить связанный список, называемый вводом */ Llist input; /* анализировть ввод и место в связанном списке */ read_cgi_input(&input);

Чтобы обратиться к информации о возрасте, можно либо проанализировать список вручную, либо использовать имеющуюся функцию cgi _val ().

#include #include Char *age = malloc (sizeof (char) * strlen (cgi _val (input, "age")) + 1); Strcpy (age, cgi _val (input, "age"));

Значение "возраста" теперь сохранено в строке age.

Примечание: Вместо использования простого массива (подобно char age ;), я занимаюсь динамическим распределением пространства памяти для строки age. Хотя это усложняет программирование, тем не менее это важно с точки зрения безопасности. Более подробно о этом говорится в Главе 9.

Простая программа CGI

Вы собираетесь записать программу CGI, называемую nameage.cgi, которая обрабатывает форму "имя / возраст". Обработка данных (что я обычно называю "промежуточным материалом") минимальна. Nameage.cgi просто декодирует ввод и отображает имя пользователя и возраст. Хотя не особенно много пользы от такого инструмента, он демонстрирует наиболее критический аспект программирования CGI: ввод и вывод.

Вы используете ту же самую форму, как описано выше, вызывая поля "имя и возраст". Пока не стоит беспокоиться об ошибкоустойчивости и эффективности; решите имеющуюся задачу простейшим образом. Решения в Perl и C показаны соответственно в листингах 2.6 и 2.7.

Листинг 2.6. Nameage.cgi в Perl

#!/usr/local/bin/perl # nameage.cgi require "cgi-lib.pl" &ReadParse(*input); print "Content-Type: text/html\r\n\r\n"; print " \n"; print "Name and Age\n"; print "\n"; print "\n"; print "Hello, " . $input{"name"} . ". You are\n"; print $input{"age"} . " years old.

\n"; print " \n";

Листинг 2.7. nameage.cgi в C

/* nameage.cgi.c */ #include #include "cgi-lib.h" int main() { llist input; read_cgi_input(&input); printf("Content-Type: text/html\r\n\r\n"); printf(" \n"); printf("Name and Age\n"); printf("\n"); printf("\n"); printf("Hello, %s. You are\n",cgi_val(input,"name")); printf("%s years old.

\n",cgi_val(input,"age")); printf(" \n"); }

Обратите внимание на то, что эти две программы почти эквивалентны. Они обе содержат подпрограммы синтаксического анализа, которые занимают только одну строку и обрабатывают весь ввод (благодаря соответствующим библиотечным подпрограммам). Вывод, по существу, является измененной версией вашей основной программы Hello, World!.

Попытайтесь выполнить программу, заполняя форму и нажимая кнопку Submit.

Общая стратегия программирования

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

  • Простота
  • Эффективность
  • Универсальность

Первые два качества достаточно распространены: старайтесь сделать код как можно более читаемым и эффективным. Универсальность больше относится к программам CGI, чем к другим приложениям. Когда Вы начнете разрабатывать свои собственные программы CGI, Вы узнаете, что имеется несколько основных приложений, которые хочет сделать каждый. Например, одна из наиболее распространенных и очевидных задач программы CGI является обработка формы и посылка по электронной почте результатов определенному получателю. Вы могли бы иметь несколько отдельных обработанных форм, каждая с различным получателем. Вместо записи программы CGI для каждой отдельной формы, Вы можете съэкономить время, написав более общую программу CGI, которая годится для всех форм.

Затронув все основные аспекты CGI, я обеспечил Вас достаточными сведениями, чтобы начать программирование CGI. Однако чтобы стать эффективным разработчиком CGI, нужно иметь более глубокое понимание того, как CGI связывается с сервером и браузером. В оставшейся части настоящей книги подробно рассматриваются те вопросы, о которых вскользь было упомянуто в данной главе, а также вопросы стратегии разработки приложений, преимущества и ограничения протокола.

Резюме

В настоящей главе вкратце были описаны основы программирования CGI. Вы создаете вывод, правильно форматируя ваши данные и печатая в stdout. Получение ввода CGI является несколько более сложным делом, потому что он должен быть проанализирован до своего использования. К счастью, уже существуют несколько библиотек, которые осуществляют синтаксический анализ.

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

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

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

Данные из заполненной клиентом HTML-формы могут передаваться на сервер двумя методами: GET и POST, это определяется параметром method соответствующего тэга <form method=... action=... >. В первом случае (GET) данные присоединяются после вопросительного знака в конец URL, указанной в параметре action , во втором случае - передаются в теле запроса - в секции, предназначенной для данных (следует после всех заголовокв и пустой строки). В обоих случаях данные кодируются одинаково - см. след. пункт.

При вызове CGI-программы все, что поступило в теле запроса, подается программе на стандартный ввод, а все, что находится в URL после вопросительного знака, помещается в переменную окружения QUERY_STRING. Веб-сервером данные запроса никак не интерпретируются и не преобразуются, эти задачи возложены на CGI-программу.

CGI-программа выдает содержимое ответа (как правило, HTML-контент) на свой стандартный вывод, который перехватывается веб-сервером с тем, чтобы отослать эти данные клиенту. Предварительно CGI-программа должна напечатать заголовок "Content-Type" и отделить его от данных пустой строкой. Например, вывод CGI-программы, генерирующей HTML, может выглядеть следующим образом:

Content-Type: text/html

Hello, world

Конфигурирование сервера Apache для исполнения CGI-скриптов

Для того, чтобы Apache воспринимал все файлы, находящиеся в некотором каталоге как CGI-скрипты, нужно использовать директиву

ScriptAlias /виртуальный/путь / /путь/к/каталогу / ScriptAlias /cgi-bin/ /usr/local/www/cgi-bin/ Это означает, что для обработки запроса URL вида http://your.server.com/cgi-bin/dir/script будет взят не файл script из каталога DocumentRoot /cgi-bin/dir/, а запущена программа /usr/local/www/cgi-bin/dir/script.

Для смешанного хранения файлов, подлежащих просмотру, и CGI-скриптов в одном каталоге внутри дерева DocumentRoot следует присвоить CGI-скриптам одинаковые расширения (например, ".cgi") и указать серверу, что интерпретировать такие файлы следует как CGI-скрипты:

AddHandler cgi-script .cgi Директива AddHandler может быть использована в любом контексте конфигурации Apache.

Структура URL и кодирование данных запроса

Для работы CGI-программ важное значение имеют части URL, называемые PATH_INFO и QUERY_STRING. Рассмотрим запрос с URL вида

Http://my.server.com/cgi-bin/dir/prog/a/b?A=1&B=qwerty

Используя директиву ScriptAlias , приведенную в предыдущем пункте, сервер определяет что произошло обращение к CGI-программе и для поиска этой программы заменяет начальное /cgi-bin/ на /usr/local/www/cgi-bin/ . Следуя запрошенному URL, сервер обнаруживает в этом каталоге подкаталог dir , однако подкаталога prog в каталоге /usr/local/www/cgi-bin/dir не обнаружено. В таком случае сервер предполагает, что prog - имя CGI-программы, подлежащей выполнению. Если программа /usr/local/www/cgi-bin/dir/prog не найдена или не может быть исполнена, сервер возвращает клиенту ошибку 403, 404 или 500. В противном случае программа prog запускается, а оставшаяся часть пути из URL - /a/b - передается программе prog в переменной окружения PATH_INFO. Таким способом можно передать в CGI-программу дополнительные параметры.

Все, что находится после вопросительного знака - A=1&B=qwerty - передается программе prog в переменной окружения QUERY_STRING. Это могут быть данные из заполненной пользователем формы, отправленные на сервер методом GET, либо какая-то другая информация (сервер не делает никаких предположений об интерпретации данных в QUERY_STRING, это задача вызываемой программы).

Данные из полей формы, заполненной пользователем - независимо от метода (POST или GET), которым они пересылаются на сервер - кодируются следующим образом:

имя_поля =значение_поля &имя_поля =значение_поля...

Пары имя-значение разделяются амперсандом. Алфавитно-цифровые символы и некоторые знаки препинания, не имеющие специального значения (тире, подчеркивание) передаются как есть. Остальные символы кодируются в виде "%NM ", где NM - двузначный шестнадцатеричный код символа. Пробел может передаваться как "%20" или как символ "+". Кириллические символы также должны кодироваться указанным способом. Кодировка производится броузером при отправке полей заполненной формы.

Например:

Http://my.server.com/cgi-bin/dir/prog?birthday=11%2F05%2F73&name=John+Smith означает, что в поле birthday пользователь внес "11/05/73", а в поле name - "John Smith".

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

При пересылке данных формы, закодированных вышеописанным способом, методом POST клиент должен установить заголовок запроса Content-Type следующим образом:

Content-Type: application/x-www-form-urlencoded

Переменные окружения CGI

При запуске CGI-скрипта веб-сервер устанавливает дополнительные переменные окружения:

Переменная Значение
AUTH_TYPE

Метод аутентифицирования, использованный для опознания пользователя. См. также REMOTE_USER и REMOTE_IDENT.

CONTENT_LENGTH

Длина данных запроса в байтах, переданных CGI-скрипту через стандартный ввод.

CONTENT_TYPE

MIME-тип данных запроса.

DOCUMENT_ROOT

Корневой каталог дерева документов веб-сервера (определяется директивой DocumentRoot ).

GATEWAY_INTERFACE

Используемая версия CGI.

HTTP_ACCEPT

Список MIME-типов данных, которые клиент может принять.

HTTP_FROM

Адрес электронной почты пользователя, сделавшего запрос (многие броузеры не передают такие данные).

HTTP_REFERER
HTTP_USER_AGENT

Броузер клиента.

PATH_INFO PATH_INFO (если есть) - см. выше " "
PATH_TRANSLATED

PATH_INFO, преобразованное в полный путь в файловой системе сервера (PATH_INFO, добавленное к DOCUMENT_ROOT).

QUERY_STRING

Данные запроса, переданные в составе URL вслед за вопросительным знаком - см. выше " ".

REMOTE_ADDR

IP-адрес клиента.

REMOTE_HOST Имя DNS клиента.
REMOTE_USER Аутентифицированное имя пользователя.
REQUEST_METHOD

Метод запроса (GET, POST, HEAD и т.д.).

SCRIPT_NAME Виртуальный путь (например, /cgi-bin/program.pl) к исполняемому CGI-скрипту.
SERVER_NAME DNS-имя сервера или, при невозможности определить имя, его IP-адрес.
SERVER_PORT

Номер порта сервера.

SERVER_PROTOCOL Имя и версия протокола, через который был сделан запрос (например, HTTP/1.1).
SERVER_SOFTWARE

Тип и номер версии ПО веб-сервера.

С Apache поставляется стандартный тестовый скрипт test-cgi, выводящий занчения переменных окружения CGI.

Cookies и другие методы сохранения состояния

Основной проблемой при написании интерактивных CGI-скриптов, т.е. скриптов, чьи последовательные вызовы одним пользователем логически связаны друг с другом, является проблема сохранения состояния. Дело в том, что в протокол HTTP рассматривает все поступающие на сервер запросы как независимые друг от друга. Соответственно, после обработки каждого вновь поступившего запроса CGI-скрипт полностью завершает свою работу, а для обработки следующего запроса, неважно относится ли он к тому же логическому сеансу работы пользователя или нет, скрипт начинает свою работу с нуля без всякой информации о предыстории.

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

Существует несколько методов сохранения состояния:

  1. cookies - сохранение на компьютере клиента,
  2. скрытые поля - сохранение внутри формы, посылаемой клиенту,
  3. сохранение в файле какого-либо формата на сервере,
  4. сохранение в параллельно работающей базе данных.

Два последних метода реализуют сохранение состояния на стороне сервера.

База данных

В качестве параллельно работающей базы данных может выступать любая из имеющихся СУБД, для обращения к которой язык программирования скрипта имеет интерфейс (в Перле есть библиотеки, обеспечивающие взаимодействие со всеми распространенными СУБД).

Также существует решение в виде демона, который запускается параллельно с http-сервером, и сохраняет требуемую информацию в своей оперативной памяти в виде переменная =значение . Для записи или извлечения данных скрипт соединяется с демоном по заранее оговоренному порту TCP или UDP, идентифицирует себя и использует набор простых команд типа "save name =value " и "extract name " (возвращается value ).

Интересно, что несмотря на сложность реализации, такое решение (или использование СУБД с возможностью доступа по сети) позволяет разделять данные между скриптами работающими на различных серверах (если реализуется какая-то сложная распределенная интерактивная веб-система), при этом не вовлекается сохранение данных на стороне пользователя.

Файл

Основным недостатком сохранения данных в файле, кроме использования дискового пространства и накладных расходов на файловые операции, является операция записи на диск как таковая. Запись на диск может быть источником серьезных проблем в плане безопасности, так как работа CGI-скрипта фактически управляется воздействием внешних пользователей, которые могут иметь враждебные намерения. Путем посылки каких-либо специальных данных неаккуратно написанному скрипту можно вызвать серьезный сбой в работе сервера. Если же скрипт имеет право записи на диск, то последствия могут быть гораздо серьезнее, поэтому обычно CGI-скрипты, как и сам веб-сервер, работают с минимальными привилегиями от имени пользователя nobody без права записи на диск.

Сохранение состояния на стороне пользователя

Сохранение данных состояния на стороне пользователя (cookies и, технически, скрытые поля) существенный недостаток: пользователь имеет полный доступ к сохраняемым данным и может их несанкционированно изменить (например, прочитать правильный ответ теста или изменить идентификатор пользователя). Достоинством является простая реализация.

Cookies

Cookies - это данные вида имя =значение , которые, будучи получены от сервера, сохраняются броузером на диске пользователя для их возврата серверу при последующих запросах к этому или другому URL. Поскольку данные сохраняются на диске, они могут быть использованы после перезапуска броузера.

Сервер передает cookie через специальное поле заголовка HTTP-ответа "Set-Cookie". Броузер возвращает cookie также через специальное поле в загловке HTTP-запроса - "Cookie". На стороне сервера cookie формируется, как правило, скриптом, который просто выводит в STDOUT соответствующий заголовок. Передача данных, полученных через cookie, от броузера в скрипт производится сервером через установку переменной окружения HTTP_COOKIE, которая доступна внутри скрипта и содержит пары имя =значение , которые броузер передал внутри поля "Cookie" в заголовке своего запроса.

Формат поля Set-Cookie (HTTP-ответ)

Set-Cookie: имя =значение ; Max-Age=секунды ; Comment=текстовый_комментарий ; Path=URI_или_часть_URI ; Domain=домен_сервера ; Secure ; Version=1

Все элементы, кроме имя =значение и Version, не являются обязательными. В заголовке одного ответа сервера может содержаться несколько полей Set-Cookie.

имя =значение информация, предназначенная для сохранения на стороне клиента и последующего возврата серверу; ни в имени , ни в значении не могут содержаться символы пробела, табуляции или точки с запятой; при необходимости такие символы должны быть закодированы в соответствии с общими правилами кодирования URL.

Max-Age=секунды устанавливает срок годности данных (в секундах с момента получения cookie); по умолчанию - до окончания работы данного проуесса броузера.

Comment=текстовый_комментарий комментарий сервера по поводу предназначения cookie; предполагается, что пользователь может отказаться работать с этим cookie, если комментарий ему не понравится.

Domain=домен_сервера домен, для которого действительно данное cookie (броузер должен возвращать cookie при обращении ко всем серверам данного домена, с учетом параметра Path [см. ниже]); домен должен начинаться с точки; данный сервер должен находиться в этом домене. Если параметр Domain не указан - возвращать cookie только данному серверу.

Path=URI_или_часть_URI путь от корня дерева документов сервера (URI); броузер должен возвращать cookie при обращении к данному URI и ко всем URI, начинающимся с данного; по умолчанию - URI, при запросе которого было сгенерировано cookie, минус имя файла.

Пример: при обращении на "http://s.vvsu.ru/a/b/c" сервер выдал ответ с установленным полем в заголовке:

SetCookie: X=5; Version=1 Это значит, что cookie должно возвращаться броузером при обращении на все URL вида "http://s.vvsu.ru/a/b/какое-то_имя_файла ".
Если же SetCookie в ответе сервера выглядит вот так: SetCookie: X=5; Domain=.vvsu.ru; Path=/a/; Version=1 то броузер должен присоединять это cookie ко всем запросам URL вида: "http://имя_без_точки .vvsu.ru/a/b/некий_путь_или_никакого ".

Secure если это параметр присутствует, то броузер должен возвращать cookie серверу только через защищенный канал связи; стандарт не специфицирует конкретный механизм защиты данных при передаче, но предполагается, что это SSL.

Формат поля Cookie (HTTP-запрос)

Cookie: имя =значение ; Path=URI_или_часть_URI ; Domain=домен_сервера ; Version=1

Параметры Path и Domain включаются только если они были установлены в заголовке Set-Cookie. Если несколько cookie удовлетворяют параметру Path, то они указываются в одном заголовке Cookie друг за другом (через точку с запятой) в следующем порядке: первыми передаются cookie с более длинным параметром Path. Порядок следования при равенстве параметров Path не определяется.

Скрытые поля

Скрытое поле создается внутри формы с помощью тега
name1 value=value1 >

Когда броузер получает документ с этой формой, содержимое полей типа "hidden" не отображается и пользователь не знает об их существовании (если только не посмотрит в HTML-текст присланного документа). После того, как пользователь отправляет форму на сервер, пара "name1=value1 " присоединяется к данным формы, которые будут обработаны вновь запущенным скриптом. Таким образом скрипт может получить данные о предыстории своей работы с пользователем. Например, при электронном шоппинге в скрытых полях может сожержаться список товаров, выбранных для покупки в других отделах, которые пользователь уже посетил в данном сеансе работы.

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

Server Side Includes

SSI представляет собой механизм разбора HTML-документов на стороне сервера с целью обнаружения в документе и выполнения директив, добавляющих в документ дополнительную информацию.

Все директивы вставляются внутрь тэгов HTML-комментариев, что позволяет клиенту, в случае, если сервер не поддерживает SSI, игнорировать эти директивы. Директивы имеют следующий формат:

Ниже следует список основных директив SSI и их параметров.

echo Подставляет в документ значение указанной в качестве параметра переменной окружения (см. также список CGI-переменных) или специальной переменной SSI (см. ):

Вы пришли на сервер, находящийся по адресу ...

include Вставляет в документ текст другого файла. Параметры: file - указывает путь к вставляемому файлу относительно расположения данного документа; virtual - указывает виртуальный путь (как он указывался бы в URL) к вставляемому файлу.

Эта директива очень удобна для создания стандартных шапок и подвалов веб-страниц.

fsize Вставляет размер указанного в параметре файла (путь к файлу виртуальный):

Размер файла archive.zip - bytes.

flastmod Вставляет в документ дату и время последней модификации указанного в параметре файла (путь к файлу виртуальный):

Дата последнего изменения: bytes. Формат вывода даты и времени может быть специфицирован параметром timefmt директивы config .

exec Выполняет внешнюю программу, указанную параметром, и вставляет вывод этой программы в документ. Параметры: cmd - выполняемая программа является неким обычным приложением; cgi - выполняемая программа является CGI-скриптом

На эту страницу заходили раз. В первом примере используется подстановка значений переменных окружения (см. CGI-переменные).

config Модифицирует различные аспекты работы SSI. Параметры:

  • errmsg - сообщение об ошибке, выдаваемое при невозможности выполнить директиву:
  • sizefmt - устанавливает формат вывода размера файла (подставляемого директивой fsize ; значения: bytes - выводит в байтах; abbrev - округляет до целого числа килобайт. Размер файла archive.zip - примерно bytes.
  • timefmt - устанавливает формат вывода даты и времени, подробнее см. .

Специальные переменные SSI

Ниже приведены переменные SSI, которые можно использовать в директиве echo в дополнение к переменным CGI.

DOCUMENT_NAME Имя данного документа. Например:

Вы читаете файл под названием:

DOCUMENT_URL Виртуальный путь к данному документу. Например:

QUERY_STRING_UNESCAPED Декодированные данные из QUERY_STRING (см " "), при этом все метасимволы шелла экранированы обратным слэшем (\).

DATE_LOCAL Текущие дата и время по местному времени. Например:

Сейчас

DATE_GMT Текущие дата и время по Гринвичу.

LAST_MODIFIED
Дата и время последней модификации данного документа. Например:

Этот файл был последний раз изменен

Задание

Написать CGI-скрипт для игры в виселицу (угадывание слова по буквам).

Правила игры

Сервер загадывает слово из словаря и показывает его пользователю в замаскированном виде (буквы заменены звездочками). Пользователь имеет некоторое число попыток; во время каждой попытки он может угадать одну букву. Если пользователь правильно угадывает букву или называет букву, которую он уже использовал, попытка не засчитывается. Иначе число попыток уменьшается на единицу.

Если пользователь правильно угадывает букву, сервер демаскирует в отображении слова все вхождения угаданной буквы. В любом случае сервер добавляет предложенную пользователем букву в список использованных букв, который демонстрируется во время каждой попытки для удобства пользователя. Также демонстрируется число оставшихся попыток.

Игра прекращается, если число попыток стало равным нулю (пользователь проиграл) или если угаданы все буквы в слове (пользователь выиграл).

Если пользователь на какой-либо попытке предлагает более одной буквы, считается, что пользователь пытается угадать слово целиком. При верной догадке пользователь выигрывает, иначе проигрывает независимо от числа оставшихся попыток.

Реализация

Слова выбираются случайным образом из заданного текстового файла.

Соотношение числа попыток и длины слова разумно определяется программистом. Например, число попыток есть заданная функция от длины слова; число попыток жестко привязано к каждому слову в словаре; длина слов в словаре и число попыток являются константами; при определении числа попыток используется заявленный пользователем уровень сложности.

При первом обращении к скрипту выдается заставка и регистрационная форма вида.

Статья гуляет в интернете уже довольно давно, но, как автор думаю имею право на ее перепост здесь. Многое (если не все) написаное здесь устарело, и может показаться бесполезным с первого взгляда, однако пройдя этот путь, спустя 6 лет могу сказать, это не оказалось лишним. Итак.
В этой статье я хочу рассказать о CGI интерфейсе вообще, его реализации для windows и использовании при написании CGI-программ языка ассемблер в частности. В рамки этой статьи не входит полное описание CGI, так-как в Интернете материала по этому вопросу просто море и пересказывать все это здесь я просто не вижу смысла.

Теория CGI
CGI – (Common Gateway Interface) – Общий Шлюзовый Интерфейс. Как не трудно догадаться интерфейс этот служит шлюзом между сервером (здесь я подразумеваю программу - сервер) и какой-либо внешней программой написанной для ОС на которой этот самый сервер запущен. Таким образом CGI отвечает за то, каким именно образом данные будут переданы от программы-сервера к CGI-программе и обратно. Интерфейс не накладывает никаких ограничений на то, на чем должна быть написана CGI-программа, это может быть как обычный исполнимый файл, так и любой другой файл – главное, чтобы сервер смог его запустить (в среде windows это например может быть файл с расширением, привязанным к какой-либо программе).
С момента когда Вы вызвали (например нажали кнопку формы, к которой привязан вызов CGI-программы) CGI-программу до получения вами результата в окно браузера происходит следующее:
- Вэб-клиент (например браузер) создает подключение к серверу, указанному в URL;
- Вэб-клиент посылает запрос серверу, запрос этот обычно делается с помощью двух методов GET или POST;
- Данные из запроса клиента (например значения полей формы) передаются сервером, используя CGI-интерфейс, CGI-программе, указанной в URL;
- CGI-программа обрабатывает данные клиента, полученные от сервера и генерирует на основе этой обработки ответ клиенту, который она передает по все тому же CGI-интерфейсу серверу, а он в свою очередь передает его уже непосредственно клиенту;
- Сервер разрывает соединение с клиентом.
В стандартной спецификации CGI принято, что сервер может обмениваться с программой следующими способами:
- Переменные окружения – они могут быть установлены сервером при запуске программы;
- Стандартный поток ввода (STDIN) – с его помощью сервер может передать данные программе;
- Стандартный поток вывода (STDOUT) – программа может писать в него свой вывод, передающийся серверу;
- Командная строка – в ней сервер может передать некоторые параметры программе.
Стандартные потоки ввода/вывода весьма удобны и широко используются на UNIX-системах, чего не скажешь о windows, поэтому существует спецификация CGI, разработанная специально для windows-систем так и называемая «Windows CGI». Но, естественно, и стандартные потоки ввода/вывода так же можно использовать в windows CGI программировании. Здесь я не буду затрагивать стандарт «Windows CGI», и на это существует по крайней мере две причины – первая, и самая главная – на данный момент не все http-сервера под windows поддерживают эту спецификацию (в частности мой любимый Apache 1.3.19). Вторую причину вы можете наблюдать набрав в любой поисковой системе строчку «Windows CGI». Отмечу относительно этого интерфейса лишь общие детали – все данные от сервера к клиенту передаются посредством обычного для windows *.ini файла, имя которого передается программе в командной строке. При этом все данные в файле уже заботливо разбиты по секциям сервером и вам лишь остается используя функции «GetPrivateProfile*» извлечь их оттуда. Ответ серверу передается опять же посредством файла, имя которого указано в соответствующей записи ini-файла.
Какие же данные могут быть переданы клиентом CGI-программе? – практически любые. В общем случае программе передаются значения полей формы, которые заполняет клиент, но это также могут быть и какие-либо двоичные данные, например файл с картинкой или музыкой. Данные могут быть переданы на сервер двумя различными методами – это метод GET и метод POST. Когда мы создаем форму для заполнения на нашей страничке мы явно указываем каким из приведенных методов мы хотим отправить введенные пользователем данные, делается это в основном тэге формы примерно так:
При отправке данных методом GET, данные браузером считываются из формы и помещаются следом за URL скрипта, за знаком вопроса, если значимых полей в форме несколько, то они передаются все через значёк «&», имя поля и его значение пишутся в URL через знак «=». Например запрос, сгенерированный браузером из формы при нажатии на кнопку, к которой привязан скрипт «/cgi-bin/test.exe», при учете что первое поле формы называется «your_name», второе – «your_age», может выглядеть так:
GET /cgi-bin/test.exe?your_name=Pupkin&your_age=90 HTTP/1.0
Использование метода GET имеет сразу несколько слабых сторон – первое и самое главное – т.к. данные передаются в URL то он имеет ограничение на количество этих самых передаваемых данных. Вторая слабость опять же вытекает из URL – это конфиденциальность, при такой передаче данные остаются абсолютно открытыми. Итак, хорошо если у нас в форме 2-3 небольших поля… встает вопрос что же делать если данных больше? Ответ – использовать метод POST!
При использовании метода POST данные передаются серверу как блок данных, а не в URL, что несколько развязывает нам руки для увеличения объема передаваемой информации, для вышеприведенного примера формы POST блок, посылаемый серверу будет примерно такой:

POST /cgi-bin/test.exe HTTP/1.0
Accept: text/plain
Accept: text/html
Accept: */*
Content-type: application/x-www-form-urlencoded
Content-length: 36
your_name=Pupkin&your_age=90

Как уже говорилось выше, после получения данных сервер должен преобразовать их и передать CGI программе. В стандартной спецификации CGI введенные клиентом данные при запросе GET помещаются сервером в переменную среды программы «QUERY_STRING». При запросе POST данные помещаются в стандартный поток ввода приложения, откуда могут быть им считаны. Кроме того, при таком запросе сервером устанавливаются еще две переменные среды - CONTENT_LENGTH и CONTENT_TYPE, по которым можно судить о длине запроса в байтах и о его содержании.
Помимо самих данных сервером устанавливаются и другие переменные окружения вызываемой программы, приведу некоторые из них:

REQUEST_METHOD
Описывает каким именно методом получены данные
Пример:REQUEST_METHOD=GET

QUERY_STRING
Строка запроса, если использовался метод GET
Пример:QUERY_STRING= your_name=Pupkin&your_age=90&hobby=asm

CONTENT_LENGTH
Длина в байтах тела запроса
Пример:CONTENT_LENGTH=31

CONTENT_TYPE
Тип тела запроса

GATEWAY_INTERFACE
Версия протокола CGI
Пример:GATEWAY_INTERFACE=CGI/1.1

REMOTE_ADDR
IP-Адрес удаленного хоста, то бишь клиента, нажавшего кнопочку в форме
Пример:REMOTE_ADDR=10.21.23.10

REMOTE_HOST
Имя удаленного хоста, это может быть его доменное имя или например имя компьютера в среде Windows, если таковые получены быть не могут, то поле содержит его IP
Пример:REMOTE_HOST=wasm.ru

SCRIPT_NAME
Имя скрипта, использованное в запросе.
Пример:SCRIPT_NAME=/cgi-bin/gols.pl

SCRIPT_FILENAME
Имя файла скрипта на сервере.
Пример:SCRIPT_FILENAME=c:/page/cgi-bin/gols.pl

SERVER_SOFTWARE
Программное обеспечение сервера
Пример:Apache/1.3.19 (WIN32)
Вызываемая CGI-программа может прочитать любую из переменных своего окружения, установленных сервером и использовать ее в своих интересах.
В общем-то это вкратце все, для получения более подробной информации о Общем Шлюзовом Интерфейсе смотрите специализированную документацию, это описание я сделал для того, чтобы напомнить вам, а если не знали то ввести в курс дела. Давайте попробуем что-нибудь сделать на практике.

Практическая часть
Для практики нам понадобятся как минимум 3 вещи – какой-нибудь http-сервер для Windows, все примеры я пробовал на Apache 1.3.19 для Windows, сервер бесплатный, скачать его можно с i
Да, и сервер нам понадобится не абы – какой, а настроенный для запуска cgi-скриптов! Как это делается для сервера используемого вами смотрите документацию. Вторая вещь, которая нам понадобится это, естественно, ассемблер, так же необходимо, чтобы компилятор поддерживал создание консольных WIN32 приложений, я использую Tasm, но прекрасно подойдут и Fasm и Masm и множество других *asm’ов. Ну и наконец самое главное, что потребуется это желание.
Итак, я допускаю, что сервер был вами благополучно поставлен и настроен, так, что в корневой директории документов сервера лежит файлик index.html, который замечательно показывается в браузере, когда вы набираете адрес 127.0.0.1 . Так же я учту, что где-то в дебрях папок сервера существует папочка «cgi-bin», в которой разрешен запуск скриптов.
Давайте проверим настройку сервера, а заодно и напишем небольшой скрипт. Скрипт наш будет обычным *.bat файлом. Предвижу вопросы – как? неужели? Да, это обычный командный файл, как уже говорилось выше спецификация CGI не делает различий между типами файлов, главное, чтобы сервер мог его запустить, а он в свою очередь, имел доступ к stdin/stdout и переменным окружения, bat-файл, пусть и не в полной мере, но для примера нас вполне устроит. Создадим файл примерно такого содержания:

@echo off
rem Заголовок апроса
echo Content-type: text/html
echo.
rem Тело запроса
echo "Привет!

echo "С запросом GET пришли данные: %QUERY_STRING%

Файл назовем test.bat и поместим его в директорию для запуска скриптов, скорее всего это будет директория «cgi-bin». Следующее, что нам нужно будет сделать, это каким либо образом вызвать этот скрипт, в принципе, сделать это можно напрямую набрав в окошке адреса браузера примерно следующее «http://127.0.0.1/cgi-bin/test.bat», но давайте сделаем его вызов с нашей главной странички, заодно проверим работу метода GET. Создадим в корне сервера файл index.html со следующим содержанием:

Введите данные для передачи серверу:
Данные:

Теперь при входе на сервер (http://127.0.0.1 в строке адреса браузера) должна появиться форма, наберите в ней что-нибудь и нажмите кнопку «послать», если все было сделано правильно, Вы увидите в окне браузера ответ нашего bat-скрипта. Теперь давайте посмотрим что же мы там намутили.
Как можно догадаться команда «echo» осуществляет вывод в stdout, первым делом мы передаем серверу заголовок нашего ответа – «echo Content-type: text/html». Это есть стандартный заголовок спецификации CGI, говорящий о том, что передавать мы хотим текст или документ html, существуют и другие заголовки. Очень важный момент – заголовок должен отделяться от тела ответа пустой строкой, что мы и делаем следующей командой «echo.». Дальше передается тело самого ответа – это обычный html-документ, в теле документа я для наглядности отображая одну из переменных среды, переданной нам сервером – «QUERY_STRING», как уже говорилось при методе GET (а это именно наш случай) в этой переменной передаются все введенные пользователем данные, что мы и можем наблюдать в ответе скрипта. Вы могли заметить «кавычки не к месту» в последних 2-х строках файла, сразу после «echo», стоят они там из-за специфичности bat-файлов, как можно заметить тэги html обрамляются символами «<» и «>», в тоже время эти символы служат перенаправлением ввода/вывода в bat-файлах, а посему мы не можем их здесь свободно использовать.
Рекомендую немного побаловаться с подобными bat-скриптами, это бывает очень полезно, попробуйте посмотреть другие переменные окружения. Немного скажу, отступив от темы, на UNIX-системах языки командных интерпретаторов очень сильно развиты и грань между программированием на языке командного интерпретатора и программированием на «реальном» языке программирования весьма и весьма размыта в некоторых случаях, поэтому на UNIX-системах частенько простенькие скрипты пишутся именно на языках командных интерпретаторов, но windows-интерпретатор cmd.exe или, ранее, command.com явно слабоваты для этих целей.
Теперь перейдем к самой главной задаче этой статьи, к собственно написанию CGI-программы на ассемблере. В принципе, если учесть все вышесказанное о CGI мы можем сделать вывод о том, что требует CGI-интерфейс от нашей программы:

  • Программа должна уметь читать стандартный поток ввода (stdin), чтобы получить доступ к данным, переданным методом POST;
  • Программа должна уметь писать в стандартный поток вывода (stdout), чтобы передать результат своей работы серверу;
  • Из первых двух пунктов следует, то, что для того, чтобы сервер мог передать нашей программе что-либо в stdin, а она могла ему что-либо ответить в stdout CGI-программа должна быть консольным приложением;
  • Наша программа должна уметь читать переменные своего окружения.
Этого вполне достаточно для создания полноценного CGI-приложения.
Начнем с последнего пункта. Для получения доступа к переменным окружения Windows-приложения используется функция API «GetEnvironmentStrings», функция не имеет аргументов и возвращает указатель на массив переменных окружения (ИМЯ=ЗНАЧЕНИЕ) разделенных между собой нулем, массив закрывается двойным нулем, при запуске программы сервером в окружение программы помимо стандартных переменных добавляются специфические CGI-переменные, описанные выше, при запуске программы из командной строки вы их не увидите, естественно.
Для того, что бы писать что-то в stdout или читать из stdin сначала мы должны получить хэндлы этих потоков, делается это с помощью функции API «GetStdHandle», в качестве параметра функции передается одно из следующих значений:
  • STD_INPUT_HANDLE - для stdin (стандартный ввод);
  • STD_OUTPUT_HANDLE - для stdout (стандартный вывод);
  • STD_ERROR_HANDLE - для stderr.

Функция возвратит необходимый нам для операций чтения/записи хэндл. Следующее что нам необходимо делать это писать/читать эти потоки. Делается это обычными операциями чтения/записи файлов, т.е. ReadFile и WriteFile. Тут есть одна тонкость, можно подумать, что для этих целей можно использовать WriteConsole/ReadConsole, да это действительно справедливо для консоли и будет прекрасно работать, результаты, так же как и с WriteFile будут выводиться на консоль, но продолжаться это будет пока мы не запустим нашу программу как скрипт на сервере. Происходит это потому что, когда нашу программу запускает сервер хндлы, возвращаемые функцией «GetStdHandle» уже не будут хндлами консоли как таковыми, они будут хэндлами pipe, что необходимо для связи двух приложений.
Вот небольшой пример того, как должна выглядеть CGI-программа на ассемблере:

386
.model flat,stdcall
includelib import32.lib
.const
PAGE_READWRITE = 4h
MEM_COMMIT = 1000h
MEM_RESERVE = 2000h
STD_INPUT_HANDLE = -10
STD_OUTPUT_HANDLE = -11

Data
hStdout dd ?
hStdin dd ?
hMem dd ?
header:
db "Content-Type: text/html",13,10,13,10,0
start_html:
db "Окружение CGI-программы выглядит так:
",13,10,0
for_stdin:
db "STDIN программы содержит:
",13,10,0
end_html:

Db "",13,10,0
nwritten dd ?
toscr db 10 dup (32)
db " - Тип файла",0
.code
_start:

Xor ebx,ebx
call GetStdHandle,STD_OUTPUT_HANDLE
mov hStdout,eax
call GetStdHandle,STD_INPUT_HANDLE
mov hStdin,eax

Call write_stdout, offset header
call write_stdout, offset start_html

Call VirtualAlloc,ebx,1000,MEM_COMMIT+MEM_RESERVE,PAGE_READWRITE
mov hMem,eax
mov edi,eax
call GetEnvironmentStringsA
mov esi,eax
next_symbol:
mov al,
or al,al
jz end_string
mov ,al
next_string:
cmpsb
jmp short next_symbol
end_string:
mov ,">rb<"
add edi,3
cmp byte ptr ,0
jnz next_string
inc edi
stosb
call write_stdout, hMem
call write_stdout, offset for_stdin

Call GetFileSize,,ebx
mov edi,hMem
call ReadFile,,edi, eax,offset nwritten, ebx
add edi,
mov byte ptr ,0
call write_stdout, hMem
call write_stdout, offset end_html
call VirtualFree,hMem
call ExitProcess,-1

Write_stdout proc bufOffs:dword
call lstrlen,bufOffs
call WriteFile,,bufOffs,eax,offset nwritten,0
ret
write_stdout endp
extrn GetEnvironmentStringsA:near
extrn GetStdHandle:near
extrn ReadFile:near
extrn WriteFile:near
extrn GetFileSize:near
extrn VirtualAlloc:near
extrn VirtualFree:near
extrn ExitProcess:near
extrn lstrlen:near
ends
end _start

Исполняемый файл строится командами:
tasm32.exe /ml test.asm
tlink32.exe /Tpe /ap /o test.obj
Не забудьте, что программа должна быть консольной.
Вызывать эту программу можно используя вышеописанную html-форму, нужно только поменять имя test.bat в форме на test.exe и скопировать его в /cgi-bin/ соответственно, при том можно выставить в методе запроса POST, программа его обрабатывает.
Еще хочу отметить, что можно вызывать программу и по-другому, можно создать в каталоге cgi-bin файл например test.cgi с одной единственной строчкой «#!c:/_путь_/test.exe» и вызывать в запросах его, а сервер в свою очередь будет читать первую его строчку и запускать exe-файл, для этого необходимо, чтобы в настройках http-сервера было прописано расширение *.cgi как расширение для скриптов. При таком подходе сервер запустит нашу программу с командной строкой «test.exe путь_к_test.exe» это имеет несколько плюсов – первое, это то, что человек, запускающий наш скрипт не будет даже догадываться на чем скрипт написан, второе – так-как нам передается имя файла с нашей строчкой мы можем например дописать в этот файл какие-либо настройки для нашего скрипта, что упрощает отладку, кстати именно так работают все интерпретаторы – вы успели заметить, что во всех perl/php/итд программах, присутствует подобная строка – указывающая на сам командный интерпретатор. Так вот сервер при запуске cgi-программы, если расширение программы прописано у него как скрипт в настройках читает первую строку файла, и если она оказывается описанного выше формата, то запускает указанную в строчке программу с именем этого файла ч/з пробел, допустим что в строчке указан интерпретатор перла, он получив такой подарок начинает его выполнение, т.к. комментарий в перле это символ «#», то первую строчку он пропускает и идет дальнейшее выполнение скрипта, в общем штука удобная.

Для получения достоверного результата анализ должен проводиться не менее чем через 2 недели после последнего приема антибиотиков и (или) антибактериальных препаратов.

  • Соскоб из уретры рекомендуется сдавать через 2 часа после последнего мочеиспускания, из зева и носоглотки – натощак (через 4-5 часов после последнего приема пищи, при этом необходимо исключить чистку зубов и полоскание рта), для других локусов специальной подготовки не требуется.
  • Моча. Исследованию подлежит средняя порция свободно выпущенной мочи, в количестве 3-5 мл в стерильный пластиковый одноразовый контейнер (контейнер можно получить в регистратуре) после тщательного туалета наружных половых органов без применения антисептиков. Срок доставки в лабораторию при комнатной температуре – 1-2часа, при температуре 2-8°С – 5-6 часов.
  • Сперма для бактериологического исследования собирается в стерильный пластиковый одноразовый контейнер с широким горлом путем мастурбации (контейнер можно получить в регистратуре). Срок доставки материала в лабораторию при комнатной температуре в течение 1-2 часов.
  • Мокроту рекомендуется собирать с утра, натощак после санации ротовой полости, в стерильную пластиковую посуду. Срок доставки материала в лабораторию при комнатной температуре в течение 1-2 часов, при температуре 2-8°С – 5-6 часов.
  • Забор секрета предстательной железы осуществляет врач-уролог, после предварительного массажа простаты (данная манипуляция выполняется только в Центральном офисе). Перед забором секрета предстательной железы рекомендуется половое воздержание в течение не менее 2-х дней.
  • Бактериологическое исследование грудного молока . Забор грудного молока проводится только до кормления ребенка или через два часа после его кормления грудью. Обследуемая пациентка обмывает левую и правую грудную железу теплой водой с мылом и насухо вытирает чистым полотенцем. Поверхность сосков и кончики пальцев обрабатывает ваткой, умеренно смоченной 70 % этиловым спиртом. Первая порция грудного молока, приблизительно в количестве 0,5 мл, сбрасывается. Затем, не касаясь соска руками, женщина сцеживает 0,5 – 1 мл молока из каждой железы в отдельный стерильный контейнер (контейнеры можно получить в регистратуре). Сроки доставки в лабораторию при комнатной температуре – 1-2 часа, при температуре 2-8°С – 5-6 часов.
  • Забор синовиальной жидкости для бактериологического исследования осуществляется врачом в стерильную пластиковую посуду (контейнер можно получить в регистратуре). В условиях лаборатории эта процедура не выполняется. Срок доставки материала в лабораторию при комнатной температуре в течение 1-2 часов, при температуре 2-8°С – 5-6 часов.
  • Забор раневого отделяемого для бактериологического исследования осуществляется врачом, в одноразовый контейнер со средой Эймса (контейнер можно получить в регистратуре). Срок доставки материала в лабораторию при комнатной температуре в течение 6 часов, при температуре 2-8°С – до 2 суток.
  • Желчь для бактериологического исследования собирается при зондировании, отдельно, по порциям А, В и С в три стерильные пробирки, либо во время операции с помощью шприца в одну пробирку, соблюдая правила асептики (в лаборатории эта процедура не выполняется). Срок доставки материала в лабораторию при комнатной температуре в течение 1-2 часов, при температуре 2-8°С – 5-6 часов.

Наша компания предлагает вам сделать вместе с нами первый шаг навстречу счастливой полноценной жизни.Помогут вам в этом препараты, которые мы предлагаем:

  • -дженерики: , Левитры и Сиалиса, а также Попперсы сделают сексуальную сторону вашей жизни яркой и насыщенной
  • -синтетические гормоны роста : Динатроп, Ансомон и Гетропин добавят силы, энергии спортсменам и решат проблемы лишнего веса
  • -препараты и БАДы: Мориамин Форте, Tribulus terrestris, Экдистерон и Guarana вернут вам утраченную энергию, повысят выносливость организма, омолодят кожу, и восстановят работу многих внутренних органов.

Почему мы предлагаем покупать именно у нас? Причин несколько:

  • -наша компания является первым и пока единственным в России официальным представителем по продаже дженериков , силденафила, и дистрибьютором других препаратов
  • -качество наших товаров гарантируется официальными поставками препаратов
  • -для покупателей, которые смущаются от одной мысли, что слово « Виагра» в аптеке нужно будет произнести вслух, анонимный заказ товара на сайте отличная возможность приобрести нужный препарат
  • -удобная и быстрая курьерская доставка в Москве и Санкт-Петербурге, возможна почтовая рассылка препаратов в другие регионы

Покупать у нас выгодно

  • !мы постоянно проводим новые акции, позволяющие покупать дженерики Левитры, Сиалиса и Силденафил и другие по очень выгодным ценам
  • !каждому новому покупателю компания дарит дисконтную карту постоянного покупателя для приобретения препаратов с 10%-ной скидкой
  • !при заказе товара на сумму более 5 тысяч рублей, вас ждет подарок - бесплатная доставка
  • !для оптовых покупателей возможны закупки по специальным ценам при сравнительно небольших партиях товара с выпиской товарного чека
  • !участие в партнерской программе дает вам еще одну весомую скидку на стоимость товара в размере 40%

Наши сотрудники прилагают максимум усилий для того, чтобы сделать приобретение препаратов максимально удобным для покупателя

доставка товаров производится без выходных и праздничных дней до 24 часов. Для VIP клиентов: Сиалис и другие препараты для потенции, а так же доставляются круглосуточно
оплата принимаются через электронные платежные системы Яндекс Деньги, Web Money и с банковских карт Master Card или Visa для бесплатной консультации в любое время можно обратиться » по многоканальным телефонам:

  • 8 (800 )200-86-85 (по России звонок бесплатный),
  • +7 (800 )200-86-85 (Санкт-Петербург)
  • +7 (800 )200-86-85 (Москва)
Обязательно назовите добавочный номер: 1275

Индия дешевый сиалис inurl read cgi board

Если внимательно прочитать Сиалис описание, становится понятно - это не возбуждающее средство, это препарат не для повышения либидо. Дозировка Мужчинам среднего возраста рекомендуется принимать в дозе 20 мг как минимум за 16 мин до предполагаемой сексуальной активности независимо от приема пищи. Никаких гормонов, никаких возбуждающих средств. Но даже при наличии таких заболеваний препарат Сиалис принимать можно. Пациенты могут осуществлять попытку полового акта в любое время в течение 36 ч после приема для того, чтобы установить оптимальное время ответа на прием тадалфила. На обратной стороне находится информация о сроке годности и о составе препарата. Если вам нужен дженерик Сиалис, вы всегда сможете заказать его в нашей аптеке. Какие противопоказания у медикамента Сиалис? Несвоевременное лечение приапизма приводит к повреждению тканей полового члена, в результате этого может наступить долговременная потеря потенции. Противопоказания Одновременный прием препаратов, содержащих любые органические нитраты; детский и подростковый возраст до 18 лет; повышенная чувствительность к тадалафилу. Фармакокинетика После приема внутрь тадалафил быстро всасывается. Как результат - медикамент действует в течение 36 часов! В нашей аптеке сиалис, цена в Украине на который очень демократична, можно купить в любое время суток. Производство: Индия Подарок: 5 таб Дженерик Сиалис при заказе от 20 таб Бесплатный самовывоз м.