- •1. Як влаштований internet
- •1.1. Що таке мережа Internet
- •1.2. Сервери в мережі Internet
- •1.2.1. Сервери ftp
- •1.2.2. Сервери Gopher
- •1.2.3. Поштові сервери
- •1.2.4. Сервери новин
- •1.2.5. Сервери www
- •1.3.1. З'єднання з сервером www
- •1.3.2. Сервер www
- •1.3.3. Статичні і динамічні документи html
- •1.3. Як працює сервер www
- •1.3.4. Зв'язок сервера www з субд
- •1.3.5. Органи управління ActiveX
- •1.3.6. Що таке орган управління ActibeX?
- •1.3.7. Мови програмування Java, JavaScript і vbScript
- •2. Створення документів html
- •2.1. Перша сторінка html
- •2.2. Структура документа html
- •2.2.1. Заголовок документа
- •2.2.2. Тіло документа
- •2.2.3. Вирівнювання параграфів тексту
- •2.3. Шрифтовое виділення
- •2.3.1. Зміна розміру шрифту
- •Мал. 2.4. Зміна розміру шрифту
- •2.4. Колір в документах html
- •2.4.1. Позначення кольору
- •2.4.2. Зміна кольору фону документа html
- •2.4.3. Зміна кольору тексту
- •2.4.4. Колір в інших елементах документа html
- •2.5. Зміна зображення шрифту
- •2.5.1. Фізичне форматування символів
- •2.5.2. Логічне форматування символів
- •2.5.3. Вставка заздалегідь отформатированного тексту
- •2.5.4. Вказівка шрифту по його назві
- •2.5.5. Виділення параграфа горизонтальною лінією
- •2.6. Організація списків
- •2.6.1. Неврегульовані списки
- •2.6.2. Нумеровані списки
- •2.6.3. Список каталогів
- •2.6.4. Список визначень
- •2.7. Рядок, що Біжить
- •2.8.1. Скасування кэширования сторінки
- •2.8.2. Автоматичне перезавантаження документа
- •2.8.3. Автоматичне завантаження іншого документа
- •2.8.4. Включення додаткових заголовків http
- •2.8.5. Визначення набору символів
- •2.9. Таблиці стилів
- •2.9.1. Способи використання стилів
- •3. Таблиці в документах html
- •3.1. Найпростіша таблиця
- •3.2. Як змінити зовнішній вигляд таблиці
- •3.3. Приклади оформлення таблиць
- •3.3.1. Таблиці із заголовком
- •3.3.2. Об'єднання елементів таблиці
- •3.3.3. Багатошарові заголовки
- •3.3.4. Таблиці з підписом
- •3.3.5. Вирівнювання тексту в елементах таблиці
- •3.3.6. Таблиці всередині таблиць
- •4. Графіка, анімація, відео і звук
- •4.1. Розміщення графічних зображень
- •4.2. Як вибрати формат графічного файла
- •4.2.1. Формат jpeg
- •4.2.2. Формат gif
- •4.2.4. Який формат краще
- •4.3. Прозорі зображення
- •4.4. Підготовка черезстрочних зображень
- •4.4. Анімация
- •4.4.1. Редактор gif Construction Set
- •4.4.2. Редактор Microsoft gif Animator
- •4.4.3. Редактор PhotoImpact gif Animator
- •4.5. Відеофрагменти в документах html
- •4.6. Звук в документах html
- •5. Посилання у документах html
- •5.1. Універсальний ідентифікатор ресурсів url
- •5.2. Вставка посилання
- •5.2.1. Посилання на інші документи
- •5.2.2. Локальні посилання усередині документа
- •5.3. Використання графіки в посиланнях
- •5.3.1. Вставка графічного зображення в посилання
- •5.3.2. Сегментированная графіка
- •5.3.3. Додаток Map This!
- •5.4. Посилання на різноманітні ресурси Internet
- •6. ФреймИ
- •6.1. Структура документа з фреймами
- •6.2. Визначення параметрів фреймов
- •6.3. Приклад документа html із фреймами
- •6.4. Плаваючі фреймы
- •7. Додатки cgi
- •7.1. Створення форм
- •7.1.1. Опис форми
- •7.1.2. Створення органів керування для форми
- •7.1.3. Приклад документа html із формою
- •7.2. Передача даних програмі cgi
- •7.2.1. Метод get
- •7.2.2. Метод post
- •7.2.3. Що краще - get або post
- •7.3. Передача відповіді з програми cgi
- •7.4. Перемінне середовище для програми cgi
- •7.5. Приклади програм cgi
- •7.5.1. Програма cgihello
- •7.5.2. Програма controls
- •7.5.3. Програма aref
- •7.5.4. Програма counter
7.5. Приклади програм cgi
У цьому поділі приведені приклади нескладних програм CGI, що демонструють динамічне створення документів HTML і опрацювання даних, уведених за допомогою форм.
7.5.1. Програма cgihello
Програма CGIHELLO являє собою найпростішу програму CGI, що запускается за допомогою кнопки у формі, повертаючи навігатору документ HTML, створений динамічно.
Ця програма гарна для перевірки можливості запуску програм CGI на вашому сервері WWW або на сервері вашого постачальника послуг Internet. Тому що вона дуже проста, існує трохи причин, по яких вона могла б не працювати. Це неправильне настроювання прав доступу до виртуальному каталога, що містить завантажувальний модуль програми CGI, а також неправильне посилання на цей каталог у параметрі ACTION оператора <FORM>.
Вихідний текст документа, у якому визначена форма, подана в листинге 7.4.
Листинг 7.4. Файл chap7\cgihello\cgihello. htm
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<ТITLЕ>СGI Script Test</TITLE>
</HEAD>
<BODY BGCOLOR=#FFFFFF>
<Н1>Запуск програми CGI</H1>
<FORM METHOD=GET ACTION="http://frolov/frolov-cgi/cgihello.exe">
<INPUT TYPE=submit VALUE="Send">
</FОРМ>
</BODY>
</HTML>
У цьому документі визначена форма, що містить єдину кнопку, створену оператором <INPUT> і имеющую тип SUBMIT.
У параметрі ACTION оператора <FORM> зазначений шлях до програми CGI, причому цей шлях є виртуальным. Для передачі даних використовується метод GET.
Зовнішній вигляд форми при її перегляді навігатором Microsoft Internet Explorer поданий на мал. 7.5.
Мал. 7.5. Форма для запуску програми CGIHELLO
У результаті роботи програми CGIHELLO динамічно створюється документ HTML, зовнішній вигляд якого показаний на мал. 7.6.
Мал. 7.6. Документ HTML, утворюваний динамічно програмою CGGIHELLO
Роздивимося вихідний текст програми CGIHELLO (листинг 7.5).
Листинг 7.5. Файл chap7\cgihello\cgihello. c
#include <stdio.h>
#include <stdlib.h>
void main(int argc, char *argv[])
{
printf(*Content-type: text/html\n\n");
printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">");
printf("<HTML><HEAD><TITLE>
XYZ Incorporation</TITLE></HEAD><BODY>");
printf("<H1>Результат роботи програми CGI/H1>");
printf("<P>Ця сторінка створена динамічно в результаті"
"роботи програми СGI");
printf("</BODY></HTML>");
}
Програма не відрізняється особливою складністю і складається з ряду викликів функції pdntf.
У перший разом функція printf виводить заголовок HTTP і порожню рядок-роздільник. Далі програма CGIHELLO записує построчно в стандартний потік висновка STDOUT текст документа HTML.
7.5.2. Програма controls
Більш складна програма CGI називається CONTROLS і виконує опрацювання даних, отриманих із форми, що була показана на мал. 7.2. Вихідний текст документа HTML із цією формою подані в листинге 7.1.
Програма CONTROLS відображає в динамічно формованому документі HTML метод, використаний для передачі (POST або GET), розмір і тип даних, що надходять від форми. Прийняті дані показуються як у вихідному виді, так і після перекодування. Крім того, у документі HTML розташовується список значень усіх поляж, визначених у формі (мал. 7.7).
З малюнка очевидно, що навігатор надіслав серверу WWW 135 байт інформації. Тому що при цьому був використаний метод POST, дані були спрямовані в стандартний потік запровадження INPUT. Дані закодированы в кодировке URL, тому що вміст перемінне середовище CONTENTJTYPE дорівнює application/x-www-form-urlencoded.
Звернете увагу на текстове поле з ім'ям textl. Всі прогалини у відповідному рядку в кодировке URL замінені на символ +. Що ж стосується символу & і символу запятой, то вони прийшли у виді %26 і %2С. Функція перекодирования повертає рядок у вихідний вид - Sample of text1 &,.
Форма, показана на мал. 7.2, має дві кнопки, призначені для передачі даних серверу WWW. Це звичайна кнопка і кнопка у виді графічного зображення. Після натискання графічної кнопки від форми приходить інформація про координати курсору миші у виді перемінних з іменами х и у.
Мал. 7.7. Фрагмент документа, сформованого динамічно програмою CONTROLS
Роздивимося вихідний текст програми CONTROLS (листинг 7.6).
Листинг 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 комбінує значення коду символу зі старшого і молодшого розряду що перетвориться комбінації символів.
