Авторизация на сайте при помощи библиотеки cUrl Продолжая цикл статей посвященный парсерам и всем, что с ними связано. В этой статье расскажу про то, как легко можно авторизоваться на любом сайте при помощи библиотеку cUrl php. Для примера я взял один Украинский портал, к которому я собственно и буду подбирать ключики. Для работы нам также понадобится библиотека simple_html_dom 

Авторизацию будем проходить на сайте http://tender.me.gov.ua , не буду создавать лишних ссылок, чтобы не накрыть нашу лавочку. 

Для начала зарегистрируйтесь на сайте, чтобы иметь тестовые логин-пароль для входа на сайт. 

На сайте мы видим ничем не примечательную форму авторизации.

Форма авторизации на сайте

"Внутренности" у нее тоже ничем не примечательны

<form id="login" name="login" method="post" action="/EDZFrontOffice/menu/uk/;jsessionid=c4651e96f5c2b9afb08776cbd1a5" enctype="application/x-www-form-urlencoded">
 <input type="hidden" name="login" value="login" />
 <input id="login:login" type="text" name="login:login" class="login" maxlength="80" />
 <input id="login:password" type="password" name="login:password" value="" maxlength="80" class="login" />
 <input type="image" src="images/t_login_button.png;jsessionid=c4651e96f5c2b9afb08776cbd1a5" name="login:j_id_id254" alt="&#1042;&#1093;&#1110;&#1076;" />
 <input type="hidden" name="javax.faces.ViewState" id="javax.faces.ViewState" value="j_id1:j_id2" autocomplete="off" />
</form>

Итак смотрим, что форма авторизации отправляет при аутентификации. Для этого возпользуемся  Google Chrome, открываем в нем сайт, затем Инструменты->Инструменты разработчика. Далее переходим на вкладку Network. Для браузера Opera Меню->Страница->Средства Разработки->Open Opera DragOnFly и вкладка Сеть. Хоть я и фанат Оперы, но на мой взгляд продукт от компании Google немного удобнее. Я конечно не про браузер =)

Теперь авторизуемся на сайте, смотрим, что посылает форма при сабмите. 

Просмотр отправляемых данных в Google Chrome

Видим, что форма посылает следующие параметры

login:login
login:login:{loginmail}
login:password:{password}
login:j_id_id254.x:8
login:j_id_id254.y:7
javax.faces.ViewState:j_id1:j_id2

Попробуем решить задачу в лоб и отправить эти данные простым массивом. Сразу учтем, что данные отправляются на защищенный ssl url, по протоколу https. Это следует учитывать при отправке данных в cUrl. Рассказывать, как работает SSL в рамках данной статьи я не стану, скажу лишь, что сертификаты, которыми обмениваются две стороны, сами по себе ничего не говорят о его обладателе. Они нужны лишь для того, чтобы передать открытый ключ, обеих сторон и служат для шифрования канала связи. Т.е. мы можем проверять наличие ssl, и подключать сертификат в cUrl, но это будет служить пользу только нам, сервер не может узнать пользуемся ли мы сертификатом, или используем незащищенный канал связи.

//О том, что мы авторизовались будем судить по наличию формы logout
function isAuth( $data ){
	return preg_match('#<form[^>]+id="logout"#Usi',$data);
}
$ch = curl_init();
$url = 'https://tender.me.gov.ua/EDZFrontOffice/menu/uk/';
curl_setopt($ch, CURLOPT_URL, $url ); // отправляем на 
curl_setopt($ch, CURLOPT_HEADER, 0); // пустые заголовки
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // возвратить то что вернул сервер
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // следовать за редиректами
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);// таймаут4
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);// просто отключаем проверку сертификата 
curl_setopt($ch, CURLOPT_POST, 1); // использовать данные в post
curl_setopt($ch, CURLOPT_POSTFIELDS, array(
	'login'=>'login',
	'login:login'=>'mylogin@sitename.ru',
	'login:password'=>'password',
	'login:j_id_id254.x'=>8,
	'login:j_id_id254.y'=>7,
	'javax.faces.ViewState'=>'j_id1:j_id2',
));
echo isAuth($data = curl_exec($ch))?'Success':'Failed';
curl_close($ch);

Запускаем и видим, что ничего не получилось. Сайт просто так не сдался. Мы не учли одну вещь, данные об авторизации должны быть сохранены в cookie. Для этого добавим две строчки в код, к примеру после curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

...
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_COOKIEJAR, dirname(__FILE__).'/cookie.txt'); // сохранять куки в файл 
curl_setopt($ch, CURLOPT_COOKIEFILE,  dirname(__FILE__).'/cookie.txt');
...

И снова мимо. Обратим внимание, что форма помимо стандартных логина-пароля, отправляет еще 3 динамических поля. Данные в них все время разные и генерируются при обновлении страницы. Значит, нужно загрузить страницу, скопировать эти данные и проходить аутентификацию уже с ними. Для этого немного "облагородим" код, заключив запрос данных с сервера cUrl'ом в отдельную функцию. Все отличие get запроса от post, заключается в том, что при пост запросе отправляются данные CURLOPT_POSTFIELDS

function request($url,$post = 0){
	$ch = curl_init();
	curl_setopt($ch, CURLOPT_URL, $url ); // отправляем на 
	curl_setopt($ch, CURLOPT_HEADER, 0); // пустые заголовки
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // возвратить то что вернул сервер
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // следовать за редиректами
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);// таймаут4
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
	curl_setopt($ch, CURLOPT_COOKIEJAR, dirname(__FILE__).'/cookie.txt'); // сохранять куки в файл 
	curl_setopt($ch, CURLOPT_COOKIEFILE,  dirname(__FILE__).'/cookie.txt');
	curl_setopt($ch, CURLOPT_POST, $post!==0 ); // использовать данные в post
	if($post)
		curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
	$data = curl_exec($ch);
	curl_close($ch);
	return $data;
}

Попытаемся выдернуть значения переменных полей 

$data = request('https://tender.me.gov.ua/EDZFrontOffice/');
include 'simple_html_dom.php';
$data = str_get_html($data);
$auth = array(
		'login'=>'login',
		'login:login'=>'***************',
		'login:password'=>'************l',
		'login:j_id_id254.x'=>$data->find('input[name="login:j_id_id254.x"]',0)->value,
		'login:j_id_id254.y'=>$data->find('input[name="login:j_id_id254.y"]',0)->value,
		'javax.faces.ViewState'=>$data->find('input[name="javax.faces.ViewState"]',0)->value,
);
$data->clear();
unset($data);
print_r($auth);

Оказывается, что поле login:j_id_id254.x и поле login:j_id_id254.y создаются и заполняются js скриптом. Попробуем оставить их как были 

$url = 'https://tender.me.gov.ua/EDZFrontOffice/menu/uk/';
$data = request('https://tender.me.gov.ua/EDZFrontOffice/');
include 'simple_html_dom.php';
$data = str_get_html($data);
$auth = array(
		'login'=>'login',
		'login:login'=>'site@sitename.ru',
		'login:password'=>'password',
		'login:j_id_id254.x'=>10,
		'login:j_id_id254.y'=>11,
		'javax.faces.ViewState'=>$data->find('input[name="javax.faces.ViewState"]',0)->value,
);
$data->clear();
unset($data);
echo isAuth(request($url,$auth))?'Success':'Failed';;

Вот  и все, сайт побежден. Далее работаем с ним, как с обычным сайтом. Данные о том, что Ваш скрипт никто иной, как авторизованный пользователь бережно хранятся в cookie.   

Скрипт работает, но в более сложных случаях, приходиться эмулировать выполнение js скриптов, либо просто выяснять механизм их работы, чтобы заполнить те самые динамически заполняемые поля. К сожалению, этому не научишь, все зависит от конкретной задачи и изобретательности программиста. За примерами далеко ходить не надо, попробуйте для интереса создать скрипт, который бы отправлял автоматически, комментарии на xdan.ru. Желаю удачи =)

 

Рассказать друзьям
author.jpg

Платная консультация по вопросам 1500 руб/час

Прочитали статью и остались вопросы? Меня зовут Валерий и я её автор. С радостью объясню Вам в скайпе все затруднительные моменты, которые остались за рамками статьи!

Подробнее ...

Добавить комментарий


Комментарии   

Евгени
+5 # Евгени 20.07.2012 18:03
Спасибо за статью, как раз её и ждал ;)
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Сергей
+5 # Сергей 18.09.2012 17:39
Спасибо очень помогло
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Сергей
+3 # Сергей 19.09.2012 22:57
пробовал сюда отправить сообщение с curl но не получилось), не смог вернуть значение из поля js_key
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Leroy
+4 # Leroy 20.09.2012 12:51
свой сайт я привел, как сайт защищенный от подобного рода деятельности. в том и фишка, у меня стоит js защита от спама. на стороне сервера генерируется js скрипт, проводиться его обфуския а затем он выполняется в браузере выдавая некий ключ, аналог которого есть на сервере. при парсинге сайта через php вы не можете выполнить js. в народе называется js капча, Очень примитивная защита, обойти которую достаточно сложно без разбора алгоритма генерации и деобфускации кода, однако и ее можно обойти. код там не сложный) Поставил ее, как только посыпались автоматические посты на сайт со всякой рекламой
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Василий
+3 # Василий 20.09.2012 21:35
А как можно выдернуть значение, которое было сгенерированно с помощью js? И вообще реально ли это сделать с помощью чистого php, или надо использовать для этих целей javascript?
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Leroy
0 # Leroy 20.09.2012 21:58
либо писать изначально на парсер js либо разбираем ручками алгоритм, уверяю вас это не так сложно как кажется, делал такое и не раз. К примеру можно запустить сайт в браузере, и посмотреть в инспекторе распакованный js, что уже сильно облегчит задачу по генерации своего key
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Maria
0 # Maria 27.09.2017 10:46
В моем непростом случае ничего не помогает чтобы авторизоваться на сайте чере курл.
Как мне выяснить, что именно недает авторизации случится?
Допустим, если там есть js - key, как его вычислить? Что значит "посмотреть в инспекторе распакованный js" и как я отличу нужный мне js?)
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Leroy
0 # Leroy 27.09.2017 16:14
Сперва посмотрите в инспектора во вкладке сеть/network какой запрос уходит при отправке формы, какие там поля есть. Если есть поля которые похожы на динамические, ищите где сайт их генерирует/получает, он может их с сервера запрашивать, может сам хитро генерировать. В самом js ищем код который отправляет запрос - в нем ищем место где в запрос вставляется хитры параметр, ищем вверх по коду, откуда этот параметр пришел, из формы ли взят или прислан с куками. туча вариантов. скорее всего все проще и там какая-нибудь crsf переменная из хидера, но могут и заморочиться, случаи бывают разные)
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Герман
+3 # Герман 08.01.2013 21:32
Огромное спасибо! Задумал сделать один сервис, без этой статьи было бы не реализовать!
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Владимир
0 # Владимир 24.01.2013 19:39
Здравствуйте, очень полезная статься, но я все же не смог сделать авторизацию на betonmarkets.com, там все данные формы передаются на cgi скрипт, но ни dragonfly ни chrome почему-то не выводят список отправленных данных формы. Подскажите пожалуйста куда копать
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Leroy
-1 # Leroy 24.01.2013 20:31
копать в сторону функций set_login_url_for_loginid и get_brokercode_from_loginid в исходниках compressed_base.js
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Yurant
-1 # Yurant 03.04.2013 12:22
Подскажите пожалуйста по какому принципу была построена строка preg_match() а конкретнее вот этот сегмент, то что после формы:



#]+id="logout"#Usi
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Leroy
0 # Leroy 03.04.2013 12:54
По принципу регулярных выражений
 preg_match('#<form[^>]+id="logout"#Usi',$data);
где
#<form[^>]+id="logout"#Usi
это регулярка, по которой находится тег form с id="logout" с флагами Usi - где U - выключаем жадность, s - игнорим пробелы, i- игнорируем регистр

В результате если в строке $data есть форма с id="logout" то preg_match вернет true, значит на странице есть форма с выходом. На вашем сайте все может быть гораздо иначе, но принцип тот же - ищем на странице то, что на ней нет до авторизации
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Yurant
0 # Yurant 03.04.2013 15:55
Благодарю, Leroy. Просто пытаюсь по аналогии с данной статьей собрать парсер к сайту, однако не могу понять почему авторизация якобы не проходит... =/

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

Голову ломаю 2й день =/
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Антон
0 # Антон 03.04.2013 16:02
function isAuth( $data )

{

return preg_match('#]+id="Authorization"#Usi',$data);

}

$ch = curl_init();

$url = 'http://www.autodoc.ru/';

curl_setopt($ch, CURLOPT_URL, $url ); // отправляем на

curl_setopt($ch, CURLOPT_HEADER, 0); // пустые заголовки

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // возвратить то что вернул сервер

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // следовать за редиректами

curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);// таймаут4

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)');

curl_setopt($ch, CURLOPT_COOKIEJAR, dirname(__FILE__).'/cookie.txt'); // сохранять куки в файл

curl_setopt($ch, CURLOPT_COOKIEFILE, dirname(__FILE__).'/cookie.txt');

curl_setopt($ch, CURLOPT_POST, 1); // использовать данные в post

curl_setopt($ch, CURLOPT_POSTFIELDS, array(

'returnUrl'=>'/',

'UserName'=>'MANGO-1344',

'RememberMe'=>'true',

'RememberMe'=>'false',

'Password'=>'QWEASDQWE',

));



isAuth($data = curl_exec($ch))?($Success=1):($Success=0);

if ($Success == 1)

{

curl_setopt($ch, CURLOPT_URL, 'http://www.autodoc.ru/Web/price/art/95659676?analog=on&access=2');

curl_setopt($ch, CURLOPT_HEADER, 0); // пустые заголовки

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // возвратить то что вернул сервер

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // следовать за редиректами

curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);// таймаут4

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)');

curl_setopt($ch, CURLOPT_COOKIEJAR, dirname(__FILE__).'/cookie.txt'); // сохранять куки в файл

curl_setopt($ch, CURLOPT_COOKIEFILE, dirname(__FILE__).'/cookie.txt');



$out = curl_exec($ch);

echo $out;

}

curl_close($ch);
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Yurant
-1 # Yurant 03.04.2013 16:07
Собственно вот сам код... В Google/.../network насколько понимаю только гет-запросы, при попытке отправить такой же гет-запрос, возвращает не совсем то.
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Yurant
0 # Yurant 08.04.2013 16:20
Спасибо большое за статью, всё очень наглядно!)
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
matissko
0 # matissko 01.07.2013 11:31
Статья хорошая, я как новенький в этом деле узнал много полезного для себя)



Но однако у меня не получается пройти авторизацию mail.arenda-gold.ru

Делал вроде всё по статье, но не выходит, поможет кто?
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Roman
0 # Roman 14.07.2013 16:45
Добрый день! А вы не пробовали с этого же сайта качать сами тендеры?))) там табличка с записями и есть пагинация! вот никак не могу ее победить! не хочет переходить по ней всегда на первой странице находиться(
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Leroy
0 # Leroy 15.07.2013 03:05
статья написана в ознакомительных целях, ни в коем случае не претендует на руководство по парсенгу одного конкретного ресурса. Все совпадения с реальными сайтами чисто случайные.
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
strongest
0 # strongest 31.07.2013 22:51
Вот сайт на котором хочу авторизоваться. Судя по POST требует кроме логина и пароля еще и значение csrfmiddlewaretoken а он находится в скрытом div. Подскажите, как вытянуть значение csrfmiddlewaretoken из скрытого div ?



И заодно на сайте Сландо не понятно каким образом происходит авторизация.

Если не затруднит вас, подскажите как разобраться с этим?
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Иванbbbffffff
+4 # Иванbbbffffff 23.02.2014 03:10
А можете скрипт автопостинга на авито на php написать? С подключением антигате...
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
weq
-2 # weq 18.01.2015 23:16
Не надо спамить, нехороший вы человек.
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
stdqin
-1 # stdqin 11.03.2014 06:01
Сейчас 'login:j_id_id254.x' и 'login:j_id_id254.y' нет в коде страницы. Как тогда отправить cookies?
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Оlеg
0 # Оlеg 28.08.2014 15:15
Вместо этого там теперь 'login:loginButton.x' и 'login:loginButton.y'.
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Alex
0 # Alex 12.07.2014 18:17
интересует такой момент

//О том, что мы авторизовались будем судить по наличию формы logout
function isAuth( $data ){
return preg_match('#<form[^>]+id="logout"#Usi',$data);



у меня после авторизации нету формы, таблицами все выстроено, как правильно написать, что бы судить по наличию этого кода на странице, что авторизация успешна

<a href="/index.php?module=SYS_users&amp;func=logout" title="Выход пользователя из системы">Выход</a>
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Alex
-2 # Alex 12.07.2014 18:20
'#<a[^>]+title="Выход пользователя из системы"#Usi'



так будет правильно?
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
ooo-palaris
0 # ooo-palaris 17.07.2014 21:08
Добрый день, спасибо большое за качественный и наглядный пошаговый пример.

Делаю по вашему образцу авторизацию на др. сайте, только одно поле меняется с name="rnd", его значение вытаскиваю при помощи регулярки.. вроде все правильно, а авторизоваться не получается.. не подскажите, что не так?



Вот код:

$url4 = 'http://www.palaris-nn.ru/shop/1559331/edit';

$ch = curl_init();

@curl_setopt($ch, CURLOPT_URL, $url4);

curl_setopt($ch, CURLOPT_FAILONERROR, 1);

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);

curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);

curl_setopt($ch, CURLOPT_TIMEOUT, 3);

$resultnew = curl_exec($ch);

preg_match_all("/name=\"rnd\" value=\"(.*)\"/isU", $resultnew, $masnew);

$perem_rnd = $masnew[1][0];

$data = array ('user' => '***', 'password' => '***', 'rem' => '1', 'a' => '2', 'ajax' => '1', 'rnd' => $perem_rnd, '_tp_' => 'xml');

curl_setopt($ch, CURLOPT_HEADER, 0);

curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, false);

curl_setopt($ch, CURLOPT_POST, 1);

curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

curl_setopt ($ch, CURLOPT_COOKIEFILE, '/var/www/u38746/data/www/new.palaris-nn.ru/massur lphp/cooki.txt'); // Сюда будем записывать cookies, файл в той же папке, что и сам скрипт

curl_setopt ($ch, CURLOPT_COOKIEJAR, '/var/www/u38746/data/www/new.palaris-nn.ru/massur lphp/cooki.txt');

$html = curl_exec($ch);

echo $html;

curl_close($ch);
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Василий
0 # Василий 02.09.2014 03:58
Здравствуйте. Не могли бы вы поделиться конечным исходником? Просто не очень понял после всяких замен и т.п. Буду очень благодарен! Заранее спасибо :)
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Радик
0 # Радик 26.11.2014 23:50
А как пройти двухфакторную аутентификацию с подтверждением номера через смс?



Встал в ступор просто.
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Leroy
0 # Leroy 27.11.2014 10:32
вероятно надо найти какой-то сервис который будет принимать смс. Иначе никак
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Настульчик
0 # Настульчик 12.12.2014 17:59
При отправке заполненной формы на движке ВордПресс плагин HttpFox к файерфоксу указал на необычный параметр с именем Y3JQMTEFTYCr со значением o0uX8RxQZA9I. Что это за имя необычное? Правильным ли будет его оформление в массиве как 'Y3JQMTEFTYCr' => 'o0uX8RxQZA9I'?
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Leroy
0 # Leroy 13.12.2014 14:43
похоже на какую-то динамическую переменную, защита. Надо изучать и обходить.
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
murzer
-1 # murzer 14.12.2014 17:41
Пытаюсь авторизоваться по Вашей программе на одном сайте. Мне показывается, что данные отправляются GETом, а не POSTом. В чём может быть причина этого? И отправляемый заголовок Host не такой как я прописал в $url, а 127.0.0.1. Я с апачи на своём компе запускаю.
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
InterSnap SEO
0 # InterSnap SEO 14.06.2019 20:56
Ӏt iis essential the keywords you ultimately chooѕe speak
straight tto the customers you ᴡould like to influence.

Squidoo enabⅼes that yoou builԁ ɑ page over a subject that they have passion ɑbout ,write
as many pages since they like, then Squidoo uѕes advertising on these pages.
It should be also cаtalogued to complement one of the most vital and relevant
search generatd insidⅾe ѕame field.

Ϝeel fгee too visit my web-site - InterSnap SEO
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Cinda
0 # Cinda 19.06.2019 17:47
If yߋu ѡish for to imρroνe your know-how just keep viѕiting this website and be updated witһ the hottest gɡօssip posted here.


Aⅼsoo viѕdit my page weight loss - Cinda,
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору