Register
phpBB.com Wiki · Home Projects Help

root / tags / release_2_0_1 / phpBB / upgrade.php

1
<?php
2
/***************************************************************************
3
*                                  upgrade.php
4
*                              -------------------
5
*     begin                : Wed Sep 05 2001
6
*     copyright            : (C) 2001 The phpBB Group
7
*     email                : support@phpbb.com
8
*
9
*     $Id: upgrade.php 2610 2002-05-20 13:52:12Z  $
10
*
11
****************************************************************************/
12
13
/***************************************************************************
14
 *
15
 *   This program is free software; you can redistribute it and/or modify
16
 *   it under the terms of the GNU General Public License as published by
17
 *   the Free Software Foundation; either version 2 of the License, or
18
 *   (at your option) any later version.
19
 *
20
 ***************************************************************************/
21
22
define('IN_PHPBB', true);
23
24
if ( !defined('INSTALLING') )
25
{
26
	error_reporting  (E_ERROR | E_WARNING | E_PARSE); // This will NOT report uninitialized variables
27
	set_magic_quotes_runtime(0); // Disable magic_quotes_runtime
28
29
	//
30
	// If we are being called from the install script then we don't need these
31
	// as they are already included.
32
	//
33
	include('extension.inc');
34
	include('config.'.$phpEx);
35
	include('includes/constants.'.$phpEx);
36
	include('includes/functions.'.$phpEx);
37
38
	if( defined("PHPBB_INSTALLED") )
39
	{
40
		$header_location = ( @preg_match('/Microsoft|WebSTAR|Xitami/', getenv('SERVER_SOFTWARE')) ) ? 'Refresh: 0; URL=' : 'Location: ';
41
		header($header_location . " index.$phpEx");
42
		exit;
43
	}
44
}
45
46
//
47
// Force the DB type to be MySQL
48
//
49
$dbms = 'mysql';
50
51
include('includes/db.'.$phpEx);
52
include('includes/bbcode.'.$phpEx);
53
include('includes/functions_search.'.$phpEx);
54
55
set_time_limit(0); // Unlimited execution time
56
57
$months = array(
58
	'Jan' => 1,
59
	'Feb' => 2,
60
	'Mar' => 3,
61
	'Apr' => 4,
62
	'May' => 5,
63
	'Jun' => 6,
64
	'Jul' => 7,
65
	'Aug' => 8,
66
	'Sep' => 9,
67
	'Sept' => 9,
68
	'Oct' => 10,
69
	'Nov' => 11,
70
	'Dec' => 12
71
);
72
73
// ---------------
74
// Begin functions
75
//
76
function common_header()
77
{
78
?>
79
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
80
<html>
81
<head>
82
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
83
<meta http-equiv="Content-Style-Type" content="text/css">
84
<style type="text/css">
85
<!--
86
/* Specifiy background images for selected styles
87
   This can't be done within the external style sheet as NS4 sees image paths relative to
88
   the page which called the style sheet (i.e. this page in the root phpBB directory)
89
   whereas all other browsers see image paths relative to the style sheet. Stupid NS again!
90
*/
91
TH			{ background-image: url(templates/subSilver/images/cellpic3.gif) }
92
TD.cat		{ background-image: url(templates/subSilver/images/cellpic1.gif) }
93
TD.rowpic	{ background-image: url(templates/subSilver/images/cellpic2.jpg); background-repeat: repeat-y }
94
td.icqback	{ background-image: url(templates/subSilver/images/icon_icq_add.gif); background-repeat: no-repeat }
95
TD.catHead,TD.catSides,TD.catLeft,TD.catRight,TD.catBottom { background-image: url(templates/subSilver/images/cellpic1.gif) }
96
97
font,th,td,p,body { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 11pt }
98
a:link,a:active,a:visited { font-family: Verdana, Arial, Helvetica, sans-serif; color : #006699; font-size:11pt }
99
a:hover		{ font-family: Verdana, Arial, Helvetica, sans-serif;  text-decoration: underline; color : #DD6900; font-size:11pt }
100
hr	{ height: 0px; border: solid #D1D7DC 0px; border-top-width: 1px;}
101
102
.maintitle,h1,h2	{font-weight: bold; font-size: 22px; font-family: "Trebuchet MS",Verdana, Arial, Helvetica, sans-serif; text-decoration: none; line-height : 120%; color : #000000;}
103
104
.ok {color:green}
105
106
/* Import the fancy styles for IE only (NS4.x doesn't use the @import function) */
107
@import url("templates/subSilver/formIE.css"); 
108
-->
109
</style>
110
</head>
111
<body bgcolor="#FFFFFF" text="#000000" link="#006699" vlink="#5584AA">
112
113
<table width="100%" border="0" cellspacing="0" cellpadding="10" align="center"> 
114
	<tr>
115
		<td><table width="100%" border="0" cellspacing="0" cellpadding="0">
116
			<tr>
117
				<td><img src="templates/subSilver/images/logo_phpBB.gif" border="0" alt="Forum Home" vspace="1" /></td>
118
				<td align="center" width="100%" valign="middle"><span class="maintitle">Upgrading to phpBB 2.0</span></td>
119
			</tr>
120
		</table></td>
121
	</tr>
122
</table>
123
124
<br clear="all" />
125
126
<?
127
	return;
128
}
129
130
function common_footer()
131
{
132
?>
133
134
<br clear="all" />
135
136
</body>
137
</html>
138
<?
139
	return;
140
}
141
142
function query($sql, $errormsg)
143
{
144
	global $db;
145
146
	if ( !($result = $db->sql_query($sql)) )
147
	{
148
		print "<br><font color=\"red\">\n";
149
		print "$errormsg<br>";
150
151
		$sql_error = $db->sql_error();
152
		print $sql_error['code'] .": ". $sql_error['message']. "<br>\n";
153
154
		print "<pre>$sql</pre>";
155
		print "</font>\n";
156
157
		return FALSE;
158
	}
159
	else
160
	{
161
		return $result;
162
	}
163
}
164
165
function smiley_replace($text = '')
166
{
167
	global $db;
168
169
	static $search, $replace;
170
171
	// Did we get the smiley info in a previous call?
172
	if ( !is_array($search) )
173
	{
174
		$sql = "SELECT code, smile_url
175
			FROM smiles";
176
		$result = query($sql, "Unable to get list of smilies from the DB");
177
178
		$smilies = $db->sql_fetchrowset($result);
179
		@usort($smilies, 'smiley_sort');
180
181
		$search = array();
182
		$replace = array();
183
		for($i = 0; $i < count($smilies); $i++)
184
		{
185
			$search[] = '/<IMG SRC=".*?\/' . phpbb_preg_quote($smilies[$i]['smile_url'], '/') .'">/i';
186
			$replace[] = $smilies[$i]['code'];
187
		}
188
	}
189
190
	return ( $text != '' ) ? preg_replace($search, $replace, $text) : '';
191
	
192
}
193
194
function get_schema()
195
{
196
	global $table_prefix;
197
198
	$schemafile = file('db/schemas/mysql_schema.sql');
199
	$tabledata = 0;
200
201
	for($i=0; $i < count($schemafile); $i++)
202
	{
203
		$line = $schemafile[$i];
204
205
		if ( preg_match('/^CREATE TABLE (\w+)/i', $line, $matches) )
206
		{
207
			// Start of a new table definition, set some variables and go to the next line.
208
			$tabledata = 1;
209
			// Replace the 'phpbb_' prefix by the user defined prefix.
210
			$table = str_replace('phpbb_', $table_prefix, $matches[1]);
211
			$table_def[$table] = "CREATE TABLE $table (\n";
212
			continue;
213
		}
214
215
		if ( preg_match('/^\);/', $line) )
216
		{
217
			// End of the table definition
218
			// After this we will skip everything until the next 'CREATE' line
219
			$tabledata = 0;
220
			$table_def[$table] .= ')'; // We don't need the closing semicolon
221
		}
222
223
		if ( $tabledata == 1 )
224
		{
225
			// We are inside a table definition, parse this line.
226
			// Add the current line to the complete table definition:
227
			$table_def[$table] .= $line;
228
			if ( preg_match('/^\s*(\w+)\s+(\w+)\(([\d,]+)\)(.*)$/', $line, $matches) )
229
			{
230
				// This is a column definition
231
				$field = $matches[1];
232
				$type = $matches[2];
233
				$size = $matches[3];
234
235
				preg_match('/DEFAULT (NULL|\'.*?\')[,\s](.*)$/i', $matches[4], $match);
236
				$default = $match[1];
237
238
				$notnull = ( preg_match('/NOT NULL/i', $matches[4]) ) ? 1 : 0;
239
				$auto_increment = ( preg_match('/auto_increment/i', $matches[4]) ) ? 1 : 0;
240
241
				$field_def[$table][$field] = array(
242
					'type' => $type,
243
					'size' => $size,
244
					'default' => $default,
245
					'notnull' => $notnull,
246
					'auto_increment' => $auto_increment
247
				);
248
			}
249
			
250
			if ( preg_match('/\s*PRIMARY\s+KEY\s*\((.*)\).*/', $line, $matches) )
251
			{
252
				// Primary key
253
				$key_def[$table]['PRIMARY'] = $matches[1];
254
			}
255
			else if ( preg_match('/\s*KEY\s+(\w+)\s*\((.*)\)/', $line, $matches) )
256
			{
257
				// Normal key
258
				$key_def[$table][$matches[1]] = $matches[2];
259
			}
260
			else if ( preg_match('/^\s*(\w+)\s*(.*?),?\s*$/', $line, $matches) )
261
			{
262
				// Column definition
263
				$create_def[$table][$matches[1]] = $matches[2];
264
			}
265
			else
266
			{
267
				// It's a bird! It's a plane! It's something we didn't expect ;(
268
			}
269
		}
270
	}
271
272
	$schema['field_def'] = $field_def;
273
	$schema['table_def'] = $table_def;
274
	$schema['create_def'] = $create_def;
275
	$schema['key_def'] = $key_def;
276
277
	return $schema;
278
}
279
280
function get_inserts()
281
{
282
	global $table_prefix;
283
284
	$insertfile = file('db/schemas/mysql_basic.sql');
285
286
	for($i = 0; $i < count($insertfile); $i++)
287
	{
288
		if ( preg_match('/(INSERT INTO (\w+)\s.*);/i', str_replace('phpbb_', $table_prefix, $insertfile[$i]), $matches) )
289
		{
290
			$returnvalue[$matches[2]][] = $matches[1];
291
		}
292
	}
293
294
	return $returnvalue;
295
}
296
297
function lock_tables($state, $tables= '')
298
{
299
	if ( $state == 1 )
300
	{
301
		if ( is_array($tables) )
302
		{
303
			$tables = join(' WRITE, ', $tables);
304
		}
305
306
		query("LOCK TABLES $tables WRITE", "Couldn't do: $sql");
307
	}
308
	else
309
	{
310
		query("UNLOCK TABLES", "Couldn't unlock all tables");
311
	}
312
}
313
314
function output_table_content($content)
315
{
316
	echo $content . "\n";
317
318
	return;
319
}
320
321
//
322
// Nathan's bbcode2 conversion routines
323
//
324
function bbdecode($message)
325
{
326
	// Undo [code]
327
	$code_start_html = '<!-- BBCode Start --><TABLE BORDER=0 ALIGN=CENTER WIDTH=85%><TR><TD><font size=-1>Code:</font><HR></TD></TR><TR><TD><FONT SIZE=-1><PRE>';
328
	$code_end_html = '</PRE></FONT></TD></TR><TR><TD><HR></TD></TR></TABLE><!-- BBCode End -->';
329
	$message = str_replace($code_start_html, '[code]', $message);
330
	$message = str_replace($code_end_html, '[/code]', $message);
331
332
	// Undo [quote]
333
	$quote_start_html = '<!-- BBCode Quote Start --><TABLE BORDER=0 ALIGN=CENTER WIDTH=85%><TR><TD><font size=-1>Quote:</font><HR></TD></TR><TR><TD><FONT SIZE=-1><BLOCKQUOTE>';
334
	$quote_end_html = '</BLOCKQUOTE></FONT></TD></TR><TR><TD><HR></TD></TR></TABLE><!-- BBCode Quote End -->';
335
	$message = str_replace($quote_start_html, '[quote]', $message);
336
	$message = str_replace($quote_end_html, '[/quote]', $message);
337
338
	// Undo [b] and [i]
339
	$message = preg_replace("#<!-- BBCode Start --><B>(.*?)</B><!-- BBCode End -->#s", "[b]\\1[/b]", $message);
340
	$message = preg_replace("#<!-- BBCode Start --><I>(.*?)</I><!-- BBCode End -->#s", "[i]\\1[/i]", $message);
341
342
	// Undo [url] (long form)
343
	$message = preg_replace("#<!-- BBCode u2 Start --><A HREF=\"([a-z]+?://)(.*?)\" TARGET=\"_blank\">(.*?)</A><!-- BBCode u2 End -->#s", "[url=\\1\\2]\\3[/url]", $message);
344
345
	// Undo [url] (short form)
346
	$message = preg_replace("#<!-- BBCode u1 Start --><A HREF=\"([a-z]+?://)(.*?)\" TARGET=\"_blank\">(.*?)</A><!-- BBCode u1 End -->#s", "[url]\\3[/url]", $message);
347
348
	// Undo [email]
349
	$message = preg_replace("#<!-- BBCode Start --><A HREF=\"mailto:(.*?)\">(.*?)</A><!-- BBCode End -->#s", "[email]\\1[/email]", $message);
350
351
	// Undo [img]
352
	$message = preg_replace("#<!-- BBCode Start --><IMG SRC=\"(.*?)\" BORDER=\"0\"><!-- BBCode End -->#s", "[img]\\1[/img]", $message);
353
354
	// Undo lists (unordered/ordered)
355
356
	// <li> tags:
357
	$message = str_replace('<!-- BBCode --><LI>', '[*]', $message);
358
359
	// [list] tags:
360
	$message = str_replace('<!-- BBCode ulist Start --><UL>', '[list]', $message);
361
362
	// [list=x] tags:
363
	$message = preg_replace('#<!-- BBCode olist Start --><OL TYPE=([A1])>#si', "[list=\\1]", $message);
364
365
	// [/list] tags:
366
	$message = str_replace('</UL><!-- BBCode ulist End -->', '[/list]', $message);
367
	$message = str_replace('</OL><!-- BBCode olist End -->', '[/list]', $message);
368
369
	return $message;
370
}
371
372
//
373
// Alternative for in_array() which is only available in PHP4
374
//
375
function inarray($needle, $haystack)
376
{ 
377
	for( $i = 0 ; $i < sizeof($haystack) ; $i++ )
378
	{ 
379
		if ( $haystack[$i] == $needle )
380
		{ 
381
			return true; 
382
		} 
383
	} 
384
385
	return false; 
386
}
387
388
function end_step($next)
389
{
390
	global $debug;
391
392
	print "<hr /><a href=\"$PHP_SELF?next=$next\">Next step: <b>$next</b></a><br /><br />\n";
393
}
394
//
395
// End functions
396
// -------------
397
398
399
//
400
// Start at the beginning if the user hasn't specified a specific starting point.
401
//
402
$next = ( isset($HTTP_GET_VARS['next']) ) ? $HTTP_GET_VARS['next'] : 'start';
403
404
// If debug is set we'll do all steps in one go.
405
$debug = 1;
406
407
// Parse the MySQL schema file into some arrays.
408
$schema = get_schema();
409
410
$table_def = $schema['table_def'];
411
$field_def = $schema['field_def'];
412
$key_def = $schema['key_def'];
413
$create_def = $schema['create_def'];
414
415
//
416
// Get mysql_basic data
417
//
418
$inserts = get_inserts();
419
420
//
421
// Get smiley data
422
//
423
smiley_replace();
424
425
common_header();
426
427
if ( !empty($next) )
428
{
429
	switch($next)
430
	{
431
		case 'start':
432
			end_step('initial_drops');
433
434
		case 'initial_drops':
435
			print " * Dropping sessions and themes tables :: ";
436
			flush();
437
438
			query("DROP TABLE sessions", "Couldn't drop table 'sessions'");
439
			query("DROP TABLE themes", "Couldn't drop table 'themes'");   
440
441
			print "<span class=\"ok\"><b>OK</b></span><br />\n";
442
443
			end_step('mod_old_tables');
444
445
		case 'mod_old_tables':
446
			$modtables = array(
447
				"banlist" => "banlist",
448
				"catagories" => "categories",
449
				"config" => "old_config",
450
				"forums" => "forums",
451
				"disallow" => "disallow",
452
				"posts" => "posts",
453
				"posts_text" => "posts_text",
454
				"priv_msgs" => "privmsgs",
455
				"ranks" => "ranks",
456
				"smiles" => "smilies",
457
				"topics" => "topics",
458
				"users" => "users",
459
				"words" => "words"
460
			);
461
462
			while( list($old, $new) = each($modtables) )
463
			{
464
				$result = query("SHOW INDEX FROM $old", "Couldn't get list of indices for table $old");
465
466
				while( $row = $db->sql_fetchrow($result) )
467
				{
468
					$index = $row['Key_name'];
469
					if ( $index != 'PRIMARY' )
470
					{
471
						query("ALTER TABLE $old DROP INDEX $index", "Couldn't DROP INDEX $old.$index");
472
					}
473
				}
474
475
				// Rename table
476
				$new = $table_prefix . $new;
477
478
				print " * Renaming '$old' to '$new' :: ";
479
				flush();
480
				query("ALTER TABLE $old RENAME $new", "Failed to rename $old to $new");
481
				print "<span class=\"ok\"><b>OK</b></span><br />\n";
482
				
483
			}
484
			end_step('create_tables');
485
			
486
		case 'create_tables':
487
			// Create array with tables in 'old' database
488
			$result = query('SHOW TABLES', "Couldn't get list of current tables");
489
490
			while( $table = $db->sql_fetchrow($result) )
491
			{
492
				$currenttables[] = $table[0];
493
			}
494
			
495
			// Check what tables we need to CREATE
496
			while( list($table, $definition) = each($table_def) )
497
			{
498
				if ( !inarray($table, $currenttables) )
499
				{
500
					print " * Creating $table :: ";
501
502
					query($definition, "Couldn't create table $table");
503
504
					print "<span class=\"ok\"><b>OK</b></span><br />\n";
505
				}
506
			}
507
			
508
			end_step('create_config');
509
			
510
		case 'create_config':
511
			print " * Inserting new values into new layout config table :: ";
512
513
			@reset($inserts);
514
			while( list($table, $inserts_table) = each($inserts) )
515
			{
516
				if ( $table == CONFIG_TABLE )
517
				{
518
					$per_pct = ceil( count($inserts_table) / 40 );
519
					$inc = 0;
520
521
					while( list($nr, $insert) = each($inserts_table) )
522
					{
523
						query($insert, "Couldn't insert value into config table");
524
525
						$inc++;
526
						if ( $inc == $per_pct )
527
						{
528
							print ".";
529
							flush();
530
							$inc = 0;
531
						}
532
					}
533
				}
534
			}
535
536
			print " <span class=\"ok\"><b>OK</b></span><br />\n";
537
538
			end_step('convert_config');
539
			
540
		case 'convert_config':
541
			print " * Converting configuration table :: ";
542
543
			$sql = "SELECT * 
544
				FROM $table_prefix" . "old_config";
545
			$result = query($sql, "Couldn't get info from old config table");
546
547
			$oldconfig = $db->sql_fetchrow($result);
548
549
			//
550
			// We don't need several original config types and two others
551
			// have changed name ... so take account of this.
552
			//
553
			$ignore_configs = array("selected", "admin_passwd", "override_themes", "allow_sig");
554
			$rename_configs = array(
555
				"email_from" => "board_email",
556
				"email_sig" => "board_email_sig"
557
			);
558
559
			while( list($name, $value) = each($oldconfig) )
560
			{
561
				if ( is_int($name) )
562
				{
563
					continue;
564
				}
565
566
				if ( !inarray($name, $ignore_configs) )
567
				{
568
					$name = ( !empty($rename_configs[$name]) ) ? $rename_configs[$name] : $name;
569
570
					$sql = "REPLACE INTO " . CONFIG_TABLE . " (config_name, config_value) 
571
						VALUES ('$name', '" . stripslashes($value) . "')";
572
					query($sql, "Couldn't update config table with values from old config table");
573
				}
574
			}
575
			
576
			$sql = "UPDATE " . CONFIG_TABLE . " 
577
				SET config_value = 'dutch' 
578
				WHERE config_name = 'default_lang' && config_value = 'nederlands'";
579
			query($sql, "Couldn't rename 'nederlands' to 'dutch' in config table");
580
			
581
			print "<span class=\"ok\"><b>OK</b></span><br />\n";
582
			end_step('convert_ips');
583
584
		case 'convert_ips':
585
			$names = array( 
586
				POSTS_TABLE => array(
587
					'id' => 'post_id',
588
					'field' => 'poster_ip'
589
				), 
590
				PRIVMSGS_TABLE => array( 
591
					'id' => 'msg_id', 
592
					'field' => 'poster_ip'
593
				), 
594
				BANLIST_TABLE => array( 
595
					'id' => 'ban_id', 
596
					'field' => 'ban_ip'
597
				)
598
			);
599
600
			lock_tables(1, array(POSTS_TABLE, PRIVMSGS_TABLE, BANLIST_TABLE));
601
602
			$batchsize = 2000;
603
			while( list($table, $data_array) = each($names) )
604
			{
605
				$sql = "SELECT MAX(" . $data_array['id'] . ") AS max_id 
606
					FROM $table";
607
				$result = query($sql, "Couldn't obtain ip data from $table (" . $fields . ")");
608
609
				$row = $db->sql_fetchrow($result);
610
611
				$maxid = $row['max_id'];
612
613
				for($i = 0; $i <= $maxid; $i += $batchsize)
614
				{
615
					$batchstart = $i;
616
					$batchend = $i + $batchsize;
617
618
					$field_id = $data_array['id'];
619
					$field = $data_array['field'];
620
621
					print " * Converting IP format '" . $field . "' / '$table' ( $batchstart to $batchend ) :: ";
622
					flush();
623
624
					$sql = "SELECT $field_id, $field 
625
						FROM $table 
626
						WHERE $field_id 
627
							BETWEEN $batchstart 
628
								AND $batchend";
629
					$result = query($sql, "Couldn't obtain ip data from $table (" . $fields . ")");
630
631
					$per_pct = ceil( $db->sql_numrows($result) / 40 );
632
					$inc = 0;
633
634
					while( $row = $db->sql_fetchrow($result) )
635
					{
636
						$sql = "UPDATE $table 
637
							SET $field = '" . encode_ip($row[$field]) . "' 
638
							WHERE $field_id = " . $row[$field_id];
639
						query($sql, "Couldn't convert IP format of $field in $table with $field_id of " . $rowset[$field_id]);
640
641
						$inc++;
642
						if ( $inc == $per_pct )
643
						{
644
							print ".";
645
							flush();
646
							$inc = 0;
647
						}
648
					}
649
650
					print " <span class=\"ok\"><b>OK</b></span><br />\n";
651
				}
652
			}
653
654
			lock_tables(0);
655
			end_step('convert_dates');
656
657
		case 'convert_dates':
658
			$names = array(
659
				POSTS_TABLE => array('post_time'),
660
				TOPICS_TABLE => array('topic_time'), 
661
				PRIVMSGS_TABLE => array('msg_time')
662
			);
663
664
			lock_tables(1, array(POSTS_TABLE, TOPICS_TABLE, PRIVMSGS_TABLE));
665
666
			while( list($table, $fields) = each($names) )
667
			{
668
				print " * Converting date format of $fields[$i] in $table :: ";
669
				flush();
670
671
				for($i = 0; $i < count($fields); $i++)
672
				{
673
					$sql = "UPDATE $table 
674
						SET " . $fields[$i] . " = UNIX_TIMESTAMP(" . $fields[$i] . ")";
675
					query($sql, "Couldn't convert date format of $table(" . $fields[$i] . ")");
676
				}
677
678
				print "<span class=\"ok\"><b>OK</b></span><br />\n";
679
			}
680
681
			lock_tables(0);
682
			end_step('fix_addslashes');
683
684
		case 'fix_addslashes':
685
			$slashfields[TOPICS_TABLE] = array('topic_title');
686
			$slashfields[FORUMS_TABLE] = array('forum_desc', 'forum_name');
687
			$slashfields[CATEGORIES_TABLE] = array('cat_title');
688
			$slashfields[WORDS_TABLE] = array('word', 'replacement');
689
			$slashfields[RANKS_TABLE] = array('rank_title');
690
			$slashfields[DISALLOW_TABLE] = array('disallow_username');
691
692
			//convert smilies?
693
			$slashes = array(
694
				"\\'" => "'",
695
				"\\\"" => "\"",
696
				"\\\\" => "\\");
697
			$slashes = array(
698
				"\\'" => "'",
699
				"\\\"" => "\"",
700
				"\\\\" => "\\");
701
702
			lock_tables(1, array(TOPICS_TABLE, FORUMS_TABLE, CATEGORIES_TABLE, WORDS_TABLE, RANKS_TABLE, DISALLOW_TABLE, SMILIES_TABLE));
703
704
			while( list($table, $fields) = each($slashfields) )
705
			{
706
				print " * Removing slashes from $table table :: ";
707
				flush();
708
709
				while( list($nr, $field) = each($fields) )
710
				{
711
					@reset($slashes);
712
					while( list($search, $replace) = each($slashes) )
713
					{
714
						$sql = "UPDATE $table 
715
							SET $field = REPLACE($field, '" . addslashes($search) . "', '" . addslashes($replace) . "')";
716
						query($sql, "Couldn't remove extraneous slashes from the old data.");
717
					}
718
				}
719
720
				print "<span class=\"ok\"><b>OK</b></span><br />\n";
721
			}
722
723
			lock_tables(0);
724
			end_step('remove_topics');
725
726
		case 'remove_topics':
727
			print " * Removing posts with no corresponding topics :: ";
728
			flush();
729
730
			$sql = "SELECT p.post_id 
731
				FROM " . POSTS_TABLE . " p 
732
				LEFT JOIN " . TOPICS_TABLE . " t ON p.topic_id = t.topic_id  
733
				WHERE t.topic_id IS NULL";
734
			$result = query($sql, "Couldn't obtain list of deleted topics");
735
			
736
			$post_total = $db->sql_numrows($result);
737
738
			if ( $post_total )
739
			{
740
				$post_id_ary = array();
741
				while( $row = $db->sql_fetchrow($result) )
742
				{
743
					$post_id_ary[] = $row['post_id'];
744
				}
745
746
				$sql = "DELETE FROM " . POSTS_TABLE . "  
747
					WHERE post_id IN (" . implode(", ", $post_id_ary) . ")";
748
				query($sql, "Couldn't update posts to remove deleted user poster_id values");
749
750
				$sql = "DELETE FROM " . POSTS_TEXT_TABLE . "
751
					WHERE post_id IN (" . implode(", ", $post_id_ary) . ")";
752
				query($sql, "Couldn't update posts to remove deleted user poster_id values");
753
			}
754
755
			echo "<span class=\"ok\"><b>OK</b></span> ( Removed $post_total posts )<br />\n";
756
			end_step('convert_users');
757
758
		case 'convert_users':
759
			//
760
			// Completely remove old soft-deleted users
761
			//
762
			$sql = "DELETE FROM " . USERS_TABLE . " 
763
				WHERE user_level = -1";
764
			query($sql, "Couldn't delete old soft-deleted users");
765
766
			$sql = "SELECT COUNT(*) AS total, MAX(user_id) AS maxid 
767
				FROM " . USERS_TABLE;
768
			$result = query($sql, "Couldn't get max post_id.");
769
770
			$maxid = $db->sql_fetchrow($result);
771
772
			$totalposts = $maxid['total'];
773
			$maxid = $maxid['maxid'];
774
775
			$sql = "ALTER TABLE " . USERS_TABLE . " 
776
				ADD user_sig_bbcode_uid CHAR(10),
777
				MODIFY user_sig text";
778
			query($sql, "Couldn't add user_sig_bbcode_uid field to users table");
779
780
			$super_mods = array();
781
			$first_admin = -2;
782
783
			$batchsize = 1000;
784
			for($i = -1; $i <= $maxid; $i += $batchsize)
785
			{
786
				$batchstart = $i;
787
				$batchend = $i + $batchsize;
788
				
789
				print " * Converting Users ( $batchstart to $batchend ) :: ";
790
				flush();
791
792
				$sql = "SELECT * 
793
					FROM " . USERS_TABLE . " 
794
					WHERE user_id 
795
						BETWEEN $batchstart 
796
							AND $batchend";
797
				$result = query($sql, "Couldn't get ". USERS_TABLE .".user_id $batchstart to $batchend");
798
799
				// Array with user fields that we want to check for invalid data (to few characters)
800
				$checklength = array(
801
					'user_occ',
802
					'user_website',
803
					'user_email',
804
					'user_from',
805
					'user_intrest',
806
					'user_aim',
807
					'user_yim',
808
					'user_msnm');
809
810
				lock_tables(1, array(USERS_TABLE, GROUPS_TABLE, USER_GROUP_TABLE, POSTS_TABLE));
811
812
				$per_pct = ceil( $db->sql_numrows($result) / 40 );
813
				$inc = 0;
814
815
				while( $row = $db->sql_fetchrow($result) )
816
				{
817
					$sql = "INSERT INTO " . GROUPS_TABLE . " (group_name, group_description, group_single_user) 
818
						VALUES ('" . addslashes($row['username']) . "', 'Personal User', 1)";
819
					query($sql, "Wasn't able to insert user ".$row['user_id']." into table ".GROUPS_TABLE);
820
821
					$group_id = $db->sql_nextid();
822
823
					if ( $group_id != 0 )
824
					{
825
						$sql = "INSERT INTO " . USER_GROUP_TABLE . " (group_id, user_id, user_pending)	
826
							VALUES ($group_id, " . $row['user_id'] . ", 0)";
827
						query($sql, "Wasn't able to insert user ".$row['user_id']." into table ".USER_GROUP_TABLE);
828
					}
829
					else
830
					{
831
						print "Couldn't get insert ID for " . GROUPS_TABLE . " table<br>\n";
832
					}
833
834
					if ( is_int($row['user_regdate']) )
835
					{
836
						// We already converted this post to the new style BBcode, skip this post.
837
						continue;
838
					}
839
840
					//
841
					// Nathan's bbcode2 conversion
842
					//
843
844
					// undo 1.2.x encoding..
845
					$row['user_sig'] = bbdecode(stripslashes($row['user_sig']));
846
					$row['user_sig'] = undo_make_clickable($row['user_sig']);
847
					$row['user_sig'] = str_replace("<BR>", "\n", $row['user_sig']);
848
849
					// make a uid
850
					$uid = make_bbcode_uid();
851
852
					// do 2.x first-pass encoding..
853
					$row['user_sig'] = bbencode_first_pass($row['user_sig'], $uid);
854
					$row['user_sig'] = addslashes($row['user_sig']);
855
856
					// Check for invalid info like '-' and '?' for a lot of fields
857
					@reset($checklength);
858
					while($field = each($checklength))
859
					{
860
						$row[$field[1]] = strlen($row[$field[1]]) < 3 ? '' : $row[$field[1]];
861
					}
862
863
					preg_match('/(.*?) (\d{1,2}), (\d{4})/', $row['user_regdate'], $parts);
864
					$row['user_regdate'] = gmmktime(0, 0, 0, $months[$parts[1]], $parts[2], $parts[3]);
865
866
					$website = $row['user_website'];
867
					if ( substr(strtolower($website), 0, 7) != "http://" )
868
					{
869
						$website = "http://" . $website;
870
					}
871
					if( strtolower($website) == 'http://' )
872
					{
873
						$website = '';
874
					}
875
					$row['user_website'] = addslashes($website);
876
					
877
					$row['user_icq'] = (ereg("^[0-9]+$", $row['user_icq'])) ? $row['user_icq'] : '';
878
					reset($checklength);
879
880
					while($field = each($checklength))
881
					{
882
						if ( strlen($row[$field[1]]) < 3 )
883
						{
884
							$row[$field[1]] = '';
885
						}
886
						$row[$field[1]] = addslashes($row[$field[1]]);
887
					}
888
					
889
					//
890
					// Is user a super moderator?
891
					//
892
					if( $row['user_level'] == 3 )
893
					{
894
						$super_mods[] = $row['user_id'];
895
					}
896
897
					$row['user_level'] = ( $row['user_level'] == 4 ) ? ADMIN : USER;
898
899
					//