форум vBSupport.ru > vBulletin > vBulletin 4.0.x-4.1.х > Made in vBSupport.org 4.0.x-4.1.х
  • »
VBsupport перешел с домена .ORG на родной .RU Ура! Пожалуйста, обновите свои закладки - VBsupport.ru
 
 
 
 
krotozer
Простоузер
Default Перенос БД с IPB 2.1.6 на vBulletin 4.1.4
2

Встала задача перенести базу данных с форума IPB версии 2.1.6 на vBulletin (версия 4.1.4). ImpEX, мягко говоря, спотыкается. Конвертация базы данных IPB в новую версию - не помогает. Приходится в свободное от работы время писать свой конвертер.

Перенос тем, постов, разделов - вопрос десятый. А вот перенос юзеров обламывается из-за различия алгоритмов хэширования паролей. Пароли не изымешь, а менять их без массовых обид не получится. Значит нужно научить vBulletin логике хэширования IPB. Делюсь решением:

Копание в коде форумов выявило сами алгоритмы:

Invision Power Board 2.1.6:
PHP Code:
$hash md5md5($salt) . md5($password) ); 
Где $salt - набор из пяти случайных печатных символов.

vBulletin 4.1.4:
PHP Code:
$hash md5md5($password) . $salt ); 
Где $salt - набор из тридцати случайных печатных символов.

Чтобы научить vBulletin логике IPB, нужно внести правки в файлы:

Файл class_dm_user.php :

1:

Ищем:

PHP Code:
define('SALT_LENGTH'30); 
Заменяем:

PHP Code:
define('SALT_LENGTH'5); 
2:

Ищем:

PHP Code:
    function hash_password($password$salt)
    {
        
// if the password is not already an md5, md5 it now
        
if ($password == '')
        {
        }
        else if (!
$this->verify_md5($password))
        {
            
$password md5($password);
        }

        
// hash the md5'd password with the salt
        
return md5($password $salt);
    } 
Заменяем:

PHP Code:
    function hash_password($password$salt)
    {
        
// if the password is not already an md5, md5 it now
        
if ($password == '')
        {
        }
        else if (!
$this->verify_md5($password))
        {
            
$password md5($password);
        }

        
// hash the md5'd password with the salt
        
return md5(md5($salt) . $password );
    } 
3:

Ищем:

PHP Code:
            if ($password == md5(md5($this->fetch_field('username')) . $salt)) 
Заменяем:

PHP Code:
            if ($password == md5(md5($salt) . md5($this->fetch_field('username')))) 
Файл functions_login.php :

Ищем:

PHP Code:
            $vbulletin->userinfo['password'] != iif($password AND !$md5passwordmd5(md5($password) . $vbulletin->userinfo['salt']), '') AND
            
$vbulletin->userinfo['password'] != iif($md5passwordmd5($md5password $vbulletin->userinfo['salt']), '') AND
            
$vbulletin->userinfo['password'] != iif($md5password_utfmd5($md5password_utf $vbulletin->userinfo['salt']), ''
Заменяем:

PHP Code:
            $vbulletin->userinfo['password'] != iif($password AND !$md5passwordmd5(md5($vbulletin->userinfo['salt']) . md5($password)), '') AND
            
$vbulletin->userinfo['password'] != iif($md5passwordmd5(md5($vbulletin->userinfo['salt']) . $md5password), '') AND
            
$vbulletin->userinfo['password'] != iif($md5password_utfmd5(md5($vbulletin->userinfo['salt']) . $md5password_utf), ''
Файл profile.php :

Ищем:

PHP Code:
        if (md5($vbulletin->userinfo['password'] . COOKIE_SALT) == $vbulletin->GPC[COOKIE_PREFIX 'password'] AND
            
$vbulletin->GPC[COOKIE_PREFIX 'userid'] == $vbulletin->userinfo['userid']
        )
        {
            
vbsetcookie('password'md5(md5($vbulletin->GPC['newpassword'] . $vbulletin->userinfo['salt']) . COOKIE_SALT), truetruetrue);
        } 
Заменяем:

PHP Code:
        if (md5($vbulletin->userinfo['password'] . COOKIE_SALT) == $vbulletin->GPC[COOKIE_PREFIX 'password'] AND
            
$vbulletin->GPC[COOKIE_PREFIX 'userid'] == $vbulletin->userinfo['userid']
        )
        {
            
vbsetcookie('password'md5(md5(md5($vbulletin->userinfo['salt']) . $vbulletin->GPC['newpassword']) . COOKIE_SALT), truetruetrue);
        } 
Хак работает - форум спокойно принимает пользователей из старой БД.

ЗЫ: Я знаю, что эта тема относится скорее к разделу http://vbsupport.ru/forum/forumdisplay.php?f=57, но поссчитал это хаком, потому выложил тут. Если не прав - исправлюсь.
Bot
Yandex Bot Yandex Bot is online now
 
Join Date: 05.05.2005
Реклама на форуме А что у нас тут интересного? =)
 
 
kerk
k0t
 
kerk's Avatar
Default
0

ок, сейчас будет работать в том виде, как исправления внесены, а дальше?
после обновления движка?
планируется каждый раз делать все перечисленные теложвижения?
или все же заставить узеров "вернуть" пасс через встроенную систему
 
 
krotozer
Простоузер
Default
0

Пока не решено. Проблема в том, что на форуме - свыше 250 000 пользователей. Есть "висячие" и/или заброшенные. Когда будем проводить "чистку рядов", выберем политику сохранности юзеров. Может тогда и обяжем народ менять пароли. А может и нет.

Форум не заставишь работать сразу с двумя алгоритмами. Точнее, заставить можно, но разве оно того стоит? Неужели форум обязательно обновлять буквально с каждой новой версией?

Скорее всего, поставлю логгер, который будет автоматом собирать и хэшировать пароли в отдельную таблицу. Пособираем пол годика, а потом просто скинем нарост из "мёртвых душ", оставив только тех, кто за это время авторизовался. А заставить их авторизоваться по-новой - просто: удаляем из БД все сессии и всё

Last edited by krotozer : 08-14-2011 at 07:55 PM.
 
 
хрюк
Гость
Default

Эм, поставить объяву на форум намного проще. IMO
 
 
krotozer
Простоузер
Default
0

Не тот контингент. Половина - ничего не читают, а просто сидят в своей теме, да общаются. Да и не хочу я обязывать людей специально вводить свои логины и пароли, ведь в правилах чётко сказано: "Администрация никогда и ни при каких обстоятельствах не потребует у вас логин и пароль, т.к. не нуждается в них.".
 
 
kerk
k0t
 
kerk's Avatar
Default
0

Quote:
Originally Posted by krotozer View Post
ни при каких обстоятельствах не потребует у вас логин и пароль, т.к. не нуждается в них
администрации пароли и не нужны, пользователь сам может восстановить пасс, для этого в вобле целая система есть
 
 
krotozer
Простоузер
Default
0

Quote:
Originally Posted by kerk View Post
администрации пароли и не нужны, пользователь сам может восстановить пасс, для этого в вобле целая система есть
Я же говорю: не стоит их ни к чему подобному принуждать. Нет желания "злить толпу") Тем более, что программа изменений и так растянута по времени. Там не только форум, но и CMS.
 
 
kerk
k0t
 
kerk's Avatar
Default
0

Quote:
Originally Posted by krotozer View Post
CMS, ради которой и выбрали vBulletin Suite.

ох эта "CMS" еще мозги съест...
 
 
krotozer
Простоузер
Default
4

Я приведу здесь ещё одну наработку по сабжу.
Однако, я не уверен, что эта информация кому-то поможет.
Зато позволит разобраться в одном из механизмов vBulletin.

Подтема: Перенос разделов.

У IPB 2.1.6 в БД ведущими полями являются:
id - содержит номер раздела;
parent_id - содержит id родительского раздела;
position - содержит индекс сортировки.
Даю замечания:
IPB 2.1.6 не позволяет создавать категории разделов внутри разделов! Только в корневом разделе. Эти категории в БД представляются как разделы - такие же, как и любые другие. Отличить их можно по parent_id, который равен -1 . Любой раздел с таким parent_id форум считает категорией. Те якобы категории, что отображаются внутри разделов, - не более чем название родительского раздела.

position - индексы в этом поле в БД могут и часто повторяются. Форум учитывает их уже после того, как отсеет записи по parent_id .
Теперь скажем про vBulletin 4.1.4:
Здесь категории и разделы - это практически одно и то же, но отображаются по-разному. Для форума категория - это параметр раздела. Т.е. параметр указывает на то, что это именно категория. Записывается это в поле options. Например, для раздела оно может быть таким: 97991, а для категории - таким: 97987.

В качестве id тут выступает forumid. В качестве parent_id тут - parentid. Указателем на корневой раздел так же является -1 . В качестве position тут - displayorder.

Но ещё тут есть очень хитрые поля: parentlist и childlist. Первый содержит индексы всех родительских разделов. Второй - индексы вложенных разделов. По ним форум определяет информацию для отображения разделов, а так же порядок их отображения. В поле displayorder при этом для всех разделов установлен индекс 1 .
Вот тут по-подробнее:
Формат parentlist такой: индексы, разделённые запятыми. Первым индексом всегда идёт ID текущего раздела. Последующими идут все разделы, в которые он вложен в порядке возрастания старшинства. Список всегда завершает терминатор -1. Обратите внимание! -1 здесь - это не указатель на корневой раздел, а лишь знак того, что список закончился!

Формат childlist такой: так же, как и parentlist, этот список начинается с ID текущего раздела, а заканчивается терминатором -1. Но между ними идёт список вложенных разделов по такому порядку: в первую очередь перебираются вложенности, а уж потом элементы списков разделов.

Поясню сказанное на примере. Для этого приведу структуру разделов:
{forumid} | {name} | {parentid}

171 | Категория-1 | -1
172 | Раздел-1 | 171
174 | Раздел-1-А | 172
175 | Раздел-1-Б | 172
173 | Раздел-2 | 171
176 | Раздел-2-А | 173
177 | Раздел-2-Б | 173
{parentlist} | {name} | {childlist}

171,-1 | Категория-1 | 171,172,174,175,173,176,177,-1
172,171,-1 | Раздел-1 | 172,174,175,-1
174,172,171,-1 | Раздел-1-А | 174,-1
175,172,171,-1 | Раздел-1-Б | 175,-1
173,171,-1 | Раздел-2 | 173,176,177,-1
176,173,171,-1 | Раздел-2-А | 176,-1
177,173,171,-1 | Раздел-2-Б | 177,-1
Теперь скажу, как сформировать эти списки:

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

PHP Code:
# Перебираем весь массив таблицы разделов и устанавливаем везде childlist равным forumid для каждой записи.
Tree({массив разделов}, -1"-1");
# Перебираем весь массив таблицы разделов и в конце каждой записи childlist добавляем терминатор ",-1".

function Tree($arr$parent$parent_list) {

    foreach(
$arr as $string) {
        if(
$string['parentid'] == $parent) {

            
$this_parent_list $string['forumid'].','.$parent_list;
            
# Обновляем запись о текущем разделе в БД, подменяя parentlist на значение $this_parent_list.

            
$parent_items explode(','$string['parentlist']);
            foreach(
$parent_items as $parent_item) {
                if(
$parent_item != -&& $parent_item != $string['forumid']) {

                    
# Читаем childlist у записи с forumid равным $parent_item.
                    
$this_child_list = {прочитанный childlist}.','.$string['forumid'];
                    
# Обновляем эту запись, подменяя childlist на значение $this_child_list.

                
}
            }
            
Tree($arr$string['forumid'], $this_parent_list);
        }
    }

Вот такой код может заполнить эти списки, ориентируясь только на id, parent_id и position от IPB 2.1.6.
Теперь дам предостережения:
Если изменить таблицу разделов, то форум её не увидит. Необходимо "перестроить структуру разделов" в пункте панели администратора "обслуживание". А если по просту, обновить КЭШ. Однако, "перестроить" тут имеет особое значение.

Дело в том, что даже если составить для форума parentlist и childlist, то он их проигнорирует и после перестройки структуры отсортирует разделы по именам.

Чтобы он-таки принял порядок из IPB 2.1.6, необходимо транслировать значения position из IPB в поля displayorder у vBulletin и "перестроить структуру разделов".
Надеюсь, эти грабли пригодятся.
 
 
krotozer
Простоузер
Default
0

Люди, я вам нечаянно соврал!
На практике полной конвертации БД форума выяснилось, что эти списки parentlist и childlist таки оказывают существенное влияние на индексацию разделов форумом. Без них форум теряет связи между большей частью разделов. Т.е. они в базе данных присутствуют, но не доступны пользователю. Равно как и темы с постами в них.
 


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off




All times are GMT +4. The time now is 11:32 PM.


Powered by vBulletin® Version 3.6.2
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Loading...