Анимация
JavaScript
|
Главная Библионтека Следует заметить очень важную деталь: то, что был использован метод post, вовсе не означает, что не был применен также и метод get. Иными словами, метод POST подразумевает также возможность передачи данных через URL-строку. Эти данные будут, как обычно, помещены в переменную окружения QUERY STRING. Но как же узнать, сколько именно данных переслал пользователь методом post? До каких пор нам читать входной поток? Для этого служит переменная окружения CONTENT LENGTH, в которой хранится строка с десятичным представлением числа переданных байтов данных (разумеется, перед использованием ее надо перевести в обычное число). Модифицируем предхдущий пример так, чтобы он принимал POST-данные, а также выводил и GET-информацию, если она задана: Листинг 3.3. Получение данных post #include <stdio.h> #include <stdlib.h> void main(void) { извлекаем значения переменн1х окружения char *RemoteAddr = getenv("REMOTE ADDR"); char *ContentLength = getenv("CONTENT LENGTH"); char *QueryString = getenv("QUERY STRING"); вгчисляем длину данн1х - переводим строку в число int NumBytes = atoi(ContentLength); в1деляем в свободной памяти буфер нужного размера char *Data = (char *)malloc(NumBytes + 1); читаем данные из стандартного потока ввода fread(Data, 1, NumBytes, stdin); добавляем нулевой код в конец строки (в Си нулевой код сигнализирует о конце строки) Data[NumBytes] = 0; Передача параметров методом POST В отличие от метода get, здесь параметры передаются сценарию не через переменные окружения, а через стандартный поток ввода (в Си он называется stdin). То есть программа должна работать так, будто никакого сервера не существует, а она читает данные, которые вводит пользователь с клавиатуры. (Конечно, на самом деле никакой клавиатуры нет и быть не может, а заправляет всем сервер, который "изображает из себя" клавиатуру.) выводим заголовок 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>"); Странслируем этот сценарий и запишем то, что получилось, под именем script.cgi в каталог, видимый извне как /cgi-bin/. Откроем в браузере следующий HTML-файл с формой: ! Листинг 3.4. POST-форма <html><body> <form action=/cgi-bin/script.cgi?param=value method=post> Name1: <input type=text name="name1"><br> Name2: <input type=text name="name2"><br> <input type=submit value="Запустить сценарий!"> </form> </body></html> Теперь, если набрать в полях ввода какой-нибудь текст и нажать кнопку, получим HTML-страницу, сгенерированную сценарием, например, следующего содержания: Здравствуйте. знаем о вас все! Ваш IP-адрес: 136.234.54.2 Количество байтов данных: 23 Вот параметры, которые Вы указали: name1=Vasya&name2=Petya А вот то, что мы получили через URL: param=value Как можно заметить, обработка метода post устроена сложнее, чем get. Тем не менее, метод POST используется чаще, особенно если нужно передавать большие объемы данных или "закачивать" файл на сервер (эта возможность также поддерживается протоколом HTTP и HTML). ( Замечание Мы не можем сначала все данные (например, полученные из стандартного потока ввода) декодировать, а уж потом работать с ними (в частности, разбивать по месту вхождения символов & и =). Действительно, вдруг после перекодировки появятся символы & и =, которые могут быть введены пользователем? Как мы тогда узнаем, разделяют ли они параметры или просто набраны с клавиатуры? Очевидно, никак. Поэтому такой способ нам не подходит, и придется работать с каждым значением отдельно, уже после разделения строки на части. Итак, приходим к следующему алгоритму: сначала разбиваем строку параметров на блоки (параметр=значение), затем из каждого блока выделяем имя параметра и его значение (обособленные символом =), а уж потом для них вызываем функцию перекодировки, приведенную ниже: \ Листинг 3.5. Функция URL-декодирования Функция преобразует строку данн1х st в нормальное представление. Результат помещается в ту же строку, что б1ла передана в параметрах. void UrlDecode(char *st) { char *p=st; указывает на текущий символ строки char hex[3]; временн1й буфер для хранения %XX int code; преобразованный код запускаем цикл, пока не кончится строка ( то есть, пока не появится символ с кодом 0, см. ниже) do { Если это %-код ... if(*st == %) { тогда копируем его во временный буфер hex[0]=*(++st); hex[1]=*(++st); hex[2]=0; Расшифровка URL-кодированных данных Если бы в предыдущем примере мы ввели параметры, содержащие, например, буквы кириллицы, то сценарию они бы поступили не в "нормальном" виде, а в URL-закодированном. Пожалуй, ни один сценарий не обходится без функции расшифровки URL-кодированных данных. И это совсем не удивительно. Радует только то, что такую функцию нужно написать один раз, а дальше можно пользоваться ей по мере необходимости. Как уже упоминалось, кодирование заключается в том, что некоторые неалфавитно-цифровые символы (в том числе и "русские" буквы, которые тоже считаются неалфавитными) преобразуются в форму %XX, где XX - код символа в шестнадцатеричной системе счисления. Далее представлена функция на Си, которая умеет декодировать подобные данные и приводить их к нормальному представлению. 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 |