Материал из Wiki.
Курс расчитывается на абсолютных новичков в программировании на PHP.
Поэтому не стесняемся задавать вопросы. Я физически не смогу детально и
в подробностях разжевать ВСЕ ньюансы программирования спамилки, но я постараюсь вам дать точку
отсчета, используя которую действительно желающие научиться чемуто, смогут
получить базис и развить заложенные идей.
Тем-же кто расчитывает на то что найдетздесь open-source продвинутой спамилки
лучше сразу закрывать страницу этого топика.
В этом курсе я планирую рассмртреть вопросы и методы решения работы с cookies,
HTTPS, captcha , а также технику написания многопоточных приложений на PHP.
Итак приступим...
Для начала немного теории.
В самом начале освоения интернет-технологий для меня была проблема понимания
основ взяимодействия клиентской прграммы и сервера.
В основе любой спамилки лежит механизм позволяющий отсылать данные скрипту, находящемся
на каком-либо сервере. Откуда мы берем адреса этих скриптов - это отдельная тема Smile
В рамках данного краткогокурса будем считать что мы имеем некоторое количество
адресов, посылая на которые правильно сформированные пакеты данных мы добъемся
появления интересующих нас данных на каких-либо страницах в Интернете, где их (наши информационные
блоки со ссылками) может найти и проиндексироватьпоисковый робот.
Протокол HTTP предусматривает достаточно много способов взаимодействия клиента (браузера) и сервера.
Нас из всего многообразия сейчас интересуют два метода - GET и POST.
При использовании матода GET происходит передача данных посредством добавлкния их в строку
запроса адресованного серверу.
Плюсы: простота использования, наглядность, большая универсальность
Минусы: необходимость кодирования данных содержащих служебные символы ("'@:,.), если на сервере
или прокси-сервере ведется лог обращений,то все ваши запросы, вместе с параметрами будут в
них зафиксированы, ограничение на длинну передаваемых данных.
Пожалуй, самый используемый метод при передаче данных к скриту в интернете.
Данные передаются в телезапроса после всех служебных полей.
Данные тоже подлежат предварительному кодированию для корректной передачи серверу (исключение, если используется
способ передачи multipart-form, данные размещяются в запросе определенным образом, но сами массивы данных
никаким образом не транформируются. этот способ применяется очень часто для аплоада файлов на сервер).
Плюсы: удобство програмной реализации,данные не "светятся" влгах серверов
Минусы: меньшая наглядность, требует некоторых основных познаний в интернет-технологиях, встречались
проксики резавшие POST-пакеты.
Далее я привожу простой скрипт, на примере которого я объясню основы написания простой спамилки...
И каждый желающий сможет развить его по своему усмотрению.
Следующаяглава будет посвящена подробному разбору приведенного скрипта.
Code:
<?php
Error_Reporting(1+2+4);
$PostUrl="http://altagrup.ru/guestbook/write.php";
$PostData="nick=1@1.com&url=NoName&message=No+message";
$OkString="";
if (!empty($HTTP_GET_VARS)) extract($HTTP_GET_VARS);
if (!empty($HTTP_POST_VARS)) extract($HTTP_POST_VARS);
$Url=substr($PostUrl,strpos($PostUrl,"//")+2);
$Url=substr($Url,strpos($Url,"/"));
$HostName=substr($PostUrl,strpos($PostUrl,"//")+2);
$HostName=substr($HostName,0,strpos($HostName,"/"));
if(strpos($HostName,":"))
{
$HostPort=substr($HostName,strpos($HostName,":")+1);
if(!is_numeric($HostPort))
{
$HostPort=80;
}
}
else
{
$HostPort=80;
}
$fp=fsockopen($HostName, $HostPort, $errno, $errstr, 30);
if (!$fp)
{
echo "$errstr ($errno)<br />\n";
}
else
{
$out = "POST $Url HTTP/1.0\r\n";
$out .= "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/msword, */*\r\n";
$out .= "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.1.4322)\r\n";
$out .= "Accept-Encoding: gzip, deflate\r\n";
$out .= "Referer: $PostUrl\r\n";
$out .= "Host: $HostName\r\n";
$out .= "Content-type: application/x-www-form-urlencoded\r\n";
$out .= "Connection: Close\r\n";
$out .= "Content-length: ".strlen($PostData)."\r\n\r\n".$PostData;
stream_set_timeout($fp, 30);
fputs($fp, $out);
if(strlen($OkString))
{
$Page="";
while (!feof($fp))
{
$Page.=fgets($fp, 128);
}
if(strpos($Page,$OkString))
echo "Ok";
else
echo "Error";
}
else
{
if($errno===0)
echo "Ok";
else
echo "Error";
}
fclose($fp);
}
?>
Домашнее задание: просмотрите приведенный выше скрипт и постарайтесь сформулировать
возникшие вопросы. Не стесняйтесь высказывать свое мнение - этот топик для тех, кто ищет знания.
PS: Желание написать "Курсы молодого спам-программера" у меня возникло давно, но вот начать
все както не получалось, в итоге я пишу этот текст на кровати в 5-звездочном отеле в Анталии
на неудобной клавиатуре своего ноута вместо того чтобы пойти на анимациюSmile
Так что в нет выходить в ближайшие 2 недели каждый день может и не получиться,
но как минимум через день я буду заглядывать на форум,выкладывать продолжение курса и отвечать
на ваши вопросы. Спасибо за понимание.
Итак начнем разбор скрипта, приведенного в главе 1.
В этом скрипте собрано большинство механизмов, составляющих суть спамминга.
Начнем с азов. Чаще всего сервера конфигурируются таким образом, что фалы с расширением
- .PHP рассматриваются как исполняемые скрипты на языке PHP.
Заметьте - я сказал "чаще всего", а не "всегда". Дело в том,что сервер можно настроить
таким образом, чтобы любо удобное вам расширение служило признаком скрипта на PHP.
Причем это относится к любым видам расширений и серверных языков.
Но мы будем рассматривать классический случай.
Итак, просто дать файлу расширение PHP недостаточно для того, чтобы он начал выполнять какие-нибудь
нужные нам действия. Внутри файла должны быть размещены блоки кодов, которые , собственно,
и составляют суть программы.
Таких блоков кода может быть от 1 до практически бесконечности,в разумных пределах, конечно Smile
Такие участки кода заключаются между тегами <?php ?> .
Все что находится за пределами этихтегов будет просто выводиться клиенту как обычный
HTML.
Code:
<?php
Открыли секцию кода на языке PHP
Code:
Error_Reporting(1+2+4);
Включили вывод всех ошибок и предупреждений.
Дело в том, что в целях безопасности, на многих хостах вывод этих сообщений по умолчанию отключен.
И это правильно, но это очень сильно затрудняет отладку и диагностику скриптов.
Соответственно я порекомендую всем на этапе разработки скрипта вставлять эту строку,
а по завершении написаниязакомментировать или вообще удалить.
Code:
$PostUrl="http://example.com/post.php";
$PostData="Text=text&User=user";
$OkString="";
Инициализация переменных.
В принципе в переменные можно заносить какие угодно данные, но лучше если значения хотябы
отдаленно будут схожи со значениями, которые будут в них заноситься на этапе выполнения.
Во первых это повысит читабельность скрипта, во-вторых облегчит процесс отладки.
- $PostUrl - переменная содержит ПОЛНЫЙ URL к скрипту принимающему данные от скрипта
- $PostData - массив данных пересылаемых удаленному скрипту
- $OkString - переменная содержит строку, возвращаемую удаленным скриптом в случае удачного постинга.
К примеру некоторые гуестбуки любят писать "Thank you for posting" или чтото подобное. Тода мы присваиваем
этой переменной значение в виде этой строки и после постинга скрипт проверит наличие строки в
полученной странице. Если строка есть - постинг успешный, если нет - проблемы. Если эту переменную оставить
пустойто признаком успешности постинга служит нулевое состояние ошибки соединенияс сервером.
Code:
if (!empty($HTTP_GET_VARS)) extract($HTTP_GET_VARS);
if (!empty($HTTP_POST_VARS)) extract($HTTP_POST_VARS);
По документации PHP самдолжен создавать переменные с именем и значением взятыми из строки запроса
или из массива данных POST. На практике эе я достаточно часто встречал хосты, на которых
этого не происходило. Для решения этой проблемы и служат эти 2 строки.
Code:
$Url=substr($PostUrl,strpos($PostUrl,"//")+2);
$Url=substr($Url,0,strpos($Url,"/"));
А вот с этого места уже начинается плезная работа скрипта. Здесь мы выделяем из полного
URL ту составляющую,которая адресует нужный нам скрипт в рамках сервера.
Code:
$HostName=substr($PostUrl,strpos($PostUrl,"//")+2);
$HostName=substr($HostName,strpos($HostName,"/"));
Выделяем из полного URL имя сервера.
Code:
if(strpos($HostName,":"))
{
$HostPort=substr($HostName,strpos($HostName,":")+1);
if(!is_numeric($HostPort))
{
$HostPort=80;
}
}
else
{
$HostPort=80;
}
Большиство www-серверов работают на 80 порту. Хотя бывают и исключения - именно для нихэтот участок кода.
Если в адресе сервера есть ":" то после него должна следовать цифра, указывающая порт на котором работает сервер.
Если этого нет,значит сервер на стандартном порту 80.
Code:
$fp=fsockopen($HostName, $HostPort, $errno, $errstr, 30);
Устанавливаем соединение с сервером.
Адрес сервера в переменной $HostName, порт $HostPort.
Переменные $errno и $errstr предназначены для хранения сообщений об ошибках в
цифровом и текстовом виде соответственно.
30 - это значение таймаута, по истечении которого принимается решение что соединение установить невозможно.
Code:
if (!$fp)
{
echo "$errstr ($errno)<br />\n";
}
Если соединение прошло неуспешно, выводим сообщение об ошибке ставшей причиной проблемы.
Code:
else
{
$out = "POST $Url HTTP/1.1\r\n";
$out .= "Host: $HostName\r\n";
$out .= "Content-type: application/x-www-form-urlencoded\r\n";
$out .= "Connection: Close\r\n";
$out .= "Content-length: ".strlen($PostData)."\r\n\r\n".$PostData;
Если соединение прошло успешно, то формируем пакет запрса к серверу.
Code:
stream_set_timeout($fp, 30);
Выставляем таймау на операции с сервером. Если в течение заданного отрезка времени не происходит никакого обмена данными,
то считаем чо соединение подвисло и обрываем его.
Code:
if(strlen($OkString))
{
$Page="";
while (!feof($fp))
{
$Page.=fgets($fp, 128);
}
if(strpos($Page,$OkString))
echo "Ok";
else
echo "Error";
}
else
{
if($errno===0)
echo "Ok";
else
echo "Error";
}
Если переменная $OkString не пустая то получаем ответ сервера в переменную $Page и проверяем
на наличие в ней сигнальной строки.
Если же в $OkString пусто то принаем решение об успешности или неуспешности на основе
значения переменной $errno.
Code:
fclose($fp);
}
Закрываем соединение с сервером, если оно до сих пор открыто.
Code:
?>
Окончание блока кода
Вот разложенный по полочкам функционал скрипта из первой главы.
Домашнее задание: Напишите код странички HTML котрая-бы передавала этому скрипту данные
в формате, который он может правильно проинтерпретировать, обработать ну и соответственно запостить.
Теперь давайте рассмотрим подробнее пакеты,которые посылаются серверу.
Собственно говоря они и являются теми носителями, которые доставляют нашу
информацию серверу. Но кроме нашей информациив этих пакетах находится
еще много других данных. Некоторые из этих данных являются необходимыми, многие - желательными,
и еще больше - необязательные.
Собственно в таком порядке мы их и рассмотрим.
Необходимые:
GET /index.php HTTP/1.1
- если обращение к серверу идет с использованием метода GET то первая строка запроса должна выглядеть
примерно таким образом. Сначала идет метод (GET/POST) , а затем путь от корня сервера к файлу который запрашивается.
Собственно если после этой строки послать строку с заголовком Host, а потом пустую строку, то это и будет
минимальный запрос для корректной обработки сервером.
POST /index.php HTTP/1.1
- если при запросе необходимо передавать данные на сервер то обычно используется метод POST.
При использовании этого метода первая строка носит примерно такой вид, как приведено в примере.
Кроме того в отличие от метода GET при использовании этого метода необходимо вставлять в запрос еще
несколько полей:
Content-Type: application/x-www-form-urlencoded
- В поле Content-Type описывается способ, которым формируется пакет передаваемых на сервер данных.
Если пакет состоит только из текстов то обычно используется способ именуемый application/x-www-form-urlencoded
Если передаются винарные файлы (картинки, архивы и пр.) то используется multipart/form-data, в этом случае вормирование
пакета данных происходит совершенно иначе и это тема для отдельной главы.
Content-Length: 48
- В этом поле передается размер пакета данных в байтах.
Act=Generate&isForm=true&srcstr=11&isSymbols=Yes
- Собственно сам пакет данных. При использовании метода application/x-www-form-urlencoded он ваглядит подобным образом:
ИмяПараметра=ЗначениеПараметра
Между собой параметры разделяются знаком &
Host: host.com
- в этом поле содержиться информация о том, к какому серверу необходимо подключаться клиенту (браузеру, спамилке и т.д.)
Желательные:
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/msword, */*
- В этом поле перечисляются те типы данных, которые может корректно переварить клиент посылающий запрос.
В нашем случае, для большей правдоподобности, это поле следует заполнять примерно так, как приведено здесь - это часть типичного
запроса браузера FireFox.
Accept-Language: en-us,en;q=0.5
- Некоторые сервера могут по этой переменной определить наиболее приемлемый для вас язык и вернуть страницу на этом языке.
Опять же лучше подставлять данные наиболее похожие значения из вашего браузера.
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.1.4322)
- Это своеобразная "подпись" клиентской программы. Именно по этой строке чаще всего сервер
опознает тип вашего браузера. Вариантов этой строки может быть множество! Как и самих браузеров Smile
Здаесь приведен пример из моего IE 6.0
Необязательные.
Accept-Encoding: gzip, deflate
- Большинство современных браузеров поддерживают получение сжатых данных.
Именно о том, понимает ваш браузер такие данные или нет извещает эта строка.
gzip - сервер может вернуть сжатые данные
deflate - сервер должен паередавать данные без сжатия.
ВНИМАНИЕ! Если вы пошлете из вашей программы запрос с этим заголовком в таком виде как он приведен то
вполне вероятно вы можете получить в ответ страницу с полной белибердой в содержании.
Во избежание этого в спамилке рекомендую использовать этот параметр в следующем виде:
Accept-Encoding: deflate
Cookie: yandexuid=2656171181149295818; yabs-frequency=744497@20060603.1
- Те самые пресловутые куки. Собственноздесь все максимально наглядно...
Устанавливаются куки по параметрам в заголовке ответа сервера или из JS
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
- Кодировки в которых ваш браузер может корректно отобразить страницу пользователю
Собственно кромек перечисленных может быть еще великое множество параметров. Как стандартных, так и
экзотических - зависящих от конкретного браузера. Я же привел тот джентельменский набор, который просто необходимо
знать каждому спемерописателю Smile
А теперь время рассмотреть, чтоже нам может вернуть сервер в ответ на наши запросы.
В версии HTTP 1.0 сервер должен минимум ответить строкой статуса.
У этой строки есть точно оговоренный формат:
(Версия HTTP) (Код статуса) (Тема ответа)
дальше тело
Прмер:
Code:
HTTP/1.1 200 OK
HTTP/1.1 404 Not Found
Тема ответа - короткое текстовое описание кода статуса.
После этой строки могут следовать другие поля с разнообразной служебной информацией.
Далее привдиться перечень некоторых наиболее часто встечающихся полей.
Location - Определяет точный адрес ресурса, на который указывает URL. Это необходимо при использовании клиентом относительных ссылок.
Server - Это поле содержит информацию о сервере, который обрабатывает запрос.
WWW-Authenticate - Это поле служит для идентификации соединения если установлена авторизация на сервере.
Код статуса состоит из 3 цифр. Эти кода делятся на классы:
- 1xx зарезирвированные
- 2хх успешно
- 3хх перенаправление
- 4хх клиент ошибся
- 5хх ошибка сервера
- Вот важные:
- 200 OK
- 201 POST выполнен
- 202 Запрос принят
- 203 GET выполнен
- 204 Запрос выполнен, но нет содержимого
- 300 Ресурс обнаружен в нескольких местах
- 301 Ресурс удален навсегда
- 302 Ресурс отсутствует временно
- 304 Ресурс изменен
- 400 Плохой запрос клиента
- 401 Неавторизированный запрос
- 402 Необходима оплата за запрос
- 403 Доступ к ресурсу завпрешен
- 404 Ресурс не найден
- 405 Метод не применим
- 406 Недопустимый тип
- 410 Ресурс недоступен
- 500 Ошибка сервера
- 501 Метод не выполнен
- 502 Сервер перегружен
Кроме того важно - каждая строка в ответе сервера должна заканчиваться кодами ПЕРЕВОД КАРКТКИ+ПЕРЕВОД СТРОКИ
В шестнадцатеричном виде это кода (0x0DOA)
А вот насчет куков отдельный разговор. Наткнулся я на статью по этой теме и понял что я не напишу лучше чем написано там.
Так что далее приводится статья взятая отсюда http://www.citforum.ru/internet/html/cookie.shtml как есть.
Что такое cookies и как с ними работать
Откуда возник термин "cookie" никто достоверно не знает, хотя считается, что во времена зарождения где-то использовалось словосочетание Magic Cookies. Имелись в виду "квитанции" (token, ticket), которыми обменивались программы.
Cookie является решением одной из наследственных проблем HTTP протокола (HyperText Transfer Protocol). Эта проблема заключается в непостоянстве соединения между клиентом и сервером, как при FTP или Telnet сессии, т.е. для каждого документа (или файла) при передаче по HTTP протоколу посылается отдельный запрос. Включение cookie в HTTP протокол дало частичное решение этой проблемы. Иначе говоря, транзакция завершается после того, как браузер сделал запрос, а сервер выдал соответствующий ответ. Сразу после этого сервер "забывает" о пользователе и каждый следующий запрос того же пользователя считает новым пользователем.
Используя cookie, можно эмулировать сессию по HTTP протоколу. Коротко принцип эмуляции сессии таков: на первом запросе выдается соотвествующее значение cookie, а при каждом последующем запросе это значение читается из переменной окружения HTTP_COOKIE и соответствующим образом обрабатывается.
Простой пример: есть форма, где пользователю предлагается указать свое имя, из нее вызывается скрипт, прописывающий значение cookie в браузер пользователя. При каждом последующем заходе на основе анализа значения cookie из браузера пользователя на странице появляется либо именное приветствие (если есть установленное значение cookie), либо первоначальная форма с запросом имени пользователя (если значение cookie не установлено).
Cookie - это небольшая порция текстовой информации, которую сервер передает браузеру. Браузер будет хранить эту информацию и передавать ее серверу с каждым запросом как часть HTTP заголовка. Одни значения cookie могут храниться только в течение одной сессии, они удаляются после закрытия броузера. Другие, установленные на некоторый период времени, записываются в файл. Обычно этот файл называется 'cookies.txt' и лежит в рабочей директории установленного на компьютер браузера. У меня, к примеру, в этом файле содержится следующее:
Code:
# Netscape HTTP Cookie File
# http://www.netscape.com/newsref/std/cookie_spec.html
# This is a generated file! Do not edit.
www.webclub.ru FALSE /ourweb FALSE 946683907 1 1
.bizlink.ru TRUE / FALSE 915148488 u_irads_watch 627633
.doubleclick.net TRUE / FALSE 1920499140 id 332666ae
.yahoo.com TRUE / FALSE 915144943 Y v=1&n=6jm0u5lgubh1k&l=0b8a0d3h/o&p=m29vvru7130a
.yahoo.com TRUE / FALSE 915144943 T z=3587c277
mail.yahoo.com TRUE / FALSE 943919791 YM.Login
id%3d%241%24rm%24L6MDTCsrCNnk3syLZl2zo.%26sid%3dszxPh4SazGg/%250a%26ts%3dX%2588%25c3%2506%25d3%25e5I-%255d%253f%2597%25ddu
.preferences.com TRUE / FALSE 1182140165 PreferencesID 3AGN9WD1D80gQfjvjAxRuq
.geocities.com TRUE / FALSE 900743217 iTag gY6bZzWItDQAAWll3T8ASk1vbiwgMTMg
search.netscape.com FALSE / FALSE 942189477 NGUserID cfc84d2a-522-898178454-1
www.webclub.ru FALSE FALSE 913543999 visited yes
Как видно, у меня оставили cookie Российский клуб вебмастеров, поисковая система AltaVista, бесплатный почтовый сервер Yahoo, Netscape Communications, рекламные сети DoubleClick и отечественная InterReklama.
В настоящее время большинство браузеров поддерживает механизм cookies. Я точно знаю, что cookie можно использовать во всех версиях Netscape Navigator, Microsoft Internet Explorer и NCSA Mosaic.
Что можно делать с помощью cookie?
Сами по себе cookies не могут делать ничего, это только лишь некоторая текстовая информация. Однако сервер может считывать содержащуюся в cookies информацию и на основании ее анализа совершать те или иные действия. Например, в случае авторизованного доступа к чему либо через WWW в cookies сохраняется login и password в течение сессии, что позволяет пользователю не вводить их снова при запросах каждого документа, защищенного паролем.
На использовании cookies также часто строят функции оформления заказов в онлайновых магазинах, в частности, в самом крупном виртуальном книжном магазине Amazon Books реализована своеобразная виртуальная корзина покупателя, как в обычном реальном супермаркете, в которую сервер записывает информацию обо всех заказанных книгах. Пользователь просто помечает интересующие его книги, а затем оформляет покупку сразу всех отмеченных книг.
Еще одна распространенная область использования cookies - при настройке индивидуального профиля каждого зарегистрированного пользователя.
И, наконец, самая последняя область - использование механизма cookie в рекламном бизнесе на Интернет. Еще год назад реклама в Интернет за деньги была довольно экзотической услугой, а сейчас этот бизнес уже устоялся и стремительно развивается. Однако рекламодатели начинают предъявлять более жесткие условия к оценке эффективности своих расходов. Cookie используются для таргетинга рекламы (определения целевой аудитории, например, по географическому положению пользователей), отслеживания интересов пользователей, учета количества показов и проходов сквозь баннеры.
Работа с cookie
Теперь, когда с принципами действия и областями применения cookie все более или менее понятно, можно приступить к изучению формата и синтаксиса, а также способов задания значений cookie.
Формат и синтаксис cookie
Предлагаемое мной в этой статье описание формата и синтаксиса cookie является вольным пересказом изначальной спецификации Netscape Communications "Persistent Client State HTTP Cookies". В настоящий момент идет разработка более строгой спецификации для cookie. Итак, cookie является частью HTTP заголовка. Полное описание поля Set-Cookie HTTP заголовка:
Code:
Set-Cookie: NAME=VALUE; expires=DATE; path=PATH; domain=DOMAIN_NAME; secure
<\pre>
Минимальное описание поля Set-Cookie HTTP заголовка:
<pre>
Code:
Set-Cookie: NAME=VALUE;
NAME=VALUE - строка символов, исключая перевод строки, запятые и пробелы. NAME-имя cookie, VALUE - значение. Не допускается использование двоеточия, запятой и пробела.
expires=DATE - время хранения cookie, т.е. вместо DATE должна стоять дата в формате "expires=Monday, DD-Mon-YYYY HH:MM:SS GMT", после которой истекает время хранения cookie. Если этот атрибут не указан, то cookie хранится в течение одного сеанса, до закрытия броузера.
domain=DOMAIN_NAME - домен, для которого значение cookie действительно. Например, "domain=cit-forum.com". В этом случае значение cookie будет действительно и для домена cit-forum.com, и для www.cit-forum.com. Но не радуйтесь, указания двух последних периодов доменных имен хватает только для доменов иерархии "COM", "EDU", "NET", "ORG", "GOV", "MIL" и "INT". Для обсуждаемых сейчас новых семи доменов первого уровня ("FIRM", "SHOP", "WEB", "ARTS", "REC", "INFO", "NOM"), вероятно, это условие сохранится. Для доменов иерархии "RU", например, придется указывать три периода.Если этот атрибут опущен, то по умолчанию используется доменное имя сервера, на котором было задано значение cookie.
path=PATH - этот атрибут устанавливает подмножество документов, для которых действительно значение cookie. Например, указание "path=/win" приведет к тому, что значение cookie будет действительно для множества документов в директории /win/, в директории /wings/ и файлов в текущей директории с именами типа wind.html и windows.shtml. Для того, чтобы cookie отсылались при каждом запросе к серверу, необходимо указать корневой каталог сервера, например, "path=/".Если этот атрибут не указан, то значение cookie распространяется только на документы в той же директории, что и документ, в котором было установлено значение cookie.
secure - если стоит этот маркер, то информация cookie пересылается только через HTTPS (HTTP с использованием SSL - Secure Socket Level), в защищенном режиме. Если этот маркер не указан, то информация пересылается обычным способом.
Синтаксис HTTP заголовка для поля Cookie
Когда запрашивается документ с HTTP сервера, браузер проверяет свои cookie на предмет соответствия домену сервера и прочей информации. В случае, если найдены удовлетворяющие всем условиям значения cookie, броузер посылает их в серверу в виде пары имя/значение:
Code:
Cookie: NAME1=OPAQUE_STRING1; NAME2=OPAQUE_STRING2 ...
Дополнительные сведения
Одновременно можно задавать несколько значений cookie.
В случае, если cookie принимает новое значение при имеющемся уже в браузере cookie с совпадающими параметрами NAME, domain и path, то старое значение заменяется новым. В остальных случаях новые значения cookie добавляются к старым.
Использование expires не гарантирует сохранность cookie в течение заданного периода времени, поскольку клиент (браузер) может удалить запись из-за нехватки выделенного места или каких-либо других причин.
Клиент (браузер) имеет следующие ограничения для cookies:
- всего может храниться до 300 значений cookies
- каждый cookie не может превышать 4Кбайт
- с одного сервера или домена может храниться до 20 значений cookie
Если ограничение 300 или 20 превышается, то удаляется первая по времени запись. При превышении лимита объема в 4Кбайт корректность значения cookie страдает - отрезается кусок записи (с начала этой записи) равный превышению объема.
В случае кэширования документов, например, proxy-сервером, поле Set-cookie HTTP заголовка никогда не кэшируется.
Если proxy-сервер принимает ответ, содержащий поле Set-cookie в заголовке, предполагается, что поле доходит до клиента вне зависимости от кода возврата 304 (Not Modified) или 200 (OK). Соответственно, если клиентский запрос содержит в заголовке Cookie, то он должен дойти до сервера, даже если жестко установлен параметр If-modified-since.
Ниже приведено несколько примеров, иллюстрирующих использование cookies
Пример 1. Управление подмножеством документов, для которых действительны значения cookie, и их сроком годности
Браузер запрашивает документ и принимает от сервера в ответ:
Code:
Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/; expires=Wednesday, 09-Nov-99 23:12:40 GMT
Когда браузер запрашивает URL с путем "/" на этом сервере, он посылает серверу:
Code:
Cookie: CUSTOMER=WILE_E_COYOTE
Браузер запрашивает документ и принимает от сервера в ответ:
Code:
Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/
Когда браузер запрашивает URL с путем "/" на этом сервере, он посылает серверу уже два значения cookie:
Code:
Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001
Сервер установил еще одно значение cookie, на этот раз с другой областью действия:
Code:
Set-Cookie: SHIPPING=FEDEX; path=/foo
Теперь браузер, запрашивая URL с путем "/" на этом сервере, посылает лишь два значения cookie:
Code:
Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001
и лишь при запросе браузером документов с путем "/foo" на этом сервере посылаются все три значения cookie:
Code:
Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001; SHIPPING=FEDEX
Комментарий: после закрытия браузера в файле 'cookies.txt' останется только одно значение cookie:
Code:
CUSTOMER=WILE_E_COYOTE
поскольку только для него установлен срок годности - 9 ноября 1999 года. Все остальные значения не будут сохранены.
Пример 2. Значения cookie с одинаковыми именами, но разными параметрами
Браузер запрашивает документ и принимает ответ от сервера:
Code:
Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/
Когда браузер запрашивает URL с путем "/" на этом сервере, он посылает значение:
Code:
Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001
Во второй раз, запрашивая документ, браузер принимает от сервера значение cookie с другой областью действия:
Code:
Set-Cookie: PART_NUMBER=RIDING_ROCKET_0023; path=/ammo
Когда браузер запрашивает URL с путем "/ammo" на этом сервере, он посылает значение:
Cookie: PART_NUMBER=RIDING_ROCKET_0023; PART_NUMBER=ROCKET_LAUNCHER_0001
Комментарий: здесь мы имеем две пары имя/значение с одинаковым именем "PART_NUMBER". При закрытии браузера ни одно из этих значений не сохранится, поскольку не задан параметр expires.
Способы задания значений cookie
Способ задания значений cookie зависит того, как эти значения будут использоваться и какие имеются серверные ресурсы. Можно манипулировать временем жизни выставленных cookie и устанавливать подмножества URL (Universal Resource Locator), в которых заданные значения действительны. Есть несколько способов задания, наиболее часто используются три - через META-таги языка HTML, JavaScript и CGI-скрипты. Любым способом можно задавать как одно, так и несколько значений сразу. Сразу хочу предупредить - не забывайте об ограничениях по объему и количеству значений cookie, а также параметре domain, так как помимо основного доменного имени узла часто бывает несколько алиасов (alias).
[править] 1. Задание cookie с помощью META-тагов
Простейший способ выставить cookie - использовать соответствующий META-таг в контейнере <HEAD>...</HEAD> любого статического HTML документа. В общем случае это выглядит следующим образом:
Code:
<META HTTP-EQUIV="Set-Cookie" CONTENT="NAME=value; EXPIRES=date; DOMAIN=domain_name; PATH=path; SECURE">
Такой способ задания cookie, на мой взгляд, наиболее интересен для создателей маленьких домашних страничек, когда нет возможности писать свои собственные CGI-скрипты. А если есть поддержка SSI (Server Side Include) или PHP/Fi, то можно делать интерактивные страницы вообще без использования внешних CGI-скриптов. При наличии SSI на узле создание интерактивности с использованием механизма cookie становится просто удовольствием.
С помощью <META HTTP-EQUIV="Set-Cookie" CONTENT="..."> cookie задается на любой статичной странице, директивой можно потом считать любые переменные окружения, в том числе и ранее заданные значения cookie (переменная HTTP_COOKIE), а с помощью конструкций , и задавать различные варианты внешнего вида страниц. Так же просто можно проделывать подобные вещи, используя PHP/Fi.
Если же ни SSI, ни PHP/Fi недоступен, то можно задавать значение cookie, используя JavaScript.
[править] 2. Задание cookie с помощью JavaScript
Можно задавать значение cookie, используя язык JavaScript. Единственный недостаток этого способа заключается в том, что не все браузеры его поддерживают. Ниже приведены примеры функций JavaScript, написанные Алексеем Александровым для скрипта "Органайзер". Этот скрипт, по-моему, один из лучших образцов программирования на JavaScript с использованием cookie, поэтому я настоятельно рекомендую посмотреть на работающий образец по адресу http://www.citforum.ru/internet/javascript/exorg.shtml
Пример 3. Функция установки значения cookie
Code:
// name - имя cookie
// value - значение cookie
// [expires] - дата окончания действия cookie (по умолчанию - до конца сессии)
// [path] - путь, для которого cookie действительно (по умолчанию - документ, в котором значение было установлено)
// [domain] - домен, для которого cookie действительно (по умолчанию - домен, в котором значение было установлено)
// [secure] - логическое значение, показывающее требуется ли защищенная передача значения cookie
function setCookie(name, value, expires, path, domain, secure) {
var curCookie = name + "=" + escape(value) +
((expires) ? "; expires=" + expires.toGMTString() : "") +
((path) ? "; path=" + path : "") +
((domain) ? "; domain=" + domain : "") +
((secure) ? "; secure" : "")
if (!caution || (name + "=" + escape(value)).length <= 4000)
document.cookie = curCookie
else
if (confirm("Cookie превышает 4KB и будет вырезан !"))
document.cookie = curCookie
}
<pre>
Пример 4. Функция чтения значения cookie
Возвращает установленное значение или пустую строку, если cookie не существует.
<pre>
Code:
// name - имя считываемого cookie
function getCookie(name) {
var prefix = name + "="
var cookieStartIndex = document.cookie.indexOf(prefix)
if (cookieStartIndex == -1)
return null
var cookieEndIndex = document.cookie.indexOf(";", cookieStartIndex + prefix.length)
if (cookieEndIndex == -1)
cookieEndIndex = document.cookie.length
return unescape(document.cookie.substring(cookieStartIndex + prefix.length, cookieEndIndex))
}
Пример 5. Функция удаления значения cookie
Принцип работы этой функции заключается в том, что cookie устанавливается с заведомо устаревшим параметром expires, в данном случае 1 января 1970 года.
Code:
// name - имя cookie
// [path] - путь, для которого cookie действительно
// [domain] - домен, для которого cookie действительно
function deleteCookie(name, path, domain) {
if (getCookie(name)) {
document.cookie = name + "=" +
((path) ? "; path=" + path : "") +
((domain) ? "; domain=" + domain : "") +
"; expires=Thu, 01-Jan-70 00:00:01 GMT"
}
[править] 3. Задание cookie с помощью CGI-скриптов
Самый мощный и гибкий способ управления документами с использованием механизма cookie - с помощью CGI-скриптов. Задание значения cookie на Perl будет выглядеть следующим образом:
Code:
print "Content-type: text/html\n";
print "Set-Cookie: username=aaa13; expires=Friday, 31-Dec-99 23:59:59 GMT; path=/; domain=www.citforum.ru;\n\n";
Скрипт при выдаче результатов работы генерирует HTTP заголовок:
Code:
Content-type: text/html
Set-Cookie: "username=aaa13; expires=Friday, 31-Dec-99 23:59:59 GMT; path=/; domain=www.citforum.ru;"
Чтобы прочитать в скрипте ранее заданное значение cookie, используется переменная окружения HTTP_COOKIE.
Code:
$cookie = $ENV{'HTTP_COOKIE'};
Далее можно анализировать полученную строку и, в зависимости от считанных значений, выполнять соответствующие действия.
Совсем недавно я написал систему рейтинга серверов для Российского Клуба Вебмастеров, которая использует механизм cookie для защиты от накрутки очков. В ней, задавая и анализируя значения cookie, я либо не допускаю пользователя до голосования (если отключены cookie в браузере или пользователь один раз уже проголосовал), либо разрешаю голосовать (если соответствующее значение не задано). Обмануть такую систему можно, только стирая каждый раз файл cookies.txt. Можно было бы использовать файл логов голосования на узле, но возникали бы проблемы разделения доступа к файлу и замедление работы вследствие использования медленных дисковых операций.
Немного о проблемах, связанных с использованием cookie
Главной проблемой является изначальное недоверие пользователей к тому, что удаленные сервера без их (пользователей) ведома и согласия записывают на их собственные локальные диски какую либо информацию. Бытовали также слухи о том, что с помощью механизма cookie можно прочесть любую информацию с любого компьютера. Это неправда, к тому же современные версии браузеров позволяют контролировать прием cookie или вовсе блокировать его. Кроме того, появилось множество специальных утилит для управления приемом cookie, так называемые Cookie Managers.
Другая сторона этой проблемы заключается в том, что на узлах Сети аккумулируются огромные массивы данных с персональной информацией, необходимые для коммерческих серверов. Вот здесь и появляются повышенные требования к защите от несанкционированного доступа к этим данным. Пользователи таких серверов должны быть уверены, что их имена, адреса электронной почты, телефонные номера и проч., не попадут в чужие руки. В противном случае последствия могут оказаться катастрофическими для "проштрафившихся" коммерческих серверов.
Здесь все, что необходимо для определения PR на php.
Вызов функции GetGooglePR("http://ya.ru/") к примеру.
Code:
<?php
define('GOOGLE_MAGIC', 0xE6359A60);
//unsigned shift right
function zeroFill($a, $b)
{
$z = hexdec(80000000);
if ($z & $a)
{
$a = ($a>>1);
$a &= (~$z);
$a |= 0x40000000;
$a = ($a>>($b-1));
}
else
{
$a = ($a>>$b);
}
return $a;
}
function mix($a,$b,$c) {
$a -= $b;
$a -= $c;
$a ^= (zeroFill($c,13));
$b -= $c; $b -= $a; $b ^= ($a<<8);
$c -= $a; $c -= $b; $c ^= (zeroFill($b,13));
$a -= $b; $a -= $c; $a ^= (zeroFill($c,12));
$b -= $c; $b -= $a; $b ^= ($a<<16);
$c -= $a; $c -= $b; $c ^= (zeroFill($b,5));
$a -= $b; $a -= $c; $a ^= (zeroFill($c,3));
$b -= $c; $b -= $a; $b ^= ($a<<10);
$c -= $a; $c -= $b; $c ^= (zeroFill($b,15));
return array($a,$b,$c);
}
function GoogleCH($url, $length=null, $init=GOOGLE_MAGIC) {
if(is_null($length)) {
$length = sizeof($url);
}
$a = $b = 0x9E3779B9;
$c = $init;
$k = 0;
$len = $length;
while($len >= 12) {
$a += ($url[$k+0] +($url[$k+1]<<8) +($url[$k+2]<<16) +($url[$k+3]<<24));
$b += ($url[$k+4] +($url[$k+5]<<8) +($url[$k+6]<<16) +($url[$k+7]<<24));
$c += ($url[$k+8] +($url[$k+9]<<8) +($url[$k+10]<<16)+($url[$k+11]<<24));
$mix = mix($a,$b,$c);
$a = $mix[0]; $b = $mix[1]; $c = $mix[2];
$k += 12;
$len -= 12;
}
$c += $length;
switch($len) /* all the case statements fall through */
{
case 11: $c+=($url[$k+10]<<24);
case 10: $c+=($url[$k+9]<<16);
case 9 : $c+=($url[$k+8]<<8);
/* the first byte of c is reserved for the length */
case 8 : $b+=($url[$k+7]<<24);
case 7 : $b+=($url[$k+6]<<16);
case 6 : $b+=($url[$k+5]<<8);
case 5 : $b+=($url[$k+4]);
case 4 : $a+=($url[$k+3]<<24);
case 3 : $a+=($url[$k+2]<<16);
case 2 : $a+=($url[$k+1]<<8);
case 1 : $a+=($url[$k+0]);
/* case 0: nothing left to add */
}
$mix = mix($a,$b,$c);
/*-------------------------------------------- report the result */
return $mix[2];
}
//converts a string into an array of integers containing the numeric value of the char
function strord($string) {
for($i=0;$i<strlen($string);$i++) {
$result[$i] = ord($string{$i});
}
return $result;
}
// converts an array of 32 bit integers into an array with 8 bit values. Equivalent to (BYTE *)arr32
function c32to8bit($arr32) {
for($i=0;$i<count($arr32);$i++) {
for ($bitOrder=$i*4;$bitOrder<=$i*4+3;$bitOrder++) {
$arr8[$bitOrder]=$arr32[$i]&255;
$arr32[$i]=zeroFill($arr32[$i], 8);
}
}
return $arr8;
}
function GetGooglePR($url)
{
$url = 'info:'.$url;
$ch = GoogleCH(strord($url));
$ch = ((($ch/7) << 2) | (((int)fmod($ch,13))&7));
$prbuf = array();
$prbuf[0] = $ch;
for($i = 1; $i < 20; $i++)
{
$prbuf[$i] = $prbuf[$i-1]-9;
}
$ch = GoogleCH(c32to8bit($prbuf), 80);
// $ch=sprintf("%u", $ch);
$HEAD = "GET /search?sourceid=navclient-ff&features=Rank&client=navclient-auto-ff&ch=".sprintf("6%u",$ch)."&q=".urlencode($url)." HTTP/1.1\r\n";
$HEAD.= "Host: toolbarqueries.google.com\r\n";
$HEAD.= "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.8) Gecko/20051111 Firefox/1.5\r\n";
$HEAD.= "Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/"."*;q=0.5\r\n";
$HEAD.= "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n";
$HEAD.= "Connection: Close\r\n";
$HEAD.= "Cache-Control: max-age=0\r\n";
$HEAD.= "Pragma: no-cache\r\n";
$HEAD.= "Content-type: text/xml\r\n";
$HEAD.= "\r\n";
$fp = fsockopen("toolbarqueries.google.com", "80", $errno, $errstr, 10);
if (!$fp)
{
echo "$errstr ($errno)<br />\n";
return "";
}
else
{
fputs($fp, $HEAD);
$Result="";
while (!feof($fp))
{
$Result.=fgets($fp, 4096);
}
fclose($fp);
}
if(strpos($Result,"Rank_"))
{
$Result=substr($Result,strpos($Result,"Rank_")+5);
$Result=trim(substr($Result,strpos($Result,":")+1));
$Result=trim(substr($Result,strpos($Result,":")+1));
$Result=trim(substr($Result,0,strpos($Result,"\n")));
}
else
$Result=-1;
return $Result;
}
?>
Может кому пригодится: показывает место сайта в большинстве поисковиках © dobrinia
Code:
<?php
// Из суперглобального массива $_POST[]
// получаем значения переменных переданных из формы
if (empty($_POST['site'])) $_POST['site'] = $_SERVER['SERVER_NAME'];
$server = $_POST['server'];
$site = $_POST['site'];
$site = str_replace('/', '\/', $site);
$phrase = $_POST['phrase'];
// Определение констант, соответствующих поисковым системам
define('YANDEX', 1); // Яndex
define('RAMBLER', 2); // Rambler
define('APORT', 3); // Апорт
define('GOOGLE', 4); // Google
define('MAIL', 5); // Поиск@Mail.ru
define('MSN', 6); // MSN Live Search
define('YAHOO', 7); // Yahoo!
// Форма ввода параметров мониторинга
?>
<form method="post">
<p>
<select name="server">
<option value=<?php print YANDEX; ?>
<? if($server==YANDEX) print " selected"; ?>>Яndex</option>
<option value=<?php print RAMBLER; ?>
<? if($server==RAMBLER) print " selected"; ?>>Rambler</option>
<option value=<?php print APORT; ?>
<? if($server==APORT) print " selected"; ?>>Aport</option>
<option value=<?php print GOOGLE; ?>
<? if($server==GOOGLE) print " selected"; ?>>Google</option>
<option value=<?php print MAIL; ?>
<? if($server==MAIL) print " selected"; ?>>@MAIL.RU</option>
<option value=<?php print MSN; ?>
<? if($server==MSN) print " selected"; ?>>MSN</option>
<option value=<?php print YAHOO; ?>
<? if($server==YAHOO) print " selected"; ?>>Yahoo!</option>
</select>
</p>
<p>
Сайт: <input type="text" name="site" size="40" maxlength="256"
value='<? print $site ?>'>
</p>
<p>
Фраза: <input type="text" name="phrase" size="40" maxlength="256"
value='<? print $phrase ?>'>
</p>
<p>
<input type="submit" value="Искать">
</p>
</form>
<?
// Если все поля в форме заполнены, то вызывается функция
// siteposition() для проведения мониторинга
if (($server!="") && ($phrase!="") && ($site!=""))
{
siteposition($server, $site, $phrase);
}
function siteposition($server, $site, $phrase)
{
// numberpage — переменная определяющая номер просматриваемой страницы
$numberpage = 0;
// Присваиваем переменным phrase, total и numberpage значения,
// определяемые индивидуально для каждой поисковой системы.
// phrase — поисковая фраза
// total — переменная, определяющая максимальное число страниц
// по которым будет произведен поиск. Для разных поисковых систем
// оно разное и подобрано таким образом, чтобы число просматриваемых
// страниц составило 10 штук.
switch($server)
{
case YANDEX:
// Обрезка пробелов в начале и конце поисковой фразы
$phrase = trim($phrase);
// URL-кодирование поисковой фразы
// неалфавитно-числовые символы заменяются
// на знак % и соответствующую 16-ричную последовательность
$phrase = rawurlencode($phrase);
// 16-ричный знак пробела, появившийся после применения
// функции rawurlencode() заменяется на знак +
$endstr = str_replace("%20", "+", $phrase);
$total = 10;
$numberpage = -1;
break;
case APORT:
$phrase = trim($phrase);
$phrase = rawurlencode($phrase);
$endstr = str_replace("%20", "+", $phrase);
$total = 10;
$numberpage = -1;
break;
case RAMBLER:
$phrase = trim($phrase);
$phrase = rawurlencode($phrase);
$endstr = str_replace("%20", "+", $phrase);
$total = 152;
$numberpage = -14;
break;
case GOOGLE:
$phrase = trim($phrase);
$phrase = rawurlencode($phrase);
$endstr = str_replace("%20", "+", $phrase);
$total = 100;
$numberpage = - 10;
break;
case MAIL:
$phrase = trim($phrase);
$phrase = rawurlencode($phrase);
$endstr = str_replace("%20", "+", $phrase);
$total = 100;
$numberpage = - 10;
break;
case MSN:
$phrase = iconv('cp1251', 'UTF-8', trim($phrase)); //mb_convert_encoding(trim($phrase), 'UTF-8',
'cp1251');
$phrase = rawurlencode($phrase);
$endstr = str_replace("%20", "+", $phrase);
$total = 10;
$numberpage = - 1;
break;
case YAHOO:
$phrase = iconv('cp1251', 'UTF-8', trim($phrase)); //mb_convert_encoding(trim($phrase), 'UTF-8',
'cp1251');
$phrase = rawurlencode($phrase);
$endstr = str_replace("%20", "+", $phrase);
$total = 91;
$numberpage = - 9;
break;
}
// Последовательно просматриваем страницы поисковых систем до тех
// пор пока не будет найдена ссылка на искомый сайт в тексте страницы
// (count($arr[0]) == 0) или число просмотренных страниц не достигнет
// максимального значения ($numberpage < $total)
while ((count($arr[0]) == 0) && ($numberpage < $total))
{
switch($server)
{
// Увеличивая значение переменной $numberpage, определяется
// текущая просматриваемая страницу с результатами поиска
// в поисковой системе.
// Число приращения зависит от конкретной поисковой системы
case YANDEX:
$numberpage += 1;
break;
case APORT:
$numberpage += 1;
break;
case RAMBLER:
$numberpage += 15;
break;
case GOOGLE:
$numberpage += 10;
break;
case MAIL:
$numberpage += 10;
break;
case MSN:
$numberpage += 1;
break;
case YAHOO:
$numberpage += 10;
break;
}
// Вызывается функцию geturl(), генерирующую строку запроса
// для поисковой системы. Передаваемые параметры:
// numberpage – переменная, определяющая номер просматриваемой
// страницы с результатами поиска в поисковой системе
// endstr — поисковая фраза после кодирования для применения
// в строке запроса
// server — имя поисковой системы
$strurl = geturl($numberpage,$endstr,$server);
// В переменную text заносится содержимое страницы поисковой системы,
// которое возвращается функцией openpage()
$text = openpage($strurl);
// Поиск ссылки на сайт в тексте страницы поисковой системы
// с помощью функции findsite(). Результаты поиска заносятся
// в массив arr[].
$arr = findsite($site, $text);
}
// Если число элементов массива arr[] больше нуля — значит ссылка
// на искомый сайт была найдена в тексте просмотренной страницы
// поисковой системы и необходимо показать результаты мониторинга.
if (count($arr[0]) > 0){
switch($server)
{
// В зависимости от поисковой системы формируются результаты
// мониторинга поисковой системы.
// Функция pattern() возвращает результаты параметры для
// регулярного выражения, с помощью которого будет производится
// поиск номера позиции сайта сайта в тексте
// страницы поисковой системы.
// Функция findposition() возвращает номер позиции сайта
case YANDEX:
// Вывод информации о странице
print "Ссылка на сайт найдена на странице: ".
($numberpage+1)."<br>";
print "Перейти по ссылке: <a href='$strurl' target='_blank'>Яndex</a><br>";
// Определение и вывод позиции запроса
list($startpattern, $endpattern) = pattern(YANDEX);
print "<br>Позиция: ".
findposition($server, $site, $text, $startpattern, $endpattern);
break;
case APORT:
// Вывод информации о странице
print "Ссылка на сайт найдена на странице: ".
($numberpage+1)."<br>";
print "Перейти по ссылке: <a href='$strurl' target='_blank'>Апорт</a><br>";
// Определение и вывод позиции запроса
list($startpattern, $endpattern) = pattern(APORT);
print "<br>Позиция: ".
findposition($server, $site, $text, $startpattern, $endpattern);
break;
case RAMBLER:
// Вычисляем страницу, на которой находится запрашиваемый сайт
$numberpage = $numberpage/15;
$numberpage = (int)$numberpage;
if($numberpage % 15 == 0 && $numberpage>15) $numberpage++;
print "Ссылка на сайт найдена на странице: ".($numberpage+1)."<br>";
// Выводим ссылку на страницу
print "Перейти по ссылке: <a href='$strurl' target='_blank'>Рамблер</a><br>";
// Определение и вывод позиции запроса
list($startpattern, $endpattern) = pattern(RAMBLER);
print "<br>Позиция: ".findposition($server, $site, $text,
$startpattern, $endpattern);
// Так как ссылка на искомый сайт найдена, то просмотр страниц
// поисковых систем в цикле While можно прекратить
break;
case GOOGLE:
// Вывод информации о странице
print "Ссылка на сайт найдена на странице: ".
($numberpage/10 + 1)."<br>";
print "Перейти по ссылке: <a href='$strurl' target='_blank'>Google</a><br>";
// Определение и вывод позиции запроса
list($startpattern, $endpattern) = pattern(GOOGLE);
$pos = findposition($server, $site, $text, $startpattern, $endpattern);
print "<br>Позиция: ".($numberpage + $pos);
break;
case MAIL:
// Вывод информации о странице
print "Ссылка на сайт найдена на странице: ".
($numberpage/10 + 1)."<br>";
print "Перейти по ссылке: <a href='$strurl' target='_blank'>Поиск@MAIL.RU</a><br>";
// Определение и вывод позиции запроса
list($startpattern, $endpattern) = pattern(MAIL);
print "<br>Позиция: ".
findposition($server, $site, $text, $startpattern, $endpattern);
break;
case MSN:
// Вывод информации о странице
print "Ссылка на сайт найдена на странице: ".
($numberpage+1)."<br>";
print "Перейти по ссылке: <a href='$strurl' target='_blank'>MSN Live Search</a><br>";
// Определение и вывод позиции запроса
list($startpattern, $endpattern) = pattern(MSN);
$pos = findposition($server, $site, $text, $startpattern, $endpattern);
print "<br>Позиция: ".(($numberpage*10)+$pos);
break;
case YAHOO:
// Вывод информации о странице
print "Ссылка на сайт найдена на странице: ".
(($numberpage-1)/10 + 1)."<br>";
print "Перейти по ссылке: <a href='$strurl' target='_blank'>Yahoo!</a><br>";
// Определение и вывод позиции запроса
list($startpattern, $endpattern) = pattern(YAHOO);
print "<br>Позиция: ".
findposition($server, $site, $text, $startpattern, $endpattern);
break;
}
}
else
{
print "На 10 первых страницах ссылка на сайт отсутствует";
}
}
function geturl($numberpage, $endstr, $server)
{
switch ($server){
case YANDEX:
return "http://www.yandex.ru/yandpage?q=818836167&p=$numberpage&ag=d&rpt=rad&qs=text%3D$endstr";
case RAMBLER:
return "http://www.rambler.ru/srch?oe=1251&words={$endstr}&start=".$numberpage;
case APORT:
return
"http://sm.aport.ru/scripts/template.dll?r={$endstr}&That=std&p={$numberpage}&HID=1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_1
7_18_19_20";
case GOOGLE:
return "http://www.google.ru/search?q={$endstr}&hl=ru&lr=&start={$numberpage}&sa=N";
case MAIL:
return "http://go.mail.ru/search?&q={$endstr}&no_morph=n&num=10&sf={$numberpage}";
case MSN:
return
"http://search.msn.com/results.aspx?q={$endstr}&first={$numberpage}1&FORM=PDRE{$numberpage}";
case YAHOO:
return
"http://search.yahoo.com/search?p={$endstr}&toggle=1&ei=UTF-8&fr=FP-tab-web-t400&b={$numberpage}";
default:
return "";
}
}
function openpage($link)
{
$link = parse_url($link);
$link['port'] = (empty($link['port'])) ? '80' : $link['port'];
$fp = fsockopen($link['host'], $link['port'], $sock_errno, $sock_errstr, 30);
if (!$fp) {
print "$sock_errstr ($sock_errno)<br>\n";
} else {
$out = "GET {$link['path']}?{$link['query']} HTTP/1.1\r\n";
$out .= "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*\r\n";
$out .= "User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows 98; DigExt)\r\n"; // маскировка под IE 5
$out .= "Host: {$link['host']}\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
$text = '';
while (!feof($fp)) {
$text .= fgets($fp, 1024);
}
fclose($fp);
}
return ($text);
}
function findsite($site, $text)
{
preg_match_all("/$site/i", $text, $arr);
return $arr;
}
function pattern($typepattern)
{
switch($typepattern)
{
case YANDEX:
return array("<li value=(?P<position>\d*)\s*>\s*<div[^>]*>\s*<a[^>]*href=\"[^\"]*",
"[^\"]*\"[^>]*>.*<\/a>\s*<\/div>");
break;
case APORT:
return array("<li value=(?P<position>\d*)>(\s*)<span([^>]*)>(\s*)<a([^>]*)href=\"([^\"]*)",
"([^\"]*)\"([^>]*)>");
break;
case RAMBLER:
return array("<li><div class=\"ttl\"><a([^>]*)href=\"([^\"]*)", "([^\"]*)\"");
break;
case GOOGLE:
return array("href=\"([^\"]*)", "([^\"]*)\"");
break;
case MAIL:
return
array("<tr>\s*<td[^>]*class=num>(?P<position>\d*)\.<\/td>\s*<td>\s*<p>\s*<a[^>]*href=\"[^\"]*", "[^\"]*\"");
break;
case MSN:
return array("<li[^>]*><h3><a href=\"[^\"]*", "[^\"]*\"[^>]*>");
break;
case YAHOO:
return array("<em class=yschurl>([^<>]*)", "(.*)<\/em>");
break;
}
}
// Функция findposition() определяет позицию искомого сайта на странице
// c результатами поиска в поисковой системе.
// Передаваемые параметры:
// server — имя поисковой системы
// site — имя искомого сайта
// text — содержимое страницы c результатами поиска в поисковой системе
// startpattern и endpattern — параметры для регулярного выражения, они
// определяются функцией pattern().
function findposition($server, $site, $text, $startpattern, $endpattern)
{
switch($server)
{
// Поиск позиции сайта в тексте страницы.
// Для каждой поисковой системы применяется свой алгоритм поиска
case YANDEX:
// Регулярное выражение, осуществляющее поиск позиции сайта
preg_match("/$startpattern$site$endpattern/isU", $text, $arr);
return $arr['position'];
case APORT:
preg_match("/$startpattern$site$endpattern/isU", $text, $arr);
return $arr['position'];
case RAMBLER:
preg_match('/<ol start="(\d*)">/isU', $text, $arr);
$pos_begin = $arr[1];
$text = substr($text, strpos($text, '<ol start='));
// Находим текст относящийся к сайту и вырезаем его
for($i=0; $i<20; $i++)
{
$pos = strpos($text,"<li>");
$posend = strpos($text, "<li>", ($pos+15));
if(preg_match("/$startpattern$site$endpattern/isU", substr($text,$pos,($posend-$pos))))
return $pos_begin;
else $text = substr($text, $posend-1);
$pos_begin++;
}
return 'Не определена';
case GOOGLE:
$pos_begin = 1;
// Находим текст относящийся к сайту и вырезаем его
for($i = 0; $i < 10; $i++){
$pos = strpos($text,"<p class=g><a class=l");
$posend = strpos($text, "<p class=g><a class=l", ($pos+25));
if(preg_match("/$startpattern$site$endpattern/isU", substr($text,$pos,($posend-$pos))))
return $pos_begin;
else $text = substr($text, $posend-1);
$pos_begin++;
}
$pos = $posend;
if(preg_match("/$startpattern$site$endpattern/isU", substr($text, $pos))) return $pos_begin;
return 'Не определена';
case MAIL:
preg_match("/$startpattern$site$endpattern/isU", $text, $arr);
return $arr['position'];
case MSN:
$pos_begin = 1;
$pos = strpos($text, '<div id="results"><h2 class="hide">Results</h2><ul>');
$posend = strpos($text, '</ul></div>', $pos + 60);
$text = substr($text, $pos + 51, $posend - $pos - 12);
// Находим текст относящийся к сайту и вырезаем его
if (preg_match_all("/$startpattern.*$endpattern/isU", $text, $regs)){
foreach ($regs[0] as $key => $value) {
if (preg_match("/.*$site.*/isU", $value)) return $key+1;
}
}else return 'Не определена';
case YAHOO:
preg_match('/<ol start=(\d*)>/isU', $text, $arr);
$pos_begin = $arr[1];
$text = substr($text, strpos($text, '<ol start='));
// Находим текст относящийся к сайту и вырезаем его
for($i = 0; $i < 10; $i++)
{
$pos = strpos($text,"<li>");
$posend = strpos($text, "<li>", ($pos+4)) ? strpos($text, "<li>", ($pos+4)) - $pos :
strlen($text);
if(preg_match("/$startpattern$site$endpattern/iU", substr($text, $pos, $posend))) return
$pos_begin;
else $text = substr($text, $pos+$posend);
$pos_begin++;
}
return 'Не определена';
default:
return 'Не определена';
}
}
?>
© BiOM
Источник | 25 февраля 2006