Current oav website

This commit is contained in:
Charlie Root
2023-03-20 12:18:38 +01:00
commit a096ce07cf
3270 changed files with 261778 additions and 0 deletions

View File

@ -0,0 +1,228 @@
<?php
/**
* @brief importExport, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugins
*
* @copyright Olivier Meunier & Association Dotclear
* @copyright GPL-2.0-only
*/
if (!defined('DC_RC_PATH')) {return;}
class dcExportFlat extends dcIeModule
{
public function setInfo()
{
$this->type = 'export';
$this->name = __('Flat file export');
$this->description = __('Exports a blog or a full Dotclear installation to flat file.');
}
public function process($do)
{
# Export a blog
if ($do == 'export_blog' && $this->core->auth->check('admin', $this->core->blog->id)) {
$fullname = $this->core->blog->public_path . '/.backup_' . sha1(uniqid());
$blog_id = $this->core->con->escape($this->core->blog->id);
try
{
$exp = new flatExport($this->core->con, $fullname, $this->core->prefix);
fwrite($exp->fp, '///DOTCLEAR|' . DC_VERSION . "|single\n");
$exp->export('category',
'SELECT * FROM ' . $this->core->prefix . 'category ' .
"WHERE blog_id = '" . $blog_id . "'"
);
$exp->export('link',
'SELECT * FROM ' . $this->core->prefix . 'link ' .
"WHERE blog_id = '" . $blog_id . "'"
);
$exp->export('setting',
'SELECT * FROM ' . $this->core->prefix . 'setting ' .
"WHERE blog_id = '" . $blog_id . "'"
);
$exp->export('post',
'SELECT * FROM ' . $this->core->prefix . 'post ' .
"WHERE blog_id = '" . $blog_id . "'"
);
$exp->export('meta',
'SELECT meta_id, meta_type, M.post_id ' .
'FROM ' . $this->core->prefix . 'meta M, ' . $this->core->prefix . 'post P ' .
'WHERE P.post_id = M.post_id ' .
"AND P.blog_id = '" . $blog_id . "'"
);
$exp->export('media',
'SELECT * FROM ' . $this->core->prefix . "media WHERE media_path = '" .
$this->core->con->escape($this->core->blog->settings->system->public_path) . "'"
);
$exp->export('post_media',
'SELECT media_id, M.post_id ' .
'FROM ' . $this->core->prefix . 'post_media M, ' . $this->core->prefix . 'post P ' .
'WHERE P.post_id = M.post_id ' .
"AND P.blog_id = '" . $blog_id . "'"
);
$exp->export('ping',
'SELECT ping.post_id, ping_url, ping_dt ' .
'FROM ' . $this->core->prefix . 'ping ping, ' . $this->core->prefix . 'post P ' .
'WHERE P.post_id = ping.post_id ' .
"AND P.blog_id = '" . $blog_id . "'"
);
$exp->export('comment',
'SELECT C.* ' .
'FROM ' . $this->core->prefix . 'comment C, ' . $this->core->prefix . 'post P ' .
'WHERE P.post_id = C.post_id ' .
"AND P.blog_id = '" . $blog_id . "'"
);
# --BEHAVIOR-- exportSingle
$this->core->callBehavior('exportSingle', $this->core, $exp, $blog_id);
$_SESSION['export_file'] = $fullname;
$_SESSION['export_filename'] = $_POST['file_name'];
$_SESSION['export_filezip'] = !empty($_POST['file_zip']);
http::redirect($this->getURL() . '&do=ok');
} catch (Exception $e) {
@unlink($fullname);
throw $e;
}
}
# Export all content
if ($do == 'export_all' && $this->core->auth->isSuperAdmin()) {
$fullname = $this->core->blog->public_path . '/.backup_' . sha1(uniqid());
try
{
$exp = new flatExport($this->core->con, $fullname, $this->core->prefix);
fwrite($exp->fp, '///DOTCLEAR|' . DC_VERSION . "|full\n");
$exp->exportTable('blog');
$exp->exportTable('category');
$exp->exportTable('link');
$exp->exportTable('setting');
$exp->exportTable('user');
$exp->exportTable('pref');
$exp->exportTable('permissions');
$exp->exportTable('post');
$exp->exportTable('meta');
$exp->exportTable('media');
$exp->exportTable('post_media');
$exp->exportTable('log');
$exp->exportTable('ping');
$exp->exportTable('comment');
$exp->exportTable('spamrule');
$exp->exportTable('version');
# --BEHAVIOR-- exportFull
$this->core->callBehavior('exportFull', $this->core, $exp);
$_SESSION['export_file'] = $fullname;
$_SESSION['export_filename'] = $_POST['file_name'];
$_SESSION['export_filezip'] = !empty($_POST['file_zip']);
http::redirect($this->getURL() . '&do=ok');
} catch (Exception $e) {
@unlink($fullname);
throw $e;
}
}
# Send file content
if ($do == 'ok') {
if (!file_exists($_SESSION['export_file'])) {
throw new Exception(__('Export file not found.'));
}
ob_end_clean();
if (substr($_SESSION['export_filename'], -4) == '.zip') {
$_SESSION['export_filename'] = substr($_SESSION['export_filename'], 0, -4); //.'.txt';
}
# Flat export
if (empty($_SESSION['export_filezip'])) {
header('Content-Disposition: attachment;filename=' . $_SESSION['export_filename']);
header('Content-Type: text/plain; charset=UTF-8');
readfile($_SESSION['export_file']);
unlink($_SESSION['export_file']);
unset($_SESSION['export_file'], $_SESSION['export_filename'], $_SESSION['export_filezip']);
exit;
}
# Zip export
else {
try
{
$file_zipname = $_SESSION['export_filename'] . '.zip';
$fp = fopen('php://output', 'wb');
$zip = new fileZip($fp);
$zip->addFile($_SESSION['export_file'], $_SESSION['export_filename']);
header('Content-Disposition: attachment;filename=' . $file_zipname);
header('Content-Type: application/x-zip');
$zip->write();
unlink($_SESSION['export_file']);
unset($zip, $_SESSION['export_file'], $_SESSION['export_filename'], $file_zipname);
exit;
} catch (Exception $e) {
unset($zip, $_SESSION['export_file'], $_SESSION['export_filename'], $file_zipname);
@unlink($_SESSION['export_file']);
throw new Exception(__('Failed to compress export file.'));
}
}
}
}
public function gui()
{
echo
'<form action="' . $this->getURL(true) . '" method="post" class="fieldset">' .
'<h3>' . __('Single blog') . '</h3>' .
'<p>' . sprintf(__('This will create an export of your current blog: %s'), '<strong>' . html::escapeHTML($this->core->blog->name)) . '</strong>.</p>' .
'<p><label for="file_name">' . __('File name:') . '</label>' .
form::field('file_name', 50, 255, date('Y-m-d-H-i-') . html::escapeHTML($this->core->blog->id . '-backup.txt')) .
'</p>' .
'<p><label for="file_zip" class="classic">' .
form::checkbox(['file_zip', 'file_zip'], 1) . ' ' .
__('Compress file') . '</label>' .
'</p>' .
'<p class="zip-dl"><a href="' . $this->core->decode('admin.media', ['d' => '', 'zipdl' => '1']) . '">' .
__('You may also want to download your media directory as a zip file') . '</a></p>' .
'<p><input type="submit" value="' . __('Export') . '" />' .
form::hidden(['do'], 'export_blog') .
$this->core->formNonce() . '</p>' .
'</form>';
if ($this->core->auth->isSuperAdmin()) {
echo
'<form action="' . $this->getURL(true) . '" method="post" class="fieldset">' .
'<h3>' . __('Multiple blogs') . '</h3>' .
'<p>' . __('This will create an export of all the content of your database.') . '</p>' .
'<p><label for="file_name2">' . __('File name:') . '</label>' .
form::field(['file_name', 'file_name2'], 50, 255, date('Y-m-d-H-i-') . 'dotclear-backup.txt') .
'</p>' .
'<p><label for="file_zip2" class="classic">' .
form::checkbox(['file_zip', 'file_zip2'], 1) . ' ' .
__('Compress file') . '</label>' .
'</p>' .
'<p><input type="submit" value="' . __('Export') . '" />' .
form::hidden(['do'], 'export_all') .
$this->core->formNonce() . '</p>' .
'</form>';
}
}
}

View File

@ -0,0 +1,81 @@
<?php
/**
* @brief importExport, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugins
*
* @copyright Olivier Meunier & Association Dotclear
* @copyright GPL-2.0-only
*/
if (!defined('DC_RC_PATH')) {
return;
}
abstract class dcIeModule
{
public $type;
public $id;
public $name;
public $description;
protected $import_url;
protected $export_url;
protected $core;
public function __construct($core)
{
$this->core = &$core;
$this->setInfo();
if (!in_array($this->type, ['import', 'export'])) {
throw new Exception(sprintf('Unknow type for module %s', get_class($this)));
}
if (!$this->name) {
$this->name = get_class($this);
}
$this->id = get_class($this);
$this->url = sprintf('plugin.php?p=importExport&type=%s&module=%s', $this->type, $this->id);
}
public function init()
{
}
abstract protected function setInfo();
final public function getURL($escape = false)
{
return $escape ? html::escapeHTML($this->url) : $this->url;
}
abstract public function process($do);
abstract public function gui();
protected function progressBar($percent)
{
$percent = ceil($percent);
if ($percent > 100) {
$percent = 100;
}
return '<div class="ie-progress"><div style="width:' . $percent . '%">' . $percent . ' %</div></div>';
}
protected function autoSubmit()
{
return form::hidden(['autosubmit'], 1);
}
protected function congratMessage()
{
return
'<h3>' . __('Congratulation!') . '</h3>' .
'<p class="success">' . __('Your blog has been successfully imported. Welcome on Dotclear 2!') . '</p>' .
'<ul><li><strong><a href="' . $this->core->adminurl->decode('admin.post') . '">' . __('Why don\'t you blog this now?') . '</a></strong></li>' .
'<li>' . __('or') . ' <a href="' . $this->core->adminurl->decode('admin.home') . '">' . __('visit your dashboard') . '</a></li></ul>';
}
}

View File

@ -0,0 +1,614 @@
<?php
/**
* @brief importExport, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugins
*
* @copyright Olivier Meunier & Association Dotclear
* @copyright GPL-2.0-only
*/
if (!defined('DC_RC_PATH')) {return;}
class dcImportDC1 extends dcIeModule
{
protected $con;
protected $prefix;
protected $blog_id;
protected $action = null;
protected $step = 1;
protected $post_offset = 0;
protected $post_limit = 20;
protected $post_count = 0;
protected $has_table = [];
protected $vars;
protected $base_vars = [
'db_driver' => 'mysql',
'db_host' => '',
'db_name' => '',
'db_user' => '',
'db_pwd' => '',
'db_prefix' => 'dc_',
'post_limit' => 20,
'cat_ids' => []
];
protected function setInfo()
{
$this->type = 'import';
$this->name = __('Dotclear 1.2 import');
$this->description = __('Import a Dotclear 1.2 installation into your current blog.');
}
public function init()
{
$this->con = &$this->core->con;
$this->prefix = $this->core->prefix;
$this->blog_id = $this->core->blog->id;
if (!isset($_SESSION['dc1_import_vars'])) {
$_SESSION['dc1_import_vars'] = $this->base_vars;
}
$this->vars = &$_SESSION['dc1_import_vars'];
if ($this->vars['post_limit'] > 0) {
$this->post_limit = $this->vars['post_limit'];
}
}
public function resetVars()
{
$this->vars = $this->base_vars;
unset($_SESSION['dc1_import_vars']);
}
public function process($do)
{
$this->action = $do;
}
# We handle process in another way to always display something to
# user
protected function guiprocess($do)
{
switch ($do) {
case 'step1':
$this->vars['db_driver'] = $_POST['db_driver'];
$this->vars['db_host'] = $_POST['db_host'];
$this->vars['db_name'] = $_POST['db_name'];
$this->vars['db_user'] = $_POST['db_user'];
$this->vars['db_pwd'] = $_POST['db_pwd'];
$this->vars['post_limit'] = abs((integer) $_POST['post_limit']) > 0 ? $_POST['post_limit'] : 0;
$this->vars['db_prefix'] = $_POST['db_prefix'];
$db = $this->db();
$db->close();
$this->step = 2;
echo $this->progressBar(1);
break;
case 'step2':
$this->step = 2;
$this->importUsers();
$this->step = 3;
echo $this->progressBar(3);
break;
case 'step3':
$this->step = 3;
$this->importCategories();
if ($this->core->plugins->moduleExists('blogroll')) {
$this->step = 4;
echo $this->progressBar(5);
} else {
$this->step = 5;
echo $this->progressBar(7);
}
break;
case 'step4':
$this->step = 4;
$this->importLinks();
$this->step = 5;
echo $this->progressBar(7);
break;
case 'step5':
$this->step = 5;
$this->post_offset = !empty($_REQUEST['offset']) ? abs((integer) $_REQUEST['offset']) : 0;
if ($this->importPosts($percent) === -1) {
http::redirect($this->getURL() . '&do=ok');
} else {
echo $this->progressBar(ceil($percent * 0.93) + 7);
}
break;
case 'ok':
$this->resetVars();
$this->core->blog->triggerBlog();
$this->step = 6;
echo $this->progressBar(100);
break;
}
}
public function gui()
{
try {
$this->guiprocess($this->action);
} catch (Exception $e) {
$this->error($e);
}
# db drivers
$db_drivers = [
'mysql' => 'mysql',
'mysqli' => 'mysqli'
];
switch ($this->step) {
case 1:
echo
'<p>' . sprintf(__('Import the content of a Dotclear 1.2\'s blog in the current blog: %s.'),
'<strong>' . html::escapeHTML($this->core->blog->name) . '</strong>') . '</p>' .
'<p class="warning">' . __('Please note that this process ' .
'will empty your categories, blogroll, entries and comments on the current blog.') . '</p>';
printf($this->imForm(1, __('General information'), __('Import my blog now')),
'<p>' . __('We first need some information about your old Dotclear 1.2 installation.') . '</p>' .
'<p><label for="db_driver">' . __('Database driver (must be mysqli if PHP 7 or higher):') . '</label> ' .
form::combo('db_driver', $db_drivers, html::escapeHTML($this->vars['db_driver'])) . '</p>' .
'<p><label for="db_host">' . __('Database Host Name:') . '</label> ' .
form::field('db_host', 30, 255, html::escapeHTML($this->vars['db_host'])) . '</p>' .
'<p><label for="db_name">' . __('Database Name:', html::escapeHTML($this->vars['db_name'])) . '</label> ' .
form::field('db_name', 30, 255, html::escapeHTML($this->vars['db_name'])) . '</p>' .
'<p><label for="db_user">' . __('Database User Name:') . '</label> ' .
form::field('db_user', 30, 255, html::escapeHTML($this->vars['db_user'])) . '</p>' .
'<p><label for="db_pwd">' . __('Database Password:') . '</label> ' .
form::password('db_pwd', 30, 255) . '</p>' .
'<p><label for="db_prefix">' . __('Database Tables Prefix:') . '</label> ' .
form::field('db_prefix', 30, 255, html::escapeHTML($this->vars['db_prefix'])) . '</p>' .
'<h3 class="vertical-separator">' . __('Entries import options') . '</h3>' .
'<p><label for="post_limit">' . __('Number of entries to import at once:') . '</label> ' .
form::number('post_limit', 0, 999, html::escapeHTML($this->vars['post_limit'])) . '</p>'
);
break;
case 2:
printf($this->imForm(2, __('Importing users')),
$this->autoSubmit()
);
break;
case 3:
printf($this->imForm(3, __('Importing categories')),
$this->autoSubmit()
);
break;
case 4:
printf($this->imForm(4, __('Importing blogroll')),
$this->autoSubmit()
);
break;
case 5:
$t = sprintf(__('Importing entries from %d to %d / %d'), $this->post_offset,
min([$this->post_offset + $this->post_limit, $this->post_count]), $this->post_count);
printf($this->imForm(5, $t),
form::hidden(['offset'], $this->post_offset) .
$this->autoSubmit()
);
break;
case 6:
echo
'<h3 class="vertical-separator">' . __('Please read carefully') . '</h3>' .
'<ul>' .
'<li>' . __('Every newly imported user has received a random password ' .
'and will need to ask for a new one by following the "I forgot my password" link on the login page ' .
'(Their registered email address has to be valid.)') . '</li>' .
'<li>' . sprintf(__('Please note that Dotclear 2 has a new URL layout. You can avoid broken ' .
'links by installing <a href="%s">DC1 redirect</a> plugin and activate it in your blog configuration.'),
'https://plugins.dotaddict.org/dc2/details/dc1redirect') . '</li>' .
'</ul>' .
$this->congratMessage();
break;
}
}
# Simple form for step by step process
protected function imForm($step, $legend, $submit_value = null)
{
if (!$submit_value) {
$submit_value = __('next step') . ' >';
}
return
'<form action="' . $this->getURL(true) . '" method="post">' .
'<h3 class="vertical-separator">' . $legend . '</h3>' .
'<div>' . $this->core->formNonce() .
form::hidden(['do'], 'step' . $step) .
'%s' . '</div>' .
'<p class="vertical-separator"><input type="submit" value="' . $submit_value . '" /></p>' .
'<p class="form-note info">' . __('Depending on the size of your blog, it could take a few minutes.') . '</p>' .
'</form>';
}
# Error display
protected function error($e)
{
echo '<div class="error"><strong>' . __('Errors:') . '</strong>' .
'<p>' . $e->getMessage() . '</p></div>';
}
# Database init
protected function db()
{
$db = dbLayer::init($this->vars['db_driver'], $this->vars['db_host'], $this->vars['db_name'], $this->vars['db_user'], $this->vars['db_pwd']);
$rs = $db->select("SHOW TABLES LIKE '" . $this->vars['db_prefix'] . "%'");
if ($rs->isEmpty()) {
throw new Exception(__('Dotclear tables not found'));
}
while ($rs->fetch()) {
$this->has_table[$rs->f(0)] = true;
}
# Set this to read data as they were written in Dotclear 1
try {
$db->execute('SET NAMES DEFAULT');
} catch (Exception $e) {}
$db->execute('SET CHARACTER SET DEFAULT');
$db->execute("SET COLLATION_CONNECTION = DEFAULT");
$db->execute("SET COLLATION_SERVER = DEFAULT");
$db->execute("SET CHARACTER_SET_SERVER = DEFAULT");
$db->execute("SET CHARACTER_SET_DATABASE = DEFAULT");
$this->post_count = $db->select(
'SELECT COUNT(post_id) FROM ' . $this->vars['db_prefix'] . 'post '
)->f(0);
return $db;
}
protected function cleanStr($str)
{
return text::cleanUTF8(@text::toUTF8($str));
}
# Users import
protected function importUsers()
{
$db = $this->db();
$prefix = $this->vars['db_prefix'];
$rs = $db->select('SELECT * FROM ' . $prefix . 'user');
try
{
$this->con->begin();
while ($rs->fetch()) {
if (!$this->core->userExists($rs->user_id)) {
$cur = $this->con->openCursor($this->prefix . 'user');
$cur->user_id = $rs->user_id;
$cur->user_name = $rs->user_nom;
$cur->user_firstname = $rs->user_prenom;
$cur->user_displayname = $rs->user_pseudo;
$cur->user_pwd = crypt::createPassword();
$cur->user_email = $rs->user_email;
$cur->user_lang = $rs->user_lang;
$cur->user_tz = $this->core->blog->settings->system->blog_timezone;
$cur->user_post_status = $rs->user_post_pub ? 1 : -2;
$cur->user_options = new ArrayObject([
'edit_size' => (integer) $rs->user_edit_size,
'post_format' => $rs->user_post_format
]);
$permissions = [];
switch ($rs->user_level) {
case '0':
$cur->user_status = 0;
break;
case '1': # editor
$permissions['usage'] = true;
break;
case '5': # advanced editor
$permissions['contentadmin'] = true;
$permissions['categories'] = true;
$permissions['media_admin'] = true;
break;
case '9': # admin
$permissions['admin'] = true;
break;
}
$this->core->addUser($cur);
$this->core->setUserBlogPermissions(
$rs->user_id,
$this->blog_id,
$permissions
);
}
}
$this->con->commit();
$db->close();
} catch (Exception $e) {
$this->con->rollback();
$db->close();
throw $e;
}
}
# Categories import
protected function importCategories()
{
$db = $this->db();
$prefix = $this->vars['db_prefix'];
$rs = $db->select('SELECT * FROM ' . $prefix . 'categorie ORDER BY cat_ord ASC');
try
{
$this->con->execute(
'DELETE FROM ' . $this->prefix . 'category ' .
"WHERE blog_id = '" . $this->con->escape($this->blog_id) . "' "
);
$ord = 2;
while ($rs->fetch()) {
$cur = $this->con->openCursor($this->prefix . 'category');
$cur->blog_id = $this->blog_id;
$cur->cat_title = $this->cleanStr(htmlspecialchars_decode($rs->cat_libelle));
$cur->cat_desc = $this->cleanStr($rs->cat_desc);
$cur->cat_url = $this->cleanStr($rs->cat_libelle_url);
$cur->cat_lft = $ord++;
$cur->cat_rgt = $ord++;
$cur->cat_id = $this->con->select(
'SELECT MAX(cat_id) FROM ' . $this->prefix . 'category'
)->f(0) + 1;
$this->vars['cat_ids'][$rs->cat_id] = $cur->cat_id;
$cur->insert();
}
$db->close();
} catch (Exception $e) {
$db->close();
throw $e;
}
}
# Blogroll import
protected function importLinks()
{
$db = $this->db();
$prefix = $this->vars['db_prefix'];
$rs = $db->select('SELECT * FROM ' . $prefix . 'link ORDER BY link_id ASC');
try
{
$this->con->execute(
'DELETE FROM ' . $this->prefix . 'link ' .
"WHERE blog_id = '" . $this->con->escape($this->blog_id) . "' "
);
while ($rs->fetch()) {
$cur = $this->con->openCursor($this->prefix . 'link');
$cur->blog_id = $this->blog_id;
$cur->link_href = $this->cleanStr($rs->href);
$cur->link_title = $this->cleanStr($rs->label);
$cur->link_desc = $this->cleanStr($rs->title);
$cur->link_lang = $this->cleanStr($rs->lang);
$cur->link_xfn = $this->cleanStr($rs->rel);
$cur->link_position = (integer) $rs->position;
$cur->link_id = $this->con->select(
'SELECT MAX(link_id) FROM ' . $this->prefix . 'link'
)->f(0) + 1;
$cur->insert();
}
$db->close();
} catch (Exception $e) {
$db->close();
throw $e;
}
}
# Entries import
protected function importPosts(&$percent)
{
$db = $this->db();
$prefix = $this->vars['db_prefix'];
$count = $db->select('SELECT COUNT(post_id) FROM ' . $prefix . 'post')->f(0);
$rs = $db->select(
'SELECT * FROM ' . $prefix . 'post ORDER BY post_id ASC ' .
$db->limit($this->post_offset, $this->post_limit)
);
try
{
if ($this->post_offset == 0) {
$this->con->execute(
'DELETE FROM ' . $this->prefix . 'post ' .
"WHERE blog_id = '" . $this->con->escape($this->blog_id) . "' "
);
}
while ($rs->fetch()) {
$this->importPost($rs, $db);
}
$db->close();
} catch (Exception $e) {
$db->close();
throw $e;
}
if ($rs->count() < $this->post_limit) {
return -1;
} else {
$this->post_offset += $this->post_limit;
}
if ($this->post_offset > $this->post_count) {
$percent = 100;
} else {
$percent = $this->post_offset * 100 / $this->post_count;
}
}
protected function importPost($rs, $db)
{
$cur = $this->con->openCursor($this->prefix . 'post');
$cur->blog_id = $this->blog_id;
$cur->user_id = $rs->user_id;
$cur->cat_id = (integer) $this->vars['cat_ids'][$rs->cat_id];
$cur->post_dt = $rs->post_dt;
$cur->post_creadt = $rs->post_creadt;
$cur->post_upddt = $rs->post_upddt;
$cur->post_title = html::decodeEntities($this->cleanStr($rs->post_titre));
$cur->post_url = date('Y/m/d/', strtotime($cur->post_dt)) . $rs->post_id . '-' . $rs->post_titre_url;
$cur->post_url = substr($cur->post_url, 0, 255);
$cur->post_format = $rs->post_content_wiki == '' ? 'xhtml' : 'wiki';
$cur->post_content_xhtml = $this->cleanStr($rs->post_content);
$cur->post_excerpt_xhtml = $this->cleanStr($rs->post_chapo);
if ($cur->post_format == 'wiki') {
$cur->post_content = $this->cleanStr($rs->post_content_wiki);
$cur->post_excerpt = $this->cleanStr($rs->post_chapo_wiki);
} else {
$cur->post_content = $this->cleanStr($rs->post_content);
$cur->post_excerpt = $this->cleanStr($rs->post_chapo);
}
$cur->post_notes = $this->cleanStr($rs->post_notes);
$cur->post_status = (integer) $rs->post_pub;
$cur->post_selected = (integer) $rs->post_selected;
$cur->post_open_comment = (integer) $rs->post_open_comment;
$cur->post_open_tb = (integer) $rs->post_open_tb;
$cur->post_lang = $rs->post_lang;
$cur->post_words = implode(' ', text::splitWords(
$cur->post_title . ' ' .
$cur->post_excerpt_xhtml . ' ' .
$cur->post_content_xhtml
));
$cur->post_id = $this->con->select(
'SELECT MAX(post_id) FROM ' . $this->prefix . 'post'
)->f(0) + 1;
$cur->insert();
$this->importComments($rs->post_id, $cur->post_id, $db);
$this->importPings($rs->post_id, $cur->post_id, $db);
# Load meta if we have some in DC1
if (isset($this->has_table[$this->vars['db_prefix'] . 'post_meta'])) {
$this->importMeta($rs->post_id, $cur->post_id, $db);
}
}
# Comments import
protected function importComments($post_id, $new_post_id, $db)
{
$count_c = $count_t = 0;
$rs = $db->select(
'SELECT * FROM ' . $this->vars['db_prefix'] . 'comment ' .
'WHERE post_id = ' . (integer) $post_id . ' '
);
while ($rs->fetch()) {
$cur = $this->con->openCursor($this->prefix . 'comment');
$cur->post_id = (integer) $new_post_id;
$cur->comment_author = $this->cleanStr($rs->comment_auteur);
$cur->comment_status = (integer) $rs->comment_pub;
$cur->comment_dt = $rs->comment_dt;
$cur->comment_upddt = $rs->comment_upddt;
$cur->comment_email = $this->cleanStr($rs->comment_email);
$cur->comment_content = $this->cleanStr($rs->comment_content);
$cur->comment_ip = $rs->comment_ip;
$cur->comment_trackback = (integer) $rs->comment_trackback;
$cur->comment_site = $this->cleanStr($rs->comment_site);
if ($cur->comment_site != '' && !preg_match('!^http(s)?://.*$!', $cur->comment_site)) {
$cur->comment_site = substr('http://' . $cur->comment_site, 0, 255);
}
if ($rs->exists('spam') && $rs->spam && $rs->comment_status = 0) {
$cur->comment_status = -2;
}
$cur->comment_words = implode(' ', text::splitWords($cur->comment_content));
$cur->comment_id = $this->con->select(
'SELECT MAX(comment_id) FROM ' . $this->prefix . 'comment'
)->f(0) + 1;
$cur->insert();
if ($cur->comment_trackback && $cur->comment_status == 1) {
$count_t++;
} elseif ($cur->comment_status == 1) {
$count_c++;
}
}
if ($count_t > 0 || $count_c > 0) {
$this->con->execute(
'UPDATE ' . $this->prefix . 'post SET ' .
'nb_comment = ' . $count_c . ', ' .
'nb_trackback = ' . $count_t . ' ' .
'WHERE post_id = ' . (integer) $new_post_id . ' '
);
}
}
# Pings import
protected function importPings($post_id, $new_post_id, $db)
{
$urls = [];
$rs = $db->select(
'SELECT * FROM ' . $this->vars['db_prefix'] . 'ping ' .
'WHERE post_id = ' . (integer) $post_id
);
while ($rs->fetch()) {
$url = $this->cleanStr($rs->ping_url);
if (isset($urls[$url])) {
continue;
}
$cur = $this->con->openCursor($this->prefix . 'ping');
$cur->post_id = (integer) $new_post_id;
$cur->ping_url = $url;
$cur->ping_dt = $rs->ping_dt;
$cur->insert();
$urls[$url] = true;
}
}
# Meta import
protected function importMeta($post_id, $new_post_id, $db)
{
$rs = $db->select(
'SELECT * FROM ' . $this->vars['db_prefix'] . 'post_meta ' .
'WHERE post_id = ' . (integer) $post_id . ' '
);
if ($rs->isEmpty()) {
return;
}
while ($rs->fetch()) {
$this->core->meta->setPostMeta($new_post_id, $this->cleanStr($rs->meta_key), $this->cleanStr($rs->meta_value));
}
}
}

View File

@ -0,0 +1,185 @@
<?php
/**
* @brief importExport, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugins
*
* @copyright Olivier Meunier & Association Dotclear
* @copyright GPL-2.0-only
*/
if (!defined('DC_RC_PATH')) {return;}
class dcImportFeed extends dcIeModule
{
protected $status = false;
protected $feed_url = '';
// IPv6 functions (from https://gist.github.com/tbaschak/7866688)
private function gethostbyname6($host, $try_a = false)
{
// get AAAA record for $host
// if $try_a is true, if AAAA fails, it tries for A
// the first match found is returned
// otherwise returns false
$dns = $this->gethostbynamel6($host, $try_a);
if ($dns == false) {
return false;
} else {
return $dns[0];
}
}
private function gethostbynamel6($host, $try_a = false)
{
// get AAAA records for $host,
// if $try_a is true, if AAAA fails, it tries for A
// results are returned in an array of ips found matching type
// otherwise returns false
$dns6 = dns_get_record($host, DNS_AAAA);
if ($try_a == true) {
$dns4 = dns_get_record($host, DNS_A);
$dns = array_merge($dns4, $dns6);
} else {
$dns = $dns6;
}
$ip6 = [];
$ip4 = [];
foreach ($dns as $record) {
if ($record["type"] == "A") {
$ip4[] = $record["ip"];
}
if ($record["type"] == "AAAA") {
$ip6[] = $record["ipv6"];
}
}
if (count($ip6) < 1) {
if ($try_a == true) {
if (count($ip4) < 1) {
return false;
} else {
return $ip4;
}
} else {
return false;
}
} else {
return $ip6;
}
}
public function setInfo()
{
$this->type = 'import';
$this->name = __('RSS or Atom feed import');
$this->description = __('Add a feed content to the blog.');
}
public function process($do)
{
if ($do == 'ok') {
$this->status = true;
return;
}
if (empty($_POST['feed_url'])) {
return;
}
$this->feed_url = $_POST['feed_url'];
// Check feed URL
if ($this->core->blog->settings->system->import_feed_url_control) {
// Get IP from URL
$bits = parse_url($this->feed_url);
if (!$bits || !isset($bits['host'])) {
throw new Exception(__('Cannot retrieve feed URL.'));
}
$ip = gethostbyname($bits['host']);
if ($ip == $bits['host']) {
$ip = $this->gethostbyname6($bits['host']);
if (!$ip) {
throw new Exception(__('Cannot retrieve feed URL.'));
}
}
// Check feed IP
$flag = FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6;
if ($this->core->blog->settings->system->import_feed_no_private_ip) {
$flag |= FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE;
}
if (!filter_var($ip, $flag)) {
throw new Exception(__('Cannot retrieve feed URL.'));
}
// IP control (white list regexp)
if ($this->core->blog->settings->system->import_feed_ip_regexp != '') {
if (!preg_match($this->core->blog->settings->system->import_feed_ip_regexp, $ip)) {
throw new Exception(__('Cannot retrieve feed URL.'));
}
}
// Port control (white list regexp)
if ($this->core->blog->settings->system->import_feed_port_regexp != '' && isset($bits['port'])) {
if (!preg_match($this->core->blog->settings->system->import_feed_port_regexp, $bits['port'])) {
throw new Exception(__('Cannot retrieve feed URL.'));
}
}
}
$feed = feedReader::quickParse($this->feed_url);
if ($feed === false) {
throw new Exception(__('Cannot retrieve feed URL.'));
}
if (count($feed->items) == 0) {
throw new Exception(__('No items in feed.'));
}
$cur = $this->core->con->openCursor($this->core->prefix . 'post');
$this->core->con->begin();
foreach ($feed->items as $item) {
$cur->clean();
$cur->user_id = $this->core->auth->userID();
$cur->post_content = $item->content ?: $item->description;
$cur->post_title = $item->title ?: text::cutString(html::clean($cur->post_content), 60);
$cur->post_format = 'xhtml';
$cur->post_status = -2;
$cur->post_dt = strftime('%Y-%m-%d %H:%M:%S', $item->TS);
try {
$post_id = $this->core->blog->addPost($cur);
} catch (Exception $e) {
$this->core->con->rollback();
throw $e;
}
foreach ($item->subject as $subject) {
$this->core->meta->setPostMeta($post_id, 'tag', dcMeta::sanitizeMetaID($subject));
}
}
$this->core->con->commit();
http::redirect($this->getURL() . '&do=ok');
}
public function gui()
{
if ($this->status) {
dcPage::success(__('Content successfully imported.'));
}
echo
'<form action="' . $this->getURL(true) . '" method="post">' .
'<p>' . sprintf(__('Add a feed content to the current blog: <strong>%s</strong>.'), html::escapeHTML($this->core->blog->name)) . '</p>' .
'<p><label for="feed_url">' . __('Feed URL:') . '</label>' .
form::url('feed_url', 50, 300, html::escapeHTML($this->feed_url)) . '</p>' .
'<p>' .
$this->core->formNonce() .
form::hidden(['do'], 1) .
'<input type="submit" value="' . __('Import') . '" /></p>' .
'</form>';
}
}

View File

@ -0,0 +1,299 @@
<?php
/**
* @brief importExport, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugins
*
* @copyright Olivier Meunier & Association Dotclear
* @copyright GPL-2.0-only
*/
if (!defined('DC_RC_PATH')) {return;}
class dcImportFlat extends dcIeModule
{
protected $status = false;
public function setInfo()
{
$this->type = 'import';
$this->name = __('Flat file import');
$this->description = __('Imports a blog or a full Dotclear installation from flat file.');
}
public function process($do)
{
if ($do == 'single' || $do == 'full') {
$this->status = $do;
return;
}
$to_unlink = false;
# Single blog import
$files = $this->getPublicFiles();
$single_upl = null;
if (!empty($_POST['public_single_file']) && in_array($_POST['public_single_file'], $files)) {
$single_upl = false;
} elseif (!empty($_FILES['up_single_file'])) {
$single_upl = true;
}
if ($single_upl !== null) {
if ($single_upl) {
files::uploadStatus($_FILES['up_single_file']);
$file = DC_TPL_CACHE . '/' . md5(uniqid());
if (!move_uploaded_file($_FILES['up_single_file']['tmp_name'], $file)) {
throw new Exception(__('Unable to move uploaded file.'));
}
$to_unlink = true;
} else {
$file = $_POST['public_single_file'];
}
try {
# Try to unzip file
$unzip_file = $this->unzip($file);
if (false !== $unzip_file) {
$bk = new flatImport($this->core, $unzip_file);
}
# Else this is a normal file
else {
$bk = new flatImport($this->core, $file);
}
$bk->importSingle();
} catch (Exception $e) {
@unlink($unzip_file);
if ($to_unlink) {
@unlink($file);
}
throw $e;
}
@unlink($unzip_file);
if ($to_unlink) {
@unlink($file);
}
http::redirect($this->getURL() . '&do=single');
}
# Full import
$full_upl = null;
if (!empty($_POST['public_full_file']) && in_array($_POST['public_full_file'], $files)) {
$full_upl = false;
} elseif (!empty($_FILES['up_full_file'])) {
$full_upl = true;
}
if ($full_upl !== null && $this->core->auth->isSuperAdmin()) {
if (empty($_POST['your_pwd']) || !$this->core->auth->checkPassword($_POST['your_pwd'])) {
throw new Exception(__('Password verification failed'));
}
if ($full_upl) {
files::uploadStatus($_FILES['up_full_file']);
$file = DC_TPL_CACHE . '/' . md5(uniqid());
if (!move_uploaded_file($_FILES['up_full_file']['tmp_name'], $file)) {
throw new Exception(__('Unable to move uploaded file.'));
}
$to_unlink = true;
} else {
$file = $_POST['public_full_file'];
}
try {
# Try to unzip file
$unzip_file = $this->unzip($file);
if (false !== $unzip_file) {
$bk = new flatImport($this->core, $unzip_file);
}
# Else this is a normal file
else {
$bk = new flatImport($this->core, $file);
}
$bk->importFull();
} catch (Exception $e) {
@unlink($unzip_file);
if ($to_unlink) {
@unlink($file);
}
throw $e;
}
@unlink($unzip_file);
if ($to_unlink) {
@unlink($file);
}
http::redirect($this->getURL() . '&do=full');
}
header('content-type:text/plain');
var_dump($_POST);
exit;
$this->status = true;
}
public function gui()
{
if ($this->status == 'single') {
dcPage::success(__('Single blog successfully imported.'));
return;
}
if ($this->status == 'full') {
dcPage::success(__('Content successfully imported.'));
return;
}
$public_files = array_merge(['-' => ''], $this->getPublicFiles());
$has_files = (boolean) (count($public_files) - 1);
echo
dcPage::jsJson('ie_import_flat_msg',
['confirm_full_import' => __('Are you sure you want to import a full backup file?')]) .
dcPage::jsLoad(dcPage::getPF('importExport/js/import_flat.js'));
echo
'<form action="' . $this->getURL(true) . '" method="post" enctype="multipart/form-data" class="fieldset">' .
'<h3>' . __('Single blog') . '</h3>' .
'<p>' . sprintf(__('This will import a single blog backup as new content in the current blog: <strong>%s</strong>.'), html::escapeHTML($this->core->blog->name)) . '</p>' .
'<p><label for="up_single_file">' . __('Upload a backup file') .
' (' . sprintf(__('maximum size %s'), files::size(DC_MAX_UPLOAD_SIZE)) . ')' . ' </label>' .
' <input type="file" id="up_single_file" name="up_single_file" size="20" />' .
'</p>';
if ($has_files) {
echo
'<p><label for="public_single_file" class="">' . __('or pick up a local file in your public directory') . ' </label> ' .
form::combo('public_single_file', $public_files) .
'</p>';
}
echo
'<p>' .
$this->core->formNonce() .
form::hidden(['do'], 1) .
form::hidden(['MAX_FILE_SIZE'], DC_MAX_UPLOAD_SIZE) .
'<input type="submit" value="' . __('Import') . '" /></p>' .
'</form>';
if ($this->core->auth->isSuperAdmin()) {
echo
'<form action="' . $this->getURL(true) . '" method="post" enctype="multipart/form-data" id="formfull" class="fieldset">' .
'<h3>' . __('Multiple blogs') . '</h3>' .
'<p class="warning">' . __('This will reset all the content of your database, except users.') . '</p>' .
'<p><label for="up_full_file">' . __('Upload a backup file') . ' ' .
' (' . sprintf(__('maximum size %s'), files::size(DC_MAX_UPLOAD_SIZE)) . ')' . ' </label>' .
'<input type="file" id="up_full_file" name="up_full_file" size="20" />' .
'</p>';
if ($has_files) {
echo
'<p><label for="public_full_file">' . __('or pick up a local file in your public directory') . ' </label>' .
form::combo('public_full_file', $public_files) .
'</p>';
}
echo
'<p><label for="your_pwd" class="required"><abbr title="' . __('Required field') . '">*</abbr> ' . __('Your password:') . '</label>' .
form::password('your_pwd', 20, 255,
[
'extra_html' => 'required placeholder="' . __('Password') . '"',
'autocomplete' => 'current-password'
]
) . '</p>' .
'<p>' .
$this->core->formNonce() .
form::hidden(['do'], 1) .
form::hidden(['MAX_FILE_SIZE'], DC_MAX_UPLOAD_SIZE) .
'<input type="submit" value="' . __('Import') . '" /></p>' .
'</form>';
}
}
protected function getPublicFiles()
{
$public_files = [];
$dir = @dir($this->core->blog->public_path);
if ($dir) {
while (($entry = $dir->read()) !== false) {
$entry_path = $dir->path . '/' . $entry;
if (is_file($entry_path) && is_readable($entry_path)) {
# Do not test each zip file content here, its too long
if (substr($entry_path, -4) == '.zip') {
$public_files[$entry] = $entry_path;
} elseif (self::checkFileContent($entry_path)) {
$public_files[$entry] = $entry_path;
}
}
}
}
return $public_files;
}
protected static function checkFileContent($entry_path)
{
$ret = false;
$fp = fopen($entry_path, 'rb');
$ret = strpos(fgets($fp), '///DOTCLEAR|') === 0;
fclose($fp);
return $ret;
}
private function unzip($file)
{
$zip = new fileUnzip($file);
if ($zip->isEmpty()) {
$zip->close();
return false; //throw new Exception(__('File is empty or not a compressed file.'));
}
foreach ($zip->getFilesList() as $zip_file) {
# Check zipped file name
if (substr($zip_file, -4) != '.txt') {
continue;
}
# Check zipped file contents
$content = $zip->unzip($zip_file);
if (strpos($content, '///DOTCLEAR|') !== 0) {
unset($content);
continue;
}
$target = path::fullFromRoot($zip_file, dirname($file));
# Check existing files with same name
if (file_exists($target)) {
$zip->close();
unset($content);
throw new Exception(__('Another file with same name exists.'));
}
# Extract backup content
if (file_put_contents($target, $content) === false) {
$zip->close();
unset($content);
throw new Exception(__('Failed to extract backup file.'));
}
$zip->close();
unset($content);
# Return extracted file name
return $target;
}
$zip->close();
throw new Exception(__('No backup in compressed file.'));
}
}

View File

@ -0,0 +1,776 @@
<?php
/**
* @brief importExport, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugins
*
* @copyright Olivier Meunier & Association Dotclear
* @copyright GPL-2.0-only
*/
if (!defined('DC_RC_PATH')) {return;}
class dcImportWP extends dcIeModule
{
protected $con;
protected $prefix;
protected $blog_id;
protected $action = null;
protected $step = 1;
protected $post_offset = 0;
protected $post_limit = 20;
protected $post_count = 0;
protected $has_table = [];
protected $vars;
protected $base_vars = [
'db_host' => '',
'db_name' => '',
'db_user' => '',
'db_pwd' => '',
'db_prefix' => 'wp_',
'ignore_first_cat' => 1,
'cat_import' => 1,
'cat_as_tags' => '',
'cat_tags_prefix' => 'cat: ',
'post_limit' => 20,
'post_formater' => 'xhtml',
'comment_formater' => 'xhtml',
'user_ids' => [],
'cat_ids' => [],
'permalink_template' => 'p=%post_id%',
'permalink_tags' => [
'%year%',
'%monthnum%',
'%day%',
'%hour%',
'%minute%',
'%second%',
'%postname%',
'%post_id%',
'%category%',
'%author%'
]
];
protected $formaters;
protected function setInfo()
{
$this->type = 'import';
$this->name = __('WordPress import');
$this->description = __('Import a WordPress installation into your current blog.');
}
public function init()
{
$this->con = &$this->core->con;
$this->prefix = $this->core->prefix;
$this->blog_id = $this->core->blog->id;
if (!isset($_SESSION['wp_import_vars'])) {
$_SESSION['wp_import_vars'] = $this->base_vars;
}
$this->vars = &$_SESSION['wp_import_vars'];
if ($this->vars['post_limit'] > 0) {
$this->post_limit = $this->vars['post_limit'];
}
$this->formaters = dcAdminCombos::getFormatersCombo();
}
public function resetVars()
{
$this->vars = $this->base_vars;
unset($_SESSION['wp_import_vars']);
}
public function process($do)
{
$this->action = $do;
}
# We handle process in another way to always display something to
# user
protected function guiprocess($do)
{
switch ($do) {
case 'step1':
$this->vars['db_host'] = $_POST['db_host'];
$this->vars['db_name'] = $_POST['db_name'];
$this->vars['db_user'] = $_POST['db_user'];
$this->vars['db_pwd'] = $_POST['db_pwd'];
$this->vars['db_prefix'] = $_POST['db_prefix'];
$this->vars['ignore_first_cat'] = isset($_POST['ignore_first_cat']);
$this->vars['cat_import'] = isset($_POST['cat_import']);
$this->vars['cat_as_tags'] = isset($_POST['cat_as_tags']);
$this->vars['cat_tags_prefix'] = $_POST['cat_tags_prefix'];
$this->vars['post_limit'] = abs((integer) $_POST['post_limit']) > 0 ? $_POST['post_limit'] : 0;
$this->vars['post_formater'] = isset($this->formaters[$_POST['post_formater']]) ? $_POST['post_formater'] : 'xhtml';
$this->vars['comment_formater'] = isset($this->formaters[$_POST['comment_formater']]) ? $_POST['comment_formater'] : 'xhtml';
$db = $this->db();
$db->close();
$this->step = 2;
echo $this->progressBar(1);
break;
case 'step2':
$this->step = 2;
$this->importUsers();
$this->step = 3;
echo $this->progressBar(3);
break;
case 'step3':
$this->step = 3;
$this->importCategories();
if ($this->core->plugins->moduleExists('blogroll')) {
$this->step = 4;
echo $this->progressBar(5);
} else {
$this->step = 5;
echo $this->progressBar(7);
}
break;
case 'step4':
$this->step = 4;
$this->importLinks();
$this->step = 5;
echo $this->progressBar(7);
break;
case 'step5':
$this->step = 5;
$this->post_offset = !empty($_REQUEST['offset']) ? abs((integer) $_REQUEST['offset']) : 0;
if ($this->importPosts($percent) === -1) {
http::redirect($this->getURL() . '&do=ok');
} else {
echo $this->progressBar(ceil($percent * 0.93) + 7);
}
break;
case 'ok':
$this->resetVars();
$this->core->blog->triggerBlog();
$this->step = 6;
echo $this->progressBar(100);
break;
}
}
public function gui()
{
try {
$this->guiprocess($this->action);
} catch (Exception $e) {
$this->error($e);
}
switch ($this->step) {
case 1:
echo
'<p>' . sprintf(__('This will import your WordPress content as new content in the current blog: %s.'),
'<strong>' . html::escapeHTML($this->core->blog->name) . '</strong>') . '</p>' .
'<p class="warning">' . __('Please note that this process ' .
'will empty your categories, blogroll, entries and comments on the current blog.') . '</p>';
printf($this->imForm(1, __('General information'), __('Import my blog now')),
'<p>' . __('We first need some information about your old WordPress installation.') . '</p>' .
'<p><label for="db_host">' . __('Database Host Name:') . '</label> ' .
form::field('db_host', 30, 255, html::escapeHTML($this->vars['db_host'])) . '</p>' .
'<p><label for="db_name">' . __('Database Name:', html::escapeHTML($this->vars['db_name'])) . '</label> ' .
form::field('db_name', 30, 255, html::escapeHTML($this->vars['db_name'])) . '</p>' .
'<p><label for="db_user">' . __('Database User Name:') . '</label> ' .
form::field('db_user', 30, 255, html::escapeHTML($this->vars['db_user'])) . '</p>' .
'<p><label for="db_pwd">' . __('Database Password:') . '</label> ' .
form::password('db_pwd', 30, 255) . '</p>' .
'<p><label for="db_prefix">' . __('Database Tables Prefix:') . '</label> ' .
form::field('db_prefix', 30, 255, html::escapeHTML($this->vars['db_prefix'])) . '</p>' .
'<h3 class="vertical-separator">' . __('Entries import options') . '</h3>' .
'<div class="two-cols">' .
'<div class="col">' .
'<p>' . __('WordPress and Dotclear\'s handling of categories are quite different. ' .
'You can assign several categories to a single post in WordPress. In the Dotclear world, ' .
'we see it more like "One category, several tags." Therefore Dotclear can only import one ' .
'category per post and will chose the lowest numbered one. If you want to keep a trace of ' .
'every category, you can import them as tags, with an optional prefix.') . '</p>' .
'<p>' . __('On the other hand, in WordPress, a post can not be uncategorized, and a ' .
'default installation has a first category labelised <i>"Uncategorized"</i>.' .
'If you did not change that category, you can just ignore it while ' .
'importing your blog, as Dotclear allows you to actually keep your posts ' .
'uncategorized.') . '</p>' .
'</div>' .
'<div class="col">' .
'<p><label for="ignore_first_cat" class="classic">' . form::checkbox('ignore_first_cat', 1, $this->vars['ignore_first_cat']) . ' ' .
__('Ignore the first category:') . '</label></p>' .
'<p><label for="cat_import" class="classic">' . form::checkbox('cat_import', 1, $this->vars['cat_import']) . ' ' .
__('Import lowest numbered category on posts:') . '</label></p>' .
'<p><label for="cat_as_tags" class="classic">' . form::checkbox('cat_as_tags', 1, $this->vars['cat_as_tags']) . ' ' .
__('Import all categories as tags:') . '</label></p>' .
'<p><label for="cat_tags_prefix">' . __('Prefix such tags with:') . '</label> ' .
form::field('cat_tags_prefix', 10, 20, html::escapeHTML($this->vars['cat_tags_prefix'])) . '</p>' .
'<p><label for="post_limit">' . __('Number of entries to import at once:') . '</label> ' .
form::number('post_limit', 0, 999, html::escapeHTML($this->vars['post_limit'])) . '</p>' .
'</div>' .
'</div>' .
'<h3 class="clear vertical-separator">' . __('Content filters') . '</h3>' .
'<p>' . __('You may want to process your post and/or comment content with the following filters.') . '</p>' .
'<p><label for="post_formater">' . __('Post content formatter:') . '</label> ' .
form::combo('post_formater', $this->formaters, $this->vars['post_formater']) . '</p>' .
'<p><label for="comment_formater">' . __('Comment content formatter:') . '</label> '
. form::combo('comment_formater', $this->formaters, $this->vars['comment_formater']) . '</p>'
);
break;
case 2:
printf($this->imForm(2, __('Importing users')),
$this->autoSubmit()
);
break;
case 3:
printf($this->imForm(3, __('Importing categories')),
$this->autoSubmit()
);
break;
case 4:
printf($this->imForm(4, __('Importing blogroll')),
$this->autoSubmit()
);
break;
case 5:
$t = sprintf(__('Importing entries from %d to %d / %d'), $this->post_offset,
min([$this->post_offset + $this->post_limit, $this->post_count]), $this->post_count);
printf($this->imForm(5, $t),
form::hidden(['offset'], $this->post_offset) .
$this->autoSubmit()
);
break;
case 6:
echo
'<p class="message">' . __('Every newly imported user has received a random password ' .
'and will need to ask for a new one by following the "I forgot my password" link on the login page ' .
'(Their registered email address has to be valid.)') . '</p>' .
$this->congratMessage();
break;
}
}
# Simple form for step by step process
protected function imForm($step, $legend, $submit_value = null)
{
if (!$submit_value) {
$submit_value = __('next step') . ' >';
}
return
'<form action="' . $this->getURL(true) . '" method="post">' .
'<h3 class="vertical-separator">' . $legend . '</h3>' .
'<div>' . $this->core->formNonce() .
form::hidden(['do'], 'step' . $step) .
'%s' . '</div>' .
'<p><input type="submit" value="' . $submit_value . '" /></p>' .
'<p class="form-note info">' . __('Depending on the size of your blog, it could take a few minutes.') . '</p>' .
'</form>';
}
# Error display
protected function error($e)
{
echo '<div class="error"><strong>' . __('Errors:') . '</strong>' .
'<p>' . $e->getMessage() . '</p></div>';
}
# Database init
protected function db()
{
$db = dbLayer::init('mysql', $this->vars['db_host'], $this->vars['db_name'], $this->vars['db_user'], $this->vars['db_pwd']);
$rs = $db->select("SHOW TABLES LIKE '" . $this->vars['db_prefix'] . "%'");
if ($rs->isEmpty()) {
throw new Exception(__('WordPress tables not found'));
}
while ($rs->fetch()) {
$this->has_table[$rs->f(0)] = true;
}
# Set this to read data as they were written
try {
$db->execute('SET NAMES DEFAULT');
} catch (Exception $e) {}
$db->execute('SET CHARACTER SET DEFAULT');
$db->execute("SET COLLATION_CONNECTION = DEFAULT");
$db->execute("SET COLLATION_SERVER = DEFAULT");
$db->execute("SET CHARACTER_SET_SERVER = DEFAULT");
$db->execute("SET CHARACTER_SET_DATABASE = DEFAULT");
$this->post_count = $db->select(
'SELECT COUNT(ID) FROM ' . $this->vars['db_prefix'] . 'posts ' .
'WHERE post_type = \'post\' OR post_type = \'page\''
)->f(0);
return $db;
}
protected function cleanStr($str)
{
return text::cleanUTF8(@text::toUTF8($str));
}
# Users import
protected function importUsers()
{
$db = $this->db();
$prefix = $this->vars['db_prefix'];
$rs = $db->select('SELECT * FROM ' . $prefix . 'users');
try
{
$this->con->begin();
while ($rs->fetch()) {
$user_login = preg_replace('/[^A-Za-z0-9@._-]/', '-', $rs->user_login);
$this->vars['user_ids'][$rs->ID] = $user_login;
if (!$this->core->userExists($user_login)) {
$cur = $this->con->openCursor($this->prefix . 'user');
$cur->user_id = $user_login;
$cur->user_pwd = crypt::createPassword();
$cur->user_displayname = $rs->user_nicename;
$cur->user_email = $rs->user_email;
$cur->user_url = $rs->user_url;
$cur->user_creadt = $rs->user_registered;
$cur->user_lang = $this->core->blog->settings->system->lang;
$cur->user_tz = $this->core->blog->settings->system->blog_timezone;
$permissions = [];
$rs_meta = $db->select('SELECT * FROM ' . $prefix . 'usermeta WHERE user_id = ' . $rs->ID);
while ($rs_meta->fetch()) {
switch ($rs_meta->meta_key) {
case 'first_name':
$cur->user_firstname = $this->cleanStr($rs_meta->meta_value);
break;
case 'last_name':
$cur->user_name = $this->cleanStr($rs_meta->meta_value);
break;
case 'description':
$cur->user_desc = $this->cleanStr($rs_meta->meta_value);
break;
case 'rich_editing':
$cur->user_options = new ArrayObject([
'enable_wysiwyg' => $rs_meta->meta_value == 'true' ? true : false
]);
break;
case 'wp_user_level':
switch ($rs_meta->meta_value) {
case '0': # Subscriber
$cur->user_status = 0;
break;
case '1': # Contributor
$permissions['usage'] = true;
$permissions['publish'] = true;
$permissions['delete'] = true;
break;
case '2': # Author
case '3':
case '4':
$permissions['contentadmin'] = true;
$permissions['media'] = true;
break;
case '5': # Editor
case '6':
case '7':
$permissions['contentadmin'] = true;
$permissions['categories'] = true;
$permissions['media_admin'] = true;
$permissions['pages'] = true;
$permissions['blogroll'] = true;
break;
case '8': # Administrator
case '9':
case '10':
$permissions['admin'] = true;
break;
}
break;
}
}
$this->core->addUser($cur);
$this->core->setUserBlogPermissions(
$cur->user_id,
$this->blog_id,
$permissions
);
}
}
$this->con->commit();
$db->close();
} catch (Exception $e) {
$this->con->rollback();
$db->close();
throw $e;
}
}
# Categories import
protected function importCategories()
{
$db = $this->db();
$prefix = $this->vars['db_prefix'];
$rs = $db->select(
'SELECT * FROM ' . $prefix . 'terms AS t, ' . $prefix . 'term_taxonomy AS x ' .
'WHERE x.taxonomy = \'category\' ' .
'AND t.term_id = x.term_id ' .
($this->vars['ignore_first_cat'] ? 'AND t.term_id <> 1 ' : '') .
'ORDER BY t.term_id ASC'
);
try
{
$this->con->execute(
'DELETE FROM ' . $this->prefix . 'category ' .
"WHERE blog_id = '" . $this->con->escape($this->blog_id) . "' "
);
$ord = 2;
while ($rs->fetch()) {
$cur = $this->con->openCursor($this->prefix . 'category');
$cur->blog_id = $this->blog_id;
$cur->cat_title = $this->cleanStr($rs->name);
$cur->cat_desc = $this->cleanStr($rs->description);
$cur->cat_url = $this->cleanStr($rs->slug);
$cur->cat_lft = $ord++;
$cur->cat_rgt = $ord++;
$cur->cat_id = $this->con->select(
'SELECT MAX(cat_id) FROM ' . $this->prefix . 'category'
)->f(0) + 1;
$this->vars['cat_ids'][$rs->term_id] = $cur->cat_id;
$cur->insert();
}
$db->close();
} catch (Exception $e) {
$db->close();
throw $e;
}
}
# Blogroll import
protected function importLinks()
{
$db = $this->db();
$prefix = $this->vars['db_prefix'];
$rs = $db->select('SELECT * FROM ' . $prefix . 'links ORDER BY link_id ASC');
try
{
$this->con->execute(
'DELETE FROM ' . $this->prefix . 'link ' .
"WHERE blog_id = '" . $this->con->escape($this->blog_id) . "' "
);
while ($rs->fetch()) {
$cur = $this->con->openCursor($this->prefix . 'link');
$cur->blog_id = $this->blog_id;
$cur->link_href = $this->cleanStr($rs->link_url);
$cur->link_title = $this->cleanStr($rs->link_name);
$cur->link_desc = $this->cleanStr($rs->link_description);
$cur->link_xfn = $this->cleanStr($rs->link_rel);
$cur->link_id = $this->con->select(
'SELECT MAX(link_id) FROM ' . $this->prefix . 'link'
)->f(0) + 1;
$cur->insert();
}
$db->close();
} catch (Exception $e) {
$db->close();
throw $e;
}
}
# Entries import
protected function importPosts(&$percent)
{
$db = $this->db();
$prefix = $this->vars['db_prefix'];
$plink = $db->select(
'SELECT option_value FROM ' . $prefix . 'options ' .
"WHERE option_name = 'permalink_structure'"
)->option_value;
if ($plink) {
$this->vars['permalink_template'] = substr($plink, 1);
}
$rs = $db->select(
'SELECT * FROM ' . $prefix . 'posts ' .
'WHERE post_type = \'post\' OR post_type = \'page\' ' .
'ORDER BY ID ASC ' .
$db->limit($this->post_offset, $this->post_limit)
);
try
{
if ($this->post_offset == 0) {
$this->con->execute(
'DELETE FROM ' . $this->prefix . 'post ' .
"WHERE blog_id = '" . $this->con->escape($this->blog_id) . "' "
);
}
while ($rs->fetch()) {
$this->importPost($rs, $db);
}
$db->close();
} catch (Exception $e) {
$db->close();
throw $e;
}
if ($rs->count() < $this->post_limit) {
return -1;
} else {
$this->post_offset += $this->post_limit;
}
if ($this->post_offset > $this->post_count) {
$percent = 100;
} else {
$percent = $this->post_offset * 100 / $this->post_count;
}
}
protected function importPost($rs, $db)
{
$post_date = !@strtotime($rs->post_date) ? '1970-01-01 00:00' : $rs->post_date;
if (!isset($this->vars['user_ids'][$rs->post_author])) {
$user_id = $this->core->auth->userID();
} else {
$user_id = $this->vars['user_ids'][$rs->post_author];
}
$cur = $this->con->openCursor($this->prefix . 'post');
$cur->blog_id = $this->blog_id;
$cur->user_id = $user_id;
$cur->post_dt = $post_date;
$cur->post_creadt = $post_date;
$cur->post_upddt = $rs->post_modified;
$cur->post_title = $this->cleanStr($rs->post_title);
if (!$cur->post_title) {
$cur->post_title = 'No title';
}
if ($this->vars['cat_import'] || $this->vars['cat_as_tags']) {
$old_cat_ids = $db->select(
'SELECT * FROM ' . $this->vars['db_prefix'] . 'terms AS t, ' .
$this->vars['db_prefix'] . 'term_taxonomy AS x, ' .
$this->vars['db_prefix'] . 'term_relationships AS r ' .
'WHERE t.term_id = x.term_id ' .
($this->vars['ignore_first_cat'] ? 'AND t.term_id <> 1 ' : '') .
'AND x.taxonomy = \'category\' ' .
'AND t.term_id = r.term_taxonomy_id ' .
'AND r.object_id =' . $rs->ID .
' ORDER BY t.term_id ASC '
);
if (!$old_cat_ids->isEmpty() && $this->vars['cat_import']) {
$cur->cat_id = $this->vars['cat_ids'][(integer) $old_cat_ids->term_id];
}
}
$permalink_infos = [
date('Y', strtotime($cur->post_dt)),
date('m', strtotime($cur->post_dt)),
date('d', strtotime($cur->post_dt)),
date('H', strtotime($cur->post_dt)),
date('i', strtotime($cur->post_dt)),
date('s', strtotime($cur->post_dt)),
$rs->post_name,
$rs->ID,
$cur->cat_id,
$cur->user_id
];
$cur->post_url = str_replace(
$this->vars['permalink_tags'],
$permalink_infos,
$rs->post_type == 'post' ? $this->vars['permalink_template'] : '%postname%'
);
$cur->post_url = substr($cur->post_url, 0, 255);
if (!$cur->post_url) {
$cur->post_url = $rs->ID;
}
$cur->post_format = $this->vars['post_formater'];
$_post_content = explode('<!--more-->', $rs->post_content, 2);
if (count($_post_content) == 1) {
$cur->post_excerpt = null;
$cur->post_content = $this->cleanStr(array_shift($_post_content));
} else {
$cur->post_excerpt = $this->cleanStr(array_shift($_post_content));
$cur->post_content = $this->cleanStr(array_shift($_post_content));
}
$cur->post_content_xhtml = $this->core->callFormater($this->vars['post_formater'], $cur->post_content);
$cur->post_excerpt_xhtml = $this->core->callFormater($this->vars['post_formater'], $cur->post_excerpt);
switch ($rs->post_status) {
case 'publish':
$cur->post_status = 1;
break;
case 'draft':
$cur->post_status = 0;
break;
case 'pending':
$cur->post_status = -2;
break;
default:
$cur->post_status = -2;
}
$cur->post_type = $rs->post_type;
$cur->post_password = $rs->post_password ?: null;
$cur->post_open_comment = $rs->comment_status == 'open' ? 1 : 0;
$cur->post_open_tb = $rs->ping_status == 'open' ? 1 : 0;
$cur->post_words = implode(' ', text::splitWords(
$cur->post_title . ' ' .
$cur->post_excerpt_xhtml . ' ' .
$cur->post_content_xhtml
));
$cur->post_id = $this->con->select(
'SELECT MAX(post_id) FROM ' . $this->prefix . 'post'
)->f(0) + 1;
$cur->post_url = $this->core->blog->getPostURL($cur->post_url, $cur->post_dt, $cur->post_title, $cur->post_id);
$cur->insert();
$this->importComments($rs->ID, $cur->post_id, $db);
$this->importPings($rs->ID, $cur->post_id, $db);
# Create tags
$this->importTags($rs->ID, $cur->post_id, $db);
if (isset($old_cat_ids)) {
if (!$old_cat_ids->isEmpty() && $this->vars['cat_as_tags']) {
$old_cat_ids->moveStart();
while ($old_cat_ids->fetch()) {
$this->core->meta->setPostMeta($cur->post_id, 'tag', $this->cleanStr($this->vars['cat_tags_prefix'] . $old_cat_ids->name));
}
}
}
}
# Comments import
protected function importComments($post_id, $new_post_id, $db)
{
$count_c = $count_t = 0;
$rs = $db->select(
'SELECT * FROM ' . $this->vars['db_prefix'] . 'comments ' .
'WHERE comment_post_ID = ' . (integer) $post_id . ' '
);
while ($rs->fetch()) {
$cur = $this->con->openCursor($this->prefix . 'comment');
$cur->post_id = (integer) $new_post_id;
$cur->comment_author = $this->cleanStr($rs->comment_author);
$cur->comment_status = (integer) $rs->comment_approved;
$cur->comment_dt = $rs->comment_date;
$cur->comment_email = $this->cleanStr($rs->comment_author_email);
$cur->comment_content = $this->core->callFormater($this->vars['comment_formater'], $this->cleanStr($rs->comment_content));
$cur->comment_ip = $rs->comment_author_IP;
$cur->comment_trackback = $rs->comment_type == 'trackback' ? 1 : 0;
$cur->comment_site = substr($this->cleanStr($rs->comment_author_url), 0, 255);
if ($cur->comment_site == '') {
$cur->comment_site = null;
}
if ($rs->comment_approved == 'spam') {
$cur->comment_status = -2;
}
$cur->comment_words = implode(' ', text::splitWords($cur->comment_content));
$cur->comment_id = $this->con->select(
'SELECT MAX(comment_id) FROM ' . $this->prefix . 'comment'
)->f(0) + 1;
$cur->insert();
if ($cur->comment_trackback && $cur->comment_status == 1) {
$count_t++;
} elseif ($cur->comment_status == 1) {
$count_c++;
}
}
if ($count_t > 0 || $count_c > 0) {
$this->con->execute(
'UPDATE ' . $this->prefix . 'post SET ' .
'nb_comment = ' . $count_c . ', ' .
'nb_trackback = ' . $count_t . ' ' .
'WHERE post_id = ' . (integer) $new_post_id . ' '
);
}
}
# Pings import
protected function importPings($post_id, $new_post_id, $db)
{
$urls = [];
$pings = [];
$rs = $db->select(
'SELECT pinged FROM ' . $this->vars['db_prefix'] . 'posts ' .
'WHERE ID = ' . (integer) $post_id
);
$pings = explode("\n", $rs->pinged);
unset($pings[0]);
foreach ($pings as $ping_url) {
$url = $this->cleanStr($ping_url);
if (isset($urls[$url])) {
continue;
}
$cur = $this->con->openCursor($this->prefix . 'ping');
$cur->post_id = (integer) $new_post_id;
$cur->ping_url = $url;
$cur->insert();
$urls[$url] = true;
}
}
# Meta import
protected function importTags($post_id, $new_post_id, $db)
{
$rs = $db->select(
'SELECT * FROM ' . $this->vars['db_prefix'] . 'terms AS t, ' .
$this->vars['db_prefix'] . 'term_taxonomy AS x, ' .
$this->vars['db_prefix'] . 'term_relationships AS r ' .
'WHERE t.term_id = x.term_id ' .
'AND x.taxonomy = \'post_tag\' ' .
'AND t.term_id = r.term_taxonomy_id ' .
'AND r.object_id =' . $post_id .
' ORDER BY t.term_id ASC'
);
if ($rs->isEmpty()) {
return;
}
while ($rs->fetch()) {
$this->core->meta->setPostMeta($new_post_id, 'tag', $this->cleanStr($rs->name));
}
}
}

View File

@ -0,0 +1,133 @@
<?php
# -- BEGIN LICENSE BLOCK ---------------------------------------
#
# This file is part of Dotclear 2.
#
# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
# Licensed under the GPL version 2.0 license.
# See LICENSE file or
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
#
# -- END LICENSE BLOCK -----------------------------------------
if (!defined('DC_RC_PATH')) { return; }
class backupFile
{
protected $fp;
private $line_cols = array();
private $line_name;
private $replacement = array(
'/(?<!\\\\)(?>(\\\\\\\\)*+)(\\\\n)/u' => "\$1\n",
'/(?<!\\\\)(?>(\\\\\\\\)*+)(\\\\r)/u' => "\$1\r",
'/(?<!\\\\)(?>(\\\\\\\\)*+)(\\\\")/u' => '$1"',
'/(\\\\\\\\)/' => '\\'
);
public function __construct($file)
{
if (file_exists($file) && is_readable($file)) {
$this->fp = fopen($file,'rb');
} else {
throw new Exception(__('No file to read.'));
}
}
public function __destruct()
{
if ($this->fp) {
fclose($this->fp);
}
}
public function getLine()
{
if (feof($this->fp)) {
return false;
}
$line = trim(fgets($this->fp));
if (substr($line,0,1) == '[')
{
$this->line_name = substr($line,1,strpos($line,' ')-1);
$line = substr($line,strpos($line,' ')+1,-1);
$this->line_cols = explode(',',$line);
return $this->getLine();
}
elseif (substr($line,0,1) == '"')
{
$line = preg_replace('/^"|"$/','',$line);
$line = preg_split('/(^"|","|"$)/m',$line);
if (count($this->line_cols) != count($line)) {
throw new Exception('Invalid row count');
}
$res = array();
for ($i=0; $i<count($line); $i++) {
$res[$this->line_cols[$i]] =
preg_replace(array_keys($this->replacement),array_values($this->replacement),$line[$i]);
}
return new backupFileItem($this->line_name,$res);
}
else
{
return $this->getLine();
}
}
}
class backupFileItem
{
public $__name;
private $__data = array();
public function __construct($name,$data)
{
$this->__name = $name;
$this->__data = $data;
}
public function f($name)
{
return iconv('UTF-8','UTF-8//IGNORE',$this->__data[$name]);
}
public function __get($name)
{
return $this->f($name);
}
public function __set($n,$v)
{
$this->__data[$n] = $v;
}
public function exists($n)
{
return isset($this->__data[$n]);
}
public function drop()
{
foreach (func_get_args() as $n) {
if (isset($this->__data[$n])) {
unset($this->__data[$n]);
}
}
}
public function substitute($old,$new)
{
if (isset($this->__data[$old])) {
$this->__data[$new] = $this->__data[$old];
unset($this->__data[$old]);
}
}
}
?>

View File

@ -0,0 +1,106 @@
<?php
# -- BEGIN LICENSE BLOCK ---------------------------------------
#
# This file is part of Dotclear 2.
#
# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
# Licensed under the GPL version 2.0 license.
# See LICENSE file or
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
#
# -- END LICENSE BLOCK -----------------------------------------
if (!defined('DC_RC_PATH')) { return; }
class dbExport
{
private $con;
private $prefix;
private $line_reg = array('/\\\\/u', '/\n/u','/\r/u','/"/u');
private $line_rep = array('\\\\\\\\', '\n' ,'\r' ,'\"');
public $fp;
function __construct($con,$out='php://output',$prefix=null)
{
$this->con =& $con;
$this->prefix = $prefix;
if (($this->fp = fopen($out,'w')) === false) {
return false;
}
@set_time_limit(300);
}
function __destruct()
{
if (is_resource($this->fp)) {
fclose($this->fp);
}
}
function export($name,$sql)
{
$rs = $this->con->select($sql);
if (!$rs->isEmpty())
{
fwrite($this->fp,"\n[".$name.' '.implode(',',$rs->columns())."]\n");
while ($rs->fetch()) {
fwrite($this->fp,$this->getLine($rs));
}
fflush($this->fp);
}
}
function exportAll()
{
$tables = $this->getTables();
foreach ($tables as $table)
{
$this->exportTable($table);
}
}
function exportTable($table)
{
$req = 'SELECT * FROM '.$this->con->escapeSystem($this->prefix.$table);
$this->export($table,$req);
}
function getTables()
{
$schema = dbSchema::init($this->con);
$db_tables = $schema->getTables();
$tables = array();
foreach ($db_tables as $t)
{
if ($this->prefix) {
if (strpos($t,$this->prefix) === 0) {
$tables[] = $t;
}
} else {
$tables[] = $t;
}
}
return $tables;
}
function getLine($rs)
{
$l = array();
$cols = $rs->columns();
foreach ($cols as $i => &$c) {
$s = $rs->f($c);
$s = preg_replace($this->line_reg,$this->line_rep,$s);
$s = '"'.$s.'"';
$l[$i] = $s;
}
return implode(',',$l)."\n";
}
}
?>

View File

@ -0,0 +1,857 @@
<?php
# -- BEGIN LICENSE BLOCK ---------------------------------------
#
# This file is part of Dotclear 2.
#
# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
# Licensed under the GPL version 2.0 license.
# See LICENSE file or
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
#
# -- END LICENSE BLOCK -----------------------------------------
if (!defined('DC_RC_PATH')) { return; }
class dcImport extends backupFile
{
private $core;
private $con;
private $prefix;
private $dc_version;
private $dc_major;
private $mode;
private $blog_url;
private $blog_name;
private $blog_desc;
private $users = array();
public $old_ids = array(
'category' => array(),
'post' => array(),
'media' => array()
);
public $stack = array(
'categories'=>null,
'cat_id'=>1,
'cat_lft'=>array(),
'post_id'=>1,
'media_id'=>1,
'comment_id'=>1,
'link_id'=>1
);
public $has_categories = false;
public function __construct($core,$file)
{
parent::__construct($file);
$first_line = fgets($this->fp);
if (strpos($first_line,'///DOTCLEAR|') !== 0) {
throw new Exception(__('File is not a DotClear backup.'));
}
@set_time_limit(300);
$l = explode('|',$first_line);
if (isset($l[1])) {
$this->dc_version = $l[1];
}
$this->mode = isset($l[2]) ? strtolower(trim($l[2])) : 'single';
if ($this->mode != 'full' && $this->mode != 'single') {
$this->mode = 'single';
}
if (version_compare('1.2',$this->dc_version,'<=') &&
version_compare('1.3',$this->dc_version,'>')) {
$this->dc_major_version = '1.2';
} else {
$this->dc_major_version = '2.0';
}
$this->core =& $core;
$this->con =& $core->con;
$this->prefix = $core->prefix;
$this->cur_blog = $this->con->openCursor($this->prefix.'blog');
$this->cur_category = $this->con->openCursor($this->prefix.'category');
$this->cur_link = $this->con->openCursor($this->prefix.'link');
$this->cur_setting = $this->con->openCursor($this->prefix.'setting');
$this->cur_user = $this->con->openCursor($this->prefix.'user');
$this->cur_pref = $this->con->openCursor($this->prefix.'pref');
$this->cur_permissions = $this->con->openCursor($this->prefix.'permissions');
$this->cur_post = $this->con->openCursor($this->prefix.'post');
$this->cur_meta = $this->con->openCursor($this->prefix.'meta');
$this->cur_media = $this->con->openCursor($this->prefix.'media');
$this->cur_post_media = $this->con->openCursor($this->prefix.'post_media');
$this->cur_log = $this->con->openCursor($this->prefix.'log');
$this->cur_ping = $this->con->openCursor($this->prefix.'ping');
$this->cur_comment = $this->con->openCursor($this->prefix.'comment');
$this->cur_spamrule = $this->con->openCursor($this->prefix.'spamrule');
$this->cur_version = $this->con->openCursor($this->prefix.'version');
# --BEHAVIOR-- importInit
$this->core->callBehavior('importInit',$this,$this->core);
}
public function importSingle()
{
if ($this->mode != 'single') {
throw new Exception(__('File is not a single blog export.'));
}
if (!$this->core->auth->check('admin',$this->core->blog->id)) {
throw new Exception(__('Permission denied.'));
}
$this->blog_id = $this->core->blog->id;
$this->stack['categories'] = $this->con->select(
'SELECT cat_id, cat_title, cat_url '.
'FROM '.$this->prefix.'category '.
"WHERE blog_id = '".$this->con->escape($this->blog_id)."' "
);
$rs = $this->con->select('SELECT MAX(cat_id) FROM '.$this->prefix.'category');
$this->stack['cat_id'] = ((integer) $rs->f(0))+1;
$rs = $this->con->select('SELECT MAX(link_id) FROM '.$this->prefix.'link');
$this->stack['link_id'] = ((integer) $rs->f(0))+1;
$rs = $this->con->select('SELECT MAX(post_id) FROM '.$this->prefix.'post');
$this->stack['post_id'] = ((integer) $rs->f(0))+1;
$rs = $this->con->select('SELECT MAX(media_id) FROM '.$this->prefix.'media');
$this->stack['media_id'] = ((integer) $rs->f(0))+1;
$rs = $this->con->select('SELECT MAX(comment_id) FROM '.$this->prefix.'comment');
$this->stack['comment_id'] = ((integer) $rs->f(0))+1;
$rs = $this->con->select(
'SELECT MAX(cat_rgt) AS cat_rgt FROM '.$this->prefix.'category '.
"WHERE blog_id = '".$this->con->escape($this->core->blog->id)."'"
);
if ((integer) $rs->cat_rgt > 0) {
$this->has_categories = true;
$this->stack['cat_lft'][$this->core->blog->id] = (integer) $rs->cat_rgt + 1;
}
$this->con->begin();
try
{
$last_line_name = '';
$constrained = array('post', 'meta', 'post_media', 'ping', 'comment');
while (($line = $this->getLine()) !== false)
{
# import DC 1.2.x, we fix lines before insert
if ($this->dc_major_version == '1.2') {
$this->prepareDC12line($line);
}
if ($last_line_name != $line->__name) {
if (in_array($last_line_name,$constrained)) {
# UNDEFER
if ($this->con->driver() == 'mysql') $this->con->execute('SET foreign_key_checks = 1');
if ($this->con->driver() == 'pgsql') $this->con->execute('SET CONSTRAINTS ALL DEFERRED');
}
if (in_array($line->__name,$constrained)) {
# DEFER
if ($this->con->driver() == 'mysql') $this->con->execute('SET foreign_key_checks = 0');
if ($this->con->driver() == 'pgsql') $this->con->execute('SET CONSTRAINTS ALL IMMEDIATE');
}
$last_line_name = $line->__name;
}
switch ($line->__name)
{
case 'category':
$this->insertCategorySingle($line);
break;
case 'link':
$this->insertLinkSingle($line);
break;
case 'post':
$this->insertPostSingle($line);
break;
case 'meta':
$this->insertMetaSingle($line);
break;
case 'media':
$this->insertMediaSingle($line);
break;
case 'post_media':
$this->insertPostMediaSingle($line);
break;
case 'ping':
$this->insertPingSingle($line);
break;
case 'comment':
$this->insertCommentSingle($line);
break;
}
# --BEHAVIOR-- importSingle
$this->core->callBehavior('importSingle',$line,$this,$this->core);
}
if ($this->con->driver() == 'mysql') $this->con->execute('SET foreign_key_checks = 1');
if ($this->con->driver() == 'pgsql') $this->con->execute('SET CONSTRAINTS ALL DEFERRED');
}
catch (Exception $e)
{
$this->con->rollback();
throw $e;
}
$this->con->commit();
}
public function importFull()
{
if ($this->mode != 'full') {
throw new Exception(__('File is not a full export.'));
}
if (!$this->core->auth->isSuperAdmin()) {
throw new Exception(__('Permission denied.'));
}
$this->con->begin();
$this->con->execute('DELETE FROM '.$this->prefix.'blog');
$this->con->execute('DELETE FROM '.$this->prefix.'media');
$this->con->execute('DELETE FROM '.$this->prefix.'spamrule');
$this->con->execute('DELETE FROM '.$this->prefix.'setting');
try
{
while (($line = $this->getLine()) !== false)
{
switch ($line->__name)
{
case 'blog':
$this->insertBlog($line);
break;
case 'category':
$this->insertCategory($line);
break;
case 'link':
$this->insertLink($line);
break;
case 'setting':
$this->insertSetting($line);
break;
case 'user':
$this->insertUser($line);
break;
case 'pref':
$this->insertPref($line);
break;
case 'permissions':
$this->insertPermissions($line);
break;
case 'post':
$this->insertPost($line);
break;
case 'meta':
$this->insertMeta($line);
break;
case 'media':
$this->insertMedia($line);
break;
case 'post_media':
$this->insertPostMedia($line);
break;
case 'log';
$this->insertLog($line);
break;
case 'ping':
$this->insertPing($line);
break;
case 'comment':
$this->insertComment($line);
break;
case 'spamrule':
$this->insertSpamRule($line);
break;
}
# --BEHAVIOR-- importFull
$this->core->callBehavior('importFull',$line,$this,$this->core);
}
}
catch (Exception $e)
{
$this->con->rollback();
throw $e;
}
$this->con->commit();
}
private function insertBlog($blog)
{
$this->cur_blog->clean();
$this->cur_blog->blog_id = (string) $blog->blog_id;
$this->cur_blog->blog_uid = (string) $blog->blog_uid;
$this->cur_blog->blog_creadt = (string) $blog->blog_creadt;
$this->cur_blog->blog_upddt = (string) $blog->blog_upddt;
$this->cur_blog->blog_url = (string) $blog->blog_url;
$this->cur_blog->blog_name = (string) $blog->blog_name;
$this->cur_blog->blog_desc = (string) $blog->blog_desc;
$this->cur_blog->blog_status = $blog->exists('blog_status') ? (integer) $blog->blog_status : 1;
$this->cur_blog->insert();
}
private function insertCategory($category)
{
$this->cur_category->clean();
$this->cur_category->cat_id = (string) $category->cat_id;
$this->cur_category->blog_id = (string) $category->blog_id;
$this->cur_category->cat_title = (string) $category->cat_title;
$this->cur_category->cat_url = (string) $category->cat_url;
$this->cur_category->cat_desc = (string) $category->cat_desc;
if (!$this->has_categories && $category->exists('cat_lft') && $category->exists('cat_rgt')) {
$this->cur_category->cat_lft = (integer) $category->cat_lft;
$this->cur_category->cat_rgt = (integer) $category->cat_rgt;
} else {
if (!isset($this->stack['cat_lft'][$category->blog_id])) {
$this->stack['cat_lft'][$category->blog_id] = 2;
}
$this->cur_category->cat_lft = $this->stack['cat_lft'][$category->blog_id]++;
$this->cur_category->cat_rgt = $this->stack['cat_lft'][$category->blog_id]++;
}
$this->cur_category->insert();
}
private function insertLink($link)
{
$this->cur_link->clean();
$this->cur_link->link_id = (integer) $link->link_id;
$this->cur_link->blog_id = (string) $link->blog_id;
$this->cur_link->link_href = (string) $link->link_href;
$this->cur_link->link_title = (string) $link->link_title;
$this->cur_link->link_desc = (string) $link->link_desc;
$this->cur_link->link_lang = (string) $link->link_lang;
$this->cur_link->link_xfn = (string) $link->link_xfn;
$this->cur_link->link_position = (integer) $link->link_position;
$this->cur_link->insert();
}
private function insertSetting($setting)
{
$this->cur_setting->clean();
$this->cur_setting->setting_id = (string) $setting->setting_id;
$this->cur_setting->blog_id = !$setting->blog_id ? null : (string) $setting->blog_id;
$this->cur_setting->setting_ns = (string) $setting->setting_ns;
$this->cur_setting->setting_value = (string) $setting->setting_value;
$this->cur_setting->setting_type = (string) $setting->setting_type;
$this->cur_setting->setting_label = (string) $setting->setting_label;
$this->cur_setting->insert();
}
private function insertPref($pref)
{
if ($this->prefExists($pref->pref_ws,$pref->pref_id,$pref->user_id)) {
return;
}
$this->cur_pref->clean();
$this->cur_pref->pref_id = (string) $pref->pref_id;
$this->cur_pref->user_id = !$pref->user_id ? null : (string) $pref->user_id;
$this->cur_pref->pref_ws = (string) $pref->pref_ws;
$this->cur_pref->pref_value = (string) $pref->pref_value;
$this->cur_pref->pref_type = (string) $pref->pref_type;
$this->cur_pref->pref_label = (string) $pref->pref_label;
$this->cur_pref->insert();
}
private function insertUser($user)
{
if ($this->userExists($user->user_id)) {
return;
}
$this->cur_user->clean();
$this->cur_user->user_id = (string) $user->user_id;
$this->cur_user->user_super = (integer) $user->user_super;
$this->cur_user->user_pwd = (string) $user->user_pwd;
$this->cur_user->user_recover_key = (string) $user->user_recover_key;
$this->cur_user->user_name = (string) $user->user_name;
$this->cur_user->user_firstname = (string) $user->user_firstname;
$this->cur_user->user_displayname = (string) $user->user_displayname;
$this->cur_user->user_email = (string) $user->user_email;
$this->cur_user->user_url = (string) $user->user_url;
$this->cur_user->user_default_blog = !$user->user_default_blog ? null : (string) $user->user_default_blog;
$this->cur_user->user_lang = (string) $user->user_lang;
$this->cur_user->user_tz = (string) $user->user_tz;
$this->cur_user->user_post_status = (integer) $user->user_post_status;
$this->cur_user->user_creadt = (string) $user->user_creadt;
$this->cur_user->user_upddt = (string) $user->user_upddt;
$this->cur_user->user_desc = $user->exists('user_desc') ? (string) $user->user_desc : null;
$this->cur_user->user_options = $user->exists('user_options') ? (string) $user->user_options : null;
$this->cur_user->user_status = $user->exists('user_status') ? (integer) $user->user_status : 1;
$this->cur_user->insert();
$this->stack['users'][$user->user_id] = true;
}
private function insertPermissions($permissions)
{
$this->cur_permissions->clean();
$this->cur_permissions->user_id = (string) $permissions->user_id;
$this->cur_permissions->blog_id = (string) $permissions->blog_id;
$this->cur_permissions->permissions = (string) $permissions->permissions;
$this->cur_permissions->insert();
}
private function insertPost($post)
{
$this->cur_post->clean();
$cat_id = (integer) $post->cat_id;
if (!$cat_id) {
$cat_id = null;
}
$post_password = $post->post_password ? (string) $post->post_password : null;
$this->cur_post->post_id = (integer) $post->post_id;
$this->cur_post->blog_id = (string) $post->blog_id;
$this->cur_post->user_id = (string) $this->getUserId($post->user_id);
$this->cur_post->cat_id = $cat_id;
$this->cur_post->post_dt = (string) $post->post_dt;
$this->cur_post->post_creadt = (string) $post->post_creadt;
$this->cur_post->post_upddt = (string) $post->post_upddt;
$this->cur_post->post_password = $post_password;
$this->cur_post->post_type = (string) $post->post_type;
$this->cur_post->post_format = (string) $post->post_format;
$this->cur_post->post_url = (string) $post->post_url;
$this->cur_post->post_lang = (string) $post->post_lang;
$this->cur_post->post_title = (string) $post->post_title;
$this->cur_post->post_excerpt = (string) $post->post_excerpt;
$this->cur_post->post_excerpt_xhtml = (string) $post->post_excerpt_xhtml;
$this->cur_post->post_content = (string) $post->post_content;
$this->cur_post->post_content_xhtml = (string) $post->post_content_xhtml;
$this->cur_post->post_notes = (string) $post->post_notes;
$this->cur_post->post_words = (string) $post->post_words;
$this->cur_post->post_meta = (string) $post->post_meta;
$this->cur_post->post_status = (integer) $post->post_status;
$this->cur_post->post_selected = (integer) $post->post_selected;
$this->cur_post->post_open_comment = (integer) $post->post_open_comment;
$this->cur_post->post_open_tb = (integer) $post->post_open_tb;
$this->cur_post->nb_comment = (integer) $post->nb_comment;
$this->cur_post->nb_trackback = (integer) $post->nb_trackback;
$this->cur_post->post_tz = $post->exists('post_tz') ? (string) $post->post_tz : 'UTC';
$this->cur_post->insert();
}
private function insertMeta($meta)
{
$this->cur_meta->clean();
$this->cur_meta->meta_id = (string) $meta->meta_id;
$this->cur_meta->meta_type = (string) $meta->meta_type;
$this->cur_meta->post_id = (integer) $meta->post_id;
$this->cur_meta->insert();
}
private function insertMedia($media)
{
$this->cur_media->clean();
$this->cur_media->media_id = (integer) $media->media_id;
$this->cur_media->user_id = (string) $media->user_id;
$this->cur_media->media_path = (string) $media->media_path;
$this->cur_media->media_title = (string) $media->media_title;
$this->cur_media->media_file = (string) $media->media_file;
$this->cur_media->media_meta = (string) $media->media_meta;
$this->cur_media->media_dt = (string) $media->media_dt;
$this->cur_media->media_creadt = (string) $media->media_creadt;
$this->cur_media->media_upddt = (string) $media->media_upddt;
$this->cur_media->media_private = (integer) $media->media_private;
$this->cur_media->media_dir = $media->exists('media_dir') ? (string) $media->media_dir : dirname($media->media_file);
if (!$this->mediaExists()) {
$this->cur_media->insert();
}
}
private function insertPostMedia($post_media)
{
$this->cur_post_media->clean();
$this->cur_post_media->media_id = (integer) $post_media->media_id;
$this->cur_post_media->post_id = (integer) $post_media->post_id;
$this->cur_post_media->insert();
}
private function insertLog($log)
{
$this->cur_log->clean();
$this->cur_log->log_id = (integer) $log->log_id;
$this->cur_log->user_id = (string) $log->user_id;
$this->cur_log->log_table = (string) $log->log_table;
$this->cur_log->log_dt = (string) $log->log_dt;
$this->cur_log->log_ip = (string) $log->log_ip;
$this->cur_log->log_msg = (string) $log->log_msg;
$this->cur_log->insert();
}
private function insertPing($ping)
{
$this->cur_ping->clean();
$this->cur_ping->post_id = (integer) $ping->post_id;
$this->cur_ping->ping_url = (string) $ping->ping_url;
$this->cur_ping->ping_dt = (string) $ping->ping_dt;
$this->cur_ping->insert();
}
private function insertComment($comment)
{
$this->cur_comment->clean();
$this->cur_comment->comment_id = (integer) $comment->comment_id;
$this->cur_comment->post_id = (integer) $comment->post_id;
$this->cur_comment->comment_dt = (string) $comment->comment_dt;
$this->cur_comment->comment_upddt = (string) $comment->comment_upddt;
$this->cur_comment->comment_author = (string) $comment->comment_author;
$this->cur_comment->comment_email = (string) $comment->comment_email;
$this->cur_comment->comment_site = (string) $comment->comment_site;
$this->cur_comment->comment_content = (string) $comment->comment_content;
$this->cur_comment->comment_words = (string) $comment->comment_words;
$this->cur_comment->comment_ip = (string) $comment->comment_ip;
$this->cur_comment->comment_status = (integer) $comment->comment_status;
$this->cur_comment->comment_spam_status = (integer) $comment->comment_spam_status;
$this->cur_comment->comment_trackback = (integer) $comment->comment_trackback;
$this->cur_comment->comment_tz = $comment->exists('comment_tz') ? (string) $comment->comment_tz : 'UTC';
$this->cur_comment->comment_spam_filter = $comment->exists('comment_spam_filter') ? (integer) $comment->comment_spam_filter : null;
$this->cur_comment->insert();
}
private function insertSpamRule($spamrule)
{
$this->cur_spamrule->clean();
$this->cur_spamrule->rule_id = (integer) $spamrule->rule_id;
$this->cur_spamrule->blog_id = !$spamrule->blog_id ? null : (string) $spamrule->blog_id;
$this->cur_spamrule->rule_type = (string) $spamrule->rule_type;
$this->cur_spamrule->rule_content = (string) $spamrule->rule_content;
$this->cur_spamrule->insert();
}
private function insertCategorySingle($category)
{
$this->cur_category->clean();
$m = $this->searchCategory($this->stack['categories'],$category->cat_url);
$old_id = $category->cat_id;
if ($m !== false)
{
$cat_id = $m;
}
else
{
$cat_id = $this->stack['cat_id'];
$category->cat_id = $cat_id;
$category->blog_id = $this->blog_id;
$this->insertCategory($category);
$this->stack['cat_id']++;
}
$this->old_ids['category'][(integer) $old_id] = $cat_id;
}
private function insertLinkSingle($link)
{
$link->blog_id = $this->blog_id;
$link->link_id = $this->stack['link_id'];
$this->insertLink($link);
$this->stack['link_id']++;
}
private function insertPostSingle($post)
{
if (!$post->cat_id || isset($this->old_ids['category'][(integer) $post->cat_id])) {
$post_id = $this->stack['post_id'];
$this->old_ids['post'][(integer) $post->post_id] = $post_id;
$cat_id = $post->cat_id ? $this->old_ids['category'][(integer) $post->cat_id] : null;
$post->post_id = $post_id;
$post->cat_id = $cat_id;
$post->blog_id = $this->blog_id;
$post->post_url = $this->core->blog->getPostURL(
$post->post_url,$post->post_dt,$post->post_title,$post->post_id
);
$this->insertPost($post);
$this->stack['post_id']++;
} else {
throw new Exception(__('The backup file does not appear to be well formed.'));
}
}
private function insertMetaSingle($meta)
{
if (isset($this->old_ids['post'][(integer) $meta->post_id])) {
$meta->post_id = $this->old_ids['post'][(integer) $meta->post_id];
$this->insertMeta($meta);
} else {
throw new Exception(__('The backup file does not appear to be well formed.'));
}
}
private function insertMediaSingle($media)
{
$media_id = $this->stack['media_id'];
$old_id = $media->media_id;
$media->media_id = $media_id;
$media->media_path = $this->core->blog->settings->system->public_path;
$media->user_id = $this->getUserId($media->user_id);
$this->insertMedia($media);
$this->stack['media_id']++;
$this->old_ids['media'][(integer) $old_id] = $media_id;
}
private function insertPostMediaSingle($post_media)
{
if (isset($this->old_ids['media'][(integer) $post_media->media_id]) &&
isset($this->old_ids['post'][(integer) $post_media->post_id])) {
$post_media->media_id = $this->old_ids['media'][(integer) $post_media->media_id];
$post_media->post_id = $this->old_ids['post'][(integer) $post_media->post_id];
$this->insertPostMedia($post_media);
} else {
throw new Exception(__('The backup file does not appear to be well formed.'));
}
}
private function insertPingSingle($ping)
{
if (isset($this->old_ids['post'][(integer) $ping->post_id])) {
$ping->post_id = $this->old_ids['post'][(integer) $ping->post_id];
$this->insertPing($ping);
} else {
throw new Exception(__('The backup file does not appear to be well formed.'));
}
}
private function insertCommentSingle($comment)
{
if (isset($this->old_ids['post'][(integer) $comment->post_id])) {
$comment_id = $this->stack['comment_id'];
$comment->comment_id = $comment_id;
$comment->post_id = $this->old_ids['post'][(integer) $comment->post_id];
$this->insertComment($comment);
$this->stack['comment_id']++;
} else {
throw new Exception(__('The backup file does not appear to be well formed.'));
}
}
public function searchCategory($rs,$url)
{
while ($rs->fetch())
{
if ($rs->cat_url == $url) {
return $rs->cat_id;
}
}
return false;
}
public function getUserId($user_id)
{
if (!$this->userExists($user_id))
{
if ($this->core->auth->isSuperAdmin())
{
# Sanitizes user_id and create a lambda user
$user_id = preg_replace('/[^A-Za-z0-9]$/','',$user_id);
$user_id .= strlen($user_id) < 2 ? '-a' : '';
# We change user_id, we need to check again
if (!$this->userExists($user_id))
{
$this->cur_user->clean();
$this->cur_user->user_id = (string) $user_id;
$this->cur_user->user_pwd = md5(uniqid());
$this->core->addUser($this->cur_user);
$this->stack['users'][$user_id] = true;
}
}
else
{
# Returns current user id
$user_id = $this->core->auth->userID();
}
}
return $user_id;
}
private function userExists($user_id)
{
if (isset($this->stack['users'][$user_id])) {
return $this->stack['users'][$user_id];
}
$strReq = 'SELECT user_id '.
'FROM '.$this->prefix.'user '.
"WHERE user_id = '".$this->con->escape($user_id)."' ";
$rs = $this->con->select($strReq);
$this->stack['users'][$user_id] = !$rs->isEmpty();
return $this->stack['users'][$user_id];
}
private function prefExists($pref_ws,$pref_id,$user_id)
{
$strReq = 'SELECT pref_id,pref_ws,user_id '.
'FROM '.$this->prefix.'pref '.
"WHERE pref_id = '".$this->con->escape($pref_id)."' ".
"AND pref_ws = '".$this->con->escape($pref_ws)."' ";
if (!$user_id) {
$strReq .= "AND user_id IS NULL ";
} else {
$strReq .= "AND user_id = '".$this->con->escape($user_id)."' ";
}
$rs = $this->con->select($strReq);
return !$rs->isEmpty();
}
private function mediaExists()
{
$strReq = 'SELECT media_id '.
'FROM '.$this->prefix.'media '.
"WHERE media_path = '".$this->cur_media->media_path."' ".
"AND media_file = '".$this->cur_media->media_file."' ";
$rs = $this->con->select($strReq);
return !$rs->isEmpty();
}
private function prepareDC12line(&$line)
{
$settings = array('dc_theme','dc_nb_post_per_page','dc_allow_comments',
'dc_allow_trackbacks','dc_comment_pub','dc_comments_ttl',
'dc_wiki_comments','dc_use_smilies','dc_date_format','dc_time_format',
'dc_url_scan');
switch ($line->__name)
{
case 'categorie':
$line->substitute('cat_libelle','cat_title');
$line->substitute('cat_libelle_url','cat_url');
$line->__name = 'category';
$line->blog_id = 'default';
break;
case 'link':
$line->substitute('href','link_href');
$line->substitute('label','link_title');
$line->substitute('title','link_desc');
$line->substitute('lang','link_lang');
$line->substitute('rel','link_xfn');
$line->substitute('position','link_position');
$line->blog_id = 'default';
break;
case 'post':
$line->substitute('post_titre','post_title');
$line->post_title = html::decodeEntities($line->post_title);
$line->post_url = date('Y/m/d/',strtotime($line->post_dt)).$line->post_id.'-'.$line->post_titre_url;
$line->post_url = substr($line->post_url,0,255);
$line->post_format = $line->post_content_wiki == '' ? 'xhtml' : 'wiki';
$line->post_content_xhtml = $line->post_content;
$line->post_excerpt_xhtml = $line->post_chapo;
if ($line->post_format == 'wiki') {
$line->post_content = $line->post_content_wiki;
$line->post_excerpt = $line->post_chapo_wiki;
} else {
$line->post_content = $line->post_content;
$line->post_excerpt = $line->post_chapo;
}
$line->post_status = (integer) $line->post_pub;
$line->post_type = 'post';
$line->blog_id = 'default';
$line->drop('post_titre_url','post_content_wiki','post_chapo','post_chapo_wiki','post_pub');
break;
case 'post_meta':
$line->drop('meta_id');
$line->substitute('meta_key','meta_type');
$line->substitute('meta_value','meta_id');
$line->__name = 'meta';
$line->blog_id = 'default';
break;
case 'comment':
$line->substitute('comment_auteur','comment_author');
if ($line->comment_site != '' && !preg_match('!^http://.*$!', $line->comment_site,$m)) {
$line->comment_site = 'http://'.$line->comment_site;
}
$line->comment_status = (integer) $line->comment_pub;
$line->drop('comment_pub');
break;
}
# --BEHAVIOR-- importPrepareDC12
$this->core->callBehavior('importPrepareDC12',$line,$this,$this->core);
}
}
?>

View File

@ -0,0 +1,142 @@
<?php
/**
* @brief importExport, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugins
*
* @copyright Olivier Meunier & Association Dotclear
* @copyright GPL-2.0-only
*/
if (!defined('DC_RC_PATH')) {return;}
class flatBackup
{
protected $fp;
private $line_cols = [];
private $line_name;
private $line_num;
private $replacement = [
'/(?<!\\\\)(?>(\\\\\\\\)*+)(\\\\n)/u' => "\$1\n",
'/(?<!\\\\)(?>(\\\\\\\\)*+)(\\\\r)/u' => "\$1\r",
'/(?<!\\\\)(?>(\\\\\\\\)*+)(\\\\")/u' => '$1"',
'/(\\\\\\\\)/' => '\\'
];
public function __construct($file)
{
if (file_exists($file) && is_readable($file)) {
$this->fp = fopen($file, 'rb');
$this->line_num = 1;
} else {
throw new Exception(__('No file to read.'));
}
}
public function __destruct()
{
if ($this->fp) {
@fclose($this->fp);
}
}
public function getLine()
{
if (($line = $this->nextLine()) === false) {
return false;
}
if (substr($line, 0, 1) == '[') {
$this->line_name = substr($line, 1, strpos($line, ' ') - 1);
$line = substr($line, strpos($line, ' ') + 1, -1);
$this->line_cols = explode(',', $line);
return $this->getLine();
} elseif (substr($line, 0, 1) == '"') {
$line = preg_replace('/^"|"$/', '', $line);
$line = preg_split('/(^"|","|(?<!\\\)\"$)/m', $line);
if (count($this->line_cols) != count($line)) {
throw new Exception(sprintf('Invalid row count at line %s', $this->line_num));
}
$res = [];
for ($i = 0; $i < count($line); $i++) {
$res[$this->line_cols[$i]] =
preg_replace(array_keys($this->replacement), array_values($this->replacement), $line[$i]);
}
return new flatBackupItem($this->line_name, $res, $this->line_num);
} else {
return $this->getLine();
}
}
private function nextLine()
{
if (feof($this->fp)) {
return false;
}
$this->line_num++;
$line = fgets($this->fp);
$line = trim($line);
return empty($line) ? $this->nextLine() : $line;
}
}
class flatBackupItem
{
public $__name;
public $__line;
private $__data = [];
public function __construct($name, $data, $line)
{
$this->__name = $name;
$this->__data = $data;
$this->__line = $line;
}
public function f($name)
{
return iconv('UTF-8', 'UTF-8//IGNORE', $this->__data[$name]);
}
public function __get($name)
{
return $this->f($name);
}
public function __set($n, $v)
{
$this->__data[$n] = $v;
}
public function exists($n)
{
return isset($this->__data[$n]);
}
public function drop(...$args)
{
foreach ($args as $n) {
if (isset($this->__data[$n])) {
unset($this->__data[$n]);
}
}
}
public function substitute($old, $new)
{
if (isset($this->__data[$old])) {
$this->__data[$new] = $this->__data[$old];
unset($this->__data[$old]);
}
}
}

View File

@ -0,0 +1,102 @@
<?php
/**
* @brief importExport, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugins
*
* @copyright Olivier Meunier & Association Dotclear
* @copyright GPL-2.0-only
*/
if (!defined('DC_RC_PATH')) {return;}
class flatExport
{
private $con;
private $prefix;
private $line_reg = ['/\\\\/u', '/\n/u', '/\r/u', '/"/u'];
private $line_rep = ['\\\\\\\\', '\n', '\r', '\"'];
public $fp;
public function __construct($con, $out = 'php://output', $prefix = null)
{
$this->con = &$con;
$this->prefix = $prefix;
if (($this->fp = fopen($out, 'w')) === false) {
return false;
}
@set_time_limit(300);
}
public function __destruct()
{
if (is_resource($this->fp)) {
fclose($this->fp);
}
}
public function export($name, $sql)
{
$rs = $this->con->select($sql);
if (!$rs->isEmpty()) {
fwrite($this->fp, "\n[" . $name . ' ' . implode(',', $rs->columns()) . "]\n");
while ($rs->fetch()) {
fwrite($this->fp, $this->getLine($rs));
}
fflush($this->fp);
}
}
public function exportAll()
{
$tables = $this->getTables();
foreach ($tables as $table) {
$this->exportTable($table);
}
}
public function exportTable($table)
{
$req = 'SELECT * FROM ' . $this->con->escapeSystem($this->prefix . $table);
$this->export($table, $req);
}
public function getTables()
{
$schema = dbSchema::init($this->con);
$db_tables = $schema->getTables();
$tables = [];
foreach ($db_tables as $t) {
if ($this->prefix) {
if (strpos($t, $this->prefix) === 0) {
$tables[] = $t;
}
} else {
$tables[] = $t;
}
}
return $tables;
}
public function getLine($rs)
{
$l = [];
$cols = $rs->columns();
foreach ($cols as $i => &$c) {
$s = $rs->f($c);
$s = preg_replace($this->line_reg, $this->line_rep, $s);
$s = '"' . $s . '"';
$l[$i] = $s;
}
return implode(',', $l) . "\n";
}
}

View File

@ -0,0 +1,881 @@
<?php
/**
* @brief importExport, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugins
*
* @copyright Olivier Meunier & Association Dotclear
* @copyright GPL-2.0-only
*/
if (!defined('DC_RC_PATH')) {return;}
class flatImport extends flatBackup
{
private $core;
private $con;
private $prefix;
private $dc_version;
private $dc_major;
private $mode;
private $blog_url;
private $blog_name;
private $blog_desc;
private $users = [];
public $old_ids = [
'category' => [],
'post' => [],
'media' => []
];
public $stack = [
'categories' => null,
'cat_id' => 1,
'cat_lft' => [],
'post_id' => 1,
'media_id' => 1,
'comment_id' => 1,
'link_id' => 1,
'log_id' => 1
];
public $has_categories = false;
public function __construct($core, $file)
{
parent::__construct($file);
$first_line = fgets($this->fp);
if (strpos($first_line, '///DOTCLEAR|') !== 0) {
throw new Exception(__('File is not a DotClear backup.'));
}
@set_time_limit(300);
$l = explode('|', $first_line);
if (isset($l[1])) {
$this->dc_version = $l[1];
}
$this->mode = isset($l[2]) ? strtolower(trim($l[2])) : 'single';
if ($this->mode != 'full' && $this->mode != 'single') {
$this->mode = 'single';
}
if (version_compare('1.2', $this->dc_version, '<=') &&
version_compare('1.3', $this->dc_version, '>')) {
$this->dc_major_version = '1.2';
} else {
$this->dc_major_version = '2.0';
}
$this->core = &$core;
$this->con = &$core->con;
$this->prefix = $core->prefix;
$this->cur_blog = $this->con->openCursor($this->prefix . 'blog');
$this->cur_category = $this->con->openCursor($this->prefix . 'category');
$this->cur_link = $this->con->openCursor($this->prefix . 'link');
$this->cur_setting = $this->con->openCursor($this->prefix . 'setting');
$this->cur_user = $this->con->openCursor($this->prefix . 'user');
$this->cur_pref = $this->con->openCursor($this->prefix . 'pref');
$this->cur_permissions = $this->con->openCursor($this->prefix . 'permissions');
$this->cur_post = $this->con->openCursor($this->prefix . 'post');
$this->cur_meta = $this->con->openCursor($this->prefix . 'meta');
$this->cur_media = $this->con->openCursor($this->prefix . 'media');
$this->cur_post_media = $this->con->openCursor($this->prefix . 'post_media');
$this->cur_log = $this->con->openCursor($this->prefix . 'log');
$this->cur_ping = $this->con->openCursor($this->prefix . 'ping');
$this->cur_comment = $this->con->openCursor($this->prefix . 'comment');
$this->cur_spamrule = $this->con->openCursor($this->prefix . 'spamrule');
$this->cur_version = $this->con->openCursor($this->prefix . 'version');
# --BEHAVIOR-- importInit
$this->core->callBehavior('importInit', $this, $this->core);
}
public function getMode()
{
return $this->mode;
}
public function importSingle()
{
if ($this->mode != 'single') {
throw new Exception(__('File is not a single blog export.'));
}
if (!$this->core->auth->check('admin', $this->core->blog->id)) {
throw new Exception(__('Permission denied.'));
}
$this->blog_id = $this->core->blog->id;
$this->stack['categories'] = $this->con->select(
'SELECT cat_id, cat_title, cat_url ' .
'FROM ' . $this->prefix . 'category ' .
"WHERE blog_id = '" . $this->con->escape($this->blog_id) . "' "
);
$rs = $this->con->select('SELECT MAX(cat_id) FROM ' . $this->prefix . 'category');
$this->stack['cat_id'] = ((integer) $rs->f(0)) + 1;
$rs = $this->con->select('SELECT MAX(link_id) FROM ' . $this->prefix . 'link');
$this->stack['link_id'] = ((integer) $rs->f(0)) + 1;
$rs = $this->con->select('SELECT MAX(post_id) FROM ' . $this->prefix . 'post');
$this->stack['post_id'] = ((integer) $rs->f(0)) + 1;
$rs = $this->con->select('SELECT MAX(media_id) FROM ' . $this->prefix . 'media');
$this->stack['media_id'] = ((integer) $rs->f(0)) + 1;
$rs = $this->con->select('SELECT MAX(comment_id) FROM ' . $this->prefix . 'comment');
$this->stack['comment_id'] = ((integer) $rs->f(0)) + 1;
$rs = $this->con->select('SELECT MAX(log_id) FROM ' . $this->prefix . 'log');
$this->stack['log_id'] = ((integer) $rs->f(0)) + 1;
$rs = $this->con->select(
'SELECT MAX(cat_rgt) AS cat_rgt FROM ' . $this->prefix . 'category ' .
"WHERE blog_id = '" . $this->con->escape($this->core->blog->id) . "'"
);
if ((integer) $rs->cat_rgt > 0) {
$this->has_categories = true;
$this->stack['cat_lft'][$this->core->blog->id] = (integer) $rs->cat_rgt + 1;
}
$this->con->begin();
try
{
$last_line_name = '';
$constrained = ['post', 'meta', 'post_media', 'ping', 'comment'];
while (($line = $this->getLine()) !== false) {
# import DC 1.2.x, we fix lines before insert
if ($this->dc_major_version == '1.2') {
$this->prepareDC12line($line);
}
if ($last_line_name != $line->__name) {
if (in_array($last_line_name, $constrained)) {
# UNDEFER
if ($this->con->syntax() == 'mysql') {
$this->con->execute('SET foreign_key_checks = 1');
}
if ($this->con->syntax() == 'postgresql') {
$this->con->execute('SET CONSTRAINTS ALL DEFERRED');
}
}
if (in_array($line->__name, $constrained)) {
# DEFER
if ($this->con->syntax() == 'mysql') {
$this->con->execute('SET foreign_key_checks = 0');
}
if ($this->con->syntax() == 'postgresql') {
$this->con->execute('SET CONSTRAINTS ALL IMMEDIATE');
}
}
$last_line_name = $line->__name;
}
switch ($line->__name) {
case 'category':
$this->insertCategorySingle($line);
break;
case 'link':
$this->insertLinkSingle($line);
break;
case 'post':
$this->insertPostSingle($line);
break;
case 'meta':
$this->insertMetaSingle($line);
break;
case 'media':
$this->insertMediaSingle($line);
break;
case 'post_media':
$this->insertPostMediaSingle($line);
break;
case 'ping':
$this->insertPingSingle($line);
break;
case 'comment':
$this->insertCommentSingle($line);
break;
}
# --BEHAVIOR-- importSingle
$this->core->callBehavior('importSingle', $line, $this, $this->core);
}
if ($this->con->syntax() == 'mysql') {
$this->con->execute('SET foreign_key_checks = 1');
}
if ($this->con->syntax() == 'postgresql') {
$this->con->execute('SET CONSTRAINTS ALL DEFERRED');
}
} catch (Exception $e) {
@fclose($this->fp);
$this->con->rollback();
throw new Exception($e->getMessage() . ' - ' . sprintf(__('Error raised at line %s'), $line->__line));
}
@fclose($this->fp);
$this->con->commit();
}
public function importFull()
{
if ($this->mode != 'full') {
throw new Exception(__('File is not a full export.'));
}
if (!$this->core->auth->isSuperAdmin()) {
throw new Exception(__('Permission denied.'));
}
$this->con->begin();
$this->con->execute('DELETE FROM ' . $this->prefix . 'blog');
$this->con->execute('DELETE FROM ' . $this->prefix . 'media');
$this->con->execute('DELETE FROM ' . $this->prefix . 'spamrule');
$this->con->execute('DELETE FROM ' . $this->prefix . 'setting');
$this->con->execute('DELETE FROM ' . $this->prefix . 'log');
try
{
while (($line = $this->getLine()) !== false) {
switch ($line->__name) {
case 'blog':
$this->insertBlog($line);
break;
case 'category':
$this->insertCategory($line);
break;
case 'link':
$this->insertLink($line);
break;
case 'setting':
$this->insertSetting($line);
break;
case 'user':
$this->insertUser($line);
break;
case 'pref':
$this->insertPref($line);
break;
case 'permissions':
$this->insertPermissions($line);
break;
case 'post':
$this->insertPost($line);
break;
case 'meta':
$this->insertMeta($line);
break;
case 'media':
$this->insertMedia($line);
break;
case 'post_media':
$this->insertPostMedia($line);
break;
case 'log';
$this->insertLog($line);
break;
case 'ping':
$this->insertPing($line);
break;
case 'comment':
$this->insertComment($line);
break;
case 'spamrule':
$this->insertSpamRule($line);
break;
}
# --BEHAVIOR-- importFull
$this->core->callBehavior('importFull', $line, $this, $this->core);
}
} catch (Exception $e) {
@fclose($this->fp);
$this->con->rollback();
throw new Exception($e->getMessage() . ' - ' . sprintf(__('Error raised at line %s'), $line->__line));
}
@fclose($this->fp);
$this->con->commit();
}
private function insertBlog($blog)
{
$this->cur_blog->clean();
$this->cur_blog->blog_id = (string) $blog->blog_id;
$this->cur_blog->blog_uid = (string) $blog->blog_uid;
$this->cur_blog->blog_creadt = (string) $blog->blog_creadt;
$this->cur_blog->blog_upddt = (string) $blog->blog_upddt;
$this->cur_blog->blog_url = (string) $blog->blog_url;
$this->cur_blog->blog_name = (string) $blog->blog_name;
$this->cur_blog->blog_desc = (string) $blog->blog_desc;
$this->cur_blog->blog_status = $blog->exists('blog_status') ? (integer) $blog->blog_status : 1;
$this->cur_blog->insert();
}
private function insertCategory($category)
{
$this->cur_category->clean();
$this->cur_category->cat_id = (string) $category->cat_id;
$this->cur_category->blog_id = (string) $category->blog_id;
$this->cur_category->cat_title = (string) $category->cat_title;
$this->cur_category->cat_url = (string) $category->cat_url;
$this->cur_category->cat_desc = (string) $category->cat_desc;
if (!$this->has_categories && $category->exists('cat_lft') && $category->exists('cat_rgt')) {
$this->cur_category->cat_lft = (integer) $category->cat_lft;
$this->cur_category->cat_rgt = (integer) $category->cat_rgt;
} else {
if (!isset($this->stack['cat_lft'][$category->blog_id])) {
$this->stack['cat_lft'][$category->blog_id] = 2;
}
$this->cur_category->cat_lft = $this->stack['cat_lft'][$category->blog_id]++;
$this->cur_category->cat_rgt = $this->stack['cat_lft'][$category->blog_id]++;
}
$this->cur_category->insert();
}
private function insertLink($link)
{
$this->cur_link->clean();
$this->cur_link->link_id = (integer) $link->link_id;
$this->cur_link->blog_id = (string) $link->blog_id;
$this->cur_link->link_href = (string) $link->link_href;
$this->cur_link->link_title = (string) $link->link_title;
$this->cur_link->link_desc = (string) $link->link_desc;
$this->cur_link->link_lang = (string) $link->link_lang;
$this->cur_link->link_xfn = (string) $link->link_xfn;
$this->cur_link->link_position = (integer) $link->link_position;
$this->cur_link->insert();
}
private function insertSetting($setting)
{
$this->cur_setting->clean();
$this->cur_setting->setting_id = (string) $setting->setting_id;
$this->cur_setting->blog_id = !$setting->blog_id ? null : (string) $setting->blog_id;
$this->cur_setting->setting_ns = (string) $setting->setting_ns;
$this->cur_setting->setting_value = (string) $setting->setting_value;
$this->cur_setting->setting_type = (string) $setting->setting_type;
$this->cur_setting->setting_label = (string) $setting->setting_label;
$this->cur_setting->insert();
}
private function insertPref($pref)
{
if ($this->prefExists($pref->pref_ws, $pref->pref_id, $pref->user_id)) {
return;
}
$this->cur_pref->clean();
$this->cur_pref->pref_id = (string) $pref->pref_id;
$this->cur_pref->user_id = !$pref->user_id ? null : (string) $pref->user_id;
$this->cur_pref->pref_ws = (string) $pref->pref_ws;
$this->cur_pref->pref_value = (string) $pref->pref_value;
$this->cur_pref->pref_type = (string) $pref->pref_type;
$this->cur_pref->pref_label = (string) $pref->pref_label;
$this->cur_pref->insert();
}
private function insertUser($user)
{
if ($this->userExists($user->user_id)) {
return;
}
$this->cur_user->clean();
$this->cur_user->user_id = (string) $user->user_id;
$this->cur_user->user_super = (integer) $user->user_super;
$this->cur_user->user_pwd = (string) $user->user_pwd;
$this->cur_user->user_recover_key = (string) $user->user_recover_key;
$this->cur_user->user_name = (string) $user->user_name;
$this->cur_user->user_firstname = (string) $user->user_firstname;
$this->cur_user->user_displayname = (string) $user->user_displayname;
$this->cur_user->user_email = (string) $user->user_email;
$this->cur_user->user_url = (string) $user->user_url;
$this->cur_user->user_default_blog = !$user->user_default_blog ? null : (string) $user->user_default_blog;
$this->cur_user->user_lang = (string) $user->user_lang;
$this->cur_user->user_tz = (string) $user->user_tz;
$this->cur_user->user_post_status = (integer) $user->user_post_status;
$this->cur_user->user_creadt = (string) $user->user_creadt;
$this->cur_user->user_upddt = (string) $user->user_upddt;
$this->cur_user->user_desc = $user->exists('user_desc') ? (string) $user->user_desc : null;
$this->cur_user->user_options = $user->exists('user_options') ? (string) $user->user_options : null;
$this->cur_user->user_status = $user->exists('user_status') ? (integer) $user->user_status : 1;
$this->cur_user->insert();
$this->stack['users'][$user->user_id] = true;
}
private function insertPermissions($permissions)
{
$this->cur_permissions->clean();
$this->cur_permissions->user_id = (string) $permissions->user_id;
$this->cur_permissions->blog_id = (string) $permissions->blog_id;
$this->cur_permissions->permissions = (string) $permissions->permissions;
$this->cur_permissions->insert();
}
private function insertPost($post)
{
$this->cur_post->clean();
$cat_id = (integer) $post->cat_id;
if (!$cat_id) {
$cat_id = null;
}
$post_password = $post->post_password ? (string) $post->post_password : null;
$this->cur_post->post_id = (integer) $post->post_id;
$this->cur_post->blog_id = (string) $post->blog_id;
$this->cur_post->user_id = (string) $this->getUserId($post->user_id);
$this->cur_post->cat_id = $cat_id;
$this->cur_post->post_dt = (string) $post->post_dt;
$this->cur_post->post_creadt = (string) $post->post_creadt;
$this->cur_post->post_upddt = (string) $post->post_upddt;
$this->cur_post->post_password = $post_password;
$this->cur_post->post_type = (string) $post->post_type;
$this->cur_post->post_format = (string) $post->post_format;
$this->cur_post->post_url = (string) $post->post_url;
$this->cur_post->post_lang = (string) $post->post_lang;
$this->cur_post->post_title = (string) $post->post_title;
$this->cur_post->post_excerpt = (string) $post->post_excerpt;
$this->cur_post->post_excerpt_xhtml = (string) $post->post_excerpt_xhtml;
$this->cur_post->post_content = (string) $post->post_content;
$this->cur_post->post_content_xhtml = (string) $post->post_content_xhtml;
$this->cur_post->post_notes = (string) $post->post_notes;
$this->cur_post->post_words = (string) $post->post_words;
$this->cur_post->post_meta = (string) $post->post_meta;
$this->cur_post->post_status = (integer) $post->post_status;
$this->cur_post->post_selected = (integer) $post->post_selected;
$this->cur_post->post_open_comment = (integer) $post->post_open_comment;
$this->cur_post->post_open_tb = (integer) $post->post_open_tb;
$this->cur_post->nb_comment = (integer) $post->nb_comment;
$this->cur_post->nb_trackback = (integer) $post->nb_trackback;
$this->cur_post->post_position = (integer) $post->post_position;
$this->cur_post->post_tz = $post->exists('post_tz') ? (string) $post->post_tz : 'UTC';
$this->cur_post->insert();
}
private function insertMeta($meta)
{
$this->cur_meta->clean();
$this->cur_meta->meta_id = (string) $meta->meta_id;
$this->cur_meta->meta_type = (string) $meta->meta_type;
$this->cur_meta->post_id = (integer) $meta->post_id;
$this->cur_meta->insert();
}
private function insertMedia($media)
{
$this->cur_media->clean();
$this->cur_media->media_id = (integer) $media->media_id;
$this->cur_media->user_id = (string) $media->user_id;
$this->cur_media->media_path = (string) $media->media_path;
$this->cur_media->media_title = (string) $media->media_title;
$this->cur_media->media_file = (string) $media->media_file;
$this->cur_media->media_meta = (string) $media->media_meta;
$this->cur_media->media_dt = (string) $media->media_dt;
$this->cur_media->media_creadt = (string) $media->media_creadt;
$this->cur_media->media_upddt = (string) $media->media_upddt;
$this->cur_media->media_private = (integer) $media->media_private;
$this->cur_media->media_dir = $media->exists('media_dir') ? (string) $media->media_dir : dirname($media->media_file);
if (!$this->mediaExists()) {
$this->cur_media->insert();
}
}
private function insertPostMedia($post_media)
{
$this->cur_post_media->clean();
$this->cur_post_media->media_id = (integer) $post_media->media_id;
$this->cur_post_media->post_id = (integer) $post_media->post_id;
$this->cur_post_media->insert();
}
private function insertLog($log)
{
$this->cur_log->clean();
$this->cur_log->log_id = (integer) $log->log_id;
$this->cur_log->user_id = (string) $log->user_id;
$this->cur_log->log_table = (string) $log->log_table;
$this->cur_log->log_dt = (string) $log->log_dt;
$this->cur_log->log_ip = (string) $log->log_ip;
$this->cur_log->log_msg = (string) $log->log_msg;
$this->cur_log->insert();
}
private function insertPing($ping)
{
$this->cur_ping->clean();
$this->cur_ping->post_id = (integer) $ping->post_id;
$this->cur_ping->ping_url = (string) $ping->ping_url;
$this->cur_ping->ping_dt = (string) $ping->ping_dt;
$this->cur_ping->insert();
}
private function insertComment($comment)
{
$this->cur_comment->clean();
$this->cur_comment->comment_id = (integer) $comment->comment_id;
$this->cur_comment->post_id = (integer) $comment->post_id;
$this->cur_comment->comment_dt = (string) $comment->comment_dt;
$this->cur_comment->comment_upddt = (string) $comment->comment_upddt;
$this->cur_comment->comment_author = (string) $comment->comment_author;
$this->cur_comment->comment_email = (string) $comment->comment_email;
$this->cur_comment->comment_site = (string) $comment->comment_site;
$this->cur_comment->comment_content = (string) $comment->comment_content;
$this->cur_comment->comment_words = (string) $comment->comment_words;
$this->cur_comment->comment_ip = (string) $comment->comment_ip;
$this->cur_comment->comment_status = (integer) $comment->comment_status;
$this->cur_comment->comment_spam_status = (string) $comment->comment_spam_status;
$this->cur_comment->comment_trackback = (integer) $comment->comment_trackback;
$this->cur_comment->comment_tz = $comment->exists('comment_tz') ? (string) $comment->comment_tz : 'UTC';
$this->cur_comment->comment_spam_filter = $comment->exists('comment_spam_filter') ? (string) $comment->comment_spam_filter : null;
$this->cur_comment->insert();
}
private function insertSpamRule($spamrule)
{
$this->cur_spamrule->clean();
$this->cur_spamrule->rule_id = (integer) $spamrule->rule_id;
$this->cur_spamrule->blog_id = !$spamrule->blog_id ? null : (string) $spamrule->blog_id;
$this->cur_spamrule->rule_type = (string) $spamrule->rule_type;
$this->cur_spamrule->rule_content = (string) $spamrule->rule_content;
$this->cur_spamrule->insert();
}
private function insertCategorySingle($category)
{
$this->cur_category->clean();
$m = $this->searchCategory($this->stack['categories'], $category->cat_url);
$old_id = $category->cat_id;
if ($m !== false) {
$cat_id = $m;
} else {
$cat_id = $this->stack['cat_id'];
$category->cat_id = $cat_id;
$category->blog_id = $this->blog_id;
$this->insertCategory($category);
$this->stack['cat_id']++;
}
$this->old_ids['category'][(integer) $old_id] = $cat_id;
}
private function insertLinkSingle($link)
{
$link->blog_id = $this->blog_id;
$link->link_id = $this->stack['link_id'];
$this->insertLink($link);
$this->stack['link_id']++;
}
private function insertPostSingle($post)
{
if (!$post->cat_id || isset($this->old_ids['category'][(integer) $post->cat_id])) {
$post_id = $this->stack['post_id'];
$this->old_ids['post'][(integer) $post->post_id] = $post_id;
$cat_id = $post->cat_id ? $this->old_ids['category'][(integer) $post->cat_id] : null;
$post->post_id = $post_id;
$post->cat_id = $cat_id;
$post->blog_id = $this->blog_id;
$post->post_url = $this->core->blog->getPostURL(
$post->post_url, $post->post_dt, $post->post_title, $post->post_id
);
$this->insertPost($post);
$this->stack['post_id']++;
} else {
self::throwIdError($post->__name, $post->__line, 'category');
}
}
private function insertMetaSingle($meta)
{
if (isset($this->old_ids['post'][(integer) $meta->post_id])) {
$meta->post_id = $this->old_ids['post'][(integer) $meta->post_id];
$this->insertMeta($meta);
} else {
self::throwIdError($meta->__name, $meta->__line, 'post');
}
}
private function insertMediaSingle($media)
{
$media_id = $this->stack['media_id'];
$old_id = $media->media_id;
$media->media_id = $media_id;
$media->media_path = $this->core->blog->settings->system->public_path;
$media->user_id = $this->getUserId($media->user_id);
$this->insertMedia($media);
$this->stack['media_id']++;
$this->old_ids['media'][(integer) $old_id] = $media_id;
}
private function insertPostMediaSingle($post_media)
{
if (isset($this->old_ids['media'][(integer) $post_media->media_id]) &&
isset($this->old_ids['post'][(integer) $post_media->post_id])) {
$post_media->media_id = $this->old_ids['media'][(integer) $post_media->media_id];
$post_media->post_id = $this->old_ids['post'][(integer) $post_media->post_id];
$this->insertPostMedia($post_media);
} elseif (!isset($this->old_ids['media'][(integer) $post_media->media_id])) {
self::throwIdError($post_media->__name, $post_media->__line, 'media');
} else {
self::throwIdError($post_media->__name, $post_media->__line, 'post');
}
}
private function insertPingSingle($ping)
{
if (isset($this->old_ids['post'][(integer) $ping->post_id])) {
$ping->post_id = $this->old_ids['post'][(integer) $ping->post_id];
$this->insertPing($ping);
} else {
self::throwIdError($ping->__name, $ping->__line, 'post');
}
}
private function insertCommentSingle($comment)
{
if (isset($this->old_ids['post'][(integer) $comment->post_id])) {
$comment_id = $this->stack['comment_id'];
$comment->comment_id = $comment_id;
$comment->post_id = $this->old_ids['post'][(integer) $comment->post_id];
$this->insertComment($comment);
$this->stack['comment_id']++;
} else {
self::throwIdError($comment->__name, $comment->__line, 'post');
}
}
private static function throwIdError($name, $line, $related)
{
throw new Exception(sprintf(
__('ID of "%3$s" does not match on record "%1$s" at line %2$s of backup file.'),
html::escapeHTML($name),
html::escapeHTML($line),
html::escapeHTML($related)
));
}
public function searchCategory($rs, $url)
{
while ($rs->fetch()) {
if ($rs->cat_url == $url) {
return $rs->cat_id;
}
}
return false;
}
public function getUserId($user_id)
{
if (!$this->userExists($user_id)) {
if ($this->core->auth->isSuperAdmin()) {
# Sanitizes user_id and create a lambda user
$user_id = preg_replace('/[^A-Za-z0-9]$/', '', $user_id);
$user_id .= strlen($user_id) < 2 ? '-a' : '';
# We change user_id, we need to check again
if (!$this->userExists($user_id)) {
$this->cur_user->clean();
$this->cur_user->user_id = (string) $user_id;
$this->cur_user->user_pwd = md5(uniqid());
$this->core->addUser($this->cur_user);
$this->stack['users'][$user_id] = true;
}
} else {
# Returns current user id
$user_id = $this->core->auth->userID();
}
}
return $user_id;
}
private function userExists($user_id)
{
if (isset($this->stack['users'][$user_id])) {
return $this->stack['users'][$user_id];
}
$strReq = 'SELECT user_id ' .
'FROM ' . $this->prefix . 'user ' .
"WHERE user_id = '" . $this->con->escape($user_id) . "' ";
$rs = $this->con->select($strReq);
$this->stack['users'][$user_id] = !$rs->isEmpty();
return $this->stack['users'][$user_id];
}
private function prefExists($pref_ws, $pref_id, $user_id)
{
$strReq = 'SELECT pref_id,pref_ws,user_id ' .
'FROM ' . $this->prefix . 'pref ' .
"WHERE pref_id = '" . $this->con->escape($pref_id) . "' " .
"AND pref_ws = '" . $this->con->escape($pref_ws) . "' ";
if (!$user_id) {
$strReq .= "AND user_id IS NULL ";
} else {
$strReq .= "AND user_id = '" . $this->con->escape($user_id) . "' ";
}
$rs = $this->con->select($strReq);
return !$rs->isEmpty();
}
private function mediaExists()
{
$strReq = 'SELECT media_id ' .
'FROM ' . $this->prefix . 'media ' .
"WHERE media_path = '" . $this->con->escape($this->cur_media->media_path) . "' " .
"AND media_file = '" . $this->con->escape($this->cur_media->media_file) . "' ";
$rs = $this->con->select($strReq);
return !$rs->isEmpty();
}
private function prepareDC12line(&$line)
{
$settings = ['dc_theme', 'dc_nb_post_per_page', 'dc_allow_comments',
'dc_allow_trackbacks', 'dc_comment_pub', 'dc_comments_ttl',
'dc_wiki_comments', 'dc_use_smilies', 'dc_date_format', 'dc_time_format',
'dc_url_scan'];
switch ($line->__name) {
case 'categorie':
$line->substitute('cat_libelle', 'cat_title');
$line->substitute('cat_libelle_url', 'cat_url');
$line->__name = 'category';
$line->blog_id = 'default';
break;
case 'link':
$line->substitute('href', 'link_href');
$line->substitute('label', 'link_title');
$line->substitute('title', 'link_desc');
$line->substitute('lang', 'link_lang');
$line->substitute('rel', 'link_xfn');
$line->substitute('position', 'link_position');
$line->blog_id = 'default';
break;
case 'post':
$line->substitute('post_titre', 'post_title');
$line->post_title = html::decodeEntities($line->post_title);
$line->post_url = date('Y/m/d/', strtotime($line->post_dt)) . $line->post_id . '-' . $line->post_titre_url;
$line->post_url = substr($line->post_url, 0, 255);
$line->post_format = $line->post_content_wiki == '' ? 'xhtml' : 'wiki';
$line->post_content_xhtml = $line->post_content;
$line->post_excerpt_xhtml = $line->post_chapo;
if ($line->post_format == 'wiki') {
$line->post_content = $line->post_content_wiki;
$line->post_excerpt = $line->post_chapo_wiki;
} else {
$line->post_content = $line->post_content;
$line->post_excerpt = $line->post_chapo;
}
$line->post_status = (integer) $line->post_pub;
$line->post_type = 'post';
$line->blog_id = 'default';
$line->drop('post_titre_url', 'post_content_wiki', 'post_chapo', 'post_chapo_wiki', 'post_pub');
break;
case 'post_meta':
$line->drop('meta_id');
$line->substitute('meta_key', 'meta_type');
$line->substitute('meta_value', 'meta_id');
$line->__name = 'meta';
$line->blog_id = 'default';
break;
case 'comment':
$line->substitute('comment_auteur', 'comment_author');
if ($line->comment_site != '' && !preg_match('!^http(s)?://.*$!', $line->comment_site, $m)) {
$line->comment_site = 'http://' . $line->comment_site;
}
$line->comment_status = (integer) $line->comment_pub;
$line->drop('comment_pub');
break;
}
# --BEHAVIOR-- importPrepareDC12
$this->core->callBehavior('importPrepareDC12', $line, $this, $this->core);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 858 B

View File

@ -0,0 +1,140 @@
<?php
/**
* @brief importExport, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugins
*
* @copyright Olivier Meunier & Association Dotclear
* @copyright GPL-2.0-only
*/
if (!defined('DC_RC_PATH')) {return;}
class ieMaintenanceExportblog extends dcMaintenanceTask
{
protected $perm = 'admin';
protected $tab = 'backup';
protected $group = 'zipblog';
protected $export_name;
protected $export_type;
protected function init()
{
$this->name = __('Database export');
$this->task = __('Download database of current blog');
$this->export_name = html::escapeHTML($this->core->blog->id . '-backup.txt');
$this->export_type = 'export_blog';
}
public function execute()
{
// Create zip file
if (!empty($_POST['file_name'])) {
// This process make an http redirect
$ie = new maintenanceDcExportFlat($this->core);
$ie->setURL($this->id);
$ie->process($this->export_type);
}
// Go to step and show form
else {
return 1;
}
}
public function step()
{
// Download zip file
if (isset($_SESSION['export_file']) && file_exists($_SESSION['export_file'])) {
// Log task execution here as we sent file and stop script
$this->log();
// This process send file by http and stop script
$ie = new maintenanceDcExportFlat($this->core);
$ie->setURL($this->id);
$ie->process('ok');
} else {
return
'<p><label for="file_name">' . __('File name:') . '</label>' .
form::field('file_name', 50, 255, date('Y-m-d-H-i-') . $this->export_name) .
'</p>' .
'<p><label for="file_zip" class="classic">' .
form::checkbox('file_zip', 1) . ' ' .
__('Compress file') . '</label>' .
'</p>';
}
}
}
class ieMaintenanceExportfull extends dcMaintenanceTask
{
protected $tab = 'backup';
protected $group = 'zipfull';
protected $export_name;
protected $export_type;
protected function init()
{
$this->name = __('Database export');
$this->task = __('Download database of all blogs');
$this->export_name = 'dotclear-backup.txt';
$this->export_type = 'export_all';
}
public function execute()
{
// Create zip file
if (!empty($_POST['file_name'])) {
// This process make an http redirect
$ie = new maintenanceDcExportFlat($this->core);
$ie->setURL($this->id);
$ie->process($this->export_type);
}
// Go to step and show form
else {
return 1;
}
}
public function step()
{
// Download zip file
if (isset($_SESSION['export_file']) && file_exists($_SESSION['export_file'])) {
// Log task execution here as we sent file and stop script
$this->log();
// This process send file by http and stop script
$ie = new maintenanceDcExportFlat($this->core);
$ie->setURL($this->id);
$ie->process('ok');
} else {
return
'<p><label for="file_name">' . __('File name:') . '</label>' .
form::field('file_name', 50, 255, date('Y-m-d-H-i-') . $this->export_name) .
'</p>' .
'<p><label for="file_zip" class="classic">' .
form::checkbox('file_zip', 1) . ' ' .
__('Compress file') . '</label>' .
'</p>';
}
}
}
class maintenanceDcExportFlat extends dcExportFlat
{
/**
* Set redirection URL of bakcup process.
*
* Bad hack to change redirection of dcExportFlat::process()
*
* @param id <b>string</b> Task id
*/
public function setURL($id)
{
$this->url = sprintf('plugin.php?p=maintenance&task=%s', $id);
}
}