Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Основи мови JavaScript.doc
Скачиваний:
1
Добавлен:
01.07.2025
Размер:
1 Мб
Скачать
☆

7.2.6. Лічильник провідин на базі cookie і програми cgi

Останній приклад, приведений у цій главі, показує основні прийоми роботи з cookie у програмах CGI і сценарії JavaScript, що вставляється в тіло динамічно формованого документа HTML.

У документі визначена форма з двома кнопками. Обидві ці кнопки призначені для виклику одной і тієї ж програми CGI, але з різними параметрами.

Якщо натиснути на кнопку з написом Go to page, програма GCI створить документ HTML. попередньо проаналізувавши заголовок запиту, що прийшов до неї, на предмет наявності в ньому інформації про cookie. Кнопка Remove All Cookies призначена для виклику програми CGI із метою видалення cookie.

У тому випадку, коли цієї інформації немає, програма CGI динамічно формує документ HTML, додавши до його заголовка HTTP заголовок Set-Cookie.

При наступних провідинах cookie уже визначено, і програма CGI одержує його значення, інтерпретуючи це значення як лічильник провідинах. Потім вона збільшує значення лічильника на одиницю і записує заголовок Set-Cookie у заголовок HTTP утворюваного документа HTML із новим значенням cookie.

Значення лічильника провідин відображається в тілі документа.

Далі програма CGI вставляє в текст цього документа сценарій JavaScript, розташований в окремому файлі. Даний сценарій визначає значення cookie своїми засобами і відображає його разом із значенням лічильника провідин у многострочном вікні редагування.

Вихідний документ HTML поданий у листинге 7.7.

Листинг 7.7. Файл chapter7/AgainCGI/AgainCGI. html

<HTML>

<HEAD>

<TITLE>Cookies demo</TITLE>

</HEAD>

<BODY BGCOLOR=white>

<Hl>Visit our page!</Hl>

<FORM METHOD=POST ACTION="http://frolov/scripts/again.exe?go">

<P><INPUT TYPE="submit" VALUE="Go to page">

</FORM>

<FORM METHOD=POST ACTION="http://frolov/scripts/again.exe?clear">

<P><INPUT TYPE="submit" VALUE="Remove All Cookies ">

</FORM>

</BODY>

</HTML>

У цьому документі визначені дві форми.

Перша форма призначена для виклику програми CGI із параметром go, а друга - із параметром clear.

Вихідний текст програми CGI, використаної в прикладі, можна знайти в листинге 7.8.

Листинг 7.8. Файл chapter7/AgainCGI/Again. c

// Розширення CGI, призначене для

// роботи з cookie //

// (С) Фролов А.В., 1998

// E-mail: frolov@glas.apc.org

// WWW: http://www.glasnet.ru/~frolov

// або

// http://www.dials.ccas.ru/frolov

#include <windows.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

// Прототипи функцій, визначених у нашій програмі

char *findCookie(char * szName);

void insertHTML(char * pszFileName, char * pszBuf);

void main(int argc, char *argv[])

{

char * pszQueryString;

char * pszCookie;

char * pszMyCookie;

int nCount;

char szBuf[4096];

char szBuf1[20];

// Заголовок для додавання cookie

char szCookieHeader[] =

"Set-Cookie:AgainCount=0;\r\nContent-type:

text/html\r\n\r\n";

// Заголовок для видалення cookie

char szCookieRemoveHeader[] =

"Set-Cookie:AgainCount=0;expires=Mon оЗ-Мау-1993 12:00:00 GMT;"

"\r\nContent-type:text/html;\r\n\r\n";

// Одержуємо параметр запуску CGI

pszQueryString = getenv("QUERY_STRING");

// Одержуємо рядок Cookie із заголовка HTTP

pszCookie = getenv("HTTP_COOKIE");

// Провідини сторінки

if(!strcmp(pszQueryString, "go"))

{

// Якщо cookie не виявлений, створюємо його

if(pszCookie == NULL)

{

// Выводим заголовок для створення cookie

printf("Content-type:text/html\r\n");

printf(szCookieHeader);

// Виводимо запрошення для перших провідин

printf ("<HTML><HEAD><TITLE>Cookie demo</ТITLE></HEAD><BODY>");

printf("<H2>Welcome to our page!</H2>");

}

else

{

// Одержуємо значення параметра cookie

// с ім'ям AgainCount

pszMyCookie = findCookie("AgainCount");

if(pszMyCookie ! = NULL)

{

// Перетворюємо це значення в число і збільшуємо

// на одиницю при кожних провідинах

nCount = atoi(pszMyCookie);

nCount++;

sprintf(szBufl, "%d", nCount);

// Выводим заголовок для відновлення cookie

printf("Content-type: text/html\r\n");

strcpy(szBuf, "Set-Cookie: AgainCount=");

strcat(szBuf, szBuf1);

strcat(szBuf, ";\r\nContent-type: text/html\r\n\r\n");

printf(szBuf);

// Виводимо запрошення для повторних провідин

printf("<H2>Welcome to our page AGAIN!</H2>");

// Выводим лічильник провідин

printf("<P>Access count: %s",szBufl);

// Вставляємо документ HTML із текстом сценарію

// JavaScript, що теж працює з cookie

insertHTML("script.ht", szBuf);

printf(szBuf);

}

}

// Видалення cookie

else

if(!strcmp(pszQueryString, "clear"))

{

// Выводим заголовок для видалення cookie

printf("Content-type: text/html\r\n");

printf(szCookieRemoveHeader);

// Виводимо повідомлення про успішне видалення cookie

printf ("<HTML><HEAD><TITLE>Cookie demo</TITLE></HEAD><BODY>");

printf("<P>Cookie Removed");

}

printf("</BODY></HTML>");

}

// findCookie

// Одержання значення параметра cookie по його

// імені

char *findCookie(char * szName)

{

char * pszCookie;

char * pszBegin;

char * pszEnd;

char szBuf[4096];

// Одержуємо текстовий рядок cookie

pszCookie = getenv("HTTP_COOKIE");

if(pszCookie != NULL)

{

// Копіюємо її в робочий буфер

strcpy(szBuf, pszCookie);

// Шукаємо в рядку ім'я параметра

pszBegin = strstr(szBuf, szName);

if(pszBegin == NULL)

return NULL;

else

{

// Пропускаємо символ рівності

pszBegin += strlen(szName) + 1;

// Шукаємо символ "точка з запятой" і заміняємо його на

// двоичный нуль

pszEnd = strstr(pszBegin, ";");

if(pszEnd != NULL)

*pszEnd = 0;

// Повертаємо значення параметра

return pszBegin;

}

}

}

// insertHTML

// Вставка в буфер умісту текстового файла

void insertHTML(char * pszFileName, char * pszBuf)

{

HFILE hSrcFile;

DWORD dwFileSize;

// Открываем файл

hSrcFile = _lopen(pszFileName, OF_READ);

// Визначаємо його довжину

dwFileSize = _llseek(hSrcFile, 0, 2);

// Встановлюємо покажчик на початок файла

_llseek(hSrcFile, 0, 0);

// Читаємо файл у буфер

_hread(hSrcFile, pszBuf, dwFileSize);

// Закриваємо буфер двоичным нулем

pszBuf[dwFileSize] = '\0';

// Закриваємо файл

_lclose(hSrcFile);

У перемінної szCookieHeader підготовлений заголовок Set-Cookie, призначений для створення параметра cookie з ім'ям AgainCount:

char szCookieHeader [] = "Set-Cookie: AgainCount=0;\r\nContent-type:

text/htnil\r\n\r\n";

Початкове значення цього параметра дорівнює нулю.

Заголовок, що зберігається в перемінної szCookieRemoveHeader, призначений для видалення cookie:

chаг szCookieRemoveHeader [] =

"Set-Cookie: AgainCount=0; expires=Mon оЗ-Мау-1993 12:00:00

GMT; \r\nContent-type: text/html;\r\n\r\n";

Ефект видалення досягається завдяки тому, що в параметрі expires зазначена дата, що вже наступила.

Відразу після запуску програма CGI одержує значення переменных середовища QUERY_STRING і НТТР_СООКIЕ:

pszQueryString = getenv("QUERY_STRING");

pszCookie = getenv("HTTP_COOKIE") ;

У перший із них зберігається параметр запуску програми CGI, а в другий - рядок cookie (якщо вона визначена).

Далі програма аналізує параметр запуску. Якщо програма викликана з параметром go, вона перевіряє перемінну pszCookie. У цю переменную функція getenv записує рядок cookie або значення NULL, якщо cookie не визначено.

При перших провідинах cookie ще немає, тому програма добавляють до заголовка HTTP формованого документа заголовок Set-Cookie:

printf ("Content-type : text/html\r\n");

printf(szCookieHeader);

Потім програма виводить запрошення для перших провідин і завершує свою роботу.

У тому випадку, якщо в прийнятому запиті вже є інформація про cookie, програма CGI витягає значення параметра cookie з ім'ям AgainCount, викликаючи для цього функцію findCookie:

pszMyCookie = findCookie("AgainCount");

Ця функція визначена в нашій програмі і буде описана трохи пізніше. Отриманий рядок преобразовывается в чисельне значення за допомогою функції atoi, після чого це значення збільшується на одиницю, преобразовывается обернено в тестовий рядок і записується в буфер szBuf1:

nCount = atoi(pszMyCookie);

nCount++;

sprintf(szBuf1, "%d", nCount);

На такому етапі програма формує заголовок Set-Cookie із новим значенням параметра AgainCount:

printf("Content-type: text/html\r\n");

strcpy(szBuf, "Set-Cookie: AgainCount=");

strcat(szBuf, szBuf1);

strcat(szBuf, ";\r\nContent-type: text/html\r\n\r\n");

printf(szBuf);

Цей заголовок разом із заголовком Content-type записується в утворюваний документ HTML.

Далі після висновка запрошення для повторних провідин сторінки програма CGI записує в документ нове значення лічильника провідин:

printf("<P>Access count: %s",szBuf1);

І, нарешті, перед завершенням своєї роботи програма вставляє в текст документа HTML файл із сценарієм JavaScript, викликаючи для цього функцію insertHTML:

insertHTML("script. ht", szBuf);

Ця функція визначена в програмі, як і функція findCookie. Коли програма CGI визивається для видалення cookie із параметром clear, вона виводить спеціально призначений для цього заголовок із простроченою датою:

Тепер коротко розповімо про роботу функції findCookie.

Отримавши текстовий рядок cookie за допомогою функції getenv, ця функція копіює рядок у робочий буфер, що можна редагувати (нагадаємо, що вміст буфера, отриманого від функції getenv, змінювати не можна).

Далі, викликом функції strstr виконується пошук у робочому буфері імені потрібного параметра cookie. Якщо це ім'я знайдене, те пропускається символ рівності і виконується пошук символу роздільника ';' і він заміняється на двоичный нуль. Після виконання всіх цих дій функція повертає адресу шуканого рядка зі значенням потрібного параметра cookie.

Функція insertHTML просто відчиняє файл, ім'я якого передається в якості параметра, читає його вміст в оперативну пам'ять і потім у буфер, адреса якого передається через другий параметр. Текст сценарію, що уставляється функцією insertHTML у динамічно формований документ HTML, поданий у листинге 7.9.

Листинг 7.9. Файл chapter7/AgainCGI/script. ht

<HR>

<P>Cookie information from JavaScript :

<FORM NAME="TestForm">

<P><TEXTAREA NAME="Comment" ROWS="3" COLS="25">

</TEXTAREA>

</FORM>

<SCRIPT LANGUAGE="JavaScript">

<!--

function findCookie(szName)

{

var i = 0;

var nStartPosition = 0;

var nEndPosition = 0;

var szCookieString = document.cookie;

var szTemp = "";

while(i <= szCookieString.length)

{

nStartPosition = i;

nEndPosition = nStartPosition + szName.length;

if(szCookieString.substring(nStartPosition, nEndPosition) == szName)

{

nStartPosition = nEndPosition + 1;

nEndPosition = document.cookie.index0f(";",nStartPosition);

if(nEndPosition < nStartPosition)

nEndPosition = document.cookie.length;

szTemp =

document.cookie.substring(nStartPosition, nEndPosition);

return unescape(szTemp);

break;

}

i++;

}

return "";

}

var szMyText = "";

szMyText = findCookie("AgainCount");

if(szMyText != "")

{

TestForm.Comment.value =

"Cookie: " + document.cookie + "\nAccess count: " + szMyText;

}

//-->

</SCRIPT>

З функцією findCookie уже знайомі. Вона призначена для одержання значення параметра cookie по його імені.

Після завершення завантаження документа HTML сценарій за допомогою цієї функції одержує поточне значення параметра cookie з ім'ям AgainCount, установлене програмою CGI:

var szMyText = "";

szMyText = findCookie("AgainCount");

Далі це значення добавляється до повного рядка cookie і відображається в многострочном полі редагування:

TestForm. Comment. value =

"Cookie: " + document. cookie + "\nAccess count: " + szMyText;

Форма, що містить поле редагування, визначена на початку що уставляється файла сценарію JavaScript.