Анимация
JavaScript


Главная  Библионтека 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [ 17 ] 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189

переводим его в число

sscanf(hex,"%X",&code);

и записываем обратно в строку

*p++=(char)code;

указатель p всегда отмечает то место в строке, в которое будет помещен очередной декодированный символ

иначе, если это "+", то заменяем его на " " else if(*st==+) *p++=

а если не то, ни другое - оставляем как есть else *p++=*st; } while(*st++!=0); пока не найдем нулевой код

Функция основана на том свойстве, что длина декодированных данных всегда меньше, чем кодированных, а значит, всегда можно поместить результат в ту же строку, не опасаясь ее переполнения. Конечно, примененный алгоритм далеко не оптимален, т. к. использует довольно медлительную функцию sscanf() для перекодирования каждого символа. Тем не менее, это самое простое, что можно придумать, вот почему я так и сделал.

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

i Листинг 3.6. Получение POST-данных с URL-декодированием

#include <stdio.h> #include <stdlib.h>

void main(void) {

получаем значения переменных окружения

char *RemoteAddr = getenv("REMOTE ADDR");

char *ContentLength = getenv("CONTENT LENGTH"); выделяем память для буфера QUERY STRING

char *QueryString = nialloc(strlen(getenv("QUERY STRING")) + 1); копируем QUERY STRING в созданный буфер

strcpy(QueryString, getenv("QUERY STRING")); декодируем QUERY STRING

UrlDecode(QueryString); вычисляем количество байтов данных - переводим строку в число

int NumBytes = atoi(ContentLength);



выделяем в свободной памяти буфер нужного размера

char *Data = (char*)malloc(NumBytes + 1); читаем данные из стандартного потока ввода

fread(Data, 1, NumBytes, stdin); добавляем нулевой код в конец строки ( в Си нулевой код сигнализирует о конце строки)

Data[NumBytes] = 0; декодируем данные ( хоть это и не совсем осмысленно, но выполняем сразу для всех POST-даннIх, не разбивая их на параметры)

UrlDecode(Data); выводим заголовок

printf("Content-type: text/html\n\n"); выводим документ

printf("<html><body>");

printf("<h1>Здравствуйте. знаем о Вас все!</h1>"); printf("Ваш IP-адрес: %s<br>",RemoteAddr); printf("Количество байтов данн1х: %d<br>", NumBytes); printf("Вот параметры, которые Вы указали: %s<br>",Data); printf("А вот то, что получили через URL: %s", QueryString);

printf("</body></html>");

Обратите внимание на строки, вхделенные жирным шрифтом. Теперь мы используем промежуточный буфер для хранения querystring. Зачем? Попробуем поставить все на место, т. е. не задействовать промежуточный буфер, а работать с переменной окружения напрямую, как это было в листинге 3.5. Тогда в одних операционных системах этот код будет работать прекрасно, а в других - генерировать ошибку общей защиты, что приведет к немедленному завершению работы сценария. В чем же дело? Очень просто: переменная QueryString ссылается на значение переменной окружения QUERY STRING, которая расположена в системной области памяти, а значит, доступна только для чтения. В то же время функция UrlDecode(), как я уже замечал, помещает результат своей работы в ту же область памяти, где находится ее параметр, что и вызывает ошибку.

Чтобы избавиться от указанного недостатка, мы и копируем значение переменной окружения QUERY STRING в область памяти, доступной сценарию для записи - например, в какой-нибудь буфер, а потом уже преобразовываем его. Что и было сделано в последнем сценарии.



Несколько однообразно и запутанно, не так ли? Да, пожалуй. Но, как говорится, "это даже хорошо, что пока нам плохо" - тем больше будет причин предпочитать PHP другим языкам программирования (так как в PHP эти проблемы изжиты как класс).

формы

До сих пор из всех полей формы мы рассматривали только текстовые поля и кнопки отправки (типа submit). Давайте теперь поглядим, в каком виде приходят данные и от других элементов формы (а их существует довольно много).

Все элементы формы по именам соответствующих им тэгов делятся на 3 категории:

□ <input... >

□ <textarea...>...</textarea>

□ <select...><option...>...</option>...</select>

Каждый из этих тэгов, конечно, может иметь имя. Ранее уже упоминалось, что пары имя=значение перед тем, как отправятся сценарию, будут разделены в строке параметров символом &. Кроме того, следует учитывать, что для тех компонентов формы, у тэгов которых не задан параметр name, соответствующая строка имя=значение передана не будет. Это ограничение введено для того, чтобы можно было в форме определять служебные элементы, которые не будут посылаться сценарию. Например, в их число входят кнопки (подтверждения отправки или обычные, используемые при программировании на JavaScript) и т. д. Так, создадим форму:

<form action=script.cgi>

... какие-то поля ...

<input type=submit value="Go!">

</form>

Несмотря на то, что кнопка Go! формально является полем ввода, ее данные не будут переданы сценарию, поскольку у нее отсутствует параметр name.

Чаще все же бывает удобно давать имена таким кнопкам. Например, для того, чтобы определить, каким образом был запущен сценарий - путем нажатия на кнопку или как-то еще (например, просто набором его URL в браузере). Создадим следующую форму:

<form action=script.cgi>

<input type=submit name="submit" value="Go!"> </form>

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



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [ 17 ] 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189