Постинг сообщений на форумы Ipb V 2.2

  • Автор темы Gisma
  • Дата начала
G

Gisma

#1
Описание библиотеки

Эта библиотека предназначена для постинга сообщений на форум.

Требования к установке

- наличие curl-расширения на сервере;

- определение констант IPB_SPAM_COOKIE_PATH;

- зарегистрированный пользователь на сайте (бот);


Ограничения

- Библиотека работает с версиями IPB v. 2.2.x с остальными работа не гарантирована;

- на файл кукисов должны быть установлены права на запись;

- библиотека не работает с модификация форума IPB, где пути к урлам видоизменены с помощью mod_rewrite. В этом случае библиотеку придется немного править (конкретно, исправить урлы в системе)

- библиотека не работает с прокси. Для включения этой возможности придется модифицировать конструктор.
Использование

Код:
 var_dump($ipb->setForumInfo('http://your_site/forum/','login','password'));
var_dump($ipb->createPost('2','IPB_SPAM','test','Lorem ipsum dolor sit amet...'));
Описание методов и констант

Констанста IPB_SPAM_COOKIE_PATH - определяет путь к файлу, куда будут сохранены кукисы. На файле должны быть установлены правы 0777. int createPost($forum_id,$subject,$description,$content) - Публикует новый пост на форуме. Возвращает код ошибки, 0 в случае удачи. Параметры функции:

$forum_id - Индекс форума
$subject - Тема поста
$description - Малое описание поста
$content - Текст поста

string describeError($nErrorCode)- По коду ошибки возвращает описание ошибки.

void setForumInfo($url,$login,$password) - устанавливает данные доступа к форуму. Эта функция должна быть вызвана ПЕРЕД постингом сообщения. Параметры:

$url - путь к форуму, должен завершаться на
$login - логин к форуму
$password - Пароль бота на сервере

Полный список ошибок

IPB_SPAM_UNKNOWN_ERROR - код: 100. Неизвестная ошибка

IPB_SPAM_ERROR_ADD_POST_FAILURE - код: 4. Ошибка добавления нового поста. Возникает в случаях когда скрипт форума не ответил редиректом на созданный топик

IPB_SPAM_ERROR_NEWTOPIC_FORM - код: 3. Библиотека не нашла форму добавления поста на форуме.

IPB_SPAM_ERROR_LOGIN - код: 2. Библиотека не смогла авторизироваться

IPB_SPAM_CURL_ERROR - код: 1. Ошибка CURL на этапе вызове скрипта.

IPB_SPAM_NO_ERROR - код: 0 Нет ошибок

Код:
<?
//************************************************************//
//	  Библиотека для организации взаимодействия с		 //
//		 удаленным ipb-форумом							 //
//	  Copyright (c) 2006 ООО SmartDesign				 //
//			  отдел/сектор								 //
//	  Email:  Dmitrey.Schevchenko@gmail.com			  //
//															//
// Разработчик: Gisma (08.05.2007)						  //
// Модифицирован: 08.05.2007 by Gisma					 //
//															//
//************************************************************//
// Проверки 
// Установлена ли CURL-библиотека
$aExtensions = get_loaded_extensions();
$bFound = array_search('curl',$aExtensions);
if (!$bFound) {
trigger_error('IPB Spam library Curl extensions not found',E_USER_ERROR);
}
// Есть ли путь COOKIE-файлу
if (!defined('IPB_SPAM_COOKIE_PATH')) {
define('IPB_SPAM_COOKIE_PATH',dirname(__FILE__).'/cookie.txt');
}

// Объявления
define('IPB_SPAM_VERSION','0.01');
define('IPB_SPAM_UNKNOWN_ERROR',100);
define('IPB_SPAM_ERROR_ADD_POST_FAILURE',4);
define('IPB_SPAM_ERROR_NEWTOPIC_FORM',3);
define('IPB_SPAM_ERROR_LOGIN',2);
define('IPB_SPAM_CURL_ERROR',1);
define('IPB_SPAM_NO_ERROR',0);
class IPB_SPAM {
/**
*  @var Хранит URL форума
*/
protected $url;
/**
*  @var Хранит логин бота
*/
protected $login;
/**
*  @var Хранит пароль бота
*/
protected $password;
/**
*  @var Хранит код ошибки CURL
*/
protected $szCurlError;
/**
*  @var Ресурс CURL
*/
protected $curl;
function IPB_SPAM() {
$this->curl = curl_init();

// CURL будет возвращать результат, а не выводить его
curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, 1);
// запретить проверку сертификата удаленного сервера
curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, 0);
// устанавливаем User-Agent
curl_setopt($this->curl, CURLOPT_USERAGENT, 'IPB SPAM v.0.01 by Gisma');

// включаем поддержку куки
$szPath = IPB_SPAM_COOKIE_PATH;
curl_setopt($this->curl, CURLOPT_COOKIEJAR, $szPath);
curl_setopt($this->curl, CURLOPT_COOKIEFILE, $szPath);

// следуем за редиректами, на всякий случай;)
curl_setopt($this->curl, CURLOPT_HEADER, true);
//curl_setopt($this->curl,CURLOPT_FOLLOWLOCATION,1);

}
/**
*  -------------------------------------------------------------------------------------------
*  @desc Создает новый пост 
*  @param $forum_id int индекс форума
*  @param $subject string тема поста
*  @param $content string содержимое поста
*  @return 
*  -------------------------------------------------------------------------------------------
*/
public function createPost($forum_id,$subject,$description,$content) {
// Открываем главную
$nResult = $this->__openIndex();
if (!empty($nResult)) return $nResult;

// Входим в систему
$nResult = $this->__login();
if (!empty($nResult)) return $nResult;

// Теперь требуется открыть страницу добавления сообщения
$aHidden = array();
$szAction = '';
$nResult = $this->__responseNewTopicPost($forum_id,$aHidden,$szAction);
if (!empty($nResult)) return $nResult;

// Посылаем форму отправки сообщения

$aHidden['TopicTitle'] = $subject;
$aHidden['TopicDesc'] = $description;
$aHidden['REPLIER'] = '1';
$aHidden['Post'] = $content;
$method = 'post';
$match = '/.+/';

$nResult = $this->__query(
$szAction,
$method,
$match,
$aHidden
);

if ($nResult != 0) {
if ($nResult == IPB_SPAM_CURL_ERROR) {
return IPB_SPAM_CURL_ERROR;
} else {
return IPB_SPAM_ERROR_ADD_POST_FAILURE;
}

}
unlink(IPB_SPAM_COOKIE_PATH);
$aInfo = curl_getinfo($this->curl);

return $aInfo['url'];
}
/**
*  -------------------------------------------------------------------------------------------
*  @desc Устанавливает данные об форуме и боте
*  @param $url string путь к форуму
*  @param $login string логин пользователя
*  @param $password string пароль пользователя
*  @return 
*  -------------------------------------------------------------------------------------------
*/
public function setForumInfo($url,$login,$password) {
$this->url = $url;
$this->login = $login;
$this->password = $password;
}
/**
*  -------------------------------------------------------------------------------------------
*  @desc Возвращает строковое значение ошибки 
*  @param $nErrorCode int возвращает код ошибки
*  @return 
*  -------------------------------------------------------------------------------------------
*/
public function describeError($nErrorCode) {
$szResult = '';
switch ($nErrorCode) {
case IPB_SPAM_UNKNOWN_ERROR:
$szResult = 'Unknown error';
break;
case IPB_SPAM_ERROR_ADD_POST_FAILURE:
$szResult = 'Error submiting new post form. Post not created';
break;
case IPB_SPAM_ERROR_NEWTOPIC_FORM:
$szResult = 'Error, new topic form not found';
break;
case IPB_SPAM_CURL_ERROR:
$szResult = 'Curl error, '.$this->szCurlError;
break;
case IPB_SPAM_ERROR_LOGIN: 
$szResult = 'Error login/password';
break;
case IPB_SPAM_NO_ERROR:
$szResult = 'No Error';
break;
default:
$szResult = 'No Error';
}	
return $szResult;
}
/**
*  -------------------------------------------------------------------------------------------
*  @desc Осуществляет вход бота в систему
*  @return 
*  -------------------------------------------------------------------------------------------
*/
function __openIndex() {
// забиваем начальные данные 
$url = 'index.php';
$method = 'get';
$aData = array();
$match = '/.+/';

// оформляем запрос
$nResult = $this->__query(
$this->url.$url,
$method,
$match,
$aData
);
if ($nResult != 0) {
if ($nResult == IPB_SPAM_CURL_ERROR) {
return IPB_SPAM_CURL_ERROR;
} else {
return IPB_SPAM_UNKNOWN_ERROR;
}

}
return IPB_SPAM_NO_ERROR;
}
/**
*  -------------------------------------------------------------------------------------------
*  @desc Осуществляет вход бота в систему
*  @return 
*  -------------------------------------------------------------------------------------------
*/
function __login() {
// забиваем начальные данные 
$url = 'index.php?act=Login&CODE=01&CookieDate=1';
$method = 'post';
$aData['UserName'] = $this->login;
$aData['PassWord'] = $this->password;

$match = '/<div id="redirectwrap">.*?<\/div>/ms';

// оформляем запрос
$nResult = $this->__query(
$this->url.$url,
$method,
$match,
$aData

);
if ($nResult != 0) {
if ($nResult == IPB_SPAM_CURL_ERROR) {
return IPB_SPAM_CURL_ERROR;
} else {
return IPB_SPAM_ERROR_LOGIN;
}

}
return IPB_SPAM_NO_ERROR;
}
/**
*  -------------------------------------------------------------------------------------------
*  @desc Входим на форму создания нового топика
*  @param $forum_id int Индекс форума
*  @param $subject string Строка темы сообщения
*  @param $content string Текст сообщения
*  @return 
*  -------------------------------------------------------------------------------------------
*/
function __responseNewTopicPost($forum_id,&$aHidden = array(),&$szPostUrl) {
// Алгоритм:
// 1. Открываем страницу
// 2. Находим форму
// 3. Вырываем все хиддены + url для формы
$url = 'index.php?act=post&do=new_post&f='.$forum_id;
$method = 'get';
$aData = array();
$match = '/<form id=\'postingform\'[^>]+>(.+?)<\/form>/ms';

// оформляем запрос, на получение страницы формы
$nResult = $this->__query(
$this->url.$url,
$method,
$match,
$aData,
$szContent
);

if ($nResult != 0) {
if ($nResult == IPB_SPAM_CURL_ERROR) {
return IPB_SPAM_CURL_ERROR;
} else {
return IPB_SPAM_ERROR_NEWTOPIC_FORM;
}

}
// выдираем контент форм
preg_match($match,$szContent,$aMatch);
$szFormContent = $aMatch[1];
//		_debug($szFormContent );
// Находим action формы
$patternFormUrl = '/<form id=\'postingform\' action=\'(.*?)\'[^>]+/ms';
$bMatch = preg_match($patternFormUrl,$szContent,$aMatch);

if ($bMatch) {
$szPostUrl = $aMatch[1];
} else {
return IPB_SPAM_ERROR_NEWTOPIC_FORM;
}
// Находим все HIDDEN-поля
$patternHidden = "/<input type='hidden' name='([^\']+)'.+?value='(.*?)' \/>/ms";

$aMatch = array();	
preg_match_all(
$patternHidden,
$szFormContent ,
$aMatch,
PREG_SET_ORDER);
if (is_array($aMatch)) {
$aHidden = array();
foreach ($aMatch as $row) {
$aHidden[$row[1]] = $row[2];
}

return IPB_SPAM_NO_ERROR;
} else {
return IPB_SPAM_ERROR_NEWTOPIC_FORM;
}

}
/**
*  -------------------------------------------------------------------------------------------
*  @desc Осуществляет подзапрос
*  @param $url string 
*  @param $method string 
*  @param $match string регулярное выражение для сравнения с контентом
*  @param $aData array массив подающихся данных на запрос
*  @param $szContent string строка, хранящая текст сграбленной страницы
*  @return 
*  -------------------------------------------------------------------------------------------
*/
function __query($url,$method,$match,$aData,&$szContent = NULL) {
// устанавливаем тип запроса
if (strtoupper($method) == 'POST') {
curl_setopt($this->curl, CURLOPT_POST, 1);
curl_setopt($this->curl, CURLOPT_POSTFIELDS, $aData);
}

// устанавливаем данные для запроса
curl_setopt($this->curl, CURLOPT_URL, $url);

$content = $this->__exec_with_redirect();
// проверяем на ошибку
if ($content === FALSE) {
$this->szCurlError = curl_error($this->curl);
return IPB_SPAM_CURL_ERROR;
}
// проверяем результаты на совпадение с регэкспом

$bMatch = preg_match($match,$content);
if ($bMatch) {
$szContent = $content;
return IPB_SPAM_NO_ERROR;
} else {
return 2;
}

}
/**
*  -------------------------------------------------------------------------------------------
*  @desc Функция заплатка. В режиме safe_mode класс не может следовать за редиректами
*  CURLOPT_FOLLOWLOCATION
*	@php.net
*	If you are trying to use CURLOPT_FOLLOWLOCATION and you get this warning:
*  Warning: curl_setopt() [function.curl-setopt]: CURLOPT_FOLLOWLOCATION cannot be activated when in safe_mode or an 
*  open_basedir is set... then you will want to read http://www.php.net/ChangeLog-4.php which says "Disabled 
*  CURLOPT_FOLLOWLOCATION in curl when open_basedir or safe_mode are enabled." as of PHP 4.4.4/5.1.5. This is due to 
*  the fact that curl is not part of PHP and doesn't know the values of open_basedir or safe_mode, so you could 
*  comprimise your webserver operating in safe_mode by redirecting (using header('Location: ...')) to "file://" urls, 
*  which curl would have gladly retrieved.
*  Until the curl extension is changed in PHP or curl (if it ever will) to deal with "Location:" headers, here is a 
*  far from perfect remake of the curl_exec function that I am using.
*  Since there's no curl_getopt function equivalent, you'll have to tweak the function to make it work for your 
*  specific use. As it is here, it returns the body of the response and not the header. It also doesn't deal with 
*  redirection urls with username and passwords in them.
*  @return 
*  -------------------------------------------------------------------------------------------
*/
function __exec_with_redirect() {
static $curl_loops = 0;
static $curl_max_loops = 20;
if ($curl_loops++ >= $curl_max_loops)
{

$curl_loops = 0;
return FALSE;
}
$data = curl_exec($this->curl);
$data1 = $data;
//		_debug(strstr($data,"\n\n"));
//		_debug(strstr($data,"\n\r\n"));
list($header, $data) = explode("\n\r\n", $data, 2);
$http_code = curl_getinfo($this->curl, CURLINFO_HTTP_CODE);

if ($http_code == 301 || $http_code == 302) {
$matches = array();
preg_match('/Location:(.*?)\n/', $data1, $matches);

$url = @parse_url(trim(array_pop($matches)));
if (!$url) {
//couldn't process the url to redirect to
$curl_loops = 0;
return $data;
}
$last_url = parse_url(curl_getinfo($this->curl, CURLINFO_EFFECTIVE_URL));
if (!$url['scheme'])
$url['scheme'] = $last_url['scheme'];
if (!$url['host'])
$url['host'] = $last_url['host'];
if (!$url['path'])
$url['path'] = $last_url['path'];
$new_url = $url['scheme'] . '://' . $url['host'] . $url['path'] . ($url['query']?'?'.$url['query']:'');
curl_setopt($this->curl, CURLOPT_POST, 0);
curl_setopt($this->curl, CURLOPT_URL, $new_url);
return $this->__exec_with_redirect();
} else {
$curl_loops=0;

return $data;
}
}
}
?>
Оригинал: http://wiki.extasy-cms.com/index.php/IPB_SPAM
 
D

deadt04ka

#2
Блин :) недавно писал похожую вещь!
У меня с добавленем столько гемороя было я все свои функции написал для добавления.. а тут :)
 
˸
#5
Хм.. А есть ли у вас скриптик, с помощью которого на форумах Invision 1.3.1 можно было бы каждому пользователю по личному сообщению выслать?
 
˸
#7
нет, там не ради спама, а для разового использования... долгая история, если есть, подкинте плиз)