Консультация № 183502
04.06.2011, 11:52
55.50 руб.
07.06.2011, 15:50
0 9 1
Уважаемые эксперты! Пожалуйста, ответьте на вопрос:
Не могу понять, почему не работает скрипт. Изучаю курл, пробую эмулировать браузер, а именно авторизацию на форуме-отправка сообщения. Авторизация получилась, а отправка ни в какую. Что не пробовал, как не меняли скрипт - все равно, одна и та же ошибка сессии.. Подскажите, что я делаю не так? Или же на этом форуме, на котором я решил попробовать (специально создал тестовый), стоит какая-то супер защита от скриптов?

1вариант моего скрипта
[code lang=php]<?php
$ch = curl_init('http://testtest.flyfolder.ru/login.php');
//@unlink('my_cookies.txt');
curl_setopt($ch, CURLOPT_POST, 1);

curl_setopt ($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.2.16) Gecko/20110319 MRA 5.7 (build 03796) Firefox/3.6.16');

$headers = array
(
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language: ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3',
'Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7'
);
curl_setopt($ch, CURLOPT_HTTPHEADER,$headers);

curl_setopt($ch, CURLOPT_REFERER, "http://testtest.flyfolder.ru/");

curl_setopt($ch, CURLOPT_POSTFIELDS, 'username=givi&password=111222&redirect=&login=%C2%F5%EE%E4');

curl_setopt($ch, CURLOPT_COOKIEJAR, "my_cookies.txt");
curl_setopt($ch, CURLOPT_COOKIEFILE, "my_cookies.txt");
$result = curl_exec($ch);

curl_setopt($ch, CURLOPT_HEADER, true);
/////////////////////пост запрос
$pm = curl_init ('http://testtest.flyfolder.ru/posting.php');
curl_setopt($pm, CURLOPT_POST, 1);
curl_setopt ($pm, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.2.16) Gecko/20110319 MRA 5.7 (build 03796) Firefox/3.6.16');

curl_setopt($pm, CURLOPT_HTTPHEADER,$headers);

curl_setopt($pm, CURLOPT_REFERER, "http://testtest.flyfolder.ru/viewtopic.php?p=28");

curl_setopt($pm, CURLOPT_POSTFIELDS, 'message=%F2%E5%F1%F2%EE%E2%EE%E5+%F1%EE%EE%E1%F9%E5%ED%E8%E5&sid=4bc642318a66e47b7d1046c8c88413d6&mode=reply&t=4&post=%CE%F2%EF%F0%E0%E2%E8%F2%FC');

$postdata = array( 'message' => 'blabla', 'sid' => 'sid');

curl_setopt($pm, CURLOPT_COOKIEJAR, "my_cookies.txt");
curl_setopt($pm, CURLOPT_COOKIEFILE, "my_cookies.txt");

$result = curl_exec($pm);
curl_setopt($pm, CURLOPT_HEADER, true);
curl_close($pm);

?>
[/code]
2вариант моего скрипта (переделал 1 человек, но ошибка осталась).
[code lang=php]<?php

function getURL($url, $postdata = "") {

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, 'Firefox');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookie.txt');
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt');

if($postdata) {
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
}

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 20);

$data = curl_exec($ch);
curl_close($ch);

return $data;

}

$url = 'http://testtest.flyfolder.ru/login.php';
$postdata = array('username'=>'givi', 'password'=>'111222', 'redirect'=>'http://testtest.flyfolder.ru/viewtopic.php?p=32', 'login'=>'true');

echo getURL($url, $postdata);

$url = 'http://testtest.flyfolder.ru/posting.php';
$postdata = array('message'=>'blabla', 'attach_sig'=>'on', 'mode'=>'reply', 't'=>'4', 'post'=>'%CE%F2%EF%F0%E0%E2%E8%F2%FC');

echo getURL($url, $postdata);
?>[/code]


3. Заголовки, полученные мозиллой, при ручной отправке сообщения в форум. http://paste.org.ru/?zvjodd

4. Код, который показывает скрипт, когда я его запускаю:
Код:
nginx/0.7.65
HTTP/1.1 100 Continue HTTP/1.1 200 OK Server: nginx/0.7.65 Date: Sat, 04 Jun 2011 07:50:27 GMT Content-Type: text/html Transfer-Encoding: chunked Connection: keep-alive Cache-Control: private, pre-check=0, post-check=0, max-age=0 Expires: 0 Pragma: no-cache

Появляется окно, в котором мое сообщение, и текст
Ошибка контроля сессий (вы слишком долго заполняли форму?). Попробуйте отправить данные заново.

А еще ниже (в другом фрейме) - 404 The requested URL /posting.php was not found on this server.
Т.е. ошибка денвера, хотя я не пойму, причем он тут вообще, ведь я писал полные пути, а не относительные.

Обсуждение

Неизвестный
06.06.2011, 13:50
общий
Попробуйте для получения отчёта о последнем запросе вставить следующие строки перед вызовом curl_close
Код:

<?php
print_r(curl_getinfo($ch));
echo "\n\ncURL error number:" .curl_errno($ch);
echo "\n\ncURL error:" . curl_error($ch);
?>
Неизвестный
06.06.2011, 17:44
общий
07.06.2011, 15:35
это ответ
Здравствуйте, Черкасов Степан Николаевич!

Проблема не в cURL. Просто Вы указываете файл для cookies cookie.txt, который cURL не может использовать, так как у пользователя, под которым он вызывается, нет прав на запись в текущий каталог.

В качестве простейшего решения Вы можете создать в каталоге со скриптом файл cookie.txt и установить к нему права на запись для всех (666).

Хотя я бы рекомендовал создавать этот файл во временном каталоге - для безопасности системы:

Код:

curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/cookie.txt');
curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/cookie.txt');



*********************************************************************************************

Я рассматривал второй вариант. Кроме проблемы доступа к файлу cookies, при втором вызове getURL необходимо было передать ещё один POST-параметр: sid. Он устанавливается во время авторизации (в первом вызове getURL) и служит для однозначной идентификации автора сообщения, которое мы передаём при втором вызове getURL. Поскольку работу браузера мы только эмулируем, то проще получить этот параметр, разобрав заголовки сервера, которые возвращает нам первый вызов cURL. Выделим sid из первого вызова cURL и добавим его в POST-параметры для второго:

$url = 'http://testtest.flyfolder.ru/login.php';
$postdata = array('username'=>'givi', 'password'=>'111222', 'redirect'=>'viewtopic.php?p=32', 'login'=>'true');


$x = getURL($url, $postdata);

list ($null, $sid) = explode ("sid=", $x, 2);
list ($sid, $null) = explode (";", $sid, 2);


$url = 'http://testtest.flyfolder.ru/posting.php';
$postdata = array('message'=>'blabla_B', 'attach_sig'=>'on', 'mode'=>'reply', 'sid'=>$sid, 't'=>'4', 'post'=>'%CE%F2%EF%F0%E0%E2%E8%F2%FC');

echo getURL($url, $postdata);


*********************************************************************************************


Скорректировано по просьбе автора ответа.
Неизвестный
06.06.2011, 17:47
общий
и, кстати, в редиректе путь должен быть относительным, посмотрите заголовки, которые отдаёт кУРЛ (Локейшн) ;-)
Неизвестный
06.06.2011, 19:27
общий
, возвращает результат
Код:
 Array ( [url] => http://testtest.flyfolder.ru/posting.php [content_type] => [http_code] => 0 [header_size] => 0 [request_size] => 0 [filetime] => 0 [ssl_verify_result] => 0 [redirect_count] => 0 [total_time] => 0 [namelookup_time] => 0 [connect_time] => 0 [pretransfer_time] => 0 [size_upload] => 0 [size_download] => 0 [speed_download] => 0 [speed_upload] => 0 [download_content_length] => -1 [upload_content_length] => -1 [starttransfer_time] => 0 [redirect_time] => 0 [certinfo] => Array ( ) ) cURL error number:0 cURL error:HTTP/1.1 302 Moved Temporarily Server: nginx/0.7.65 Date: Mon, 06 Jun 2011 15:24:42 GMT Content-Type: text/html Transfer-Encoding: chunked Connection: keep-alive Set-Cookie: flbbb_data=a%3A2%3A%7Bs%3A11%3A%22autologinid%22%3Bs%3A0%3A%22%22%3Bs%3A6%3A%22userid%22%3Bi%3A-1%3B%7D; expires=Tue, 05-Jun-2012 15:24:42 GMT; path=/; domain=testtest.flyfolder.ru Set-Cookie: flbbb_sid=7c22857c9b6558b09a5220abb4e62567; path=/; domain=testtest.flyfolder.ru Location: http://testtest.flyfolder.ru/login.php?redirect=posting.php&mode=reply&t=4

, а как сделать относительный путь? Заголовки - какие имеются ввиду? Надо запустить мой скрипт под сниффером, и посмотреть, что он отдает сайту?
Кукис изменил, насчет прав доступа - у меня виндовс) в нем же вроде нет такого? Кроме "только для чтения", но это я убрал.
Неизвестный
07.06.2011, 10:43
общий
Если у Вас NTFS, то в этом случае применяется система управления доступом и разрешениями.
В Windows 7 см. в свойствах (директории или файла) вкладка "Безопасность"
В Windows XP необходимо предварительно снять галку "Использовать простой общий доступ к файлам" в свойствах папки на вкладке "Вид"
Неизвестный
07.06.2011, 12:58
общий
07.06.2011, 13:37
тестировал второй вариант, двойка мне, простите )) я ж совершенно забыл, что ещё выделил ид сессии из первого вызова кУРЛа и добавил его в пост-параметры для второго:

$url = 'http://testtest.flyfolder.ru/login.php';
$postdata = array('username'=>'givi', 'password'=>'111222', 'redirect'=>'viewtopic.php?p=32', 'login'=>'true');


$x = getURL($url, $postdata);

list ($null, $sid) = explode ("sid=", $x, 2);
list ($sid, $null) = explode (";", $sid, 2);


$url = 'http://testtest.flyfolder.ru/posting.php';
$postdata = array('message'=>'blabla_B', 'attach_sig'=>'on', 'mode'=>'reply', 'sid'=>$sid, 't'=>'4', 'post'=>'%CE%F2%EF%F0%E0%E2%E8%F2%FC');

echo getURL($url, $postdata);
Неизвестный
07.06.2011, 13:50
общий
07.06.2011, 13:53
можно удалить это соообщение
Неизвестный
07.06.2011, 13:53
общий
07.06.2011, 13:57
Я сделал все как Волков Алексей aka Lupo сказал, запрос вышел, но не сработало полностью, видимо изза проблем с доступом к файлу кукис. Потом отключил доступ, и наконец-то получилось.

Большое спасибо вам за консультацию.
Неизвестный
07.06.2011, 15:22
общий
прошу Вас дополнить мой ответ следующим текстом:


Я рассматривал второй вариант. Кроме проблемы доступа к файлу cookies, при втором вызове getURL необходимо было передать ещё один POST-параметр: sid. Он устанавливается во время авторизации (в первом вызове getURL) и служит для однозначной идентификации автора сообщения, которое мы передаём при втором вызове getURL. Поскольку работу браузера мы только эмулируем, то проще получить этот параметр, разобрав заголовки сервера, которые возвращает нам первый вызов cURL. Выделим sid из первого вызова cURL и добавим его в POST-параметры для второго:

$url = 'http://testtest.flyfolder.ru/login.php';
$postdata = array('username'=>'givi', 'password'=>'111222', 'redirect'=>'viewtopic.php?p=32', 'login'=>'true');


$x = getURL($url, $postdata);

list ($null, $sid) = explode ("sid=", $x, 2);
list ($sid, $null) = explode (";", $sid, 2);


$url = 'http://testtest.flyfolder.ru/posting.php';
$postdata = array('message'=>'blabla_B', 'attach_sig'=>'on', 'mode'=>'reply', 'sid'=>$sid, 't'=>'4', 'post'=>'%CE%F2%EF%F0%E0%E2%E8%F2%FC');

echo getURL($url, $postdata);
Форма ответа