Zenway

Linux - это интересно!

Вы не вошли.

#1 31-10-2012 17:37:22

vovans
Администратор
Откуда: Ростов-на-Дону
Здесь с 19-10-2010
Сообщений: 448
Сайт
LinuxSeaMonkey 2.13

Импорт базы пользователей из Openfire в Ejabberd

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

Есть плагин openfire-export в модулях у Ejabberd. Отлично. Только там исходники. И ни слова, как его собирать. И собранного модуля в инете не нашёл. По имени файла гугл выдаёт всего 2 страницы в поиске. В общем, удалось-таки разобраться с компилияцией и openfireExporter.jar я получил, установил, экспортировал. Но импортировать это добро в Ejabberd не удалось. Куча ошибок. Наверно, давно формат требуемого xml-файла давно изменился. Как бы там ни было, нужно что-то делать. Гуглением нашёл заметку на сайте Ejabberd, где фигурирует openfire-jabberd-convertor.jar :)

И да, выполнив сие:

$ java -jar openfire-jabberd-convertor.jar users.xml /tmp/jusers/ my.domen.org

и получил-таки директорию с выгрузкой, аналогичной таковой из jabberd14. Теперь заходим в админку - Узлы => Работающие узлы => Резервное копирование => Импорт пользовательских данных из буферной директории jabberd 1.4. Указываем нашу директорию и ждём окончания процесса :)

Жаль, не переносятся группы (shared roster), но всё равно так проще, чем всё руками переносить.

Да, есть ещё скрипт на пёрле для перенесения пользователей из users.xml (экспорт из Openfire) сразу в БД (mysql) Ejabberd:

Скрытый текст
#!/usr/bin/perl -w
#
# Convert a Openfire user export file to a ejabberd mysql user database
#
# See http://www.igniterealtime.org/projects/openfire/plugins/userimportexport/readme.html
# for spec of XML User export format
#
# Licensed in the same terms as perl
#
# Author: Pedro Melo <melo@simplicidade.org>
# Date: 2007/09/20
# Version: 1.0
#

use strict;
use DBI;
use XML::LibXML;
use XML::LibXML::XPathContext;
use Getopt::Long;

# FIXME: not all state are covered yet
my %states = (
  '3 -1 -1' => [ 'B', 'N', 'N' ],
  '2 0 -1' => [ 'F', 'O', 'N' ],
  '2 -1 -1' => [ 'F', 'N', 'N' ],
  '1 -1 -1' => [ 'T', 'N', 'N' ],
  '0 -1 -1' => [ 'N', 'N', 'N' ],
  '0 0 -1' => [ 'N', 'O', 'N' ],
  '0 -1 2' => [ 'N', 'I', 'N' ],
);

my $db;
my $host = 'localhost';
my $user;
my $pass;

my $ok = GetOptions(
  "database=s" => \$db,
  "host=s"     => \$host,
  "user=s"     => \$user,
  "password=s" => \$pass,
);
my $user_file = $ARGV[0];

if (!$ok || !$user_file) {
  print STDERR "Usage: x-convert-openfire-to-ejabberd OPTIONS FILE\n\n";
  print STDERR "Use the OPTIONS to select the destination MySQL database,\n";
  print STDERR "and use your Openfire user export file as the final parameter.\n\n";
  print STDERR "Valid options are:\n";
  print STDERR "    --host: hostname of the MySQL server (default: localhost)\n";
  print STDERR "    --database: database to use in the MySQL server\n";
  print STDERR "    --user: authenticate as\n";
  print STDERR "    --password: authenticate with\n";
  print STDERR "\n";
  exit(1);
}

# Connect to database
my $dbh = DBI->connect(
  "dbi:mysql:database=$db;host=$host",
  $user,
  $pass,
  {
    AutoCommit => 0,
    RaiseError => 1,
    PrintError => 1,
  }
);
if (!$dbh) {
  print STDERR "FATAL: could not connect to the database: $DBI::errstr\n";
  exit(1);
}
$dbh->do(q{SET NAMES 'utf8'});

# Parse the XML file
my $parser = XML::LibXML->new;
my $doc = $parser->parse_file($user_file);
my $xp = XML::LibXML::XPathContext->new($doc);

# Scan for users
foreach my $user ($xp->findnodes('/Openfire/User')) {
  # fetch login and password
  my $login = $xp->findvalue('Username', $user);
  my $passw = $xp->findvalue('Password', $user);
  $dbh->do(q{
    INSERT INTO users (username, password) VALUES (?, ?)
  }, undef, $login, $passw);
  
  # fetch some vcard fields: email, and name
  my $email = exml($xp->findvalue('Email', $user) || '');
  my $name  = exml($xp->findvalue('Name', $user)  || '');
  my $nick  = exml($login);
  my $vcard = q{<vCard xmlns='vcard-temp' version='2.0' prodid='-//HandGen//NONSGML vGen v1.0//EN'>};
  $vcard .= qq{<FN>$name</FN>} if $name;
  $vcard .= qq{<EMAIL><INTERNET/><USERID>$email</USERID></EMAIL>} if $email;
  $vcard .= qq{<NICKNAME>$nick</NICKNAME>};
  $vcard .= q{</vCard>};
  $dbh->do(q{
    INSERT INTO vcard (username, vcard) VALUES (?, ?)
  }, undef, $login, $vcard);
  
  # fetch and insert roster items, including groups
  foreach my $item ($xp->findnodes('Roster/Item', $user)) {
    my $r_jid  = $item->getAttribute('jid');
    my $r_name = $item->getAttribute('name') || '';
    my $r_ask  = $item->getAttribute('askstatus');
    my $r_recv = $item->getAttribute('recvstatus');
    my $r_sub  = $item->getAttribute('substatus');

    my $key = "$r_sub $r_ask $r_recv";
    if (!exists $states{$key}) {
      die "State combination '$key' not found in valid state table\n";
      exit(1);
    }

    my ($sub, $ask, $server) = @{$states{$key}};
    
    $dbh->do(q{
      INSERT INTO rosterusers (username, jid, nick, subscription, ask, server, type,   askmessage, subscribe   )
                       VALUES (?,        ?,   ?,    ?,            ?,   ?,      'item', '',         '' )
    }, undef, $login, $r_jid, $r_name, $sub, $ask, $server);
    
    # deal with groups also
    foreach my $group ($xp->findnodes('Group', $item)) {
      $group = $group->textContent;
      next unless $group;

      $dbh->do(q{
        INSERT INTO rostergroups ( username, jid, grp )
                          VALUES ( ?,        ?,   ?   )
      }, undef, $login, $r_jid, $group);
    }
  }
  
  $dbh->commit;
 # print "User: $login   Passw: $passw   Name: $name  Email: $email\n";
}

$dbh->disconnect;


sub exml {
  # fast path for the commmon case:
  return $_[0] unless $_[0] =~ /[&\"\'<>]/;
  
  my $x = shift;
  for ($x) {
    s/\&/&amp;/g;
    s/\"/&quot;/g;
    s/\'/&apos;/g;
    s/</&lt;/g;
    s/>/&gt;/g;
  }
  return $x;
}

С ним у меня тоже всё получилось.

Кроме того, есть свежая заметка на хабре, как хранить всё необходимое во внешней БД (mysql, н-р). Я себе так и сделал. Странно, что указывая все настройки внешней базы данных почти все данные всё равно хранятся во внутренней по умолчанию :(


zenway admin

Вне форума

Сейчас в этой теме пользователей: 0, гостей: 1
[Bot] CCBot

Подвал форума

Под управлением FluxBB
Модифицировал Visman

[ Сгенерировано за 0.012 сек, 7 запросов выполнено - Использовано памяти: 492.99 Кбайт (Пик: 576.23 Кбайт) ]