Реализация маскирования

В описанном ниже упражнении вы реализуете простую библиотеку маскирования,
в виде класса SimpleCloak. Этот класс будет иметь две функции, к которым можно
обращаться из Web-приложений:
• updateAll () — обновляет базу данных маскирования на основе IP-адреса поискового механизма и данных пользовательского агента;
• ipSpider () — проверяет, является ли посетитель поисковым агентом.
Маскируемые данные выбираются с сайта Дэна Крамера (Dan Kramer) iplists. com.
Большое спасибо Дэну за предоставление всем желающим такого полезного набора данных!
Для проверки работы библиотеки SimpleCloak вы создадите сценарий с именем
cloakin.g_test.php, который будет выдавать данные, показанные на рис. 11.1, при
чтении "нормальным" посетителем и данные, приведенные на рис. 11.2, при чтении
поисковым механизмом.
Реализация маскирования
1. В данном примере используется библиотека cURL. Если вы подготовили Apache
и РНР к работе так, как было описано в главе 1, то cURL должна быть у вас
установлена и готова к работе, иначе она может быть неактивной. Чтобы активизировать c URL, откройте конфигурационный файл php. ini (находящийся в
каталоге \XAMPP\apache\bin, снимите комментарий со следующей строке, удалив
в ее начале точку с запятой, и затем перезапустив Apache:
extehsion=php_curl.dll
2. Теперь нужно подготовить таблицу базы данных simplecloack, которая будет
содержать IP-адреса поисковых механизмов. Проверьте, что СУБД MySQL настроена
так, как описано в главе 1. Затем откройте окно командной строки и
войдите в папку mysql\bin с помощью команды
cd \XAMPP\mysql\bin
3. Подключитесь к серверу MySQL с помощью команды
mysql -u seouser -р.
Маскирование, региональная привязка и подмена по IP 233
и при появлении запроса введите пароль seomaster. (Если при создании пользователя вы выбрали другой пароль, то введите его.)
Подключиться к серверу базы данных можно и с помощью других средств, а не только окна командной строки. Например, можно использовать средство phpMyAdmin, которое в стандартной инсталляции ХАМРР доступно по адресу http://localhost/phpmyadmin/.
Описанные ниже шаги не зависят от способа подключения к MySQL.
4. Введите команду подключения к базе данных seophp:
use seophp
5. Создайте таблицы cloakdata
и cloak_update, введя следующие команды
SQL:
CREATE TABLE * cloak_data " (
id " int(ll ) NOT NULL AUTO_INCREMENT,
"spider_name" VARCHAR(255) NOT NULL DEFAULT ' ' ,
record_type" ENUM (' UA' , 'IP') NOT NULL DEFAULT 'DA' ,
value" VARCHAR(255) NOT NULL DEFAULT ' ' ,
PRIMARY KEY (id),
KEY "value' ("value")
) ;
CREATE TABLE "cloak_update" (
version" VARCHAR(255) NOT NULL,
"updated_on" DATETIME NOT NULL
);
6. Введите команду exit, чтобы выйти из консоли MySQL. После выполнения всех
этих команд консоль должна иметь такой вид, как показано на рис. 11.3.
7. Добавьте в файл seophp/include/config.inc.php константы, выделенные затенением в приведенном ниже фрагменте. (Если вы не создали этот файл при
выполнении предыдущих упражнений, создайте его сейчас с указанным содержимым.)
<?php
// определение данных для подключения к базе
define("DB_HOST", "looalhost");
define("DB_USER", "seouser");
define("DB_PASSWORD", "seomaster");
define("DB_DATABASE", "seophp");
?>
8. Создайте в папке seophp/include новый файл с именем simple_cloak. inc.php
и поместите в него следующий код:
<?php
/*
// + +
// | SimpleCloak |
// | Класс для маскирования контента I
// | http://www.SEOEgghead.com |
// + .
+
// | Copyright (с) 2005-2006 Джейми Сирович и Кристиан Дейри |
//
+ +
// загрузка конфигурационного файла
require_once('config.inc.php1);
class SimpleCloak
{
// возвращает уровень доверия
function isSpider ($spider_name = '1, $check_uas = true, $check_ips = true)
{
//no умолчанию уровень доверия равен О
$confidence = 0;
// соответствует пользовательскому агенту?
if ($check_uas)

if (SimpleCloak: :_get(О, $spider_name, 'OA1, $_SEHVER['HTTP_USER_AGENT']))
$confidence += 2;

// соответствует IP?
if ($check_ips)
if (SinpleCloak: :_get(0, $spider_name, 'IP', ", $_SERVER[ 'REM0TE_ADDR' ]))
$confidence += 3;

// возврат уровня доверия
return $confidence;

}
// выборка маскируемых данных, отфильтрованных по переданным параметрам
function _get ($id = 0, $spider_name = ' ', $record_type = ' ',

$value = ' ' , $wildcard_value = ' ')

{

//no умолчанию выбираются все записи
$q = " SELECT cloak_data.* FROM cloak_data WHERE TRUE " ;

// добавление фильтров

if ($id) {
$id = (int) $id;
$q .= " AND id = $id ";

}
if ($spider_name) {
$ spider_name = mysql_escape_string($spider_name)
$q .= " AND spider_name = ' $spider_name' ";

}
if ($record_type) {
$record_type = mysql_escape_string($record_type) ;

$q .= " AND record_type = ' $record_type' ";

)

if ($value) {
$value = mysql_escape_string($value) ;
$q .= " AND value = '$value' ";

}

if ($wildcard_value) {
$wildcard_value = ioysql_eecape_etring($wildcard_value) ;
$q .= " AND '$wildcard_value' LIKE CONCAT(value, '%') ";

}

// Подключение к серверу MySQL
$dbLink = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD)
or die ("He удалось подключиться: " . mysql_error ()) ;

// Подключение к базе данных seophp
mysql_select_db (DB_DATABASE) or die ("He удалось выбрать базу данных") ;

// выполнение запроса
$tmp = mysql_query ($q) ;

// закрытие подключения к базе данных
mysql_close($dbLink);

// возврат результатов в ассоциативной массиве
$rows = array () ;
while ($_х = raysql_fetch_assoc($tirip)) {

$rows [] = $_х;
}
return $rows;

}

// обновление всей базы данных полученными от паука данными, но только если
// наши данные старте 7 дней и если изменилась онлайновая версия iplists.org
function updateAll ()
{

// Подключение к серверу MySQL
$dbLink = mysql_conneot(DB_HOST, DBJOSER, DB_PASSWORD)
or die ("He удалось подключиться: " . mysql_error ()) ;

// Подключение к базе данных seophp
mysql_select_db (DB_DATABASE) or die ("He удалось выбрать базу данных") ;

// выборка из базы данных информации последнего обновления
$q = "SELECT Cloak_update.* FROM cloak_update";
$tmp = mysql_query ($q) ;
$updated = mysql_fetch_assoc($tnrp) ;
$db_version = $updated[ 'version' ] ;
$updated_on = $updated [' updated_on' ] ;

// если последнее обновление свежее 7 дней, то обновление не выполняется
if (isset($updated_on) SS
(strtotiine($updated_on) > strtotime("-604800 seconds")))
// закрытие подключения к базе данных
mysql_close($dbLink);
// возврат false, означающий, что обновление не было выполнено
return false;

1 |
// чтение последней версии iplists
$version_url = 'http://www.iplists.com/nw/version.php';
$latest_version = mysql_escape_string(file_get_contents ($version_url)) ;

// если не выбрана информация об обновленной версии - прекращение работы
if (!$latest_version)
{

// возврат false, означающий, что обновление не было выполнено
return false;

}
// сохранение обновленных данных
$q = "DELETE FROM cloakjipdate"; ч
mysql_query($q);
$q = "INSERT INTO cloak_update (version, updated_on) " .
"VALUES('$latest_version', NOW())";
mysql_query($q) ;

// если текущие данные уже имеются, обновление не выполняется
if ($latest_version == $db_version)

{

// закрытие подключения к базе данных
mysql_close($dbLink);
// возврат false, означающий, что обновление не было выполнено
return false;

)

// обновление базы данных
SimpleCloak::_updateCloakingDB('google',
'http://www.iplists.com/nw/google.txt');
SimpleCloak::_updateCloakingDB('yahoo1,
'http://www.iplists.com/nw/inktomi.txt');
SimpleCloak::_updateCloakingDB('msn',
'http://www.iplists.com/nw/msn.txt');
SimpleCloak::_updateCloakingDB('ask',
'http://www.iplists.com/nw/askjeeves.txt');
SimpleCloak::_updateCloakingDB('altavista',
'http://www.iplists.com/nw/altavista.txt');
SimpleCloak::_updateCloakingDB('lycos',
'http://www.iplists.com/nw/lycos.txt');
SimpleCloak::_updateCloakingDB('wisenut',
1http://www.iplists.com/nw/wisenut.txt');

// закрытие подключения
mysql_close($dbLink); 4

// возврат true, означающий успешное обновление
return true;

}
// чтение предоставленного URL для обновления базы данных для указанного паука
function _updateCloakingDB($spider_name, $url,

$ua_regex = '/A#UA "(.*)"$/•', $ip_regex = '/A([0-9.]+)$/m')
{

• Маскирование, региональная привязка и подмена по IP
// использование cURL для чтения данных из $url
// ПРИМЕЧАНИЕ: для доступа к web через прокси нужны дополнительные параметры
$ch = curl_init() ;
curl_setopt ($ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_HEADER, 1) ;
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1) ;
curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, 1) ;
curl_setopt ($ch, CURLOPT_TJME0UT, 60) ;

n_url));

$result = curl_exec ($ch) ;
te работы curl_close(Sen);

// раэбор списка IP и пользовательских агентов с помощью _parseListURL
$lists = SimpleCloak::_parseListURL($result, $ua_regex, $ip_regex);

// если агенты и IP-адреса не выбраны, обновление отменяется
if (!$lists['ua_list'] || !$liets['ip_liet']) return;

// блокировка таблицы cloack_data, чтобы не было параллельных обращений
mysql_query (' LOCK TABLES cloak_data WRITE') ;

// удаление всех существующих данных для $ spider^name
SimpleCloak::_deleteSpiderData($spider_name);

// вставка списка пользовательских агентов для пауха
foreach ($lista['ua_liat' ] as $ua) {
SimpleCloak::_insertSpiderData($spider_name, 'OA', $ua) ;

}
// вставка списка IP для паука
foreach ($lists['ip_list'] as $ip) {

SimpleCloak::_insertSpiderOata($spider_name, 'IP', $ip) ;

}

// снятие блокировки таблицы
mysql_query (' UNLOCK TABLES') ;

}
// вспомогательная функция для разбора списков пользовательских агентов и IP
function _parseListURL($data, $ua_regex, $ip_regex)

{
$ua_list_ret = preg_match_all($ua_regex,, $data, $ua_list) ;
$ip_list_ret = preg_match_all ($ip_regex, $data, $ip_list) ;
return array ('ua_list' => $ua_list[l], 'ip_list' => $ip_list[l]) ;

}

// вставка в таблицу маскирования новой строки данных
function _insertSpiderData($spider_name, $record_type, $value)
{

// литерализация входных данных
$spider_name = mysql_escape_string($spider_name) ;
$record_type = mysql_escape_string($record_type) ;
Svalue = mysql_escape_string($value) ;

// составление и выполнение запроса INSERT
$q = "INSERT INTO cloak_data (spider_name, record_type, value)
"VALUES ('$spider_name', '$record_type', '$value')";
mysql_query($q);

)

// удаление данных маскирования для указанного паука
function _deleteSpiderData($spider_name)
// литерализация входных данных

$spider_name = rnysql_escape_string($spider_nama) ;

// составление и выполнение запроса DELETE
$q = "DELETE FROM cloak_data WHERE spider_name=' $apider_name' ";
mysql_query ($q) ;
}
}
?>

9.
Создайте в папке seophp файл с именем cloaking_prepare .php и поместите в
него приведенный ниже код. Этот сценарий лишь проверяет работоспособность
функции SimpleCloak: :updateAll (), которая обновляет базу данных свежими
данными.
<?php

// загрузка библиотеки SimpleCloak
require_once 'include/simple^cloak.inc.php';

// обновление маскирующих данных и сообщение об успешности выполнения
if (SimpleCloak::updateAll())
{

echo "Ваза данных маскирования обновлена!";

>

else
{

echo "В базе уже были свежие данные, либо не удалось выполнить
обновление.";
}

?>

10.
Загрузите страницу http: //seophp. example. com/cloaking_prepare. php. Если
все работает так, как надо, то будет выведено сообщение "База данных маскирования
обновлена!". А на каждый последующий запрос (пока не пройдет неделя)
будет появляться сообщение "В базе уже были свежие данные, либо не удалось
выполнить обновление".
11. Таблица simplecloak в базе данных seophp должна содержать данные о поисковых
механизмах. Для просмотра содержимого таблицы simple_cloak можно
использовать утилиту phpMyAdmin, которая поставляется вместе с ХАМРР.
Загрузите утилиту с помощью адреса http: //localhost/phpmyadmin/, выберите
в левой панели базу данных seophp и щелкните на кнопке Browse (Просмотр)
для таблицы cloak_data. Если все работает так, как надо, вы должны увидеть в
своей таблице список IP-адресов, как показано на рис. 11.4.
12. Теперь, для эффективного использования вашей библиотеки маскирования,
создайте в папке seophp новый файл с именем cloaking_test .php и введите в
него следующий код:
<?php

// загрузка библиотеки SimpleCloak
require_once 'include/simple_cloak.inc.php';

// Применение маскирования для вывода текста вместо изображений
if (SimpleCloak::isSpider() >= 3)
{
echo ' Твити и Сильвестр';
13.
Создайте в папке seophp папку images и скопируйте в нее изображение
tweety. jpg со страницы загрузки кода для данной книги.
14.
Загрузите страницу http: /./seophp. example . com/cloaking_test. php.
Поскольку вы — не поисковый механизм, вы увидите картинку с Твити и
Сильвестром, показанную на рис. 11.1.
15. Проще всего проверить, что будет при появлении поискового механизма — это
добавить ваш локальный IP-адрес в таблицу simple_cloak. Подключитесь к базе
данных seophp с помощью консоли MySQL или утилиты phpMyAdmin и выпол-'
ните следующий запрос:
INSERT INTO cloax_data (spider_name, record_type, value)

VALUES ('localteet', 'IP', '127.0.0.1');

16.
Снова загрузите страницу http: //seophp.example.com/cloaking_test.php.
На этот раз сценарий решит, что вы — поисковый механизм, и выведет вместо
картинки текст "Твити и Сильвестр", как показано на рис. 11.2.
Процесс реализации маскирования состоит из трех базовых шагов.

Вначале нужно подготовить базу данных маскирования и библиотеку маскирования.
Таблица cloakdata хранит сведения об IP-адресах и пользовательских агентах,
а таблица cloakupdate — о последнем обновлении в базе данных. В последней таблице
хранятся время и версия последнего обновления.
Класс SimpleCloak содержит два метода, которые можно использовать в программах:
updateAll() и isSpider().

Метод updateAll () выбирает данные с сайта www. iplists. com и сохраняет их в
локальной базе данных — но не чаще чем раз в неделю, и только в том случае, если
информация о версии, выбранная из www.iplists.com, отличается от хранимой в
таблице cloak_update.

На страницах, где нужно реализовать маскирование, применяется метод
SimpleCloak: :isSpider (), который возвращает положительное число, означающее
"доверие" тому, что запрос выполняется поисковым агентом. Доверие может иметь
одно из следующих значений:


0, если ни пользовательский агент, ни IP не соответствуют поисковому агенту;

2, если пользовательский агент — это поисковый агент;

3, если IP-адрес — адрес поискового агента; /

5, если и IP, и пользовательский агент соответствуют поисковому агенту.
В данном примере выполняется проверка, что значение больше или равно 3; это
гарантирует, что IP-адрес — это адрес поискового агента. Кроме того, обратите внимание,
что метод isSpider () может принимать несколько необязательных параметров,
которые позволяют проверить, что посетитель является конкретным поисковым
агентом, и/или проверять только пользовательский агент или IP-адрес.