// ===============================================
// Расширение CGI, предназначенное для
// работы с cookie
//
// (C) Фролов А.В., 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 03-May-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</TITLE></HEAD><BODY>");
      printf("<H2>Welcome to our page!</H2>");
    }

    else
    {
      // Получаем значение параметра cookie с именем AgainCount
      pszMyCookie = findCookie("AgainCount");

      if(pszMyCookie != NULL)
      {
        // Преобразуем это значение в число и увеличиваем 
        // на единицу при каждом посещении
        nCount = atoi(pszMyCookie);
        nCount++;
        sprintf(szBuf1, "%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",szBuf1);

        // Вставляем документ 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);
}