Шестнадцатеричные символы создаются в том случае, когда пользователь вводит значения в свободные текстовые поля. Однако эти символы могут также являться частью выбранного текста меню. Для выполнения декодирования закодированной строки нужно выполнить следующее:

   • заменить все символы & символами перевода строки;

   • заменить все символы + пробелами;

   • заменить все символы = пробелами;

   • преобразовать все значения %xy в эквивалентные символы ASCII.

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

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

$ pg conv.cgi

#!/bin/sh

#сценарий conv.cgi

#декодирование строки URL

echo "Content‑type: text/html"

echo ""

echo "<HTML><PRE>"

#отображение метода кодированной строки

echo "Method : $REQUEST_METHOD"

echo "Query String : $QUERY_STRING"

echo "<HR>"

#применение редактора sed для замены символов & символами табуляции

LINE=`echo $QUERY_STRING | sed 's/&/ /g'`

for LOOP in $LINE do

# разбивка на поля NAME и TYPE

NAME=`echo $LOOP | sed 's/=/ /g' | awk '{print $1}'`

#получение TYPE, замена всех символов=пробелами, a %hex_num - \xhex_num

#замена всех символов + пробелами

TYPE=`echo $LOOP | sed 's/=/ /g' | awk '{print $2}' | \ sed -e 's/%\(\)/\\\x/g' | sed 's/+/ /g'`

#используется функция printf, которая отображает значения переменных:

#после завершения преобразований шестнадцатеричных значений

printf "${NAME}=${TYPE}\n"

#в переменную VARS записываются значения отдельных полей, которые затем

#передаются команде eval, благодаря чему отдельные поля можно адресовать;

#при этом, если поля содержат пробелы, требуется удвоенная обратная косая черта

VARS=`printf "${NAME}=\\${TYPE}\n"`

eval `printf $VARS`

done

echo "<HR>"

#используется printf для отображения специальных символов в случае их наличия

printf "Your name is : $contact\n"

printf "Your choice of film is : $film\n"

printf "Your choice of actor is : $actor\n"

printf "You watch films at the cinema : $view_cine\n"

printf "You watch films on video : $view_vid\n"

printf "And here are your comments : $textarea\n"

echo "</PRE>"

echo "</HTML>"

Нетрудно заметить, что в данном случае используется функция printf для вывода данных на экран. Причина этому весьма проста. Функция printf выполняет те же действия, что и обычная команда echo, но дополнительно выполняет шестнадцатеричные преобразования. В связи с этим следует сделать небольшое замечание. При использовании функции printf не происходит вставка символа новой строки; для устранения этого недостатка необходимо после каждой функции printf указать символы "\n", Шестнадцатеричные числа, хранящиеся в переменной QUERY_STRING, имеют формат %hex_num. Этот формат будет просто преобразован в формат \xhex_num с помощью потокового редактора sed, а также функции printf, выполняющей все необходимые преобразования. Зачем создавать себе дополнительные трудности, если для решения задачи существует простой способ?

Сохраните указанный выше сценарий под именем conv.cgi в каталоге cgi‑bin. Теперь осталось выполнить небольшое изменение в сценарии books.cgi, в результате чего форма будет вызывать сценарий conv.cgi вместо сценария books_result.cgi. Для этого следует воспользоваться следующей строкой:

<FORM action = "/cgi‑bin/conv.cgi" METHOD=GET>

Если теперь повторно передать форму (содержащую одну и ту же информацию), получим результаты, приведенные на рис. 29.10.

Теперь, когда строка имеет более удобочитаемый формат, можно выполнить некоторую обработку информации.

Метод get является стандартным методом, применяемым для работы с формами. В зависимости от имеющегося окружения, при использовании метода get существуют две потенциальные проблемы. Вся закодированная строка добавляется к адресу URL при отсылке информации, поэтому отсылаемая информация может быть просмотрена в окне URL, Хотя многие пользователи не видят в этом особой опасности, все же не стоит посылать информацию частного характера с помощью Web или сети.

Рис. 29.10. Полностью декодированные данные формы

Linux и UNIX: программирование в shell. Руководство разработчика _16.jpg

Если пользовательская форма включает множество полей ввода, длина переменной query_string может чрезмерно возрасти. В этом случае многие пользователи для работы с такими формами используют метод post. Этот метод подробно рассматривается в следующем разделе.

29.5.2. Метод post

Метод post, также как и метод get, предназначен для работы с закодированными строками. Разница заключается в способе получения данных: метод post считывает данные из стандартного потока. Для отсылки данных с помощью метода post просто замените ключевое слово get словом post в конструкции form action сценария.

<FORM action="/cgi‑bin/conv.cgi" METHOD=POST>

Переменная CONTENT_LENGTH будет хранить общее количество байтов, отосланных с применением метода post. Производится считывание строки из потока стандартного ввода, а затем выполняется то же самое преобразование, что и при использовании метода get. Процесс считывания завершается после того, как считанное количество байтов становится равным количеству байтов, хранящихся в переменной CONTENT_LENGTH.

После выполнения небольшого изменения в конструкции form action получится обобщенный декодер форм. Для осуществления считывания из стандартного потока ввода можно использовать команду cat. Ниже показана конструкция, которую следует добавить в сценарий conv.cgi, в результате чего появится возможность использования методов get и post.

if ["$REQUEST_METHOD"="POST"]; then

QUERY_STRING=`cat -`

fi

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

При использовании метода post осуществляется обычная проверка значения переменной QUERY_string. Затем все символы, поступающие из стандартного потока ввода, присваиваются переменной QUERY_STRING. В этой ситуации возможно использование метода get, поскольку в любом случае требуется получить информацию из переменной querY_string.

Замените строку form action в cgi–сценарии books.cgi:

<FORM action="/cgi‑bin/conv.cgi" METHOD=GET>

строкой

<FORM action ="/cgi‑bin/conv.cgi" METHOD=POST>

Кроме того, будут выполнены небольшие изменения в сценарии conv.cgi, благодаря чему можно будет проверять значения, введенные в текстовые поля, а также определять установленные флажки. Обновленный сценарий будет иметь следующий вид:

$ pg conv.cgi

#!/bin/sh

#conv.cgi

#декодирование строки URL

echo "Content‑type: text/html"

echo ""

echo "<HTML><PRE>"

# это post ???

if [ "$REQUEST_METHOD"="POST" ]; then

QUERY_STRING=`cat -`