Листинг 7.6. Файл chap7\controls\controls. c
// =====
// Програма CGI controls.с
// Демонструє методи одержання й опрацювання
// даних від форм, розташованих у документах HTML
//
// (С) Фролов А.В., 1997
// E-mail: frolov@glas.apc.org
// WWW: http://www.glasnet.ru/~frolov
// або
// http://www.dials.ccas.ru/frolov //====
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Прототипи функцій перекодування
void Decode Str(char *szString);
char DecodeHex(char *str);
// функція main
// Точка входу програми CGI
void main(int argc, char *argv[])
{
int ISize;
FILE *fileReceived;
char *szMethod;
char *szQueryString;
char szBuf[8196];
char szSrcBuf[8196];
char *szPtr;
char *szParam;
// Висновок заголовка HTTP і розділювального рядка
printf("Content-type: text/html\n\n");
// Висновок початкового фрагмента документа HTML,
// формованого динамічно
printf("<!DOCTYPE HTML PUBLIC" " \"-//W3C//DTD HTML 3.2//EN\">");
printf("<HTML><HEAD><TITLE>XYZ Incorporation"
"</TITLE></HEAD><BODY BGCOLOR=#FFFFFF>");
// Визначаємо метод передачі даних
szMethod = getenv("REQUEST_METHOD");
// Опрацювання методу POST
if(!strcmp (szMethod, "POST"))
{
// Визначаємо розмір даних, отриманих від навігатора
// при передачі даних із полів форми
ISize = atoi(getenv("CONTENT_LENGTH"));
// Читаємо ці дані в буфер szBuf із
// стандартного потоку запровадження STDIN
fread(szBuf, ISize, 1, stdin);
// Створюємо файл, у який будуть записані
// прийняті дані
fileReceived = fopen("received.dot", "w");
// Виконуємо запис прийнятих даних
fwrite(szBuf, ISize, 1, fileReceived);
// Закриваємо файл прийнятих даних
fclose(fileReceived);
// Відображаємо значення деякий переменных середовища
printf("<Н2>Перемінне середовище</Н2>");
// Метод доступу
printf("REQUEST_METHOD = %s", getenv("REQUEST_METHOD"));
// Размep отриманих даних у байтах
printf("<BR>CONTENT_LENGTH = %ld", ISize);
// Тип отриманих даних
printf("<BR>CONTENT_TYPE = %s", getenv("CONTENT_TYPE"));
// Закриваємо буфер даних двоичным нулем,
// перетворюючи його в такий спосіб у рядок
szBuf[ISize] = '\0';
// Робимо копію прийнятих даних у буфер szSrcBuf
strcpy(szSrcBuf, szBuf);
// Відображаємо прийняті дані без опрацювання
printf("<Н2>Прийняті дані</Н2>");
printf("<P>%s", szSrcBuf);
// Виконуємо перекодування прийнятих даних
DecodeStr(szSrcBuf);
// Відображаємо результат перекодування
printf("<Н2>Дані після перекодування</Н2>");
printf("<P>%s", szSrcBuf);
// Выводим список значень поляж форми
printf("<H2>Список значень поляж</Н2>");
// Дописуємо в кінець буфера прийнятих даних
// символ &, що використовується в якості
// роздільника значень поляж
szBuf[ISize] = '&';
szBuf[ISize + 1] = '\0';
// Цикл по полях форми
for(szParam = szBuf;;)
{
// Ищем черговий разделитель
szPtr = strchr(szParam, '&');
// Якщо він знайдений, раскодируем рядок параметрів
if{szPtr != NULL)
{
*szPtr = '\0';
DecodeStr(szParam);
// Выводим у документ значення параметра
printf("%s<BR>", szParam);
// Переходимо до такого параметра
szParam = szPtr + 1;
// Якщо досягнутий кінець буфера, завершуємо цикл
if(szParam >= (szBuf + ISize))
break;
}
else
break;
}
// Выводим завершальний фрагмент документа HTML
printf("</BODY></HTML>");
return;
}
// Опрацювання методу GET
else if(!strcmp{szMethod, *GET"))
{
// Одержуємо дані, отримані від форми.
// При використанні методу GET ці дані
// передаються в перемінне середовище QUERY_STRING
szOueryString = getenv("QUERY_STRING");
// Записуємо ці дані у вихідний файл
fileReceived = fopen("received.dot", "w");
fwrite(szQuerySiring, strlen(szQueryString) + 1, 1, fileReceived);
fclose(fileReceived);
// Выводим у динамічно формований документ HTML
// значення деякий переменных середовища
printf("<Н2>Перемінне середовище</Н2>");
// Метод передачі даних
printf("REQUEST_METHOD = %s", getenv("REQUEST_METHOD"));
// Отримані дані
printf("<BR>QUERY_STRING = %s", szQueryString);
// Копіюємо прийняті дані в буфер szSrcBuf
strcpy(szSrcBuf, szQueryString);
// Відображаємо прийняті дані
printf("<Н2>Прийняті дані</Н2>");
printf("<P>%s", szSrcBuf);
// Перекодируем дані і відображаємо результат
// перекодування
DecodeStr(szSrcBuf);
printf("<Н2>Дані після перекодування</Н2>");
printf("<P>%s", szSrcBuf);
// Выводим у документ список значень поляж форми
strcpy(szBuf, szQueryString);
printf("<H2>Список значень поляж</Н2>");
szBuf[strlen{szBuf)] = '&';
szBuf[slrien(szBuf) + 1] = '\0';
for(szParam = szBuf;;)
{
szPtr = strchr(szParam, '&');
if(szPtr != NULL)
{
*szPtr = '\0';
DecodeStr(szParam);
printf("%s<BR>", szParam);
szParam = szPtr + 1;
if(szParam >= (szBuf + ISize))
break;
}
else
break;
}
printf("</BODY></HTML>");
}
}
// Функція DecodeStr
// Раскодирование рядка з кодировки URL
void DecodeStr(char *szString)
{
int src;
int dst;
char ch;
// Цикл по рядку
for(src=0, dst=0; szString[src]; src++, dst++)
{
// Одержуємо черговий символ перекодирует рядка
ch = szString[src];
// Заміняємо символ + на прогалину
ch = (ch == '+') ? ’' : ch;
// Сохраняем результат
szString[dst] = ch;
// Опрацювання шестнадцатиричных кодів виду %хх
if(ch == '%')
{
// Виконуємо перетворення рядка %хх
// у код символу
szString[dst] = DecodeHex(&szString[src + 1]);
src += 2;
}
}
// Закриваємо рядок двоичным нулем
szString[dst] = '\0';
}
// функція DecodeHex
// Раскодирование рядка %хх
char Decode Hex (char *str)
{
char ch;
// Опрацьовуємо старший розряд
if(str[0] >= 'А')
ch = ((str[0] & 0xdf) - 'А') + 10;
else
ch = str[0] - '0';
// Зрушуємо його вліво на 4 бита
ch <<= 4;
// Опрацьовуємо молодший розряд і складаємо
// його зі старшим
if(str[1] >= 'A')
ch += ((str[l] & 0xdf) - 'А') + 10;
else
ch += str[1] - 'О';
// Повертаємо результат перекодування
return ch;
}
Функція main програми CONTROLS спочатку виводить у стандартний потік висновка STDOUT заголовок HTTP і початкові рядки динамічно формованого документа HTML Для висновка використаний функція printf.
Далі функція main визначає використаний метод передачі даних, аналізуючи вміст перемінне середовище REQUEST_METHOD. Це необхідно, тому що при різних методах передача необхідно використовувати різноманітні методи одержання вхідних даних. Значення перемінне середовище програма одержує за допомогою функції getenv.
Якщо дані передаються методом POST, програма буде считывать їх із стандартного потоку запровадження STDIN. Розмір даних знаходиться в перемінне середовище CONTENT_LENGTH. Відповідний текстовий рядок утворюється функцією getenv і перетвориться в чисельне значення функцією atoi.
Читання даних із вхідного потоку виконується за один виклик функції fread:
fread(szBuf, ISize, 1, stdin);
Цій функції передається адреса буфера для запису прийнятих даних, розмір даних, кількість буферів, що потрібно вважати, і вхідної потік.
Програма CGI може зберегти прийняті дані у файлі для подальшого опрацювання. Програма створює в поточному каталозі файл із назвою received. dat:
fileReceived = fopen("received.dat", "w");
fwrite(szBuf, ISize, 1, fileReceived);
fclose(fileReceived);
Поточним каталогом при запуску цієї програми в середовищі серверу Microsoft Information Server буде каталог із завантажувальним модулем програми CONTROLS. Для того, щоб програма CGI могла створити файл у каталозі, необхідно відповідним чином настроїти права доступу. У останній главі курсу є інформація про те, як це можна зробити для серверу Microsoft Information Server.
Після зберігання прийнятих даних у файлі програма CONTROLS виводить у стандартний потік висновка вміст деякий переменных середовища: REQUEST_METHOD, CONTENT_LENGTH і CONTENT_TYPE.
Далі програма виконує перекодування отриманих даних із кодировки URL. Перед цим прийняті дані копіюються в буфер, де вони будуть обновлятися по місцю.
Для копіювання закривається буфер двоичным нулем, після чого копіювання можна виконати функцією копіювання рядка strcpy.
Перекодування виконується функцією DecodeStr, визначеної в нашому додатку. Цю функція буде розглянута пізніше.
Після перекодирования результат буде знаходитися в буфері szSrcBuf, відкіля він і береться для відображення.
На завершальному етапі опрацювання даних, отриманих від форми, програма CONTROLS записує у вихідний документ HTML значення окремих поляж. Ці значення мають формат &<Ім'я_поля>=<Значення>, при цьому символ & використовується як роздільник.
Програма закриває вихідний буфер із прийнятими даними додатковим символом & (для простоти сканування), після чого запускає цикл по полях форми.
У цьому циклі у вхідному рядку за допомогою функції strchr шукається символ-роздільник. Якщо цей символ знайдений, він заміняється на двоичный нуль, після чого отриманий текстовий рядок значення параметра перекодируется функцією DecodeStr і виводиться у вихідний потік STDOUT.
Цикл завершується тоді, коли в процесі сканування покажчик поточної позиції виходить за межі буфера даних.
Наприкінці програма CONTROLS закриває документ HTML, записуючи в нього команди </BODY> і </HTML>.
Якщо дані передаються в програму CONTROLS методом GET, вхідні дані знаходяться в перемінне середовище QUERY_STRING, що утворюється в такий спосіб:
szQueryString = getenv("QUERY_STRING");
Опрацювання прийнятих даних виконується аналогічно тому, як це робиться при методі POST. Різниця полягає лише в тому, що в документі відображається вміст тільки перемінних REQUEST_METHOD і QUERY_STRING.
Тепер можна зайнятися перекодуванням прийнятих даних, що виконується функцією DecodeStr.
Ця функція сканує вхідний рядок, замінюючи символ + на прогалину. Якщо в перекодирует рядку зустрічається комбінація символів виду %хх, вона заміняється на однобайтовый код відповідного символу за допомогою функції DecodeHex.
Функція DecodeHex комбінує значення коду символу зі старшого і молодшого розряду що перетвориться комбінації символів.
7.5.3. Програма AREF
Дотепер у прикладах використовувалися програми CGI тільки для опрацювання даних із полів форм із зазначенням адреси URL завантажувального файла програми в параметрі ACTION оператора <FORM>. Проте є й інша можливість виклику програм CGI: Можна зазначити їхню адресу в параметрі HREF оператора посилання <А>. У цьому випадку можливо передати програмі CGI параметри, указавши їх після імені файла завантажувального модуля через розділювальний символ ?. Програма одержить рядок параметрів методом GET і зможе витягти її з перемінне середовище з ім'ям QUERY. STRING.
Приклад документа HTML, у якому демонструється виклик програми CGI зазначеним вище засобом, приведений у листинге 7.7.
Дата добавления: 2015-04-19; просмотров: 622;