Команды Curl для HTTP
Curl также можно использовать c прокси-сервером. Если вы находитесь за прокси-сервером, прослушивающим порт 8090 на sampleproxy.com, загрузите файлы, как показано ниже:
curl -x sampleproxy.com:8090 -U username:password -O http:// testdomain.com/testfile.tar.gz
В приведённом выше примере вы можете выбросить -U username:password, если прокси-сервер не требует метода аутентификации.
Типичный HTTP-запрос всегда содержит заголовок. Заголовок HTTP отправляет дополнительную информацию об удалённом веб-сервере вместе с фактическим запросом. С помощью инструментов разработчика в браузере вы можете посмотреть сведения о заголовке, а проверить их можно с помощью команды curl.
Пример ниже демонстрирует, как получить информацию о заголовке с веб-сайта.
curl -I www.testdomain.com
Используя curl, вы можете сделать запрос GET и POST. Запрос GET будет выглядеть следующим образом:
curl http://mydomain.com
А вот пример запроса POST:
curl –data “text=Hello” https://myDomain.com/firstPage.jsp
Здесь text=Hello — это параметр запроса POST. Такое поведение похоже на HTML-формы.
Вы также можете указать несколько методов HTTP в одной команде curl. Сделайте это, используя опцию –next, например:
curl –data “text=Hello” https://myDomain.com/firstPage.jsp –next https://myDomain.com/displayResult.jsp
Команда содержит запрос POST, за которым следует запрос GET.
Каждый HTTP-запрос содержит агент пользователя, который отправляется как часть запроса. Он указывает информацию о браузере клиента. По умолчанию запрос содержит curl и номер версии в качестве информации об агенте пользователя. Пример вывода показан ниже:
“GET / HTTP/1.1” 200 “_” ”curl/7/29/0”
Вы можете изменить дефолтную информацию об агенте пользователя, используя следующую команду:
curl -I http://mydomain.com –-user-agent “My new Browser”
Теперь вывод будет выглядеть так:
“GET / HTTP/1.1” 200 “_” ”My new Browser”
Получить содержимое страницы (GET)
Самый простой и обычный HTTP-запрос — получить содержимое заданного URL. URL может ссылаться на веб-страницу, изображение или какой либо-другой файл. Клиент отсылает GET-запрос на сервер и получает запрашиваемый документ. Если выполнить команду
$ curl http://curl.haxx.se
вы получите веб-страницу, выведенную в окно терминала (точнее, в стандартный вывод). Чтобы сохранить эту страницу в файл , нужно указать
$ curl http://curl.haxx.se -o "curl.html"
Все HTTP-ответы содержат набор заголовков, которые обычно скрыты. Чтобы увидеть эти заголовки вместе с самим документом, используйте ключ .
Создание POST запроса на определённый URL
При формировании GET запроса передаваемые данные могут быть переданы на URL через “строку запроса”. Например, когда Вы делаете поиск в Google, критерий поиска располагаются в адресной строке нового URL:
http://www.google.com/search?q=ruseller
Для того чтобы сымитировать данный запрос, вам не нужно пользоваться средствами cURL. Если лень вас одолевает окончательно, воспользуйтесь функцией “file_get_contents()”, для того чтобы получить результат.
Но дело в том, что некоторые HTML-формы отправляют POST запросы. Данные этих форм транспортируются через тело HTTP запроса, а не как в предыдущем случае. Например, если вы заполнили форму на форуме и нажали на кнопку поиска, то скорее всего будет совершён POST запрос:
http://codeigniter.com/forums/do_search/
Мы можем написать PHP скрипт, который может сымитировать этот вид URL запроса. Сначала давайте создадим простой файл для принятия и отображения POST данных. Назовём его post_output.php:
print_r($_POST);
Затем мы создаем PHP скрипт, чтобы выполнить cURL запрос:
$url = "http://localhost/post_output.php"; $post_data = array ( "foo" => "bar", "query" => "Nettuts", "action" => "Submit" ); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // указываем, что у нас POST запрос curl_setopt($ch, CURLOPT_POST, 1); // добавляем переменные curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); $output = curl_exec($ch); curl_close($ch); echo $output;
При запуске данного скрипта вы должны получить подобный результат:
Таким образом, POST запрос был отправлен скрипту post_output.php, который в свою очередь, вывел суперглобальный массив $_POST, содержание которого мы получили при помощи cURL.
Проверьте, не работает ли веб-сайт
Мы все были там. Сайт, который вам абсолютно необходим, внезапно перестает работать. Тогда Facebook не загрузится. Столкнувшись с настоящей проблемой первого мира, что вы делаете?
Вы можете найти его в Google, попросить друга протестировать его для вас или использовать один из тех сайтов, обслуживающих один человек, которые сообщают вам, не работает ли веб-сайт. Или вы можете просто запустить терминал и запустить cURL:
Переключатель I в верхнем регистре (-I) проверяет заголовок HTTP веб-страницы, и добавляется опция -L (расположение), чтобы cURL следовал за перенаправлениями. Это означает, что вам не нужно вводить полный URL-адрес Facebook; просто напишите facebook.com, а cURL позаботится обо всем остальном благодаря -L. Если есть какие-либо перенаправления, они будут отображаться со своим собственным статусом HTTP.
Сообщение, которое нас интересует, это «200 OK», что означает, что с веб-сайтом все в порядке. Если это действительно не работает, вы увидите что-то вроде этого:
Коды состояния HTTP носят исключительно информационный характер, насколько позволяет ваше понимание. Этот метод не является полностью надежным, поскольку веб-сайт может возвращать код состояния, указывающий на успешно обработанный запрос, но он будет пустым, когда вы откроете его в браузере. Тем не менее, в большинстве случаев это должно соответствовать реальной ситуации, и дать вам знать, что вверх или вниз.
Ответ 3
Живой пример использования php curl_exec для создания HTTP-сообщения:
Поместите это в файл с именем foobar.php:
<?php
$ch = curl_init();
$skipper = «Какой-то поисковый запрос..»;
$fields = array( ‘penguins’=>$skipper, ‘bestpony’=>’rainbowdash’);
$postvars= »;
foreach($fields as $key=>$value) {
$postvars .= $key.»=».$value.»&»;
}
$url = «http://www.google.com»;
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST, 1);
curl_setopt($ch,CURLOPT_POSTFIELDS,$postvars);
curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT ,3);
curl_setopt($ch,CURLOPT_TIMEOUT, 20);
$response = curl_exec($ch);
print «curl ответ:».$response;
curl_close ($ch);
?>
Затем запустите его с помощью команды php foobar.php, скрипт выведет на экран следующее:
<!DOCTYPE HTML PUBLIC «-//W3C//DTD HTML 4.01//EN»
«http://www.w3.org/TR/html4/strict.dtd»>
<html>
<head>
<meta http-equiv=»Content-Type» content=»text/html; charset=utf-8″>
<title>Заголовок</title>
<meta http-equiv=»Pragma» content=»no-cache»>
<meta http-equiv=»Expires» content=»0″>
<body>
Некоторое содержимое…
</body>
</html>
Вы сделали PHP POST на www.google.com и отправили ему некоторые данные.
Загрузка файлов, используя HTTPie
Загрузить файл с сервера через HTTPie так же просто как вызвать команду . Чтобы скачать файл вам нужно указать параметр download перед URL.
В результате выполнения команды получим следующий результат:
HTTP/1.1 200 OK Accept-Ranges: bytes Access-Control-Allow-Headers: X-Requested-With Access-Control-Allow-Origin: * Content-Length: 3945951 Content-Type: application/pdf Date: Tue, 18 Oct 2016 04:01:43 GMT Etag: "3c35df-52fe21b892a6f" Last-Modified: Thu, 07 Apr 2016 09:57:34 GMT Server: ECS (pnq/AF9A) X-Cache: HIT Downloading 3.76 MB to "python_tutorial.pdf-1" | 28.03 % 1.05 MB 63.85 kB/s 0:00:43 ETA
Получение информации о запросе cUrl
Чтобы получить исчерпывающую информацию о самом запросе используется функция curl_getinfo(). Главным образом эта информация полезна для отладки работы скрипта, в котором выполняются cURL запросы.
curl_exec($ch); $info = curl_getinfo($ch); echo 'Запрос для url ' . $info . ' занял ' . $info . ' секунд ';
Функция возвращает данные в виде массива со следующими ключами:
- url
- content_type
- http_code
- header_size
- request_size
- filetime
- ssl_verify_result
- redirect_count
- total_time
- namelookup_time
- connect_time
- pretransfer_time
- size_upload
- size_download
- speed_download
- speed_upload
- download_content_length
- upload_content_length
- starttransfer_time
- redirect_time
Подключение библиотеки CURL в PHP
Для того чтобы использовать библиотеку CURL ее соответственно нужно подключить.
Примечание! В качестве примера мы будем использовать PHP 5.4.39 на Windows 7, а в качестве Web-сервера у нас будет выступать Apache 2.2.22.
Первое что нужно сделать, это скопировать библиотеки ssleay32.dll, libeay32.dll, libssh2.dll они расположены в директории с PHP, в системный каталог Windows, а именно в C:\Windows\System32.
Затем в php.ini подключить библиотеку php_curl.dll, т.е. раскомментировать следующую строку
Библиотека не подключена
;extension=php_curl.dll
Библиотека подключена
extension=php_curl.dll
Все, перезапускаем Apache, вызываем функцию phpinfo() и в случае успешного подключения у Вас должен появиться раздел curl
Если его нет, то это означает только одно, что библиотека не загрузилась, самая распространенная причина этого небыли скопированы вышеперечисленные DLL в системный каталог Windows.
Загрузка файла
Загрузка файла будет выглядеть практически так же, как и обычный POST запрос, так как все формы загрузки файла работают только с ним.
Сначала давайте создадим файл для того, чтобы сформировать его и отправить файлу upload_output.php:
print_r($_FILES);
А вот и код скрипта, который выполняет указанный выше функционал:
$url = "http://localhost/upload_output.php"; $post_data = array ( "foo" => "bar", // файл, который необходимо загрузить "upload" => "@C:/wamp/www/test.zip" ); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); $output = curl_exec($ch); curl_close($ch); echo $output;
Когда вы хотите загрузить файл, все, что вам нужно сделать, так это передать его как обычную post переменную, предварительно поместив перед ней символ @. При запуске написанного скрипта вы получите следующий результат:
Curl и FTP
Утилита поддерживает FTP! Вы можете использовать её для загрузки файлов с удалённого сервера.
curl -u username:password -O ftp://sampleftpserver/testfile.tar.gz
В приведённой выше команде ftp://sampleftpserver — это FTP-сервер, который принимает соединения. Вы можете не указывать имя пользователя и пароль для анонимных FTP-соединений. Введите команду и посмотрите, как заполняется индикатор выполнения.
Вы также можете загружать файлы с помощью этой команды:
curl -u username:password -T testfile.tar.gz ftp://sampleftpserver
Опять же таки, мы можем пропустить имя пользователя и пароль для анонимных FTP-соединений.
Начало работы с HTTPie
Для того чтобы начать работать с HTTPie на Ubuntu необходимо установить специальный пакет, используя apt-get.
После завершения процесса установки HTTPie будет доступен для запуска на вашей ОС. Для отправки GET запроса на любой сайт воспользуйтесь HTTPie командой:
Результат вышеуказанной команды вернёт нам следующий результат:
Похоже, что HTTPie действительно внедрён в нашу ОС. Если внимательно проанализировать результат, то можно понять, что запрашиваемый URL перенаправляет запрос на https://tutsplus.com. Подкорректируем наш GET запрос:
На этот раз результатом выполнения GET запроса будет HTML код запрашиваемого URL https://tutsplus.com.
Данный пример показывает нам, что для выполнения запроса достаточно будет указать только URL.
Какие версии HTTP поддерживает cURL. Как в cURL выбрать версию HTTP
Как уже было сказано, cURL поддерживает следующие версии HTTP: 0.9, 1.0, 1.1, 2 и 3.
Для их выбора используются следующие опции:
—http0.9
Рассмотрена чуть выше
-0, —http1.0
Указывает curl использовать HTTP версии 1.0 вместо внутренней предпочитаемой версии HTTP.
Этот параметр имеет приоритет над —http1.1 и —http2.
—http1.1
Указывает curl использовать HTTP версии 1.1.
Этот параметр имеет приоритет над -0, —http1.0 и —http2. Добавлено в версии 7.33.0.
—http2-prior-knowledge
Указывает curl выдавать HTTP-запросы, отличные от TLS, с использованием HTTP/2 без обновления HTTP/1.1. Требуется предварительное знание того, что сервер сразу поддерживает HTTP/2. Запросы HTTPS по-прежнему будут выполнять HTTP/2 стандартным способом с согласованной версией протокола в рукопожатии TLS.
—http2-prior-knowledge требует, чтобы базовая библиотека libcurl была собрана с поддержкой HTTP/2. Этот параметр переопределяет —http1.1 и -0, —http1.0 и —http2. Добавлено в версии 7.49.0.
—http2
Указывает curl использовать HTTP версии 2.
—http2 требует, чтобы базовая библиотека libcurl была собрана с поддержкой HTTP/2. Этот параметр переопределяет —http1.1 и -0, —http1.0 и —http2-prior-knowledge. Добавлено в версии 7.33.0.
—http3
ВНИМАНИЕ: это экспериментальная опция. Не использовать в производстве.. Указывает curl использовать HTTP версии 3 непосредственно для хоста и номера порта, используемого в URL-адресе
Обычная транзакция HTTP/3 будет выполнена на хосте, а затем будет перенаправлена через Alt-SVc, но эта опция позволяет пользователю обойти это, когда вы знаете, что цель говорит по HTTP/3 на данном хосте и порту.
Указывает curl использовать HTTP версии 3 непосредственно для хоста и номера порта, используемого в URL-адресе. Обычная транзакция HTTP/3 будет выполнена на хосте, а затем будет перенаправлена через Alt-SVc, но эта опция позволяет пользователю обойти это, когда вы знаете, что цель говорит по HTTP/3 на данном хосте и порту.
Эта опция приведёт к сбою curl, если соединение QUIC не может быть установлено, при её использовании утилита не может самостоятельно вернуться к более низкой версии HTTP.
—http3 требует, чтобы базовая библиотека libcurl была собрана с поддержкой HTTP/3. Этот параметр переопределяет —http1.1 и -0, —http1.0 и —http2 и —http2-prior-knowledge. Добавлено в 7.66.0.
Как разрешить ошибку «bash: wget: command not found»
Для того, чтобы решить ошибку «bash: wget: command not found», вам необходимо установить утилиту wget на сервере.
В Debian и Ubuntu:
root@ubuntu:~# apt-get install wget
Пример журнала установки:
root@ubuntu:~# apt-get install wget Reading package lists... Done Building dependency tree Reading state information... Done The following NEW packages will be installed: wget 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. Need to get 298 kB of archives. After this operation, 901 kB of additional disk space will be used. Get:1 http://ap-south-1.ec2.archive.ubuntu.com/ubuntu xenial-updates/main amd64 wget amd64 1.17.1-1ubuntu1.2 Fetched 298 kB in 0s (401 kB/s) Selecting previously unselected package wget. (Reading database ... 51222 files and directories currently installed.) Preparing to unpack .../wget_1.17.1-1ubuntu1.2_amd64.deb ... Unpacking wget (1.17.1-1ubuntu1.2) ... Processing triggers for install-info (6.1.0.dfsg.1-5) ... Processing triggers for man-db (2.7.5-1) ... Setting up wget (1.17.1-1ubuntu1.2) ...
На RHEL и Centos.
# yum install wget
Пример журнала установки:
# yum install wget Loaded plugins: amazon-id, rhui-lb, search-disabled-repos Resolving Dependencies --> Running transaction check ---> Package wget.x86_64 0:1.14-13.el7 will be installed --> Finished Dependency Resolution Dependencies Resolved ======================================================================================================================================================================== Package Arch Version Repository Size ======================================================================================================================================================================== Installing: wget x86_64 1.14-13.el7 rhui-REGION-rhel-server-releases 546 k Transaction Summary ======================================================================================================================================================================== Install 1 Package Total download size: 546 k Installed size: 2.0 M Is this ok [y/d/N]: y Downloading packages: wget-1.14-13.el7.x86_64.rpm | 546 kB 00:00:00 Running transaction check Running transaction test Transaction test succeeded Running transaction Installing : wget-1.14-13.el7.x86_64 1/1 Verifying : wget-1.14-13.el7.x86_64 1/1 Installed: wget.x86_64 0:1.14-13.el7 Complete! #
Как использовать wget для загрузки файлов через Интернет.
Синтаксис:
wget http://url/file or wget ftp://url/file
Примеры журнала загрузки:
# wget http://packages.sw.be/rpmforge-release/rpmforge-release-0.5.2-2.el6.rf.x86_64.rpm --2017-05-06 11:21:34-- http://packages.sw.be/rpmforge-release/rpmforge-release-0.5.2-2.el6.rf.x86_64.rpm Resolving packages.sw.be (packages.sw.be)... failed: Name or service not known. wget: unable to resolve host address ‘packages.sw.be’ # wget http://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-9.noarch.rpm --2017-05-06 11:21:34-- http://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-9.noarch.rpm Resolving dl.fedoraproject.org (dl.fedoraproject.org)... 209.132.181.24, 209.132.181.25, 209.132.181.23 Connecting to dl.fedoraproject.org (dl.fedoraproject.org)|209.132.181.24|:80... connected. HTTP request sent, awaiting response... 200 OK Length: 14704 (14K) [application/x-rpm] Saving to: ‘epel-release-7-9.noarch.rpm’ 100% 14,704 57.8KB/s in 0.2s 2017-05-06 11:21:34 (57.8 KB/s) - ‘epel-release-7-9.noarch.rpm’ saved [14704/14704]
В приведенном выше примере мы загрузили файл «rpmforge-релиз-0.5.2-2.el6.rf.x86_64.rpm» с адреса URL «packages.sw.be/rpmforge-release/rpmforge-release-0.5.2- 2.el6.rf.x86_64.rpm»с использованием протокола HTTP.
5 последних уроков рубрики «PHP»
Когда речь идёт о безопасности веб-сайта, то фраза «фильтруйте всё, экранируйте всё» всегда будет актуальна. Сегодня поговорим о фильтрации данных.
Обеспечение безопасности веб-сайта — это не только защита от SQL инъекций, но и протекция от межсайтового скриптинга (XSS), межсайтовой подделки запросов (CSRF) и от других видов атак
В частности, вам нужно очень осторожно подходить к формированию HTML, CSS и JavaScript кода.
Expressive 2 поддерживает возможность подключения других ZF компонент по специальной схеме. Не всем нравится данное решение
В этой статье мы расскажем как улучшили процесс подключение нескольких модулей.
Предположим, что вам необходимо отправить какую-то информацию в Google Analytics из серверного скрипта. Как это сделать. Ответ в этой заметке.
Подборка PHP песочниц
Подборка из нескольких видов PHP песочниц. На некоторых вы в режиме online сможете потестить свой код, но есть так же решения, которые можно внедрить на свой сайт.
Команда Curl для Работы с Файлами
Команды Curl могут загружать файлы из удалённой локации. Есть два способа это сделать:
- -O сохранит файл в текущем рабочем каталоге с тем же именем, что и у удалённого;
- -o позволяет указать другое имя файла или местоположение.
Вот пример:
curl -O http://testdomain.com/testfile.tar.gz
Приведённая выше команда сохранит файл как testfile.tar.gz.
curl -o newtestfile.tar.gz http://testdomain.com/testfile.tar.gz
А эта команда сохранит его как newtestfile.tar.gz.
Если по какой-либо причине загрузка будет прервана, вы можете возобновить её с помощью следующей команды:
curl -C – -O http://testdomain.com/testfile.tar.gz
Curl также позволяет загрузить несколько файлов одновременно. Пример:
curl -O http://testdomain.com/testfile.tar.gz -O http://mydomain.com/myfile.tar.gz
Если вы хотите загрузить несколько файлов с нескольких URL, перечислите их все в файле. Команды Curl могут быть объединены с xargs для загрузки различных URL-адресов.
Например, если у нас есть файл allUrls.txt, который содержит список всех URL-адресов для загрузки, то приведённый ниже пример выполнит загрузку всех файлов с этих URL.
xargs –n 1 curl -O < allUrls.txt
Cookies
С помощью cookies веб-браузеры контролируют состояние на стороне
клиента. Cookie — это имя с присоединенным содержимым. Сервер при
помощи отправки cookies сообщает клиенту путь и имя хоста, по
которому в следующий раз должны быть отправлены cookies, сообщает
время жизни cookies и некоторые другие параметры.
Когда клиент соединяется с сервером по адресу, указанному в
принятом cookie, клиент посылает этот cookie к серверу (если время
жизни не истекло).
Многие приложения и сервера используют этот метод, чтобы
объединить нескольких запросов в одну логическую сессию. Чтобы curl
также мог выполнять такую функцию, мы должны уметь сохранять и
отправлять cookies, как и делают браузеры.
Простейший способ отправить cookie к серверу при получении
страницы с помощью curl, это добавить соответствующий ключ в
командной строке:
# curl -b "name=Daniel" www.cookiesite.com
Cookies отправляются как обычные HTTP-заголовки. Это позволяет curl
сохранять cookies, сохраняя заголовки. Сохранение cookies с помощью
curl выполняется командой:
# curl -D headers_and_cookies www.cookiesite.com
(кстати, для сохранения cookies лучше использовать ключ -c, об этом
ниже).
У curl имеется полнофункциональный обработчик cookies, который
полезен, когда вы хотите соединиться в очередной раз к серверу и
использовать cookies, сохраненные в прошлый раз (либо подработанные
вручную). Для использования cookies, сохраненных в файле, вызовите
curl так:
# curl -b stored_cookies_in_file www.cookiesite.com
«Cookie-движок» curl включается, когда вы указываете ключ
-b. Если вы хотите, чтобы curl лишь воспринимал cookies, используйте
-b с указанием файла, которого не существует. Например, если вы
хотите, чтобы curl принял cookies со страницы, а затем пошел по
перенаправлению (возможно, отдав принятый только что cookie), то
можно вызывать curl так:
# curl -b nada -L www.cookiesite.com
Curl умеет читать и писать cookie-файлы, имеющие формат Netscape и
Mozilla. Это удобный способ обмениваться cookies между браузерами и
автоматическими скриптами. Ключ -b автоматически определяет, является
ли данный файл cookie-файлом указанных браузеров и обрабатывает его
соответствующим образом, а используя ключ -c/—cookie-jar, вы можете
заставить curl записать новый cookie-файл по завершении операции:
# curl -b cookies.txt -c newcookies.txt www.cookiesite.com
Настройка формата вывода результатов
Любой запрос повлечёт за собой вывод полного ответа в командную строку. HTTPie позволяет настроить формат вывода результатов. Вы можете вывести заголовки или тело ответа, воспользовавшись параметрами и .
После выполнения данной команды мы увидим только заголовки:
HTTP/1.1 301 Moved Permanently CF-RAY: 2f6669f88fc43548-LHR Connection: keep-alive Date: Sun, 23 Oct 2016 16:02:32 GMT Location: https://tutsplus.com/ Server: cloudflare-nginx Set-Cookie: __cfduid=dfea480f2567e7c463e66999adfdc73d71477238552; expires=Mon, 23-Oct-17 16:02:32 GMT; path=/; domain=.tutsplus.com; HttpOnly Transfer-Encoding: chunked
Если же выполнить HTTP запрос с параметром , то будет осуществлён вывод “тела” ответа.
Результат выполнения вышеуказанной команды:
<HTML> <HEAD> <meta http-equiv="content-type" content="text/html;charset=utf-8"> <TITLE>302 Moved</TITLE> </HEAD> <BODY> <H1>302 Moved</H1> The document has moved <A HREF="http://www.google.co.in/?gfe_rd=cr&ei=OBwQWPO7Juyq8wf13bzYBw">here</A>. </BODY> </HTML>