Написание CGI-программы на C++ — HackZona.Ru

Написание CGI-программы на C++

Написание CGI-программы на C++

Тип статьи:
Со старой ХакЗоны.
Источник:
MBR
Иногда случается, что для написания движка, работающего с Web, интерпретируемые языки типа PHP/Perl/ASP не подходят. Это бывает когда, например, требуется высокопроизводительная CMS или что-то низкоуровневое (например, сбор данных с веб-камеры). Конечно, существуют такие языки как C#, но иногда для небольших проектов их применение не окупит затраты.

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

#include
#include
#include // без расширения, подключает класс std::string
#include <string.h> // strlen, strcat, strncpy, ...

using std::string;
using std::cout;
using std::cin;
using std::endl;

int main(int argc, char *argv[])
{
string POST_data;
string QUERY_STRING;
cout << «content-type: text/plain; charset=windows-1251» << endl << endl;
char* var = 0;
var = getenv(«CONTENT_LENGTH»);
if ((var != 0) && (var) != «0»)
{
int post_length = atoi(var);
free(var); var = 0;
cout << «POST data: n»;
var = (char*)malloc(post_length+1);
cin.get(var, post_length+1);
cout << var;
free(var);
}
var = getenv(«QUERY_STRING»);
if (var)
{
QUERY_STRING = var;
free(var); var = 0;
cout << endl << «QUERY_STRING: » << QUERY_STRING << endl;
}
return EXIT_SUCCESS;
}


Как видите, для упрощения работы со строками используется класс string из библиотеки std.

Первым делом cgi-программа должна отправить заголовки. В нашем случае здесь все просто: content-type задает тип передаваемой информации (в данном случае, обычный текст), после чего идут два символа новой строки. Если не передать заголовок, сервер выдаст ошибку 'Internal Server Error'. Как вы уже поняли, отправлять все данные нужно в стандартное устройство вывода (да, кстати, приложение должно быть консольным).

Далее, необходимо научиться считывать полученные от сервера данные и переменные окружения. Значение конкретной переменной окружения можно получить используя функцию getenv(const char* имя_переменной). Эта функция вернет 0, если переменной не существует.

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

extern char** environ; // Глобальная переменная, объявляется в начале модуля

for (int i=0; environ[i] != 0; i++)
printf(%sn, environ[i]);

Внешняя переменная environ стандартизирована POSIX и доступна на большинстве платформ и операционных систем (совместимых с POSIX).

Те параметры, которые передаются через URI, могут быть найдены в переменной QUERY_STRING.

С методом POST дело обстоит несколько сложнее. Сначала мы должны узнать длину данных. Она хранится в переменной CONTENT_LENGTH в виде строки с числом. К счастью, в библиотеке С/C++ есть функция atoi, которая умеет переводить строку в число.

После того, как длина данных известна, мы просто считываем содержимое стандартного устройства ввода (им будет не клавиатура, а канал между web-сервером и cgi-программой)

Данные, хранящиеся в QUERY_STRING и в потоке стандартного ввода зашифрованы так называемым urlencode. Поэтому следующим шагом станет дешифровка и разбор всех параметров, чем наша небольшая программа заниматься не станет.

Так как мы написали CGI-программу, то для её тестирования вам понадобится Web-сервер. Можете использовать свой, а можно и на хостинге (если, конечно, он позволяет выполнение программ, а не только скриптов). Для тестирования необходимо скопировать программу в папку cgi-bin на сервере или любую другую, допускающую выполнение сценариев. И придется написать небольшую html-страницу, чтобы было удобнее посылать POST-запросы:
<*html>
<*head>
<*meta http-equiv=«content-type» content=«text/html; charset=windows-1251»>
<*title>Test Page
<*/head>
<*body>
<*form method=«post» action=«cgi-bin/cgi.exe?id=1» name=«myform»>
<*p>Entry text:<*/p>
<*input type=«text» name=«mytext» value="">
<*input type=«submit»>
<*/form>
<*/body>
<*/html>

Измените путь к cgi-программе и запустите страницу на сервере через браузер (не локально сохраненный html, а именно на сервере).

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

Цель этой статьи достигнута вы теперь знаете, как получить данные от сервера (а может быть знали и до этого :))

By MBR, 2008

Нравится
Не нравится

4 комментария

18:29
Поправки того, что не пропечаталось:
В первых строках подключаем файлы iostream, string.h, string, stdlib.h. Обратите внимание: string и string.h не одно и то же.
Далее, если в конце строки есть символ n, то естественно, на этом месте подразумевается конец строки и перед n нужно ставить слэш ()
21:53
Имхо cgi мертв его заменили такие языки как Пхп,Питон,Руби.
22:27
Не совсем понятны ваши слова, Shaitan-Devil. PHP сам использует CGI, равно как и Python и Ruby. Хотя и есть исключения в виде модулей некоторых сереров, например Apache. Но принцип остался тем же. CGI жил, живет и будет жить. Поясните подробнее, может быть неправильно трактую...
Далее, чтобы избежать возможных недоразумений по восприятию статьи - cgi-приложение на компилируемом языке уровня C, C++ и Assembler требуется использовать в критичных во времени службах. Всякий интерпретируемый язык уступает по скорости компилируемому. Представьте например себе скрипт, который собирает скажем астрономические данные, как то анализирует их, формирует flash-файл и выводит его пользователю. Да, на разработку уйдет больше времени, но зато для пользователя существенно возрастет продуктивность работы.
Следовательно, подобная реализация требуется в научных сферах. Для "простых смертных" (фирм, пользователей, развлекательных и информационных порталов) конечно лучше выбрать что-то более удобное.
Но, статистика гласит: чем больше средств используется в системе, тем больше потенциальных дыр открывается злоумышленнику. Если отказаться от PHP, можно убрать те потенциальные дыры, которые регулярно находят в его исходном коде.
З.Ы. Хостинг с поддержкой cgi-exe редкость, распространен PHP. Ну и с Python, а тем более Ruby, ситуация обстоит не лучше.
16:23
В том то и дело,что CGI на С++ и Ассемблере редкость,и практически не используется.Но бузеусловно компилируемые языки в разы превосходят интерпретируемые,по крайнер мере по быстроте работы.