Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Сценарии JavaScript в активных страницах Web

© Александр Фролов, Григорий Фролов
Том 34, М.: Диалог-МИФИ, 1998, 288 стр.

[Назад] [Содеожание] [Дальше]

Проверка заполнения формы

Для того чтобы сократить количество обращений к расширению сервера Web можно с помощью сценария JavaScript выполнить локальную проверку правильности заполнения формы. О том как проверить содержимое отдельных полей формы вы уже знаете из предыдущих разделов этой главы. Сейчас же мы остановимся на взаимодействии формы, сценария JavaScript и расширения сервера Web, такого как программа CGI или приложение ISAPI.

Если вы ранее занимались созданием расширений сервера Web, обрабатывающих данные, полученные от форм, то знаете, что для посылки данных расширению используется кнопка типа submit. Эта кнопка встраивается в форму следующим образом:


<INPUT TYPE="submit"
  NAME="Имя_кнопки_submit"
  VALUE="Текст_на_поверхности_кнопки"
  onClick="Обработчик_события">

Параметры NAME и VALUE здесь имеют такое же назначение, что и для изученной нами ранее кнопки типа button.

Обработчик события onClick позволяет сценарию JavaScript выполнить обработку содержимого полей формы, прежде чем данные из этих полей будут переданы расширению сервера Web.

К сожалению, вне зависимости от результатов обработки данные из формы всегда передаются серверу Web, что не всегда удобно. Было бы лучше, если бы сценарий JavaScript мог отказаться от посылки этих данных, если они введены пользователем с ошибкой.

Простейший выход из этой ситуации - замена кнопки типа submit на обычную кнопку button. С этой кнопкой должен быть связан сценарий JavaScript, который проверяет данные, введенные пользователем в поля формы, и посылающий их серверу Web явным образом.

В этом разделе мы приведем исходные тексты документа HTML, предназначенного для ввода идентификатора пользователя и пароля (листинг 3.7). Это документ аналогичен приведенному в предыдущем разделе. В нашем примере с помощью сценария JavaScript мы не только проверяем пароль, но и отправляем данные расширению сервера Web, если пароль введен правильно.

Листинг 3.7. Файл chapter3/validation/validation.html


<HTML>
  <HEAD>
    <TITLE>Ввод и проверка пароля</TITLE>
    <SCRIPT LANGUAGE="JavaScript">
    <!--
    function Complete()
    {
      if(Sel.pwd.value != Sel.pwd1.value)
        alert("Ошибка при вводе пароля\nПопробуйте еще раз");  
      else    
      {
        var szId="";
        var szPwd="";
        szId = Sel.id.value;
        szPwd = Sel.pwd.value;
        alert("Регистрация выполнена:\n" + "ID=" +
          szId + "\nPassword=" + szPwd);  
        
        document.forms[0].submit();
      }
    }
    // -->
    </SCRIPT>
  </HEAD>
  <BODY BGCOLOR=white>
    <H1>Регистрация</H1>

    <FORM METHOD=POST NAME="Sel" ACTION="http://frolov/scripts/controls.exe">
      <TABLE>
       <TR><TD><B>Идентификатор:</B></TD><TD><INPUT TYPE="text" 
        NAME="id" onChange="this.value=this.value.toUpperCase()"
        SIZE="20" ></TD></TR>

      <TR><TD><B>Пароль:</B></TD><TD><INPUT TYPE="password" 
        NAME="pwd" SIZE="20"></TD></TR>

      <TR><TD><B>Проверка пароля:</B></TD><TD><INPUT TYPE="password" 
        NAME="pwd1" SIZE="20"></TD></TR>
      </TABLE>
      <P>
      <TABLE>
        <TR><TD><INPUT TYPE="button" VALUE="Complete"
        onClick="Complete();"></TD>

        <TD><INPUT TYPE="reset" VALUE="Reset"></TD></TR>
      </TABLE>
    </FORM>
  </BODY>
</HTML>

При определении формы для оператора <FROM> мы указали параметр ACTION:


<FORM METHOD=POST NAME="Sel" ACTION="http://frolov/scripts/controls.exe">

Этот параметр задает путь к загрузочному файлу программы CGI, расположенному в каталоге сценариев сервера Web. Отметим, что такой каталог создается администратором сервера Web. С помощью специальной программы администратор указывает права доступа к этому каталогу, разрешающие исполнение расположенных там загрузочных файлов CGI и библиотек динамической компоновки DLL приложений ISAPI. Подробно об этом вы можете прочитать в 29 томе нашей “Библиотеки системного программиста”, который называется “Сервер Web своими руками”.

Функция Complete, которая вызывается при нажатии на одноименную кнопку, проверяет пароли, введенные в полях pwd и pwd1. Если эти пароли совпадают, сценарий посылает данные серверу с помощью метода submit, определенного в форме:


document.forms[0].submit();

Здесь мы обращаемся к первой (и единственной) форме, определенной в нашем документе HTML.

Программа CGI с именем control.exe отображает полученные данные в динамически создаваемом документе HTML (рис. 3.18).

Рис. 3.18. Данные, полученные программой CGI от формы

В списке значений полей, расположенным в нижней части этого документа, находится идентификатор и пароль пользователя.

Исходный текст программы CGI, с которой работает наш документ HTML, показан в листинге 3.8.

Листинг 3.8. Файл chapter3/validation/controls/controls.c


// ===============================================
// Программа CGI controls.c
// Получение данных от формы и их 
// отображение в документе HTML,
// создаваемом динамически
//
// (C) Фролов А.В., 1997, 1998
// 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 DecodeStr(char *szString);
char DecodeHex(char *str);

// ------------------------------------------------
// Функция main
// Точка входа программы CGI
// ------------------------------------------------
void main(int argc, char *argv[])
{
  int lSize;
  FILE * fileReceived;
  char * szMethod;
  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>User Registration"
    "</TITLE></HEAD><BODY BGCOLOR=#FFFFFF>");

  // Определяем метод передачи данных
  szMethod = getenv("REQUEST_METHOD");

  // Обработка метода POST
  if(!strcmp(szMethod, "POST"))
  {
    // Определяем размер данных, полученных от браузера
    // при передаче данных из полей формы
    lSize = atoi(getenv("CONTENT_LENGTH"));

    // Читаем эти данные в буфер szBuf из
    // стандартного потока ввода STDIN
    fread(szBuf, lSize, 1, stdin);

    // Создаем файл, в который будут записаны
    // принятые данные
    fileReceived = fopen("received.dat", "w");

    // Выполняем запись принятых данных
    fwrite(szBuf, lSize, 1, fileReceived);

    // Закрываем файл принятых данных
    fclose(fileReceived);

    // Отображаем значения некоторых переменных среды
    printf("<H2>Переменные среды</H2>");
    
    // Метод доступа
    printf("REQUEST_METHOD = %s", getenv("REQUEST_METHOD"));

    // Размер полученных данных в байтах
    printf("<BR>CONTENT_LENGTH = %ld", lSize);

    // Тип полученных данных
    printf("<BR>CONTENT_TYPE = %s", getenv("CONTENT_TYPE"));

    // Закрываем буфер данных двоичным нулем, 
    // превращая его таким образом в строку
    szBuf[lSize] = '\0';

    // Делаем копию принятых данных в буфер szSrcBuf
    strcpy(szSrcBuf, szBuf);

    // Отображаем принятые данные без обработки
    printf("<H2>Принятые данные</H2>");
    printf("<P>%s", szSrcBuf);

    // Выполняем перекодировку принятых данных
    DecodeStr(szSrcBuf);

    // Отображаем результат перекодировки
    printf("<H2>Данные после перекодировки</H2>");
    printf("<P>%s", szSrcBuf);

    // Выводим список значений полей формы
    printf("<H2>Список значений полей</H2>");
    
    // Дописываем в конец буфера принятых данных
    // символ "&", который используется в качестве
    // разделителя значений полей
    szBuf[lSize] = '&';
    szBuf[lSize + 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 + lSize))
          break;
      }
      else
        break;
    }
    
    // Выводим завершающий фрагмент документа HTML
    printf("</BODY></HTML>");
    return;
  }
}

// ------------------------------------------------
// Функция 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;
    
    // Обработка шестнадцатеричных кодов вида "%xx"
    if(ch == '%')
    {
      // Выполняем преобразование строки "%xx"
      // в код символа
      szString[dst] = DecodeHex(&szString[src + 1]);
      src += 2;
    }
  }
  
  // Закрываем строку двоичным нулем
  szString[dst] = '\0';
}

// ------------------------------------------------
// Функция DecodeHex
// Раскодирование строки "%xx"
// ------------------------------------------------
char DecodeHex(char *str)
{
  char ch;

  // Обрабатываем старший разряд
  if(str[0] >= 'A')
    ch = ((str[0] & 0xdf) - 'A') + 10;
  else
    ch = str[0] - '0';

  // Сдвигаем его влево на 4 бита
  ch <<= 4;

  // Обрабатываем младший разряд и складываем
  // его со старшим
  if(str[1] >= 'A')
    ch += ((str[1] & 0xdf) - 'A') + 10;
  else
    ch += str[1] - '0';

  // Возвращаем результат перекодировки
  return ch;
}

Это упрощенный вариант программы CGI, которую мы описали в упомянутом выше 29 томе “Библиотеки системного программиста”. Там вы найдете ее полное описание.

[Назад] [Содеожание] [Дальше]