[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * 4 * @package install 5 * @version $Id$ 6 * @copyright (c) 2006 phpBB Group 7 * @license http://opensource.org/licenses/gpl-license.php GNU Public License 8 * 9 */ 10 11 /** 12 */ 13 14 if (!defined('IN_INSTALL')) 15 { 16 // Someone has tried to access the file direct. This is not a good idea, so exit 17 exit; 18 } 19 20 if (!empty($setmodules)) 21 { 22 $module[] = array( 23 'module_type' => 'install', 24 'module_title' => 'CONVERT', 25 'module_filename' => substr(basename(__FILE__), 0, -strlen($phpEx)-1), 26 'module_order' => 20, 27 'module_subs' => '', 28 'module_stages' => array('INTRO', 'SETTINGS', 'IN_PROGRESS', 'FINAL'), 29 'module_reqs' => '' 30 ); 31 } 32 33 /** 34 * Class holding all convertor-specific details. 35 * @package install 36 */ 37 class convert 38 { 39 var $options = array(); 40 41 var $convertor_tag = ''; 42 var $src_dbms = ''; 43 var $src_dbhost = ''; 44 var $src_dbport = ''; 45 var $src_dbuser = ''; 46 var $src_dbpasswd = ''; 47 var $src_dbname = ''; 48 var $src_table_prefix = ''; 49 50 var $convertor_data = array(); 51 var $tables = array(); 52 var $config_schema = array(); 53 var $convertor = array(); 54 var $src_truncate_statement = 'DELETE FROM '; 55 var $truncate_statement = 'DELETE FROM '; 56 57 var $fulltext_search; 58 59 // Batch size, can be adjusted by the conversion file 60 // For big boards a value of 6000 seems to be optimal 61 var $batch_size = 2000; 62 // Number of rows to be inserted at once (extended insert) if supported 63 // For installations having enough memory a value of 60 may be good. 64 var $num_wait_rows = 20; 65 66 // Mysqls internal recoding engine messing up with our (better) functions? We at least support more encodings than mysql so should use it in favor. 67 var $mysql_convert = false; 68 69 var $p_master; 70 71 function convert(&$p_master) 72 { 73 $this->p_master = &$p_master; 74 } 75 } 76 77 /** 78 * Convert class for conversions 79 * @package install 80 */ 81 class install_convert extends module 82 { 83 /** 84 * Variables used while converting, they are accessible from the global variable $convert 85 */ 86 function install_convert(&$p_master) 87 { 88 $this->p_master = &$p_master; 89 } 90 91 function main($mode, $sub) 92 { 93 global $lang, $template, $phpbb_root_path, $phpEx, $cache, $config, $language, $table_prefix; 94 global $convert; 95 96 $this->tpl_name = 'install_convert'; 97 $this->mode = $mode; 98 99 $convert = new convert($this->p_master); 100 101 switch ($sub) 102 { 103 case 'intro': 104 // Try opening config file 105 // @todo If phpBB is not installed, we need to do a cut-down installation here 106 // For now, we redirect to the installation script instead 107 if (@file_exists($phpbb_root_path . 'config.' . $phpEx)) 108 { 109 include($phpbb_root_path . 'config.' . $phpEx); 110 } 111 112 if (!defined('PHPBB_INSTALLED')) 113 { 114 $template->assign_vars(array( 115 'S_NOT_INSTALLED' => true, 116 'TITLE' => $lang['BOARD_NOT_INSTALLED'], 117 'BODY' => sprintf($lang['BOARD_NOT_INSTALLED_EXPLAIN'], append_sid($phpbb_root_path . 'install/index.' . $phpEx, 'mode=install&language=' . $language)), 118 )); 119 120 return; 121 } 122 123 require($phpbb_root_path . 'config.' . $phpEx); 124 require($phpbb_root_path . 'includes/constants.' . $phpEx); 125 require($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx); 126 require($phpbb_root_path . 'includes/functions_convert.' . $phpEx); 127 128 $db = new $sql_db(); 129 $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true); 130 unset($dbpasswd); 131 132 // We need to fill the config to let internal functions correctly work 133 $sql = 'SELECT * 134 FROM ' . CONFIG_TABLE; 135 $result = $db->sql_query($sql); 136 137 $config = array(); 138 while ($row = $db->sql_fetchrow($result)) 139 { 140 $config[$row['config_name']] = $row['config_value']; 141 } 142 $db->sql_freeresult($result); 143 144 // Detect if there is already a conversion in progress at this point and offer to resume 145 // It's quite possible that the user will get disconnected during a large conversion so they need to be able to resume it 146 $new_conversion = request_var('new_conv', 0); 147 148 if ($new_conversion) 149 { 150 $config['convert_progress'] = ''; 151 $config['convert_db_server'] = ''; 152 $config['convert_db_user'] = ''; 153 $db->sql_query('DELETE FROM ' . CONFIG_TABLE . " 154 WHERE config_name = 'convert_progress' 155 OR config_name = 'convert_db_server' 156 OR config_name = 'convert_db_user'" 157 ); 158 } 159 160 // Let's see if there is a conversion in the works... 161 $options = array(); 162 if (!empty($config['convert_progress']) && !empty($config['convert_db_server']) && !empty($config['convert_db_user']) && !empty($config['convert_options'])) 163 { 164 $options = unserialize($config['convert_progress']); 165 $options = array_merge($options, unserialize($config['convert_db_server']), unserialize($config['convert_db_user']), unserialize($config['convert_options'])); 166 } 167 168 // This information should have already been checked once, but do it again for safety 169 if (!empty($options) && !empty($options['tag']) && 170 isset($options['dbms']) && 171 isset($options['dbhost']) && 172 isset($options['dbport']) && 173 isset($options['dbuser']) && 174 isset($options['dbpasswd']) && 175 isset($options['dbname']) && 176 isset($options['table_prefix'])) 177 { 178 $this->page_title = $lang['CONTINUE_CONVERT']; 179 180 $template->assign_vars(array( 181 'TITLE' => $lang['CONTINUE_CONVERT'], 182 'BODY' => $lang['CONTINUE_CONVERT_BODY'], 183 'L_NEW' => $lang['CONVERT_NEW_CONVERSION'], 184 'L_CONTINUE' => $lang['CONTINUE_OLD_CONVERSION'], 185 'S_CONTINUE' => true, 186 187 'U_NEW_ACTION' => $this->p_master->module_url . "?mode={$this->mode}&sub=intro&new_conv=1&language=$language", 188 'U_CONTINUE_ACTION' => $this->p_master->module_url . "?mode={$this->mode}&sub=in_progress&tag={$options['tag']}{$options['step']}&language=$language", 189 )); 190 191 return; 192 } 193 194 $this->list_convertors($sub); 195 196 break; 197 198 case 'settings': 199 $this->get_convert_settings($sub); 200 break; 201 202 case 'in_progress': 203 $this->convert_data($sub); 204 break; 205 206 case 'final': 207 $this->page_title = $lang['CONVERT_COMPLETE']; 208 209 $template->assign_vars(array( 210 'TITLE' => $lang['CONVERT_COMPLETE'], 211 'BODY' => $lang['CONVERT_COMPLETE_EXPLAIN'], 212 )); 213 214 // If we reached this step (conversion completed) we want to purge the cache and log the user out. 215 // This is for making sure the session get not screwed due to the 3.0.x users table being completely new. 216 $cache->purge(); 217 218 require($phpbb_root_path . 'config.' . $phpEx); 219 require($phpbb_root_path . 'includes/constants.' . $phpEx); 220 require($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx); 221 require($phpbb_root_path . 'includes/functions_convert.' . $phpEx); 222 223 $db = new $sql_db(); 224 $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true); 225 unset($dbpasswd); 226 227 $sql = 'SELECT config_value 228 FROM ' . CONFIG_TABLE . ' 229 WHERE config_name = \'search_type\''; 230 $result = $db->sql_query($sql); 231 232 if ($db->sql_fetchfield('config_value') != 'fulltext_mysql') 233 { 234 $template->assign_vars(array( 235 'S_ERROR_BOX' => true, 236 'ERROR_TITLE' => $lang['SEARCH_INDEX_UNCONVERTED'], 237 'ERROR_MSG' => $lang['SEARCH_INDEX_UNCONVERTED_EXPLAIN'], 238 )); 239 } 240 241 switch ($db->sql_layer) 242 { 243 case 'sqlite': 244 case 'firebird': 245 $db->sql_query('DELETE FROM ' . SESSIONS_KEYS_TABLE); 246 $db->sql_query('DELETE FROM ' . SESSIONS_TABLE); 247 break; 248 249 default: 250 $db->sql_query('TRUNCATE TABLE ' . SESSIONS_KEYS_TABLE); 251 $db->sql_query('TRUNCATE TABLE ' . SESSIONS_TABLE); 252 break; 253 } 254 255 break; 256 } 257 } 258 259 /** 260 * Generate a list of all available conversion modules 261 */ 262 function list_convertors($sub) 263 { 264 global $lang, $language, $template, $phpbb_root_path, $phpEx; 265 266 $this->page_title = $lang['SUB_INTRO']; 267 268 $template->assign_vars(array( 269 'TITLE' => $lang['CONVERT_INTRO'], 270 'BODY' => $lang['CONVERT_INTRO_BODY'], 271 272 'L_AUTHOR' => $lang['AUTHOR'], 273 'L_AVAILABLE_CONVERTORS' => $lang['AVAILABLE_CONVERTORS'], 274 'L_CONVERT' => $lang['CONVERT'], 275 'L_NO_CONVERTORS' => $lang['NO_CONVERTORS'], 276 'L_OPTIONS' => $lang['CONVERT_OPTIONS'], 277 'L_SOFTWARE' => $lang['SOFTWARE'], 278 'L_VERSION' => $lang['VERSION'], 279 280 'S_LIST' => true, 281 )); 282 283 $convertors = $sort = array(); 284 $get_info = true; 285 286 $handle = @opendir('./convertors/'); 287 288 if (!$handle) 289 { 290 $this->error('Unable to access the convertors directory', __LINE__, __FILE__); 291 } 292 293 while ($entry = readdir($handle)) 294 { 295 if (preg_match('/^convert_([a-z0-9_]+).' . $phpEx . '$/i', $entry, $m)) 296 { 297 include('./convertors/' . $entry); 298 if (isset($convertor_data)) 299 { 300 $sort[strtolower($convertor_data['forum_name'])] = sizeof($convertors); 301 302 $convertors[] = array( 303 'tag' => $m[1], 304 'forum_name' => $convertor_data['forum_name'], 305 'version' => $convertor_data['version'], 306 'dbms' => $convertor_data['dbms'], 307 'dbhost' => $convertor_data['dbhost'], 308 'dbport' => $convertor_data['dbport'], 309 'dbuser' => $convertor_data['dbuser'], 310 'dbpasswd' => $convertor_data['dbpasswd'], 311 'dbname' => $convertor_data['dbname'], 312 'table_prefix' => $convertor_data['table_prefix'], 313 'author' => $convertor_data['author'] 314 ); 315 } 316 unset($convertor_data); 317 } 318 } 319 closedir($handle); 320 321 @ksort($sort); 322 323 foreach ($sort as $void => $index) 324 { 325 $template->assign_block_vars('convertors', array( 326 'AUTHOR' => $convertors[$index]['author'], 327 'SOFTWARE' => $convertors[$index]['forum_name'], 328 'VERSION' => $convertors[$index]['version'], 329 330 'U_CONVERT' => $this->p_master->module_url . "?mode={$this->mode}&language=$language&sub=settings&tag=" . $convertors[$index]['tag'], 331 )); 332 } 333 } 334 335 /** 336 */ 337 function get_convert_settings($sub) 338 { 339 global $lang, $language, $template, $db, $phpbb_root_path, $phpEx, $config, $cache; 340 341 require($phpbb_root_path . 'config.' . $phpEx); 342 require($phpbb_root_path . 'includes/constants.' . $phpEx); 343 require($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx); 344 require($phpbb_root_path . 'includes/functions_convert.' . $phpEx); 345 346 $db = new $sql_db(); 347 $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true); 348 unset($dbpasswd); 349 350 $this->page_title = $lang['STAGE_SETTINGS']; 351 352 // We need to fill the config to let internal functions correctly work 353 $sql = 'SELECT * 354 FROM ' . CONFIG_TABLE; 355 $result = $db->sql_query($sql); 356 357 $config = array(); 358 while ($row = $db->sql_fetchrow($result)) 359 { 360 $config[$row['config_name']] = $row['config_value']; 361 } 362 $db->sql_freeresult($result); 363 364 $convertor_tag = request_var('tag', ''); 365 366 if (empty($convertor_tag)) 367 { 368 $this->p_master->error($lang['NO_CONVERT_SPECIFIED'], __LINE__, __FILE__); 369 } 370 $get_info = true; 371 372 // check security implications of direct inclusion 373 $convertor_tag = basename($convertor_tag); 374 if (!file_exists('./convertors/convert_' . $convertor_tag . '.' . $phpEx)) 375 { 376 $this->p_master->error($lang['CONVERT_NOT_EXIST'], __LINE__, __FILE__); 377 } 378 379 include('./convertors/convert_' . $convertor_tag . '.' . $phpEx); 380 381 // The test_file is a file that should be present in the location of the old board. 382 if (!isset($test_file)) 383 { 384 $this->p_master->error($lang['DEV_NO_TEST_FILE'], __LINE__, __FILE__); 385 } 386 387 $submit = (isset($_POST['submit'])) ? true : false; 388 389 $src_dbms = request_var('src_dbms', $convertor_data['dbms']); 390 $src_dbhost = request_var('src_dbhost', $convertor_data['dbhost']); 391 $src_dbport = request_var('src_dbport', $convertor_data['dbport']); 392 $src_dbuser = request_var('src_dbuser', $convertor_data['dbuser']); 393 $src_dbpasswd = request_var('src_dbpasswd', $convertor_data['dbpasswd']); 394 $src_dbname = request_var('src_dbname', $convertor_data['dbname']); 395 $src_table_prefix = request_var('src_table_prefix', $convertor_data['table_prefix']); 396 $forum_path = request_var('forum_path', $convertor_data['forum_path']); 397 $refresh = request_var('refresh', 1); 398 399 // Default URL of the old board 400 // @todo Are we going to use this for attempting to convert URL references in posts, or should we remove it? 401 // -> We should convert old urls to the new relative urls format 402 // $src_url = request_var('src_url', 'Not in use at the moment'); 403 404 // strip trailing slash from old forum path 405 $forum_path = (strlen($forum_path) && $forum_path[strlen($forum_path) - 1] == '/') ? substr($forum_path, 0, -1) : $forum_path; 406 407 $error = array(); 408 if ($submit) 409 { 410 if (!@file_exists('./../' . $forum_path . '/' . $test_file)) 411 { 412 $error[] = sprintf($lang['COULD_NOT_FIND_PATH'], $forum_path); 413 } 414 415 $connect_test = false; 416 $available_dbms = get_available_dbms(false, true, true); 417 418 if (!isset($available_dbms[$src_dbms]) || !$available_dbms[$src_dbms]['AVAILABLE']) 419 { 420 $error['db'][] = $lang['INST_ERR_NO_DB']; 421 $connect_test = false; 422 } 423 else 424 { 425 $connect_test = connect_check_db(true, $error, $available_dbms[$src_dbms], $src_table_prefix, $src_dbhost, $src_dbuser, htmlspecialchars_decode($src_dbpasswd), $src_dbname, $src_dbport, true, ($src_dbms == $dbms) ? false : true, false); 426 } 427 428 // The forum prefix of the old and the new forum can only be the same if two different databases are used. 429 if ($src_table_prefix == $table_prefix && $src_dbms == $dbms && $src_dbhost == $dbhost && $src_dbport == $dbport && $src_dbname == $dbname) 430 { 431 $error[] = sprintf($lang['TABLE_PREFIX_SAME'], $src_table_prefix); 432 } 433 434 // Check table prefix 435 if (!sizeof($error)) 436 { 437 // initiate database connection to old db if old and new db differ 438 global $src_db, $same_db; 439 $src_db = $same_db = false; 440 441 if ($src_dbms != $dbms || $src_dbhost != $dbhost || $src_dbport != $dbport || $src_dbname != $dbname || $src_dbuser != $dbuser) 442 { 443 $sql_db = 'dbal_' . $src_dbms; 444 $src_db = new $sql_db(); 445 $src_db->sql_connect($src_dbhost, $src_dbuser, htmlspecialchars_decode($src_dbpasswd), $src_dbname, $src_dbport, false, true); 446 $same_db = false; 447 } 448 else 449 { 450 $src_db = $db; 451 $same_db = true; 452 } 453 454 $src_db->sql_return_on_error(true); 455 $db->sql_return_on_error(true); 456 457 // Try to select one row from the first table to see if the prefix is OK 458 $result = $src_db->sql_query_limit('SELECT * FROM ' . $src_table_prefix . $tables[0], 1); 459 460 if (!$result) 461 { 462 $prefixes = array(); 463 464 $tables_existing = get_tables($src_db); 465 $tables_existing = array_map('strtolower', $tables_existing); 466 foreach ($tables_existing as $table_name) 467 { 468 compare_table($tables, $table_name, $prefixes); 469 } 470 unset($tables_existing); 471 472 foreach ($prefixes as $prefix => $count) 473 { 474 if ($count >= sizeof($tables)) 475 { 476 $possible_prefix = $prefix; 477 break; 478 } 479 } 480 481 $msg = ''; 482 if (!empty($convertor_data['table_prefix'])) 483 { 484 $msg .= sprintf($lang['DEFAULT_PREFIX_IS'], $convertor_data['forum_name'], $convertor_data['table_prefix']); 485 } 486 487 if (!empty($possible_prefix)) 488 { 489 $msg .= '<br />'; 490 $msg .= ($possible_prefix == '*') ? $lang['BLANK_PREFIX_FOUND'] : sprintf($lang['PREFIX_FOUND'], $possible_prefix); 491 $src_table_prefix = ($possible_prefix == '*') ? '' : $possible_prefix; 492 } 493 494 $error[] = $msg; 495 } 496 $src_db->sql_freeresult($result); 497 $src_db->sql_return_on_error(false); 498 } 499 500 if (!sizeof($error)) 501 { 502 // Save convertor Status 503 set_config('convert_progress', serialize(array( 504 'step' => '', 505 'table_prefix' => $src_table_prefix, 506 'tag' => $convertor_tag, 507 )), true); 508 set_config('convert_db_server', serialize(array( 509 'dbms' => $src_dbms, 510 'dbhost' => $src_dbhost, 511 'dbport' => $src_dbport, 512 'dbname' => $src_dbname, 513 )), true); 514 set_config('convert_db_user', serialize(array( 515 'dbuser' => $src_dbuser, 516 'dbpasswd' => $src_dbpasswd, 517 )), true); 518 519 // Save options 520 set_config('convert_options', serialize(array('forum_path' => './../' . $forum_path, 'refresh' => $refresh)), true); 521 522 $template->assign_block_vars('checks', array( 523 'TITLE' => $lang['VERIFY_OPTIONS'], 524 'RESULT' => $lang['CONVERT_SETTINGS_VERIFIED'], 525 )); 526 527 $template->assign_vars(array( 528 'L_SUBMIT' => $lang['BEGIN_CONVERT'], 529 // 'S_HIDDEN' => $s_hidden_fields, 530 'U_ACTION' => $this->p_master->module_url . "?mode={$this->mode}&sub=in_progress&tag=$convertor_tag&language=$language", 531 )); 532 533 return; 534 } 535 else 536 { 537 $template->assign_block_vars('checks', array( 538 'TITLE' => $lang['VERIFY_OPTIONS'], 539 'RESULT' => '<b style="color:red">' . implode('<br />', $error) . '</b>', 540 )); 541 } 542 } // end submit 543 544 foreach ($this->convert_options as $config_key => $vars) 545 { 546 if (!is_array($vars) && strpos($config_key, 'legend') === false) 547 { 548 continue; 549 } 550 551 if (strpos($config_key, 'legend') !== false) 552 { 553 $template->assign_block_vars('options', array( 554 'S_LEGEND' => true, 555 'LEGEND' => $lang[$vars]) 556 ); 557 558 continue; 559 } 560 561 $options = isset($vars['options']) ? $vars['options'] : ''; 562 563 $template->assign_block_vars('options', array( 564 'KEY' => $config_key, 565 'TITLE' => $lang[$vars['lang']], 566 'S_EXPLAIN' => $vars['explain'], 567 'S_LEGEND' => false, 568 'TITLE_EXPLAIN' => ($vars['explain']) ? $lang[$vars['lang'] . '_EXPLAIN'] : '', 569 'CONTENT' => $this->p_master->input_field($config_key, $vars['type'], $$config_key, $options), 570 ) 571 ); 572 } 573 574 $template->assign_vars(array( 575 'TITLE' => $lang['STAGE_SETTINGS'], 576 'BODY' => $lang['CONV_OPTIONS_BODY'], 577 'L_SUBMIT' => $lang['BEGIN_CONVERT'], 578 'U_ACTION' => $this->p_master->module_url . "?mode={$this->mode}&sub=settings&tag=$convertor_tag&language=$language", 579 )); 580 } 581 582 /** 583 * The function which does the actual work (or dispatches it to the relevant places) 584 */ 585 function convert_data($sub) 586 { 587 global $template, $user, $phpbb_root_path, $phpEx, $db, $lang, $config, $cache; 588 global $convert, $convert_row, $message_parser, $skip_rows, $language; 589 590 require($phpbb_root_path . 'config.' . $phpEx); 591 require($phpbb_root_path . 'includes/constants.' . $phpEx); 592 require($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx); 593 require($phpbb_root_path . 'includes/functions_convert.' . $phpEx); 594 595 $db = new $sql_db(); 596 $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true); 597 unset($dbpasswd); 598 599 $sql = 'SELECT * 600 FROM ' . CONFIG_TABLE; 601 $result = $db->sql_query($sql); 602 603 $config = array(); 604 while ($row = $db->sql_fetchrow($result)) 605 { 606 $config[$row['config_name']] = $row['config_value']; 607 } 608 $db->sql_freeresult($result); 609 610 // Override a couple of config variables for the duration 611 $config['max_quote_depth'] = 0; 612 613 // @todo Need to confirm that max post length in source is <= max post length in destination or there may be interesting formatting issues 614 $config['max_post_chars'] = $config['min_post_chars'] = 0; 615 616 // Set up a user as well. We _should_ have enough of a database here at this point to do this 617 // and it helps for any core code we call 618 $user->session_begin(); 619 $user->page = $user->extract_current_page($phpbb_root_path); 620 621 // This is a little bit of a fudge, but it allows the language entries to be available to the 622 // core code without us loading them again 623 $user->lang = &$lang; 624 625 $this->page_title = $user->lang['STAGE_IN_PROGRESS']; 626 627 $convert->options = array(); 628 if (isset($config['convert_progress'])) 629 { 630 $convert->options = unserialize($config['convert_progress']); 631 $convert->options = array_merge($convert->options, unserialize($config['convert_db_server']), unserialize($config['convert_db_user']), unserialize($config['convert_options'])); 632 } 633 634 // This information should have already been checked once, but do it again for safety 635 if (empty($convert->options) || empty($convert->options['tag']) || 636 !isset($convert->options['dbms']) || 637 !isset($convert->options['dbhost']) || 638 !isset($convert->options['dbport']) || 639 !isset($convert->options['dbuser']) || 640 !isset($convert->options['dbpasswd']) || 641 !isset($convert->options['dbname']) || 642 !isset($convert->options['table_prefix'])) 643 { 644 $this->p_master->error($user->lang['NO_CONVERT_SPECIFIED'], __LINE__, __FILE__); 645 } 646 647 // Make some short variables accessible, for easier referencing 648 $convert->convertor_tag = basename($convert->options['tag']); 649 $convert->src_dbms = $convert->options['dbms']; 650 $convert->src_dbhost = $convert->options['dbhost']; 651 $convert->src_dbport = $convert->options['dbport']; 652 $convert->src_dbuser = $convert->options['dbuser']; 653 $convert->src_dbpasswd = $convert->options['dbpasswd']; 654 $convert->src_dbname = $convert->options['dbname']; 655 $convert->src_table_prefix = $convert->options['table_prefix']; 656 657 // initiate database connection to old db if old and new db differ 658 global $src_db, $same_db; 659 $src_db = $same_db = null; 660 if ($convert->src_dbms != $dbms || $convert->src_dbhost != $dbhost || $convert->src_dbport != $dbport || $convert->src_dbname != $dbname || $convert->src_dbuser != $dbuser) 661 { 662 if ($convert->src_dbms != $dbms) 663 { 664 require($phpbb_root_path . 'includes/db/' . $convert->src_dbms . '.' . $phpEx); 665 } 666 $sql_db = 'dbal_' . $convert->src_dbms; 667 $src_db = new $sql_db(); 668 $src_db->sql_connect($convert->src_dbhost, $convert->src_dbuser, htmlspecialchars_decode($convert->src_dbpasswd), $convert->src_dbname, $convert->src_dbport, false, true); 669 $same_db = false; 670 } 671 else 672 { 673 $src_db = $db; 674 $same_db = true; 675 } 676 677 $convert->mysql_convert = false; 678 switch ($src_db->sql_layer) 679 { 680 case 'sqlite': 681 case 'firebird': 682 $convert->src_truncate_statement = 'DELETE FROM '; 683 break; 684 685 // Thanks MySQL, for silently converting... 686 case 'mysql': 687 case 'mysql4': 688 if (version_compare($src_db->sql_server_info(true, false), '4.1.3', '>=')) 689 { 690 $convert->mysql_convert = true; 691 } 692 $convert->src_truncate_statement = 'TRUNCATE TABLE '; 693 break; 694 695 case 'mysqli': 696 $convert->mysql_convert = true; 697 $convert->src_truncate_statement = 'TRUNCATE TABLE '; 698 break; 699 700 default: 701 $convert->src_truncate_statement = 'TRUNCATE TABLE '; 702 break; 703 } 704 705 if ($convert->mysql_convert && !$same_db) 706 { 707 $src_db->sql_query("SET NAMES 'binary'"); 708 } 709 710 switch ($db->sql_layer) 711 { 712 case 'sqlite': 713 case 'firebird': 714 $convert->truncate_statement = 'DELETE FROM '; 715 break; 716 717 default: 718 $convert->truncate_statement = 'TRUNCATE TABLE '; 719 break; 720 } 721 722 $get_info = false; 723 724 // check security implications of direct inclusion 725 if (!file_exists('./convertors/convert_' . $convert->convertor_tag . '.' . $phpEx)) 726 { 727 $this->p_master->error($user->lang['CONVERT_NOT_EXIST'], __LINE__, __FILE__); 728 } 729 730 if (file_exists('./convertors/functions_' . $convert->convertor_tag . '.' . $phpEx)) 731 { 732 include('./convertors/functions_' . $convert->convertor_tag . '.' . $phpEx); 733 } 734 735 $get_info = true; 736 include('./convertors/convert_' . $convert->convertor_tag . '.' . $phpEx); 737 738 // Map some variables... 739 $convert->convertor_data = $convertor_data; 740 $convert->tables = $tables; 741 $convert->config_schema = $config_schema; 742 743 // Now include the real data 744 $get_info = false; 745 include('./convertors/convert_' . $convert->convertor_tag . '.' . $phpEx); 746 747 $convert->convertor_data = $convertor_data; 748 $convert->tables = $tables; 749 $convert->config_schema = $config_schema; 750 $convert->convertor = $convertor; 751 752 // The test_file is a file that should be present in the location of the old board. 753 if (!file_exists($convert->options['forum_path'] . '/' . $test_file)) 754 { 755 $this->p_master->error(sprintf($user->lang['COULD_NOT_FIND_PATH'], $convert->options['forum_path']), __LINE__, __FILE__); 756 } 757 758 $search_type = basename(trim($config['search_type'])); 759 760 // For conversions we are a bit less strict and set to a search backend we know exist... 761 if (!file_exists($phpbb_root_path . 'includes/search/' . $search_type . '.' . $phpEx)) 762 { 763 $search_type = 'fulltext_native'; 764 set_config('search_type', $search_type); 765 } 766 767 if (!file_exists($phpbb_root_path . 'includes/search/' . $search_type . '.' . $phpEx)) 768 { 769 trigger_error('NO_SUCH_SEARCH_MODULE'); 770 } 771 772 require($phpbb_root_path . 'includes/search/' . $search_type . '.' . $phpEx); 773 774 $error = false; 775 $convert->fulltext_search = new $search_type($error); 776 777 if ($error) 778 { 779 trigger_error($error); 780 } 781 782 include($phpbb_root_path . 'includes/message_parser.' . $phpEx); 783 $message_parser = new parse_message(); 784 785 $jump = request_var('jump', 0); 786 $final_jump = request_var('final_jump', 0); 787 $sync_batch = request_var('sync_batch', -1); 788 $last_statement = request_var('last', 0); 789 790 // We are running sync... 791 if ($sync_batch >= 0) 792 { 793 $this->sync_forums($sync_batch); 794 return; 795 } 796 797 if ($jump) 798 { 799 $this->jump($jump, $last_statement); 800 return; 801 } 802 803 if ($final_jump) 804 { 805 $this->final_jump($final_jump); 806 return; 807 } 808 809 $current_table = request_var('current_table', 0); 810 $old_current_table = min(-1, $current_table - 1); 811 $skip_rows = request_var('skip_rows', 0); 812 813 if (!$current_table && !$skip_rows) 814 { 815 if (empty($_REQUEST['confirm'])) 816 { 817 // If avatars / ranks / smilies folders are specified make sure they are writable 818 $bad_folders = array(); 819 820 $local_paths = array( 821 'avatar_path' => path($config['avatar_path']), 822 'avatar_gallery_path' => path($config['avatar_gallery_path']), 823 'icons_path' => path($config['icons_path']), 824 'ranks_path' => path($config['ranks_path']), 825 'smilies_path' => path($config['smilies_path']) 826 ); 827 828 foreach ($local_paths as $folder => $local_path) 829 { 830 if (isset($convert->convertor[$folder])) 831 { 832 if (empty($convert->convertor['test_file'])) 833 { 834 // test_file is mandantory at the moment so this should never be reached, but just in case... 835 $this->p_master->error($user->lang['DEV_NO_TEST_FILE'], __LINE__, __FILE__); 836 } 837 838 if (!$local_path || !phpbb_is_writable($phpbb_root_path . $local_path)) 839 { 840 if (!$local_path) 841 { 842 $bad_folders[] = sprintf($user->lang['CONFIG_PHPBB_EMPTY'], $folder); 843 } 844 else 845 { 846 $bad_folders[] = $local_path; 847 } 848 } 849 } 850 } 851 852 if (sizeof($bad_folders)) 853 { 854 $msg = (sizeof($bad_folders) == 1) ? $user->lang['MAKE_FOLDER_WRITABLE'] : $user->lang['MAKE_FOLDERS_WRITABLE']; 855 sort($bad_folders); 856 $this->p_master->error(sprintf($msg, implode('<br />', $bad_folders)), __LINE__, __FILE__, true); 857 858 $template->assign_vars(array( 859 'L_SUBMIT' => $user->lang['INSTALL_TEST'], 860 'U_ACTION' => $this->p_master->module_url . "?mode={$this->mode}&sub=in_progress&tag={$convert->convertor_tag}&language=$language", 861 )); 862 return; 863 } 864 865 // Grab all the tables used in convertor 866 $missing_tables = $tables_list = $aliases = array(); 867 868 foreach ($convert->convertor['schema'] as $schema) 869 { 870 // Skip those not used (because of addons/plugins not detected) 871 if (!$schema['target']) 872 { 873 continue; 874 } 875 876 foreach ($schema as $key => $val) 877 { 878 // we're dealing with an array like: 879 // array('forum_status', 'forums.forum_status', 'is_item_locked') 880 if (is_int($key) && !empty($val[1])) 881 { 882 $temp_data = $val[1]; 883 if (!is_array($temp_data)) 884 { 885 $temp_data = array($temp_data); 886 } 887 888 foreach ($temp_data as $val) 889 { 890 if (preg_match('/([a-z0-9_]+)\.([a-z0-9_]+)\)* ?A?S? ?([a-z0-9_]*?)\.?([a-z0-9_]*)$/i', $val, $m)) 891 { 892 $table = $convert->src_table_prefix . $m[1]; 893 $tables_list[$table] = $table; 894 895 if (!empty($m[3])) 896 { 897 $aliases[] = $convert->src_table_prefix . $m[3]; 898 } 899 } 900 } 901 } 902 // 'left_join' => 'topics LEFT JOIN vote_desc ON topics.topic_id = vote_desc.topic_id AND topics.topic_vote = 1' 903 else if ($key == 'left_join') 904 { 905 // Convert the value if it wasn't an array already. 906 if (!is_array($val)) 907 { 908 $val = array($val); 909 } 910 911 for ($j = 0; $j < sizeof($val); ++$j) 912 { 913 if (preg_match('/LEFT JOIN ([a-z0-9_]+) AS ([a-z0-9_]+)/i', $val[$j], $m)) 914 { 915 $table = $convert->src_table_prefix . $m[1]; 916 $tables_list[$table] = $table; 917 918 if (!empty($m[2])) 919 { 920 $aliases[] = $convert->src_table_prefix . $m[2]; 921 } 922 } 923 } 924 } 925 } 926 } 927 928 // Remove aliased tables from $tables_list 929 foreach ($aliases as $alias) 930 { 931 unset($tables_list[$alias]); 932 } 933 934 // Check if the tables that we need exist 935 $src_db->sql_return_on_error(true); 936 foreach ($tables_list as $table => $null) 937 { 938 $sql = 'SELECT 1 FROM ' . $table; 939 $_result = $src_db->sql_query_limit($sql, 1); 940 941 if (!$_result) 942 { 943 $missing_tables[] = $table; 944 } 945 $src_db->sql_freeresult($_result); 946 } 947 $src_db->sql_return_on_error(false); 948 949 // Throw an error if some tables are missing 950 // We used to do some guessing here, but since we have a suggestion of possible values earlier, I don't see it adding anything here to do it again 951 952 if (sizeof($missing_tables) == sizeof($tables_list)) 953 { 954 $this->p_master->error($user->lang['NO_TABLES_FOUND'] . ' ' . $user->lang['CHECK_TABLE_PREFIX'], __LINE__, __FILE__); 955 } 956 else if (sizeof($missing_tables)) 957 { 958 $this->p_master->error(sprintf($user->lang['TABLES_MISSING'], implode(', ', $missing_tables)) . '<br /><br />' . $user->lang['CHECK_TABLE_PREFIX'], __LINE__, __FILE__); 959 } 960 961 $url = $this->save_convert_progress('&confirm=1'); 962 $msg = $user->lang['PRE_CONVERT_COMPLETE']; 963 964 if ($convert->convertor_data['author_notes']) 965 { 966 $msg .= '</p><p>' . sprintf($user->lang['AUTHOR_NOTES'], $convert->convertor_data['author_notes']); 967 } 968 969 $template->assign_vars(array( 970 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'], 971 'L_MESSAGE' => $msg, 972 'U_ACTION' => $url, 973 )); 974 975 return; 976 } // if (empty($_REQUEST['confirm'])) 977 978 $template->assign_block_vars('checks', array( 979 'S_LEGEND' => true, 980 'LEGEND' => $user->lang['STARTING_CONVERT'], 981 )); 982 983 // Convert the config table and load the settings of the old board 984 if (!empty($convert->config_schema)) 985 { 986 restore_config($convert->config_schema); 987 988 // Override a couple of config variables for the duration 989 $config['max_quote_depth'] = 0; 990 991 // @todo Need to confirm that max post length in source is <= max post length in destination or there may be interesting formatting issues 992 $config['max_post_chars'] = $config['min_post_chars'] = 0; 993 } 994 995 $template->assign_block_vars('checks', array( 996 'TITLE' => $user->lang['CONFIG_CONVERT'], 997 'RESULT' => $user->lang['DONE'], 998 )); 999 1000 // Now process queries and execute functions that have to be executed prior to the conversion 1001 if (!empty($convert->convertor['execute_first'])) 1002 { 1003 eval($convert->convertor['execute_first']); 1004 } 1005 1006 if (!empty($convert->convertor['query_first'])) 1007 { 1008 if (!is_array($convert->convertor['query_first'])) 1009 { 1010 $convert->convertor['query_first'] = array('target', array($convert->convertor['query_first'])); 1011 } 1012 else if (!is_array($convert->convertor['query_first'][0])) 1013 { 1014 $convert->convertor['query_first'] = array(array($convert->convertor['query_first'][0], $convert->convertor['query_first'][1])); 1015 } 1016 1017 foreach ($convert->convertor['query_first'] as $query_first) 1018 { 1019 if ($query_first[0] == 'src') 1020 { 1021 if ($convert->mysql_convert && $same_db) 1022 { 1023 $src_db->sql_query("SET NAMES 'binary'"); 1024 } 1025 1026 $src_db->sql_query($query_first[1]); 1027 1028 if ($convert->mysql_convert && $same_db) 1029 { 1030 $src_db->sql_query("SET NAMES 'utf8'"); 1031 } 1032 } 1033 else 1034 { 1035 $db->sql_query($query_first[1]); 1036 } 1037 } 1038 } 1039 1040 $template->assign_block_vars('checks', array( 1041 'TITLE' => $user->lang['PREPROCESS_STEP'], 1042 'RESULT' => $user->lang['DONE'], 1043 )); 1044 } // if (!$current_table && !$skip_rows) 1045 1046 $template->assign_block_vars('checks', array( 1047 'S_LEGEND' => true, 1048 'LEGEND' => $user->lang['FILLING_TABLES'], 1049 )); 1050 1051 // This loop takes one target table and processes it 1052 while ($current_table < sizeof($convert->convertor['schema'])) 1053 { 1054 $schema = $convert->convertor['schema'][$current_table]; 1055 1056 // The target table isn't set, this can be because a module (for example the attachement mod) is taking care of this. 1057 if (empty($schema['target'])) 1058 { 1059 $current_table++; 1060 continue; 1061 } 1062 1063 $template->assign_block_vars('checks', array( 1064 'TITLE' => sprintf($user->lang['FILLING_TABLE'], $schema['target']), 1065 )); 1066 1067 // This is only the case when we first start working on the tables. 1068 if (!$skip_rows) 1069 { 1070 // process execute_first and query_first for this table... 1071 if (!empty($schema['execute_first'])) 1072 { 1073 eval($schema['execute_first']); 1074 } 1075 1076 if (!empty($schema['query_first'])) 1077 { 1078 if (!is_array($schema['query_first'])) 1079 { 1080 $schema['query_first'] = array('target', array($schema['query_first'])); 1081 } 1082 else if (!is_array($schema['query_first'][0])) 1083 { 1084 $schema['query_first'] = array(array($schema['query_first'][0], $schema['query_first'][1])); 1085 } 1086 1087 foreach ($schema['query_first'] as $query_first) 1088 { 1089 if ($query_first[0] == 'src') 1090 { 1091 if ($convert->mysql_convert && $same_db) 1092 { 1093 $src_db->sql_query("SET NAMES 'binary'"); 1094 } 1095 $src_db->sql_query($query_first[1]); 1096 if ($convert->mysql_convert && $same_db) 1097 { 1098 $src_db->sql_query("SET NAMES 'utf8'"); 1099 } 1100 } 1101 else 1102 { 1103 $db->sql_query($query_first[1]); 1104 } 1105 } 1106 } 1107 1108 if (!empty($schema['autoincrement'])) 1109 { 1110 switch ($db->sql_layer) 1111 { 1112 case 'postgres': 1113 $db->sql_query("SELECT SETVAL('" . $schema['target'] . "_seq',(select case when max(" . $schema['autoincrement'] . ")>0 then max(" . $schema['autoincrement'] . ")+1 else 1 end from " . $schema['target'] . '));'); 1114 break; 1115 1116 case 'oracle': 1117 $result = $db->sql_query('SELECT MAX(' . $schema['autoincrement'] . ') as max_id FROM ' . $schema['target']); 1118 $row = $db->sql_fetchrow($result); 1119 $db->sql_freeresult($result); 1120 1121 $largest_id = (int) $row['max_id']; 1122 1123 if ($largest_id) 1124 { 1125 $db->sql_query('DROP SEQUENCE ' . $schema['target'] . '_seq'); 1126 $db->sql_query('CREATE SEQUENCE ' . $schema['target'] . '_seq START WITH ' . ($largest_id + 1)); 1127 } 1128 break; 1129 } 1130 } 1131 } 1132 1133 // Process execute_always for this table 1134 // This is for code which needs to be executed on every pass of this table if 1135 // it gets split because of time restrictions 1136 if (!empty($schema['execute_always'])) 1137 { 1138 eval($schema['execute_always']); 1139 } 1140 1141 // 1142 // Set up some variables 1143 // 1144 // $waiting_rows holds rows for multirows insertion (MySQL only) 1145 // $src_tables holds unique tables with aliases to select from 1146 // $src_fields will quickly refer source fields (or aliases) corresponding to the current index 1147 // $select_fields holds the names of the fields to retrieve 1148 // 1149 1150 $sql_data = array( 1151 'source_fields' => array(), 1152 'target_fields' => array(), 1153 'source_tables' => array(), 1154 'select_fields' => array(), 1155 ); 1156 1157 // This statement is building the keys for later insertion. 1158 $insert_query = $this->build_insert_query($schema, $sql_data, $current_table); 1159 1160 // If no source table is affected, we skip the table 1161 if (empty($sql_data['source_tables'])) 1162 { 1163 $skip_rows = 0; 1164 $current_table++; 1165 continue; 1166 } 1167 1168 $distinct = (!empty($schema['distinct'])) ? 'DISTINCT ' : ''; 1169 1170 $sql = 'SELECT ' . $distinct . implode(', ', $sql_data['select_fields']) . " \nFROM " . implode(', ', $sql_data['source_tables']); 1171 1172 // Where 1173 $sql .= (!empty($schema['where'])) ? "\nWHERE (" . $schema['where'] . ')' : ''; 1174 1175 // Group By 1176 if (!empty($schema['group_by'])) 1177 { 1178 $schema['group_by'] = array($schema['group_by']); 1179 foreach ($sql_data['select_fields'] as $select) 1180 { 1181 $alias = strpos(strtolower($select), ' as '); 1182 $select = ($alias) ? substr($select, 0, $alias) : $select; 1183 if (!in_array($select, $schema['group_by'])) 1184 { 1185 $schema['group_by'][] = $select; 1186 } 1187 } 1188 } 1189 $sql .= (!empty($schema['group_by'])) ? "\nGROUP BY " . implode(', ', $schema['group_by']) : ''; 1190 1191 // Having 1192 $sql .= (!empty($schema['having'])) ? "\nHAVING " . $schema['having'] : ''; 1193 1194 // Order By 1195 if (empty($schema['order_by']) && !empty($schema['primary'])) 1196 { 1197 $schema['order_by'] = $schema['primary']; 1198 } 1199 $sql .= (!empty($schema['order_by'])) ? "\nORDER BY " . $schema['order_by'] : ''; 1200 1201 // Counting basically holds the amount of rows processed. 1202 $counting = -1; 1203 $batch_time = 0; 1204 1205 while ($counting === -1 || ($counting >= $convert->batch_size && still_on_time())) 1206 { 1207 $old_current_table = $current_table; 1208 1209 $rows = ''; 1210 $waiting_rows = array(); 1211 1212 if (!empty($batch_time)) 1213 { 1214 $mtime = explode(' ', microtime()); 1215 $mtime = $mtime[0] + $mtime[1]; 1216 $rows = ceil($counting/($mtime - $batch_time)) . " rows/s ($counting rows) | "; 1217 } 1218 1219 $template->assign_block_vars('checks', array( 1220 'TITLE' => "skip_rows = $skip_rows", 1221 'RESULT' => $rows . ((defined('DEBUG_EXTRA') && function_exists('memory_get_usage')) ? ceil(memory_get_usage()/1024) . ' ' . $user->lang['KIB'] : ''), 1222 )); 1223 1224 $mtime = explode(' ', microtime()); 1225 $batch_time = $mtime[0] + $mtime[1]; 1226 1227 if ($convert->mysql_convert && $same_db) 1228 { 1229 $src_db->sql_query("SET NAMES 'binary'"); 1230 } 1231 1232 // Take skip rows into account and only fetch batch_size amount of rows 1233 $___result = $src_db->sql_query_limit($sql, $convert->batch_size, $skip_rows); 1234 1235 if ($convert->mysql_convert && $same_db) 1236 { 1237 $src_db->sql_query("SET NAMES 'utf8'"); 1238 } 1239 1240 // This loop processes each row 1241 $counting = 0; 1242 1243 $convert->row = $convert_row = array(); 1244 1245 if (!empty($schema['autoincrement'])) 1246 { 1247 switch ($db->sql_layer) 1248 { 1249 case 'mssql': 1250 case 'mssql_odbc': 1251 case 'mssqlnative': 1252 $db->sql_query('SET IDENTITY_INSERT ' . $schema['target'] . ' ON'); 1253 break; 1254 } 1255 } 1256 1257 // Now handle the rows until time is over or no more rows to process... 1258 while ($counting === 0 || still_on_time()) 1259 { 1260 $convert_row = $src_db->sql_fetchrow($___result); 1261 1262 if (!$convert_row) 1263 { 1264 // move to the next batch or table 1265 break; 1266 } 1267 1268 // With this we are able to always save the last state 1269 $convert->row = $convert_row; 1270 1271 // Increment the counting variable, it stores the number of rows we have processed 1272 $counting++; 1273 1274 $insert_values = array(); 1275 1276 $sql_flag = $this->process_row($schema, $sql_data, $insert_values); 1277 1278 if ($sql_flag === true) 1279 { 1280 switch ($db->sql_layer) 1281 { 1282 // If MySQL, we'll wait to have num_wait_rows rows to submit at once 1283 case 'mysql': 1284 case 'mysql4': 1285 case 'mysqli': 1286 $waiting_rows[] = '(' . implode(', ', $insert_values) . ')'; 1287 1288 if (sizeof($waiting_rows) >= $convert->num_wait_rows) 1289 { 1290 $errored = false; 1291 1292 $db->sql_return_on_error(true); 1293 1294 if (!$db->sql_query($insert_query . implode(', ', $waiting_rows))) 1295 { 1296 $errored = true; 1297 } 1298 $db->sql_return_on_error(false); 1299 1300 if ($errored) 1301 { 1302 $db->sql_return_on_error(true); 1303 1304 // Because it errored out we will try to insert the rows one by one... most of the time this 1305 // is caused by duplicate entries - but we also do not want to miss one... 1306 foreach ($waiting_rows as $waiting_sql) 1307 { 1308 if (!$db->sql_query($insert_query . $waiting_sql)) 1309 { 1310 $this->p_master->db_error($user->lang['DB_ERR_INSERT'], htmlspecialchars($insert_query . $waiting_sql) . '<br /><br />' . htmlspecialchars(print_r($db->_sql_error(), true)), __LINE__, __FILE__, true); 1311 } 1312 } 1313 1314 $db->sql_return_on_error(false); 1315 } 1316 1317 $waiting_rows = array(); 1318 } 1319 1320 break; 1321 1322 default: 1323 $insert_sql = $insert_query . '(' . implode(', ', $insert_values) . ')'; 1324 1325 $db->sql_return_on_error(true); 1326 1327 if (!$db->sql_query($insert_sql)) 1328 { 1329 $this->p_master->db_error($user->lang['DB_ERR_INSERT'], htmlspecialchars($insert_sql) . '<br /><br />' . htmlspecialchars(print_r($db->_sql_error(), true)), __LINE__, __FILE__, true); 1330 } 1331 $db->sql_return_on_error(false); 1332 1333 $waiting_rows = array(); 1334 1335 break; 1336 } 1337 } 1338 1339 $skip_rows++; 1340 } 1341 $src_db->sql_freeresult($___result); 1342 1343 // We might still have some rows waiting 1344 if (sizeof($waiting_rows)) 1345 { 1346 $errored = false; 1347 $db->sql_return_on_error(true); 1348 1349 if (!$db->sql_query($insert_query . implode(', ', $waiting_rows))) 1350 { 1351 $errored = true; 1352 } 1353 $db->sql_return_on_error(false); 1354 1355 if ($errored) 1356 { 1357 $db->sql_return_on_error(true); 1358 1359 // Because it errored out we will try to insert the rows one by one... most of the time this 1360 // is caused by duplicate entries - but we also do not want to miss one... 1361 foreach ($waiting_rows as $waiting_sql) 1362 { 1363 $db->sql_query($insert_query . $waiting_sql); 1364 $this->p_master->db_error($user->lang['DB_ERR_INSERT'], htmlspecialchars($insert_query . $waiting_sql) . '<br /><br />' . htmlspecialchars(print_r($db->_sql_error(), true)), __LINE__, __FILE__, true); 1365 } 1366 1367 $db->sql_return_on_error(false); 1368 } 1369 1370 $waiting_rows = array(); 1371 } 1372 1373 if (!empty($schema['autoincrement'])) 1374 { 1375 switch ($db->sql_layer) 1376 { 1377 case 'mssql': 1378 case 'mssql_odbc': 1379 case 'mssqlnative': 1380 $db->sql_query('SET IDENTITY_INSERT ' . $schema['target'] . ' OFF'); 1381 break; 1382 1383 case 'postgres': 1384 $db->sql_query("SELECT SETVAL('" . $schema['target'] . "_seq',(select case when max(" . $schema['autoincrement'] . ")>0 then max(" . $schema['autoincrement'] . ")+1 else 1 end from " . $schema['target'] . '));'); 1385 break; 1386 1387 case 'oracle': 1388 $result = $db->sql_query('SELECT MAX(' . $schema['autoincrement'] . ') as max_id FROM ' . $schema['target']); 1389 $row = $db->sql_fetchrow($result); 1390 $db->sql_freeresult($result); 1391 1392 $largest_id = (int) $row['max_id']; 1393 1394 if ($largest_id) 1395 { 1396 $db->sql_query('DROP SEQUENCE ' . $schema['target'] . '_seq'); 1397 $db->sql_query('CREATE SEQUENCE ' . $schema['target'] . '_seq START WITH ' . ($largest_id + 1)); 1398 } 1399 break; 1400 } 1401 } 1402 } 1403 1404 // When we reach this point, either the current table has been processed or we're running out of time. 1405 if (still_on_time() && $counting < $convert->batch_size/* && !defined('DEBUG_EXTRA')*/) 1406 { 1407 $skip_rows = 0; 1408 $current_table++; 1409 } 1410 else 1411 {/* 1412 if (still_on_time() && $counting < $convert->batch_size) 1413 { 1414 $skip_rows = 0; 1415 $current_table++; 1416 }*/ 1417 1418 // Looks like we ran out of time. 1419 $url = $this->save_convert_progress('&current_table=' . $current_table . '&skip_rows=' . $skip_rows); 1420 1421 $current_table++; 1422 // $percentage = ($skip_rows == 0) ? 0 : floor(100 / ($total_rows / $skip_rows)); 1423 1424 $msg = sprintf($user->lang['STEP_PERCENT_COMPLETED'], $current_table, sizeof($convert->convertor['schema'])); 1425 1426 $template->assign_vars(array( 1427 'L_MESSAGE' => $msg, 1428 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'], 1429 'U_ACTION' => $url, 1430 )); 1431 1432 $this->meta_refresh($url); 1433 return; 1434 } 1435 } 1436 1437 // Process execute_last then we'll be done 1438 $url = $this->save_convert_progress('&jump=1'); 1439 1440 $template->assign_vars(array( 1441 'L_SUBMIT' => $user->lang['FINAL_STEP'], 1442 'U_ACTION' => $url, 1443 )); 1444 1445 $this->meta_refresh($url); 1446 return; 1447 } 1448 1449 /** 1450 * Sync function being executed at the middle, some functions need to be executed after a successful sync. 1451 */ 1452 function sync_forums($sync_batch) 1453 { 1454 global $template, $user, $db, $phpbb_root_path, $phpEx, $config, $cache; 1455 global $convert; 1456 1457 $template->assign_block_vars('checks', array( 1458 'S_LEGEND' => true, 1459 'LEGEND' => $user->lang['SYNC_TOPICS'], 1460 )); 1461 1462 $batch_size = $convert->batch_size; 1463 1464 $sql = 'SELECT MIN(topic_id) as min_value, MAX(topic_id) AS max_value 1465 FROM ' . TOPICS_TABLE; 1466 $result = $db->sql_query($sql); 1467 $row = $db->sql_fetchrow($result); 1468 $db->sql_freeresult($result); 1469 1470 // Set values of minimum/maximum primary value for this table. 1471 $primary_min = $row['min_value']; 1472 $primary_max = $row['max_value']; 1473 1474 if ($sync_batch == 0) 1475 { 1476 $sync_batch = (int) $primary_min; 1477 } 1478 1479 if ($sync_batch == 0) 1480 { 1481 $sync_batch = 1; 1482 } 1483 1484 // Fetch a batch of rows, process and insert them. 1485 while ($sync_batch <= $primary_max && still_on_time()) 1486 { 1487 $end = ($sync_batch + $batch_size - 1); 1488 1489 // Sync all topics in batch mode... 1490 sync('topic_approved', 'range', 'topic_id BETWEEN ' . $sync_batch . ' AND ' . $end, true, false); 1491 sync('topic', 'range', 'topic_id BETWEEN ' . $sync_batch . ' AND ' . $end, true, true); 1492 1493 $template->assign_block_vars('checks', array( 1494 'TITLE' => sprintf($user->lang['SYNC_TOPIC_ID'], $sync_batch, ($sync_batch + $batch_size)) . ((defined('DEBUG_EXTRA') && function_exists('memory_get_usage')) ? ' [' . ceil(memory_get_usage()/1024) . ' ' . $user->lang['KIB'] . ']' : ''), 1495 'RESULT' => $user->lang['DONE'], 1496 )); 1497 1498 $sync_batch += $batch_size; 1499 } 1500 1501 if ($sync_batch >= $primary_max) 1502 { 1503 $url = $this->save_convert_progress('&final_jump=1'); 1504 1505 $template->assign_vars(array( 1506 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'], 1507 'U_ACTION' => $url, 1508 )); 1509 1510 $this->meta_refresh($url); 1511 return; 1512 } 1513 else 1514 { 1515 $sync_batch--; 1516 } 1517 1518 $url = $this->save_convert_progress('&sync_batch=' . $sync_batch); 1519 1520 $template->assign_vars(array( 1521 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'], 1522 'U_ACTION' => $url, 1523 )); 1524 1525 $this->meta_refresh($url); 1526 return; 1527 } 1528 1529 /** 1530 * Save the convertor status 1531 */ 1532 function save_convert_progress($step) 1533 { 1534 global $convert, $language; 1535 1536 // Save convertor Status 1537 set_config('convert_progress', serialize(array( 1538 'step' => $step, 1539 'table_prefix' => $convert->src_table_prefix, 1540 'tag' => $convert->convertor_tag, 1541 )), true); 1542 1543 set_config('convert_db_server', serialize(array( 1544 'dbms' => $convert->src_dbms, 1545 'dbhost' => $convert->src_dbhost, 1546 'dbport' => $convert->src_dbport, 1547 'dbname' => $convert->src_dbname, 1548 )), true); 1549 1550 set_config('convert_db_user', serialize(array( 1551 'dbuser' => $convert->src_dbuser, 1552 'dbpasswd' => $convert->src_dbpasswd, 1553 )), true); 1554 1555 return $this->p_master->module_url . "?mode={$this->mode}&sub=in_progress&tag={$convert->convertor_tag}$step&language=$language"; 1556 } 1557 1558 /** 1559 * Finish conversion, the last function to be called. 1560 */ 1561 function finish_conversion() 1562 { 1563 global $db, $phpbb_root_path, $phpEx, $convert, $config, $language, $user, $template; 1564 1565 $db->sql_query('DELETE FROM ' . CONFIG_TABLE . " 1566 WHERE config_name = 'convert_progress' 1567 OR config_name = 'convert_options' 1568 OR config_name = 'convert_db_server' 1569 OR config_name = 'convert_db_user'"); 1570 $db->sql_query('DELETE FROM ' . SESSIONS_TABLE); 1571 1572 @unlink($phpbb_root_path . 'cache/data_global.' . $phpEx); 1573 cache_moderators(); 1574 1575 // And finally, add a note to the log 1576 add_log('admin', 'LOG_INSTALL_CONVERTED', $convert->convertor_data['forum_name'], $config['version']); 1577 1578 $url = $this->p_master->module_url . "?mode={$this->mode}&sub=final&language=$language"; 1579 1580 $template->assign_vars(array( 1581 'L_SUBMIT' => $user->lang['FINAL_STEP'], 1582 'U_ACTION' => $url, 1583 )); 1584 1585 $this->meta_refresh($url); 1586 return; 1587 } 1588 1589 /** 1590 * This function marks the steps after syncing 1591 */ 1592 function final_jump($final_jump) 1593 { 1594 global $template, $user, $src_db, $same_db, $db, $phpbb_root_path, $phpEx, $config, $cache; 1595 global $convert; 1596 1597 $template->assign_block_vars('checks', array( 1598 'S_LEGEND' => true, 1599 'LEGEND' => $user->lang['PROCESS_LAST'], 1600 )); 1601 1602 if ($final_jump == 1) 1603 { 1604 $db->sql_return_on_error(true); 1605 1606 update_topics_posted(); 1607 1608 $template->assign_block_vars('checks', array( 1609 'TITLE' => $user->lang['UPDATE_TOPICS_POSTED'], 1610 'RESULT' => $user->lang['DONE'], 1611 )); 1612 1613 if ($db->sql_error_triggered) 1614 { 1615 $template->assign_vars(array( 1616 'S_ERROR_BOX' => true, 1617 'ERROR_TITLE' => $user->lang['UPDATE_TOPICS_POSTED'], 1618 'ERROR_MSG' => $user->lang['UPDATE_TOPICS_POSTED_ERR'], 1619 )); 1620 } 1621 $db->sql_return_on_error(false); 1622 1623 $this->finish_conversion(); 1624 return; 1625 } 1626 } 1627 1628 /** 1629 * This function marks the steps before syncing (jump=1) 1630 */ 1631 function jump($jump, $last_statement) 1632 { 1633 global $template, $user, $src_db, $same_db, $db, $phpbb_root_path, $phpEx, $config, $cache; 1634 global $convert; 1635 1636 $template->assign_block_vars('checks', array( 1637 'S_LEGEND' => true, 1638 'LEGEND' => $user->lang['PROCESS_LAST'], 1639 )); 1640 1641 if ($jump == 1) 1642 { 1643 // Execute 'last' statements/queries 1644 if (!empty($convert->convertor['execute_last'])) 1645 { 1646 if (!is_array($convert->convertor['execute_last'])) 1647 { 1648 eval($convert->convertor['execute_last']); 1649 } 1650 else 1651 { 1652 while ($last_statement < sizeof($convert->convertor['execute_last'])) 1653 { 1654 eval($convert->convertor['execute_last'][$last_statement]); 1655 1656 $template->assign_block_vars('checks', array( 1657 'TITLE' => $convert->convertor['execute_last'][$last_statement], 1658 'RESULT' => $user->lang['DONE'], 1659 )); 1660 1661 $last_statement++; 1662 $url = $this->save_convert_progress('&jump=1&last=' . $last_statement); 1663 1664 $percentage = ($last_statement == 0) ? 0 : floor(100 / (sizeof($convert->convertor['execute_last']) / $last_statement)); 1665 $msg = sprintf($user->lang['STEP_PERCENT_COMPLETED'], $last_statement, sizeof($convert->convertor['execute_last']), $percentage); 1666 1667 $template->assign_vars(array( 1668 'L_SUBMIT' => $user->lang['CONTINUE_LAST'], 1669 'L_MESSAGE' => $msg, 1670 'U_ACTION' => $url, 1671 )); 1672 1673 $this->meta_refresh($url); 1674 return; 1675 } 1676 } 1677 } 1678 1679 if (!empty($convert->convertor['query_last'])) 1680 { 1681 if (!is_array($convert->convertor['query_last'])) 1682 { 1683 $convert->convertor['query_last'] = array('target', array($convert->convertor['query_last'])); 1684 } 1685 else if (!is_array($convert->convertor['query_last'][0])) 1686 { 1687 $convert->convertor['query_last'] = array(array($convert->convertor['query_last'][0], $convert->convertor['query_last'][1])); 1688 } 1689 1690 foreach ($convert->convertor['query_last'] as $query_last) 1691 { 1692 if ($query_last[0] == 'src') 1693 { 1694 if ($convert->mysql_convert && $same_db) 1695 { 1696 $src_db->sql_query("SET NAMES 'binary'"); 1697 } 1698 1699 $src_db->sql_query($query_last[1]); 1700 1701 if ($convert->mysql_convert && $same_db) 1702 { 1703 $src_db->sql_query("SET NAMES 'utf8'"); 1704 } 1705 } 1706 else 1707 { 1708 $db->sql_query($query_last[1]); 1709 } 1710 } 1711 } 1712 1713 // Sanity check 1714 $db->sql_return_on_error(false); 1715 $src_db->sql_return_on_error(false); 1716 1717 fix_empty_primary_groups(); 1718 1719 $sql = 'SELECT MIN(user_regdate) AS board_startdate 1720 FROM ' . USERS_TABLE; 1721 $result = $db->sql_query($sql); 1722 $row = $db->sql_fetchrow($result); 1723 $db->sql_freeresult($result); 1724 1725 if (!isset($config['board_startdate']) || ($row['board_startdate'] < $config['board_startdate'] && $row['board_startdate'] > 0)) 1726 { 1727 set_config('board_startdate', $row['board_startdate']); 1728 $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_regdate = ' . $row['board_startdate'] . ' WHERE user_id = ' . ANONYMOUS); 1729 } 1730 1731 update_dynamic_config(); 1732 1733 $template->assign_block_vars('checks', array( 1734 'TITLE' => $user->lang['CLEAN_VERIFY'], 1735 'RESULT' => $user->lang['DONE'], 1736 )); 1737 1738 $url = $this->save_convert_progress('&jump=2'); 1739 1740 $template->assign_vars(array( 1741 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'], 1742 'U_ACTION' => $url, 1743 )); 1744 1745 $this->meta_refresh($url); 1746 return; 1747 } 1748 1749 if ($jump == 2) 1750 { 1751 $db->sql_query('UPDATE ' . USERS_TABLE . " SET user_permissions = ''"); 1752 1753 // TODO: sync() is likely going to bomb out on forums with a considerable amount of topics. 1754 // TODO: the sync function is able to handle FROM-TO values, we should use them here (batch processing) 1755 sync('forum', '', '', false, true); 1756 $cache->destroy('sql', FORUMS_TABLE); 1757 1758 $template->assign_block_vars('checks', array( 1759 'TITLE' => $user->lang['SYNC_FORUMS'], 1760 'RESULT' => $user->lang['DONE'], 1761 )); 1762 1763 // Continue with synchronizing the forums... 1764 $url = $this->save_convert_progress('&sync_batch=0'); 1765 1766 $template->assign_vars(array( 1767 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'], 1768 'U_ACTION' => $url, 1769 )); 1770 1771 $this->meta_refresh($url); 1772 return; 1773 } 1774 } 1775 1776 function build_insert_query(&$schema, &$sql_data, $current_table) 1777 { 1778 global $db, $user; 1779 global $convert; 1780 1781 // Can we use IGNORE with this DBMS? 1782 $sql_ignore = (strpos($db->sql_layer, 'mysql') === 0 && !defined('DEBUG_EXTRA')) ? 'IGNORE ' : ''; 1783 $insert_query = 'INSERT ' . $sql_ignore . 'INTO ' . $schema['target'] . ' ('; 1784 1785 $aliases = array(); 1786 1787 $sql_data = array( 1788 'source_fields' => array(), 1789 'target_fields' => array(), 1790 'source_tables' => array(), 1791 'select_fields' => array(), 1792 ); 1793 1794 foreach ($schema as $key => $val) 1795 { 1796 // Example: array('group_name', 'extension_groups.group_name', 'htmlspecialchars'), 1797 if (is_int($key)) 1798 { 1799 if (!empty($val[0])) 1800 { 1801 // Target fields 1802 $sql_data['target_fields'][$val[0]] = $key; 1803 $insert_query .= $val[0] . ', '; 1804 } 1805 1806 if (!is_array($val[1])) 1807 { 1808 $val[1] = array($val[1]); 1809 } 1810 1811 foreach ($val[1] as $valkey => $value_1) 1812 { 1813 // This should cover about any case: 1814 // 1815 // table.field => SELECT table.field FROM table 1816 // table.field AS alias => SELECT table.field AS alias FROM table 1817 // table.field AS table2.alias => SELECT table2.field AS alias FROM table table2 1818 // table.field AS table2.field => SELECT table2.field FROM table table2 1819 // 1820 if (preg_match('/^([a-z0-9_]+)\.([a-z0-9_]+)( +AS +(([a-z0-9_]+?)\.)?([a-z0-9_]+))?$/i', $value_1, $m)) 1821 { 1822 // There is 'AS ...' in the field names 1823 if (!empty($m[3])) 1824 { 1825 $value_1 = ($m[2] == $m[6]) ? $m[1] . '.' . $m[2] : $m[1] . '.' . $m[2] . ' AS ' . $m[6]; 1826 1827 // Table alias: store it then replace the source table with it 1828 if (!empty($m[5]) && $m[5] != $m[1]) 1829 { 1830 $aliases[$m[5]] = $m[1]; 1831 $value_1 = str_replace($m[1] . '.' . $m[2], $m[5] . '.' . $m[2], $value_1); 1832 } 1833 } 1834 else 1835 { 1836 // No table alias 1837 $sql_data['source_tables'][$m[1]] = (empty($convert->src_table_prefix)) ? $m[1] : $convert->src_table_prefix . $m[1] . ' ' . $m[1]; 1838 } 1839 1840 $sql_data['select_fields'][$value_1] = $value_1; 1841 $sql_data['source_fields'][$key][$valkey] = (!empty($m[6])) ? $m[6] : $m[2]; 1842 } 1843 } 1844 } 1845 else if ($key == 'where' || $key == 'group_by' || $key == 'order_by' || $key == 'having') 1846 { 1847 if (@preg_match_all('/([a-z0-9_]+)\.([a-z0-9_]+)/i', $val, $m)) 1848 { 1849 foreach ($m[1] as $value) 1850 { 1851 $sql_data['source_tables'][$value] = (empty($convert->src_table_prefix)) ? $value : $convert->src_table_prefix . $value . ' ' . $value; 1852 } 1853 } 1854 } 1855 } 1856 1857 // Add the aliases to the list of tables 1858 foreach ($aliases as $alias => $table) 1859 { 1860 $sql_data['source_tables'][$alias] = $convert->src_table_prefix . $table . ' ' . $alias; 1861 } 1862 1863 // 'left_join' => 'forums LEFT JOIN forum_prune ON forums.forum_id = forum_prune.forum_id', 1864 if (!empty($schema['left_join'])) 1865 { 1866 if (!is_array($schema['left_join'])) 1867 { 1868 $schema['left_join'] = array($schema['left_join']); 1869 } 1870 1871 foreach ($schema['left_join'] as $left_join) 1872 { 1873 // This won't handle concatened LEFT JOINs 1874 if (!preg_match('/([a-z0-9_]+) LEFT JOIN ([a-z0-9_]+) A?S? ?([a-z0-9_]*?) ?(ON|USING)(.*)/i', $left_join, $m)) 1875 { 1876 $this->p_master->error(sprintf($user->lang['NOT_UNDERSTAND'], 'LEFT JOIN', $left_join, $current_table, $schema['target']), __LINE__, __FILE__); 1877 } 1878 1879 if (!empty($aliases[$m[2]])) 1880 { 1881 if (!empty($m[3])) 1882 { 1883 $this->p_master->error(sprintf($user->lang['NAMING_CONFLICT'], $m[2], $m[3], $schema['left_join']), __LINE__, __FILE__); 1884 } 1885 1886 $m[2] = $aliases[$m[2]]; 1887 $m[3] = $m[2]; 1888 } 1889 1890 $right_table = $convert->src_table_prefix . $m[2]; 1891 if (!empty($m[3])) 1892 { 1893 unset($sql_data['source_tables'][$m[3]]); 1894 } 1895 else if ($m[2] != $m[1]) 1896 { 1897 unset($sql_data['source_tables'][$m[2]]); 1898 } 1899 1900 if (strpos($sql_data['source_tables'][$m[1]], "\nLEFT JOIN") !== false) 1901 { 1902 $sql_data['source_tables'][$m[1]] = '(' . $sql_data['source_tables'][$m[1]] . ")\nLEFT JOIN $right_table"; 1903 } 1904 else 1905 { 1906 $sql_data['source_tables'][$m[1]] .= "\nLEFT JOIN $right_table"; 1907 } 1908 1909 if (!empty($m[3])) 1910 { 1911 unset($sql_data['source_tables'][$m[3]]); 1912 $sql_data['source_tables'][$m[1]] .= ' AS ' . $m[3]; 1913 } 1914 else if (!empty($convert->src_table_prefix)) 1915 { 1916 $sql_data['source_tables'][$m[1]] .= ' AS ' . $m[2]; 1917 } 1918 $sql_data['source_tables'][$m[1]] .= ' ' . $m[4] . $m[5]; 1919 } 1920 } 1921 1922 // Remove ", " from the end of the insert query 1923 $insert_query = substr($insert_query, 0, -2) . ') VALUES '; 1924 1925 return $insert_query; 1926 } 1927 1928 /** 1929 * Function for processing the currently handled row 1930 */ 1931 function process_row(&$schema, &$sql_data, &$insert_values) 1932 { 1933 global $template, $user, $phpbb_root_path, $phpEx, $db, $lang, $config, $cache; 1934 global $convert, $convert_row; 1935 1936 $sql_flag = false; 1937 1938 foreach ($schema as $key => $fields) 1939 { 1940 // We are only interested in the lines with: 1941 // array('comment', 'attachments_desc.comment', 'htmlspecialchars'), 1942 if (is_int($key)) 1943 { 1944 if (!is_array($fields[1])) 1945 { 1946 $fields[1] = array($fields[1]); 1947 } 1948 1949 $firstkey_set = false; 1950 $firstkey = 0; 1951 1952 foreach ($fields[1] as $inner_key => $inner_value) 1953 { 1954 if (!$firstkey_set) 1955 { 1956 $firstkey = $inner_key; 1957 $firstkey_set = true; 1958 } 1959 1960 $src_field = isset($sql_data['source_fields'][$key][$inner_key]) ? $sql_data['source_fields'][$key][$inner_key] : ''; 1961 1962 if (!empty($src_field)) 1963 { 1964 $fields[1][$inner_key] = $convert->row[$src_field]; 1965 } 1966 } 1967 1968 if (!empty($fields[0])) 1969 { 1970 // We have a target field, if we haven't set $sql_flag yet it will be set to TRUE. 1971 // If a function has already set it to FALSE it won't change it. 1972 if ($sql_flag === false) 1973 { 1974 $sql_flag = true; 1975 } 1976 1977 // No function assigned? 1978 if (empty($fields[2])) 1979 { 1980 $value = $fields[1][$firstkey]; 1981 } 1982 else if (is_array($fields[2])) 1983 { 1984 // Execute complex function/eval/typecast 1985 $value = $fields[1]; 1986 1987 foreach ($fields[2] as $type => $execution) 1988 { 1989 if (strpos($type, 'typecast') === 0) 1990 { 1991 if (!is_array($value)) 1992 { 1993 $value = array($value); 1994 } 1995 $value = $value[0]; 1996 settype($value, $execution); 1997 } 1998 else if (strpos($type, 'function') === 0) 1999 { 2000 if (!is_array($value)) 2001 { 2002 $value = array($value); 2003 } 2004 2005 $value = call_user_func_array($execution, $value); 2006 } 2007 else if (strpos($type, 'execute') === 0) 2008 { 2009 if (!is_array($value)) 2010 { 2011 $value = array($value); 2012 } 2013 2014 $execution = str_replace('{RESULT}', '$value', $execution); 2015 $execution = str_replace('{VALUE}', '$value', $execution); 2016 eval($execution); 2017 } 2018 } 2019 } 2020 else 2021 { 2022 $value = call_user_func_array($fields[2], $fields[1]); 2023 } 2024 2025 if (is_null($value)) 2026 { 2027 $value = ''; 2028 } 2029 2030 $insert_values[] = $db->_sql_validate_value($value); 2031 } 2032 else if (!empty($fields[2])) 2033 { 2034 if (is_array($fields[2])) 2035 { 2036 // Execute complex function/eval/typecast 2037 $value = ''; 2038 2039 foreach ($fields[2] as $type => $execution) 2040 { 2041 if (strpos($type, 'typecast') === 0) 2042 { 2043 $value = settype($value, $execution); 2044 } 2045 else if (strpos($type, 'function') === 0) 2046 { 2047 if (!is_array($value)) 2048 { 2049 $value = array($value); 2050 } 2051 2052 $value = call_user_func_array($execution, $value); 2053 } 2054 else if (strpos($type, 'execute') === 0) 2055 { 2056 if (!is_array($value)) 2057 { 2058 $value = array($value); 2059 } 2060 2061 $execution = str_replace('{RESULT}', '$value', $execution); 2062 $execution = str_replace('{VALUE}', '$value', $execution); 2063 eval($execution); 2064 } 2065 } 2066 } 2067 else 2068 { 2069 call_user_func_array($fields[2], $fields[1]); 2070 } 2071 } 2072 } 2073 } 2074 2075 return $sql_flag; 2076 } 2077 2078 /** 2079 * Own meta refresh function to be able to change the global time used 2080 */ 2081 function meta_refresh($url) 2082 { 2083 global $convert, $template; 2084 2085 if ($convert->options['refresh']) 2086 { 2087 // Because we should not rely on correct settings, we simply use the relative path here directly. 2088 $template->assign_vars(array( 2089 'S_REFRESH' => true, 2090 'META' => '<meta http-equiv="refresh" content="5; url=' . $url . '" />') 2091 ); 2092 } 2093 } 2094 2095 /** 2096 * The information below will be used to build the input fields presented to the user 2097 */ 2098 var $convert_options = array( 2099 'legend1' => 'SPECIFY_OPTIONS', 2100 'src_dbms' => array('lang' => 'DBMS', 'type' => 'select', 'options' => 'dbms_select(\'{VALUE}\', true)', 'explain' => false), 2101 'src_dbhost' => array('lang' => 'DB_HOST', 'type' => 'text:25:100', 'explain' => true), 2102 'src_dbport' => array('lang' => 'DB_PORT', 'type' => 'text:25:100', 'explain' => true), 2103 'src_dbname' => array('lang' => 'DB_NAME', 'type' => 'text:25:100', 'explain' => false), 2104 'src_dbuser' => array('lang' => 'DB_USERNAME', 'type' => 'text:25:100', 'explain' => false), 2105 'src_dbpasswd' => array('lang' => 'DB_PASSWORD', 'type' => 'password:25:100', 'explain' => false), 2106 'src_table_prefix' => array('lang' => 'TABLE_PREFIX', 'type' => 'text:25:100', 'explain' => false), 2107 //'src_url' => array('lang' => 'FORUM_ADDRESS', 'type' => 'text:50:100', 'explain' => true), 2108 'forum_path' => array('lang' => 'FORUM_PATH', 'type' => 'text:25:100', 'explain' => true), 2109 'refresh' => array('lang' => 'REFRESH_PAGE', 'type' => 'radio:yes_no', 'explain' => true), 2110 ); 2111 } 2112 2113 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Oct 2 15:03:47 2013 | Cross-referenced by PHPXref 0.7.1 |