1<?php
2/***************************************************************************
3*                             admin_db_utilities.php
4*                              -------------------
5*     begin                : Thu May 31, 2001
6*     copyright            : (C) 2001 The phpBB Group
7*     email                : support@phpbb.com
8*
9*     $Id: admin_db_utilities.php 5539 2006-02-10 20:35:40Z grahamje $
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/***************************************************************************
23*	We will attempt to create a file based backup of all of the data in the
24*	users phpBB database.  The resulting file should be able to be imported by
25*	the db_restore.php function, or by using the mysql command_line
26*
27*	Some functions are adapted from the upgrade_20.php script and others
28*	adapted from the unoficial phpMyAdmin 2.2.0.
29***************************************************************************/
30
31define('IN_PHPBB', 1);
32
33if( !empty($setmodules) )
34{
35	$filename = basename(__FILE__);
36	$module['General']['Backup_DB'] = $filename . "?perform=backup";
37
38	$file_uploads = (@phpversion() >= '4.0.0') ? @ini_get('file_uploads') : @get_cfg_var('file_uploads');
39
40	if( (empty($file_uploads) || $file_uploads != 0) && (strtolower($file_uploads) != 'off') && (@phpversion() != '4.0.4pl1') )
41	{
42		$module['General']['Restore_DB'] = $filename . "?perform=restore";
43	}
44
45	return;
46}
47
48//
49// Load default header
50//
51$no_page_header = TRUE;
52$phpbb_root_path = "./../";
53require($phpbb_root_path . 'extension.inc');
54require('./pagestart.' . $phpEx);
55include($phpbb_root_path . 'includes/sql_parse.'.$phpEx);
56
57//
58// Set VERBOSE to 1  for debugging info..
59//
60define("VERBOSE", 0);
61
62//
63// Increase maximum execution time, but don't complain about it if it isn't
64// allowed.
65//
66@set_time_limit(1200);
67
68// -----------------------
69// The following functions are adapted from phpMyAdmin and upgrade_20.php
70//
71function gzip_PrintFourChars($Val)
72{
73	for ($i = 0; $i < 4; $i ++)
74	{
75		$return .= chr($Val % 256);
76		$Val = floor($Val / 256);
77	}
78	return $return;
79}
80
81
82
83//
84// This function is used for grabbing the sequences for postgres...
85//
86function pg_get_sequences($crlf, $backup_type)
87{
88	global $db;
89
90	$get_seq_sql = "SELECT relname FROM pg_class WHERE NOT relname ~ 'pg_.*'
91		AND relkind = 'S' ORDER BY relname";
92
93	$seq = $db->sql_query($get_seq_sql);
94
95	if( !$num_seq = $db->sql_numrows($seq) )
96	{
97
98		$return_val = "# No Sequences Found $crlf";
99
100	}
101	else
102	{
103		$return_val = "# Sequences $crlf";
104		$i_seq = 0;
105
106		while($i_seq < $num_seq)
107		{
108			$row = $db->sql_fetchrow($seq);
109			$sequence = $row['relname'];
110
111			$get_props_sql = "SELECT * FROM $sequence";
112			$seq_props = $db->sql_query($get_props_sql);
113
114			if($db->sql_numrows($seq_props) > 0)
115			{
116				$row1 = $db->sql_fetchrow($seq_props);
117
118				if($backup_type == 'structure')
119				{
120					$row['last_value'] = 1;
121				}
122
123				$return_val .= "CREATE SEQUENCE $sequence start " . $row['last_value'] . ' increment ' . $row['increment_by'] . ' maxvalue ' . $row['max_value'] . ' minvalue ' . $row['min_value'] . ' cache ' . $row['cache_value'] . "; $crlf";
124
125			}  // End if numrows > 0
126
127			if(($row['last_value'] > 1) && ($backup_type != 'structure'))
128			{
129				$return_val .= "SELECT NEXTVALE('$sequence'); $crlf";
130				unset($row['last_value']);
131			}
132
133			$i_seq++;
134
135		} // End while..
136
137	} // End else...
138
139	return $returnval;
140
141} // End function...
142
143//
144// The following functions will return the "CREATE TABLE syntax for the
145// varying DBMS's
146//
147// This function returns, will return the table def's for postgres...
148//
149function get_table_def_postgresql($table, $crlf)
150{
151	global $drop, $db;
152
153	$schema_create = "";
154	//
155	// Get a listing of the fields, with their associated types, etc.
156	//
157
158	$field_query = "SELECT a.attnum, a.attname AS field, t.typname as type, a.attlen AS length, a.atttypmod as lengthvar, a.attnotnull as notnull
159		FROM pg_class c, pg_attribute a, pg_type t
160		WHERE c.relname = '$table'
161			AND a.attnum > 0
162			AND a.attrelid = c.oid
163			AND a.atttypid = t.oid
164		ORDER BY a.attnum";
165	$result = $db->sql_query($field_query);
166
167	if(!$result)
168	{
169		message_die(GENERAL_ERROR, "Failed in get_table_def (show fields)", "", __LINE__, __FILE__, $field_query);
170	} // end if..
171
172	if ($drop == 1)
173	{
174		$schema_create .= "DROP TABLE $table;$crlf";
175	} // end if
176
177	//
178	// Ok now we actually start building the SQL statements to restore the tables
179	//
180
181	$schema_create .= "CREATE TABLE $table($crlf";
182
183	while ($row = $db->sql_fetchrow($result))
184	{
185		//
186		// Get the data from the table
187		//
188		$sql_get_default = "SELECT d.adsrc AS rowdefault
189			FROM pg_attrdef d, pg_class c
190			WHERE (c.relname = '$table')
191				AND (c.oid = d.adrelid)
192				AND d.adnum = " . $row['attnum'];
193		$def_res = $db->sql_query($sql_get_default);
194
195		if (!$def_res)
196		{
197			unset($row['rowdefault']);
198		}
199		else
200		{
201			$row['rowdefault'] = @pg_result($def_res, 0, 'rowdefault');
202		}
203
204		if ($row['type'] == 'bpchar')
205		{
206			// Internally stored as bpchar, but isn't accepted in a CREATE TABLE statement.
207			$row['type'] = 'char';
208		}
209
210		$schema_create .= '	' . $row['field'] . ' ' . $row['type'];
211
212		if (eregi('char', $row['type']))
213		{
214			if ($row['lengthvar'] > 0)
215			{
216				$schema_create .= '(' . ($row['lengthvar'] -4) . ')';
217			}
218		}
219
220		if (eregi('numeric', $row['type']))
221		{
222			$schema_create .= '(';
223			$schema_create .= sprintf("%s,%s", (($row['lengthvar'] >> 16) & 0xffff), (($row['lengthvar'] - 4) & 0xffff));
224			$schema_create .= ')';
225		}
226
227		if (!empty($row['rowdefault']))
228		{
229			$schema_create .= ' DEFAULT ' . $row['rowdefault'];
230		}
231
232		if ($row['notnull'] == 't')
233		{
234			$schema_create .= ' NOT NULL';
235		}
236
237		$schema_create .= ",$crlf";
238
239	}
240	//
241	// Get the listing of primary keys.
242	//
243
244	$sql_pri_keys = "SELECT ic.relname AS index_name, bc.relname AS tab_name, ta.attname AS column_name, i.indisunique AS unique_key, i.indisprimary AS primary_key
245		FROM pg_class bc, pg_class ic, pg_index i, pg_attribute ta, pg_attribute ia
246		WHERE (bc.oid = i.indrelid)
247			AND (ic.oid = i.indexrelid)
248			AND (ia.attrelid = i.indexrelid)
249			AND	(ta.attrelid = bc.oid)
250			AND (bc.relname = '$table')
251			AND (ta.attrelid = i.indrelid)
252			AND (ta.attnum = i.indkey[ia.attnum-1])
253		ORDER BY index_name, tab_name, column_name ";
254	$result = $db->sql_query($sql_pri_keys);
255
256	if(!$result)
257	{
258		message_die(GENERAL_ERROR, "Failed in get_table_def (show fields)", "", __LINE__, __FILE__, $sql_pri_keys);
259	}
260
261	while ( $row = $db->sql_fetchrow($result))
262	{
263		if ($row['primary_key'] == 't')
264		{
265			if (!empty($primary_key))
266			{
267				$primary_key .= ', ';
268			}
269
270			$primary_key .= $row['column_name'];
271			$primary_key_name = $row['index_name'];
272
273		}
274		else
275		{
276			//
277			// We have to store this all this info because it is possible to have a multi-column key...
278			// we can loop through it again and build the statement
279			//
280			$index_rows[$row['index_name']]['table'] = $table;
281			$index_rows[$row['index_name']]['unique'] = ($row['unique_key'] == 't') ? ' UNIQUE ' : '';
282			$index_rows[$row['index_name']]['column_names'] .= $row['column_name'] . ', ';
283		}
284	}
285
286	if (!empty($index_rows))
287	{
288		while(list($idx_name, $props) = each($index_rows))
289		{
290			$props['column_names'] = ereg_replace(", $", "" , $props['column_names']);
291			$index_create .= 'CREATE ' . $props['unique'] . " INDEX $idx_name ON $table (" . $props['column_names'] . ");$crlf";
292		}
293	}
294
295	if (!empty($primary_key))
296	{
297		$schema_create .= "	CONSTRAINT $primary_key_name PRIMARY KEY ($primary_key),$crlf";
298	}
299
300	//
301	// Generate constraint clauses for CHECK constraints
302	//
303	$sql_checks = "SELECT rcname as index_name, rcsrc
304		FROM pg_relcheck, pg_class bc
305		WHERE rcrelid = bc.oid
306			AND bc.relname = '$table'
307			AND NOT EXISTS (
308				SELECT *
309					FROM pg_relcheck as c, pg_inherits as i
310					WHERE i.inhrelid = pg_relcheck.rcrelid
311						AND c.rcname = pg_relcheck.rcname
312						AND c.rcsrc = pg_relcheck.rcsrc
313						AND c.rcrelid = i.inhparent
314			)";
315	$result = $db->sql_query($sql_checks);
316
317	if (!$result)
318	{
319		message_die(GENERAL_ERROR, "Failed in get_table_def (show fields)", "", __LINE__, __FILE__, $sql_checks);
320	}
321
322	//
323	// Add the constraints to the sql file.
324	//
325	while ($row = $db->sql_fetchrow($result))
326	{
327		$schema_create .= '	CONSTRAINT ' . $row['index_name'] . ' CHECK ' . $row['rcsrc'] . ",$crlf";
328	}
329
330	$schema_create = ereg_replace(',' . $crlf . '$', '', $schema_create);
331	$index_create = ereg_replace(',' . $crlf . '$', '', $index_create);
332
333	$schema_create .= "$crlf);$crlf";
334
335	if (!empty($index_create))
336	{
337		$schema_create .= $index_create;
338	}
339
340	//
341	// Ok now we've built all the sql return it to the calling function.
342	//
343	return (stripslashes($schema_create));
344
345}
346
347//
348// This function returns the "CREATE TABLE" syntax for mysql dbms...
349//
350function get_table_def_mysql($table, $crlf)
351{
352	global $drop, $db;
353
354	$schema_create = "";
355	$field_query = "SHOW FIELDS FROM $table";
356	$key_query = "SHOW KEYS FROM $table";
357
358	//
359	// If the user has selected to drop existing tables when doing a restore.
360	// Then we add the statement to drop the tables....
361	//
362	if ($drop == 1)
363	{
364		$schema_create .= "DROP TABLE IF EXISTS $table;$crlf";
365	}
366
367	$schema_create .= "CREATE TABLE $table($crlf";
368
369	//
370	// Ok lets grab the fields...
371	//
372	$result = $db->sql_query($field_query);
373	if(!$result)
374	{
375		message_die(GENERAL_ERROR, "Failed in get_table_def (show fields)", "", __LINE__, __FILE__, $field_query);
376	}
377
378	while ($row = $db->sql_fetchrow($result))
379	{
380		$schema_create .= '	' . $row['Field'] . ' ' . $row['Type'];
381
382		if(!empty($row['Default']))
383		{
384			$schema_create .= ' DEFAULT \'' . $row['Default'] . '\'';
385		}
386
387		if($row['Null'] != "YES")
388		{
389			$schema_create .= ' NOT NULL';
390		}
391
392		if($row['Extra'] != "")
393		{
394			$schema_create .= ' ' . $row['Extra'];
395		}
396
397		$schema_create .= ",$crlf";
398	}
399	//
400	// Drop the last ',$crlf' off ;)
401	//
402	$schema_create = ereg_replace(',' . $crlf . '$', "", $schema_create);
403
404	//
405	// Get any Indexed fields from the database...
406	//
407	$result = $db->sql_query($key_query);
408	if(!$result)
409	{
410		message_die(GENERAL_ERROR, "FAILED IN get_table_def (show keys)", "", __LINE__, __FILE__, $key_query);
411	}
412
413	while($row = $db->sql_fetchrow($result))
414	{
415		$kname = $row['Key_name'];
416
417		if(($kname != 'PRIMARY') && ($row['Non_unique'] == 0))
418		{
419			$kname = "UNIQUE|$kname";
420		}
421
422		if(!is_array($index[$kname]))
423		{
424			$index[$kname] = array();
425		}
426
427		$index[$kname][] = $row['Column_name'];
428	}
429
430	while(list($x, $columns) = @each($index))
431	{
432		$schema_create .= ", $crlf";
433
434		if($x == 'PRIMARY')
435		{
436			$schema_create .= '	PRIMARY KEY (' . implode($columns, ', ') . ')';
437		}
438		elseif (substr($x,0,6) == 'UNIQUE')
439		{
440			$schema_create .= '	UNIQUE ' . substr($x,7) . ' (' . implode($columns, ', ') . ')';
441		}
442		else
443		{
444			$schema_create .= "	KEY $x (" . implode($columns, ', ') . ')';
445		}
446	}
447
448	$schema_create .= "$crlf);";
449
450	if(get_magic_quotes_runtime())
451	{
452		return(stripslashes($schema_create));
453	}
454	else
455	{
456		return($schema_create);
457	}
458
459} // End get_table_def_mysql
460
461
462//
463// This fuction will return a tables create definition to be used as an sql
464// statement.
465//
466//
467// The following functions Get the data from the tables and format it as a
468// series of INSERT statements, for each different DBMS...
469// After every row a custom callback function $handler gets called.
470// $handler must accept one parameter ($sql_insert);
471//
472//
473// Here is the function for postgres...
474//
475function get_table_content_postgresql($table, $handler)
476{
477	global $db;
478
479	//
480	// Grab all of the data from current table.
481	//
482
483	$result = $db->sql_query("SELECT * FROM $table");
484
485	if (!$result)
486	{
487		message_die(GENERAL_ERROR, "Failed in get_table_content (select *)", "", __LINE__, __FILE__, "SELECT * FROM $table");
488	}
489
490	$i_num_fields = $db->sql_numfields($result);
491
492	for ($i = 0; $i < $i_num_fields; $i++)
493	{
494		$aryType[] = $db->sql_fieldtype($i, $result);
495		$aryName[] = $db->sql_fieldname($i, $result);
496	}
497
498	$iRec = 0;
499
500	while($row = $db->sql_fetchrow($result))
501	{
502		$schema_vals = '';
503		$schema_fields = '';
504		$schema_insert = '';
505		//
506		// Build the SQL statement to recreate the data.
507		//
508		for($i = 0; $i < $i_num_fields; $i++)
509		{
510			$strVal = $row[$aryName[$i]];
511			if (eregi("char|text|bool", $aryType[$i]))
512			{
513				$strQuote = "'";
514				$strEmpty = "";
515				$strVal = addslashes($strVal);
516			}
517			elseif (eregi("date|timestamp", $aryType[$i]))
518			{
519				if (empty($strVal))
520				{
521					$strQuote = "";
522				}
523				else
524				{
525					$strQuote = "'";
526				}
527			}
528			else
529			{
530				$strQuote = "";
531				$strEmpty = "NULL";
532			}
533
534			if (empty($strVal) && $strVal != "0")
535			{
536				$strVal = $strEmpty;
537			}
538
539			$schema_vals .= " $strQuote$strVal$strQuote,";
540			$schema_fields .= " $aryName[$i],";
541
542		}
543
544		$schema_vals = ereg_replace(",$", "", $schema_vals);
545		$schema_vals = ereg_replace("^ ", "", $schema_vals);
546		$schema_fields = ereg_replace(",$", "", $schema_fields);
547		$schema_fields = ereg_replace("^ ", "", $schema_fields);
548
549		//
550		// Take the ordered fields and their associated data and build it
551		// into a valid sql statement to recreate that field in the data.
552		//
553		$schema_insert = "INSERT INTO $table ($schema_fields) VALUES($schema_vals);";
554
555		$handler(trim($schema_insert));
556	}
557
558	return(true);
559
560}// end function get_table_content_postgres...
561
562//
563// This function is for getting the data from a mysql table.
564//
565
566function get_table_content_mysql($table, $handler)
567{
568	global $db;
569
570	// Grab the data from the table.
571	if (!($result = $db->sql_query("SELECT * FROM $table")))
572	{
573		message_die(GENERAL_ERROR, "Failed in get_table_content (select *)", "", __LINE__, __FILE__, "SELECT * FROM $table");
574	}
575
576	// Loop through the resulting rows and build the sql statement.
577	if ($row = $db->sql_fetchrow($result))
578	{
579		$handler("\n#\n# Table Data for $table\n#\n");
580		$field_names = array();
581
582		// Grab the list of field names.
583		$num_fields = $db->sql_numfields($result);
584		$table_list = '(';
585		for ($j = 0; $j < $num_fields; $j++)
586		{
587			$field_names[$j] = $db->sql_fieldname($j, $result);
588			$table_list .= (($j > 0) ? ', ' : '') . $field_names[$j];
589
590		}
591		$table_list .= ')';
592
593		do
594		{
595			// Start building the SQL statement.
596			$schema_insert = "INSERT INTO $table $table_list VALUES(";
597
598			// Loop through the rows and fill in data for each column
599			for ($j = 0; $j < $num_fields; $j++)
600			{
601				$schema_insert .= ($j > 0) ? ', ' : '';
602
603				if(!isset($row[$field_names[$j]]))
604				{
605					//
606					// If there is no data for the column set it to null.
607					// There was a problem here with an extra space causing the
608					// sql file not to reimport if the last column was null in
609					// any table.  Should be fixed now :) JLH
610					//
611					$schema_insert .= 'NULL';
612				}
613				elseif ($row[$field_names[$j]] != '')
614				{
615					$schema_insert .= '\'' . addslashes($row[$field_names[$j]]) . '\'';
616				}
617				else
618				{
619					$schema_insert .= '\'\'';
620				}
621			}
622
623			$schema_insert .= ');';
624
625			// Go ahead and send the insert statement to the handler function.
626			$handler(trim($schema_insert));
627
628		}
629		while ($row = $db->sql_fetchrow($result));
630	}
631
632	return(true);
633}
634
635function output_table_content($content)
636{
637	global $tempfile;
638
639	//fwrite($tempfile, $content . "\n");
640	//$backup_sql .= $content . "\n";
641	echo $content ."\n";
642	return;
643}
644//
645// End Functions
646// -------------
647
648
649//
650// Begin program proper
651//
652if( isset($HTTP_GET_VARS['perform']) || isset($HTTP_POST_VARS['perform']) )
653{
654	$perform = (isset($HTTP_POST_VARS['perform'])) ? $HTTP_POST_VARS['perform'] : $HTTP_GET_VARS['perform'];
655
656	switch($perform)
657	{
658		case 'backup':
659
660			$error = false;
661			switch(SQL_LAYER)
662			{
663				case 'oracle':
664					$error = true;
665					break;
666				case 'db2':
667					$error = true;
668					break;
669				case 'msaccess':
670					$error = true;
671					break;
672				case 'mssql':
673				case 'mssql-odbc':
674					$error = true;
675					break;
676			}
677
678			if ($error)
679			{
680				include('./page_header_admin.'.$phpEx);
681
682				$template->set_filenames(array(
683					"body" => "admin/admin_message_body.tpl")
684				);
685
686				$template->assign_vars(array(
687					"MESSAGE_TITLE" => $lang['Information'],
688					"MESSAGE_TEXT" => $lang['Backups_not_supported'])
689				);
690
691				$template->pparse("body");
692
693				include('./page_footer_admin.'.$phpEx);
694			}
695
696			$tables = array('auth_access', 'banlist', 'categories', 'config', 'disallow', 'forums', 'forum_prune', 'groups', 'posts', 'posts_text', 'privmsgs', 'privmsgs_text', 'ranks', 'search_results', 'search_wordlist', 'search_wordmatch', 'sessions', 'smilies', 'themes', 'themes_name', 'topics', 'topics_watch', 'user_group', 'users', 'vote_desc', 'vote_results', 'vote_voters', 'words', 'confirm', 'sessions_keys');
697
698			$additional_tables = (isset($HTTP_POST_VARS['additional_tables'])) ? $HTTP_POST_VARS['additional_tables'] : ( (isset($HTTP_GET_VARS['additional_tables'])) ? $HTTP_GET_VARS['additional_tables'] : "" );
699
700			$backup_type = (isset($HTTP_POST_VARS['backup_type'])) ? $HTTP_POST_VARS['backup_type'] : ( (isset($HTTP_GET_VARS['backup_type'])) ? $HTTP_GET_VARS['backup_type'] : "" );
701
702			$gzipcompress = (!empty($HTTP_POST_VARS['gzipcompress'])) ? $HTTP_POST_VARS['gzipcompress'] : ( (!empty($HTTP_GET_VARS['gzipcompress'])) ? $HTTP_GET_VARS['gzipcompress'] : 0 );
703
704			$drop = (!empty($HTTP_POST_VARS['drop'])) ? intval($HTTP_POST_VARS['drop']) : ( (!empty($HTTP_GET_VARS['drop'])) ? intval($HTTP_GET_VARS['drop']) : 0 );
705
706			if(!empty($additional_tables))
707			{
708				if(ereg(",", $additional_tables))
709				{
710					$additional_tables = split(",", $additional_tables);
711
712					for($i = 0; $i < count($additional_tables); $i++)
713					{
714						$tables[] = trim($additional_tables[$i]);
715					}
716
717				}
718				else
719				{
720					$tables[] = trim($additional_tables);
721				}
722			}
723
724			if( !isset($HTTP_POST_VARS['backupstart']) && !isset($HTTP_GET_VARS['backupstart']))
725			{
726				include('./page_header_admin.'.$phpEx);
727
728				$template->set_filenames(array(
729					"body" => "admin/db_utils_backup_body.tpl")
730				);
731				$s_hidden_fields = "<input type=\"hidden\" name=\"perform\" value=\"backup\" /><input type=\"hidden\" name=\"drop\" value=\"1\" /><input type=\"hidden\" name=\"perform\" value=\"$perform\" />";
732
733				$template->assign_vars(array(
734					"L_DATABASE_BACKUP" => $lang['Database_Utilities'] . " : " . $lang['Backup'],
735					"L_BACKUP_EXPLAIN" => $lang['Backup_explain'],
736					"L_FULL_BACKUP" => $lang['Full_backup'],
737					"L_STRUCTURE_BACKUP" => $lang['Structure_backup'],
738					"L_DATA_BACKUP" => $lang['Data_backup'],
739					"L_ADDITIONAL_TABLES" => $lang['Additional_tables'],
740					"L_START_BACKUP" => $lang['Start_backup'],
741					"L_BACKUP_OPTIONS" => $lang['Backup_options'],
742					"L_GZIP_COMPRESS" => $lang['Gzip_compress'],
743					"L_NO" => $lang['No'],
744					"L_YES" => $lang['Yes'],
745
746					"S_HIDDEN_FIELDS" => $s_hidden_fields,
747					"S_DBUTILS_ACTION" => append_sid("admin_db_utilities.$phpEx"))
748				);
749				$template->pparse("body");
750
751				break;
752
753			}
754			else if( !isset($HTTP_POST_VARS['startdownload']) && !isset($HTTP_GET_VARS['startdownload']) )
755			{
756				if(is_array($additional_tables))
757				{
758					$additional_tables = implode(',', $additional_tables);
759				}
760				$template->set_filenames(array(
761					"body" => "admin/admin_message_body.tpl")
762				);
763
764				$template->assign_vars(array(
765					"META" => '<meta http-equiv="refresh" content="2;url=' . append_sid("admin_db_utilities.$phpEx?perform=backup&additional_tables=" . quotemeta($additional_tables) . "&backup_type=$backup_type&drop=1&amp;backupstart=1&gzipcompress=$gzipcompress&startdownload=1") . '">',
766
767					"MESSAGE_TITLE" => $lang['Database_Utilities'] . " : " . $lang['Backup'],
768					"MESSAGE_TEXT" => $lang['Backup_download'])
769				);
770
771				include('./page_header_admin.'.$phpEx);
772
773				$template->pparse("body");
774
775				include('./page_footer_admin.'.$phpEx);
776
777			}
778			header("Pragma: no-cache");
779			$do_gzip_compress = FALSE;
780			if( $gzipcompress )
781			{
782				$phpver = phpversion();
783
784				if($phpver >= "4.0")
785				{
786					if(extension_loaded("zlib"))
787					{
788						$do_gzip_compress = TRUE;
789					}
790				}
791			}
792			if($do_gzip_compress)
793			{
794				@ob_start();
795				@ob_implicit_flush(0);
796				header("Content-Type: application/x-gzip; name=\"phpbb_db_backup.sql.gz\"");
797				header("Content-disposition: attachment; filename=phpbb_db_backup.sql.gz");
798			}
799			else
800			{
801				header("Content-Type: text/x-delimtext; name=\"phpbb_db_backup.sql\"");
802				header("Content-disposition: attachment; filename=phpbb_db_backup.sql");
803			}
804
805			//
806			// Build the sql script file...
807			//
808			echo "#\n";
809			echo "# phpBB Backup Script\n";
810			echo "# Dump of tables for $dbname\n";
811			echo "#\n# DATE : " .  gmdate("d-m-Y H:i:s", time()) . " GMT\n";
812			echo "#\n";
813
814			if(SQL_LAYER == 'postgresql')
815			{
816				 echo "\n" . pg_get_sequences("\n", $backup_type);
817			}
818			for($i = 0; $i < count($tables); $i++)
819			{
820				$table_name = $tables[$i];
821
822				switch (SQL_LAYER)
823				{
824					case 'postgresql':
825						$table_def_function = "get_table_def_postgresql";
826						$table_content_function = "get_table_content_postgresql";
827						break;
828
829					case 'mysql':
830					case 'mysql4':
831						$table_def_function = "get_table_def_mysql";
832						$table_content_function = "get_table_content_mysql";
833						break;
834				}
835
836				if($backup_type != 'data')
837				{
838					echo "#\n# TABLE: " . $table_prefix . $table_name . "\n#\n";
839					echo $table_def_function($table_prefix . $table_name, "\n") . "\n";
840				}
841
842				if($backup_type != 'structure')
843				{
844					$table_content_function($table_prefix . $table_name, "output_table_content");
845				}
846			}
847
848			if($do_gzip_compress)
849			{
850				$Size = ob_get_length();
851				$Crc = crc32(ob_get_contents());
852				$contents = gzcompress(ob_get_contents());
853				ob_end_clean();
854				echo "\x1f\x8b\x08\x00\x00\x00\x00\x00".substr($contents, 0, strlen($contents) - 4).gzip_PrintFourChars($Crc).gzip_PrintFourChars($Size);
855			}
856			exit;
857
858			break;
859
860		case 'restore':
861			if(!isset($HTTP_POST_VARS['restore_start']))
862			{
863				//
864				// Define Template files...
865				//
866				include('./page_header_admin.'.$phpEx);
867
868				$template->set_filenames(array(
869					"body" => "admin/db_utils_restore_body.tpl")
870				);
871
872				$s_hidden_fields = "<input type=\"hidden\" name=\"perform\" value=\"restore\" /><input type=\"hidden\" name=\"perform\" value=\"$perform\" />";
873
874				$template->assign_vars(array(
875					"L_DATABASE_RESTORE" => $lang['Database_Utilities'] . " : " . $lang['Restore'],
876					"L_RESTORE_EXPLAIN" => $lang['Restore_explain'],
877					"L_SELECT_FILE" => $lang['Select_file'],
878					"L_START_RESTORE" => $lang['Start_Restore'],
879
880					"S_DBUTILS_ACTION" => append_sid("admin_db_utilities.$phpEx"),
881					"S_HIDDEN_FIELDS" => $s_hidden_fields)
882				);
883				$template->pparse("body");
884
885				break;
886
887			}
888			else
889			{
890				//
891				// Handle the file upload ....
892				// If no file was uploaded report an error...
893				//
894				$backup_file_name = (!empty($HTTP_POST_FILES['backup_file']['name'])) ? $HTTP_POST_FILES['backup_file']['name'] : "";
895				$backup_file_tmpname = ($HTTP_POST_FILES['backup_file']['tmp_name'] != "none") ? $HTTP_POST_FILES['backup_file']['tmp_name'] : "";
896				$backup_file_type = (!empty($HTTP_POST_FILES['backup_file']['type'])) ? $HTTP_POST_FILES['backup_file']['type'] : "";
897
898				if($backup_file_tmpname == "" || $backup_file_name == "")
899				{
900					message_die(GENERAL_MESSAGE, $lang['Restore_Error_no_file']);
901				}
902				//
903				// If I file was actually uploaded, check to make sure that we
904				// are actually passed the name of an uploaded file, and not
905				// a hackers attempt at getting us to process a local system
906				// file.
907				//
908				if( file_exists(phpbb_realpath($backup_file_tmpname)) )
909				{
910					if( preg_match("/^(text\/[a-zA-Z]+)|(application\/(x\-)?gzip(\-compressed)?)|(application\/octet-stream)$/is", $backup_file_type) )
911					{
912						if( preg_match("/\.gz$/is",$backup_file_name) )
913						{
914							$do_gzip_compress = FALSE;
915							$phpver = phpversion();
916							if($phpver >= "4.0")
917							{
918								if(extension_loaded("zlib"))
919								{
920									$do_gzip_compress = TRUE;
921								}
922							}
923
924							if($do_gzip_compress)
925							{
926								$gz_ptr = gzopen($backup_file_tmpname, 'rb');
927								$sql_query = "";
928								while( !gzeof($gz_ptr) )
929								{
930									$sql_query .= gzgets($gz_ptr, 100000);
931								}
932							}
933							else
934							{
935								message_die(GENERAL_ERROR, $lang['Restore_Error_decompress']);
936							}
937						}
938						else
939						{
940							$sql_query = fread(fopen($backup_file_tmpname, 'r'), filesize($backup_file_tmpname));
941						}
942						//
943						// Comment this line out to see if this fixes the stuff...
944						//
945						//$sql_query = stripslashes($sql_query);
946					}
947					else
948					{
949						message_die(GENERAL_ERROR, $lang['Restore_Error_filename'] ." $backup_file_type $backup_file_name");
950					}
951				}
952				else
953				{
954					message_die(GENERAL_ERROR, $lang['Restore_Error_uploading']);
955				}
956
957				if($sql_query != "")
958				{
959					// Strip out sql comments...
960					$sql_query = remove_remarks($sql_query);
961					$pieces = split_sql_file($sql_query, ";");
962
963					$sql_count = count($pieces);
964					for($i = 0; $i < $sql_count; $i++)
965					{
966						$sql = trim($pieces[$i]);
967
968						if(!empty($sql) and $sql[0] != "#")
969						{
970							if(VERBOSE == 1)
971							{
972								echo "Executing: $sql\n<br>";
973								flush();
974							}
975
976							$result = $db->sql_query($sql);
977
978							if(!$result && ( !(SQL_LAYER == 'postgresql' && eregi("drop table", $sql) ) ) )
979							{
980								message_die(GENERAL_ERROR, "Error importing backup file", "", __LINE__, __FILE__, $sql);
981							}
982						}
983					}
984				}
985
986				include('./page_header_admin.'.$phpEx);
987
988				$template->set_filenames(array(
989					"body" => "admin/admin_message_body.tpl")
990				);
991
992				$message = $lang['Restore_success'];
993
994				$template->assign_vars(array(
995					"MESSAGE_TITLE" => $lang['Database_Utilities'] . " : " . $lang['Restore'],
996					"MESSAGE_TEXT" => $message)
997				);
998
999				$template->pparse("body");
1000				break;
1001			}
1002			break;
1003	}
1004}
1005
1006include('./page_footer_admin.'.$phpEx);
1007
1008?>
1009