<?php
/***************************************************************************
 *                             admin_easymod.php
 *                            -------------------
 *   begin                : Sunday Mar 31, 2002
 *   copyright            : (C) 2002-2004 by Nuttzy - Craig Nuttall, 2005 The phpBB Group
 *   email                : support@phpbb.com
 *
 *   $Id: admin_easymod.php.txt,v 1.23 2005/07/10 22:10:01 wgeric Exp $
 *
 *
 ***************************************************************************/

/***************************************************************************
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 ***************************************************************************/

define('IN_PHPBB', 1);

// entries to be displayed in the ACP index
if (!empty($setmodules))
{
	if ( !file_exists(@phpbb_realpath($phpbb_root_path . 'language/lang_' . $board_config['default_lang'] . '/lang_easymod.' . $phpEx)) ) 
	{ 
		include($phpbb_root_path . 'language/lang_english/lang_easymod.' . $phpEx); 
	} else 
	{ 
		include($phpbb_root_path . 'language/lang_' . $board_config['default_lang'] . '/lang_easymod.' . $phpEx); 
	} 

	$file = basename(__FILE__);
	$module['Modifications']['MOD_ainstall'] = "$file?mode=install";
	$module['Modifications']['MOD_settings'] = "$file?mode=settings";
	$module['Modifications']['MOD_history'] = "$file?mode=history";
	return;
}


//
// Let's set the root dir for phpBB
//
$phpbb_root_path = './../';
$script_path = 'admin/';
require($phpbb_root_path . 'extension.inc');

// if we are downloading the file (or backup), then we don't want to call pagestart.php
$mode = (isset($HTTP_POST_VARS['mode'])) ? htmlspecialchars($HTTP_POST_VARS['mode']) : '';
$mode = (isset($HTTP_GET_VARS['mode'])) ? htmlspecialchars($HTTP_GET_VARS['mode']) : $mode;
if (($mode == 'download_file') || ($mode == 'download_backup') ||
	($mode == 'display_file') || ($mode == 'display_backup'))
{
	include($phpbb_root_path . 'config.'.$phpEx);
	include($phpbb_root_path . 'includes/constants.'.$phpEx);
	include($phpbb_root_path . 'includes/functions.'.$phpEx);
	include($phpbb_root_path . 'includes/functions_admin.'.$phpEx);
	include($phpbb_root_path . 'includes/db.'.$phpEx);
	include($phpbb_root_path . 'language/lang_english/lang_easymod.' . $phpEx);
}

// normal operation
else
{
	require('./pagestart.' . $phpEx);

	// load the EM functions; make sure we are using the proper lang; if this is a download or display, then we won't
	//   know the lang, so default to english; there is probably a better way to do this though
	if ($board_config['default_lang'] == '')
	{
		include($phpbb_root_path . 'language/lang_english/lang_easymod.' . $phpEx);
	}
	else
	{
		include($phpbb_root_path . 'language/lang_' . $board_config['default_lang'] . '/lang_easymod.' . $phpEx);
	}
}
$mode = '' ;

// make sure em_functions is where it needs to be or else the user will get a blank screen :roll:
if (!file_exists($phpbb_root_path . 'admin/em_includes/em_functions.' . $phpEx))
{
	die('CRITICAL ERROR: could not find [' . $phpbb_root_path . 'admin/em_includes/em_functions.' . $phpEx . '].  Aborting.') ;
}

include($phpbb_root_path . 'admin/em_includes/em_ftp.' . $phpEx) ;
include($phpbb_root_path . 'admin/em_includes/em_modio.' . $phpEx) ;
include($phpbb_root_path . 'admin/em_includes/em_functions.' . $phpEx) ;



///
///
define('EASYMOD_VER', 'beta1 (0.2.1a)') ;
define('FAQ_LINK', '<a href="http://area51.phpbb.com/phpBB/viewtopic.php?t=12141" target="_blank">') ;
define('REPORT_LINK', '<a href="http://area51.phpbb.com/phpBB/viewtopic.php?t=12143" target="_blank">') ;
///
///


// write command info to the screen (add to template)
function display_line( $command, $body)
{
	global $template, $theme ;

	// print the command
	$template->assign_block_vars('processed', array(
		'ROW_CLASS' => $theme['td_class2'],
		'LINE' => '<b>' . htmlspecialchars($command['command']) . '</b> &nbsp;&nbsp;&nbsp;line #' . $command['line'] . "\n")
	);


	// print the command body
	$line = '' ;
	for ($i=0; $i<count($body); $i++)
	{
//		$line .= htmlspecialchars($body[$i]) . "<br />\n" ;
		$line .= htmlspecialchars($body[$i]) ;
	}

	// make sure there is a body to print!
	if (count($body) > 0)
	{
		$template->assign_block_vars('processed', array(
			'ROW_CLASS' => $theme['td_class1'],
//			'LINE' => $line)
			'LINE' => "\n<pre>$line</pre>\n")
		);
	}
}


// write command info to the screen (add to template)
function display_unprocessed_line( $command, $body)
{
	global $template, $theme ;

	// print the command
	$template->assign_block_vars('unprocessed', array(
		'ROW_CLASS' => $theme['td_class2'],
		'LINE' => '<b>' . htmlspecialchars($command['command']) . '</b> &nbsp;&nbsp;&nbsp;line #' . $command['line'] . "\n")
	);

	// print the command body
	$line = '' ;	
	for ($i=0; $i<count($body); $i++)
	{
//		$line .= htmlspecialchars($body[$i]) . "<br />\n" ;
		$line .= htmlspecialchars($body[$i]) ;
	}
	$template->assign_block_vars('unprocessed', array(
		'ROW_CLASS' => $theme['td_class1'],
//		'LINE' => $line)
		'LINE' => "\n<pre>$line</pre>\n")
	);
}


// display error message info; it will look like a message_die box
function display_error( $message)
{
	global $template, $mode, $lang ;

	// template is not defined if we are displaying/downloading the file so echo the error
	if (($mode == 'display_file') || ($mode == 'download_file'))
	{
		echo ( $mode == 'display_file' ) ? '</pre>' . $message . ' :: ' . FAQ_LINK . $lang['EM_FAQ'] . '</a> :: ' . REPORT_LINK . $lang['EM_report'] . '</a><br /><br />' : '';
		return ;
	}
		
	$template->assign_block_vars('error', array(
		'L_TITLE' => $lang['EM_error_detail'],
		'ERROR_MESSAGE' => $message . ' :: ' . FAQ_LINK . $lang['EM_FAQ'] . '</a> :: ' . REPORT_LINK . $lang['EM_report'] . '</a>')
	) ;
}


// look in the DB to see if we already processed this MOD
function is_unprocessed( $db, $mod_title, $mod_version, $phpbb_version)
{
	$sql = "SELECT *
		FROM " . EASYMOD_TABLE . " 
		WHERE mod_title = '" . substr( $mod_title, 0, 255) . "' 
			AND mod_version = '" . substr( $mod_version, 0, 15) . "' 
		ORDER BY mod_id DESC" ;
	if ( !($result = $db->sql_query($sql)) )
	{
		return true ;
	}

	$row = $db->sql_fetchrow($result) ;
	if ( $row['mod_phpBB_version'] == $phpbb_version)
	{
		return false ;
	}
	else
	{
		return true ;
	}
}


// parse the MOD file and get properties about it (make sure it really is a MOD too)
function get_mod_properties( $file, &$mod_title, &$mod_author_handle, &$mod_author_email, &$mod_author_name, &$mod_author_url, &$mod_description, &$mod_version, &$compliant)
{
	// used to add a little tolerance on the Author line
	$faux_author = false ;
	$legit_author = false ;

	// open the file and grab the first line
	$f_mod_script = fopen ( $file, 'r');
	if (!$f_mod_script)
	{
		return false ;
	}
	$buffer = fgets($f_mod_script, 1024);


	// see if it is EMC right away; first line starts with ## on it and contains "easymod"
	$compliant = false ;
	if ((stristr( $buffer, 'easymod')) && (substr($buffer,0,2) == '##'))
	{
		$compliant = true ;
	}

	// loop through file and try to get MOD info; only look at lines starting with ##
	$getting_desc = 0 ;
	$first_line = true ;
	while ( (!feof($f_mod_script)) && ( substr($buffer,0,2) == '##'))
	{
		// we've already gotten the first line but still need to process it
		$buffer = ($first_line) ? $buffer : fgets($f_mod_script, 1024);
		$first_line = false ;

		// check for mod title; allow just "title" if we don't have a title yet
		if ((stristr( $buffer, 'MOD Title:')) || (($mod_title == '') && (stristr( $buffer, 'Title:'))))
		{
			$mod_title = htmlspecialchars( trim(substr( $buffer, strpos( $buffer, ":")+1))) ;
			$getting_desc = 0 ;
		}

		// check for author info
		else if ( (stristr( $buffer, 'MOD Author:')) || (stristr( $buffer, 'Author:') ))
		{
			// if we've already gotten a legit MOD Author, then don't go looking for another
			if ($legit_author)
			{
				continue ;
			}

			// they are using just Author instead of MOD author and we've already gotten a "faux" one; get outta here
			else if ((!stristr( $buffer, 'MOD Author:')) && ($faux_author))
			{
				continue ;
			}

			// again using some variant of "Author" but allow it; we'll only accept the first non-MOD Author entry
			else if ((!stristr( $buffer, 'MOD Author:')) && (!$faux_author))
			{
				$faux_author = true ;
			}

			// they are using the proper "MOD Author" label
			else
			{
				$legit_author = true ;
			}

			// init our vars
			$mod_author_handle = '' ;
			$mod_author_email = '' ;
			$mod_author_name = '' ;
			$mod_author_url = '' ;

			// trim off the label
			$orig = trim(substr( $buffer, strpos( $buffer, ":")+1)) ;

			// get real name + email address
			if (strstr($orig, '<'))
			{
				$left = strpos( $orig, "<")+1 ;
				$len = strpos( $orig, ">") - $left ;
				$mod_author_email = htmlspecialchars( trim(substr( $orig, $left, $len))) ;
				$mod_author_handle = htmlspecialchars( trim(substr( $orig, 0, $left-1))) ;
				$mod_author_url = htmlspecialchars( trim(substr( $orig, $left + $len +1))) ;
			}

			// get handle + web site
			if (strstr($orig, '('))
			{
				$left = strpos( $orig, "(")+1 ;
				$len = strpos( $orig, ")") - $left ;
				$mod_author_name = htmlspecialchars( trim(substr( $orig, $left, $len))) ;
				$mod_author_url = htmlspecialchars( trim(substr( $orig, $left + $len +1))) ;
				if ( $mod_author_handle == '')
				{
					$mod_author_handle = htmlspecialchars( trim(substr( $orig, 0, $left-1))) ;
				}
			}

			// could't get proper format so make it all the handle field
			else if ($mod_author_handle == '')
			{
				$mod_author_handle = htmlspecialchars( $orig) ;
			}

			// see if we can debork a borked url; if there is "http:" but also spaces, take the chunck without spaces
			if ((strstr($mod_author_url, ' ')) && (strstr($mod_author_url, 'http:')))
			{
				$url_array = explode(' ', $mod_author_url) ;
				$pos_name = '' ;

				// looking for the element that has no http without any spaces; that will be our URL
				for ($url=0; $url<count($url_array); $url++)
				{
					// found our proper url
					if (strstr($url_array[$url], 'http:'))
					{
						$mod_author_url = htmlspecialchars( $url_array[$url]) ;

						// if we didn't get a proper real name, then use whatever was in front of the url
						if ($mod_author_name == '')
						{
							$mod_author_name = htmlspecialchars( $pos_name) ;
						}
						break ;
					}

					// didn't find a url so build a potentially new value for real name
					else
					{
						$pos_name .= ($pos_name != '') ? ' ' . $url_array[$url] : $url_array[$url] ;
					}
				}
			}

			// if we don't have an author handle, then see what we can do
			if (($mod_author_handle == '') && ($mod_author_name != ''))
			{
				$mod_author_handle = htmlspecialchars( $mod_author_name) ;
			}
			else if (($mod_author_handle == '') && ($mod_author_email != ''))
			{
				$mod_author_handle = htmlspecialchars( $mod_author_email) ;
			}


			$getting_desc = 0 ;
		}

		// get the description (up to 3 lines); allow just "description" if we don't have a description yet
		else if ((stristr( $buffer, 'MOD Description:')) || (($mod_description == '') && (stristr( $buffer, 'Description:'))))
		{
			$mod_description = htmlspecialchars( trim(substr( $buffer, strpos( $buffer, ":")+1))) ;
			$getting_desc = 1 ;
		}

		// get the version; allow just "version" if we don't have a version yet
		else if ((stristr( $buffer, 'MOD Version:')) || (($mod_description == '') && (stristr( $buffer, 'Version:'))))
		{
			$mod_version = htmlspecialchars( trim(substr( $buffer, strpos( $buffer, ":")+1))) ;
			$getting_desc = 0 ;
		}

		// if we are getting the description, chop carriage returns and make one long line; only allow 3 lines
		else if ($getting_desc > 0)
		{
			$new_line = ' ' . trim( substr( $buffer, 2)) ;
			$mod_description .= htmlspecialchars( $new_line) ;
			$getting_desc = ($getting_desc >= 3) ? 0 : $getting_desc + 1 ;
		}
	}
	fclose( $f_mod_script) ;

	// if we have a title and a handle, then that is good enough to call this a MOD (fixed in 0.0.10; used to be name)
	if (($mod_title != '') && ($mod_author_handle != ''))
	{
		return true ;
	}
	else
	{
		return false ;
	}
}


// strip the body array of a command down to the minimum
function strip_whitespace( $body, $single_line=true)
{
	$new_array = array() ;
	$have_line = false ;

	// rebuild the array and drop the whitespace lines
	for ($i=0; $i<count($body); $i++)
	{
		// if we already have line and are only looking for one, then skip this line
		if (($have_line) && ($single_line))
		{
			// do nothing
		}

		// if the line has something on it, then we'll want to store it
		else if (strlen(trim($body[$i])) > 0)
		{
			$new_array[] = $body[$i] ;
			$have_line = true ;
		}

		// empty line so get this out of our body array
		else
		{
			// do nothing
		}
	}

	// the white space is now gone, return the result
	return $new_array ;
}


// if we encounter an error will modifiying a file then print errors, clean up, and terminate processing if need be
function handle_error( $result, &$file_list, $line, $close_files=false, $find_array=array())
{
	global $lang ;

	// if we are halting the processing then finish writing all files, just to be neat i guess
	if (($close_files) && ($result == FIND_FAIL_CRITICAL))
	{
		// if we failed on an IN-LINE command be sure to write the find_array
		if (count($find_array) > 0)
		{
			write_find_array( $find_array, $file_list) ;
		}

		// don't worry if file repro fails since we are halting anyway
		complete_file_reproduction( $file_list) ;
	}


	// handle warnings and critical errors
	$failed_close = false ;
	if ( $result != OPEN_OK)
	{
		// loop through all files; print errors; and remove file from our file array
		$new_list = array() ;
		for ($err=0; $err<count($file_list); $err++)
		{
			// if there was an error associated with this file, then get down to biz
			if ($file_list[$err]->err_msg != '')
			{
				// if this file through a warning and we aren't halting then close just this file
				if (($close_files) && ($result != FIND_FAIL_CRITICAL))
				{
					$temp_array = array() ;
					$temp_array[] = $file_list[$err] ;

					// if we failed on an IN-LINE command be sure to write the find_array
					if (count($find_array) > 0)
					{
						write_find_array( $find_array, $temp_array) ;
					}

					// clean up this file
					if (!complete_file_reproduction( $temp_array))
					{
						// repro failed meaning close failed meaning we now have a show stopping error!
						$failed_close = true ;
					}
				}

				// show the error(s); do this last in case file repro throw another error
				display_error( $file_list[$err]->err_msg . "<br />\n" . $lang['EM_line_num'] . $line) ;
			}

			// no error so this file can stay in our file list; ones with errors are removed
			else
			{
				$new_list[] = $file_list[$err] ;
			}
		}
		$file_list = $new_list ;

		// if we have a critical error, then we have to halt the processing NOW!
		if ( ($result == OPEN_FAIL_CRITICAL) || ($failed_close))
		{
			return true ;
		}
	}

	// no show stopping errors
	return false ;
}


// look in the config table to get the EM settings
function get_em_settings( $filename, $path, $em_pass, $preview = false)
{
	global $db, $phpbb_root_path ;

	//
	// grab the EM settings
	//
	$sql = "SELECT *
		FROM " . CONFIG_TABLE ;
	if( !$result = $db->sql_query($sql) )
	{
		message_die(GENERAL_ERROR, $lang['EM_err_config_info'], '', __LINE__, __FILE__, $sql);
	}

	// loop through all the settings and assign the EM ones as appropriate
	while ( $row = $db->sql_fetchrow($result))
	{
		if ( $row['config_name'] == 'EM_read')
		{
			$read = $row['config_value'] ;
		}
		else if ( $row['config_name'] == 'EM_write')
		{
			$write = $row['config_value'] ;
		}
		else if ( $row['config_name'] == 'EM_move')
		{
			$move = $row['config_value'] ;
		}
		else if ( $row['config_name'] == 'EM_ftp_dir')
		{
			$ftp_dir = $row['config_value'] ;
		}
		else if ( $row['config_name'] == 'EM_ftp_user')
		{
			$ftp_user = $row['config_value'] ;
		}
		else if ( $row['config_name'] == 'EM_ftp_pass')
		{
			$ftp_pass = $row['config_value'] ;
		}
		else if ( $row['config_name'] == 'EM_ftp_host')
		{
			$ftp_host = $row['config_value'] ;
		}
		else if ( $row['config_name'] == 'EM_ftp_port')
		{
			$ftp_port = $row['config_value'] ;
		}
		else if ( $row['config_name'] == 'EM_ftp_type')
		{
			$ftp_type = $row['config_value'] ;
		}
		else if ( $row['config_name'] == 'EM_ftp_cache')
		{
			$ftp_cache = $row['config_value'] ;
		}
	}

	// decrypt the FTP password
	include($phpbb_root_path . 'admin/em_includes/em_cipher.php') ;
	$cipher = new Cipher_BlockMode_cbc();
	$cipher->blowfish->setKey( $em_pass);
	$ftp_pass = $cipher->decrypt($ftp_pass) ;


	// if we are in preview mode, then no matter what we will set to display to screen
	if ($preview)
	{
		$write = 'screen' ;
		$move = 'ftpm' ;
	}

	// easiest thing to do is return a mod_io object
	return new mod_io( $filename, $path, $read, $write, $move, $ftp_user, $ftp_pass, $ftp_dir, $ftp_host, $ftp_port, $ftp_type, $ftp_cache) ;
}


// look in the config table to get the EM Version
function get_em_version()
{
	global $db ;

	// look in db
	$sql = "SELECT *
		FROM " . CONFIG_TABLE . " 
		WHERE config_name = 'EM_version'";
	if( !$result = $db->sql_query($sql) )
	{
		message_die(GENERAL_ERROR, $lang['EM_err_config_info'], '', __LINE__, __FILE__, $sql);
	}

	// loop through all the settings and assign the EM ones as appropriate
	if ( $row = $db->sql_fetchrow($result))
	{
		return $row['config_value'] ;
	}

	return '';
}








// handle the mode; this is the key to securing EM
$mode = '' ;
$preview = false ;
$get_password = false ;

// if mode is passed in a GET, be very suspicious!  we don't like it when the user sends us GET vars so make sure they
//   are supposed to be
if (isset($HTTP_GET_VARS['mode']))
{
	// be very selective about what we allow from GET;  the allowed types will also require password auth
	$mode = (isset($HTTP_GET_VARS['mode'])) ? htmlspecialchars($HTTP_GET_VARS['mode']) : '';
	if (($mode == 'install') || ($mode == 'settings') || ($mode == 'history'))
	{
		$get_password = true ;
	}

	// if we are displaying the file to screen, then get the pw to confirm against
	else if (($mode == 'display_file') || ($mode == 'display_backup'))
	{
		$password = (isset($HTTP_GET_VARS['password'])) ? htmlspecialchars($HTTP_GET_VARS['password']) : '' ;
		$install_file = ( !empty($HTTP_GET_VARS['install_file']) ) ? htmlspecialchars(trim($HTTP_GET_VARS['install_file'])) : '';
		$install_path = ( !empty($HTTP_GET_VARS['install_path']) ) ? htmlspecialchars(trim($HTTP_GET_VARS['install_path'])) : '';

		// important! we are writing the file output to screen so the PRE tag will format it nicely for us
		echo '<style type="text/css"><!-- .preview {color:red; margin: 0px; padding: 0px} --></style>' . "\n" ;
		echo "<PRE>\n" ;
	}

	// unexpected mode, someone is trying to circumvent the password!  we'll fix 'em ;-)
	else
	{
		// they'll now end up at the password screen instead of whatever they were trying
		$mode = 'install' ;
		$get_password = true ;
	}
}

// get post variables; we trust post variables ;-)
else
{
	$mode = ( !empty($HTTP_POST_VARS['mode']) ) ? htmlspecialchars(trim($HTTP_POST_VARS['mode'])) : '';

	$password = ( !empty($HTTP_POST_VARS['password']) ) ? htmlspecialchars($HTTP_POST_VARS['password']) : '' ; 
	$install_file = ( !empty($HTTP_POST_VARS['install_file']) ) ? trim($HTTP_POST_VARS['install_file']) : '';
	$install_path = ( !empty($HTTP_POST_VARS['install_path']) ) ? trim($HTTP_POST_VARS['install_path']) : '';
	$SQL_lines = ( isset($HTTP_POST_VARS['SQL_lines']) ) ? intval($HTTP_POST_VARS['SQL_lines']) : 0;

	// 0.0.11 preview mode
	$preview = (isset($HTTP_POST_VARS['preview'])) ? true : false ;
}


// make sure mode is valid; if not then set to default mode and get pw
if (($mode != 'history') && ($mode != 'settings') && ($mode != 'install') &&
	($mode != 'display_file') && ($mode != 'download_file') &&
	($mode != 'display_backup') && ($mode != 'download_backup') &&
	($mode != 'SQL_view') && ($mode != 'SQL_execute') &&
	($mode != 'update') && ($mode != 'process') && ($mode != 'post_process') && ($mode != 'diy_process') &&
	($mode != 'history_details') && ($mode != 'del_files') && ($mode != 'del_record') && ($mode != 'restore_backups') && ($mode != 'install_lang') && ($mode != 'install_themes') && ($mode != 'uninstall'))
{
	$mode = 'install' ;
	$get_password = true ;
}



//
// if they are trying to get to the first page, check the pw; after that assume they are validated
//
$pass_message = '' ;
if ((($mode == 'install') || ($mode == 'settings') || ($mode == 'history') ||
	($mode == 'display_file') || ($mode == 'display_backup')) && (!$get_password))
{
	// compare passwords and send them back to the password screen if they fail
	if ( md5($password) != get_em_pw())
	{
		$get_password = true ;
		$pass_message = '<b>' . $lang['EM_err_pw_fail'] . '</b><br />' ;
	}
}



//
// if they are downloading or displaying a file or backup then we need to get setup
//

// downloading a file or a backup from the completed processing screen
if (($mode == 'download_file') || ($mode == 'download_backup'))
{
	// they clicked a form button; we need to figure out which one so we know what file they are looking for
	$num_files = ( isset($HTTP_POST_VARS['mod_count'])) ? intval($HTTP_POST_VARS['mod_count']) : 0 ;

	// loop through all the submit buttons to see which one was pressed
///////////////////////////////////
///////////////////////////////////
/////////////////////////////////// possible error.... should start at 0? was a 1 before
///////////////////////////////////
///////////////////////////////////
	for ( $i=0; $i<=$num_files; $i++)
	{
		$var_name = 'submitfile' . $i ;

		// if this is the button that was pressed then we are all set!  get the file name
		if ( isset($HTTP_POST_VARS[$var_name]))
		{
			$file = ( isset($HTTP_POST_VARS['file'.$i])) ? htmlspecialchars($HTTP_POST_VARS['file'.$i]) : '' ;
			break ;
		}
	}

	// we'll need to look at the path and filename so split things up
	$split = explode('/', $file) ;

	// if a file, then make sure we have the filename correct
	if ($mode == 'download_file')
	{
		// by default the filename sent will match the one in the MOD script
		$process_file = (substr($file, 0, 9) == '../../../') ? substr($file, 9) : '' ;
		$orig_file = $process_file ;

		// handle the special cases of a template file to download; only subSilver will appear in the MOD script
		if (($split[3] == 'templates') && ($split[4] != 'subSilver'))
		{
			$process_file = str_replace( $split[4], 'subSilver', $process_file) ;
		}

		// handle the special cases of a language file to download; only english will appear in the MOD script
		else if (($split[3] == 'language') && ($split[4] != 'lang_english'))
		{
			$process_file = str_replace( $split[4], 'lang_english', $process_file) ;
		}
	}

	// if a backup then we can assume the filename is valid
	else
	{
		$orig_file = $file ;
		$process_file = (substr($file, 0, 9) == '../../../') ? substr($file, 9) : '' ;
		$process_file = $phpbb_root_path . $process_file ;
	}


	// if there is no file to process then we are in trouble!
	if ( $process_file == '')
	{
		message_die(GENERAL_ERROR, $lang['EM_err_no_process_file'], '', __LINE__, __FILE__, $sql);
	}


	// set up the redirects so we will download a file, the contents of which we will echo out
	header('Content-Type: text/x-delimtext; name="' . $split[count($split)-1] . '"');
	header('Content-disposition: attachment; filename="' . $split[count($split)-1] . '"');
}

// writing to screen, get set up
else if (($mode == 'display_file') || ($mode == 'display_backup'))
{
	// get the file name
	$file = (isset($HTTP_GET_VARS['file'])) ? htmlspecialchars($HTTP_GET_VARS['file']) : '' ;
	$split = explode('/', $file) ;

	// if a file, then make sure we have the filename correct
	if ($mode == 'display_file')
	{
		// by default the filename sent will match the one in the MOD script
		$process_file = (substr($file, 0, 9) == '../../../') ? substr($file, 9) : '' ;
		$orig_file = $process_file ;

		// handle the special cases of a template file to display; only subSilver will appear in the MOD script
		if (($split[3] == 'templates') && ($split[4] != 'subSilver'))
		{
			$process_file = str_replace( $split[4], 'subSilver', $process_file) ;
		}

		// handle the special cases of a language file to display; only english will appear in the MOD script
		else if (($split[3] == 'language') && ($split[4] != 'lang_english'))
		{
			$process_file = str_replace( $split[4], 'lang_english', $process_file) ;
		}
	}

	// if a backup then we can assume the filename is valid
	else
	{
		$orig_file = $file ;
		$process_file = (substr($file, 0, 9) == '../../../') ? substr($file, 9) : '' ;
		$process_file = $phpbb_root_path . $process_file ;
	}

	// if there is no file to process then we are in trouble!
	if ( $process_file == '')
	{
		message_die(GENERAL_ERROR, $lang['EM_err_no_process_file'], '', __LINE__, __FILE__, $sql);
	}
}



//
// Show the page header (if we aren't doing the display modes)
//
if (($mode != 'display_file') && ($mode != 'download_file') && ($mode != 'display_backup') && ($mode != 'download_backup'))
{
	$template->set_filenames(array(
		'mod_header' => 'admin/mod_header.tpl')
	);

	$template->assign_vars(array(
		'L_TITLE' => $lang['EM_Title'],
		'L_EM_VERSION' => EASYMOD_VER)
	);

	$template->pparse('mod_header');
}





//
// password authentication page
//
if ($get_password)
{
	// load the password page template
	$template->set_filenames(array(
		"body" => "admin/mod_login.tpl")
	);


	$template->assign_vars(array(
		'S_ACTION' => append_sid('admin_easymod.' . $phpEx),
		'L_ACCESS_WARNING' => $lang['EM_access_warning'],
		'L_MESSAGE' => $pass_message,
		'L_PASSWORD_TITLE' => $lang['EM_password_title'],
		'L_PASSWORD' => $lang['EM_password'],
		'L_ACCESS_EM' => $lang['EM_access_EM'],

		'MODE' => $mode)
	);
}


//
// display the settings page
//
else if ($mode == 'settings')
{
	// load the settings page template
	$template->set_filenames(array(
		"body" => "admin/mod_settings.tpl")
	);

	$command_file = get_em_settings( '6E7574747A79.72756C657321', '', $password) ;

	$select_read =  '<option value="server"' . (($command_file->read_method == 'server') ? ' selected=selected' : ''). '>' . $lang['EM_read_server'] . '</option>' ;

	$select_write =  '<option value="server"' . (($command_file->write_method == 'server') ? ' selected=selected' : ''). '>' . $lang['EM_write_server'] . '</option>' . "\n" ;
	$select_write .= '<option value="ftpb"' . (($command_file->write_method == 'ftpb') ? ' selected=selected' : ''). '>' . $lang['EM_write_ftp'] . '</option>' . "\n" ;
	$select_write .= '<option value="local"' . (($command_file->write_method == 'local') ? ' selected=selected' : ''). '>' . $lang['EM_write_download'] . '</option>' . "\n" ;
	$select_write .= '<option value="screen">' . (($command_file->write_method == 'screen') ? ' selected=selected' : ''). '' . $lang['EM_write_screen'] . '</option>' . "\n" ;

	$select_move =  '<option value="copy"' . (($command_file->move_method == 'copy') ? ' selected=selected' : ''). '>' . $lang['EM_move_copy'] . '</option>' . "\n" ;
	$select_move .= '<option value="ftpa"' . (($command_file->move_method == 'ftpa') ? ' selected=selected' : ''). '>' . $lang['EM_move_ftp'] . '</option>' . "\n" ;
	$select_move .= '<option value="exec"' . (($command_file->move_method == 'exec') ? ' selected=selected' : ''). '>' . $lang['EM_move_exec'] . '</option>' . "\n" ;
	$select_move .= '<option value="ftpm"' . (($command_file->move_method == 'ftpm') ? ' selected=selected' : ''). '>' . $lang['EM_move_manual'] . '</option>' . "\n" ;

	$template->assign_vars(array(
		'S_ACTION' => append_sid('admin_easymod.' . $phpEx),
		'L_SETTINGS' => $lang['EM_settings'],
		'L_DESC' => $lang['EM_settings_desc'],

		'L_PW_TITLE' => $lang['EM_password_title'],
		'L_PW_DESC' => $lang['EM_settings_pw'],
		'L_PW_SET' => $lang['EM_password_set'],
		'L_PW_CONFIRM' => $lang['EM_password_confirm'],
		'L_EM_VERSION' => $lang['EM_easymod_version'],
		'L_EMV_DESC' => $lang['EM_emv_description'],

		'L_FILE_TITLE' => $lang['EM_file_title'],
		'L_FILE_DESC' => $lang['EM_file_desc'],
		'L_FILE_READ' => $lang['EM_file_reading'],
		'L_FILE_WRITE' => $lang['EM_file_writing'],
		'L_FILE_MOVE' => $lang['EM_file_moving'],

		'L_FTP_TITLE' => $lang['EM_ftp_title'],
		'L_FTP_DESC' => $lang['EM_ftp_desc'],
		'L_FTP_DIR' => $lang['EM_ftp_dir'],
		'L_FTP_USER' => $lang['EM_ftp_user'],
		'L_FTP_PASS' => $lang['EM_ftp_pass'],
		'L_FTP_HOST' => $lang['EM_ftp_host'],
		'L_FTP_PORT' => $lang['EM_ftp_port'],
		'L_FTP_EXT' => $lang['EM_ftp_use_ext'],
		'L_FTP_EXT_WARN' => $lang['EM_ftp_ext_not'],
		'L_FTP_CACHE' => $lang['EM_ftp_cache'],
		'L_SUPPLY_CHANGE' => $lang['EM_supply_on_change'],
		'L_YES' => $lang['EM_yes'],
		'L_NO' => $lang['EM_no'],
		'L_SUBMIT' => $lang['EM_settings_update'],

		'EM_PASS' => $password,
		'EM_VERSION' => get_em_version(),

		'SELECT_READ' => $select_read,
		'SELECT_WRITE' => $select_write,
		'SELECT_MOVE' => $select_move,

		'FTP_USER' => $command_file->ftp_user,
		'FTP_PASS' => '', // don't send FTP password to page, is unsecure $command_file->ftp_pass,
		'FTP_PATH' => $command_file->ftp_path,
		'FTP_HOST' => $command_file->ftp_host,
		'FTP_PORT' => $command_file->ftp_port,
		'FTP_EXT' => ($command_file->ftp_type == 'ext') ? 'checked="checked"' : '',
		'FTP_FSOCK' => ($command_file->ftp_type == 'fsock') ? 'checked="checked"' : '',
		'FTP_CACHE_YES' => ($command_file->ftp_cache) ? 'checked="checked"' : '',
		'FTP_CACHE_NO' => (!$command_file->ftp_cache) ? 'checked="checked"' : '',

		'MODE' => 'update')
	);
}


//
// update the EM settings; they already filled out the settings page and hit submit
//
else if ($mode == 'update')
{
	// password settings
	$em_pass = (isset($HTTP_POST_VARS['em_pass'])) ? htmlspecialchars( $HTTP_POST_VARS['em_pass']) : '' ;
	$em_pass_confirm = (isset($HTTP_POST_VARS['em_pass_confirm'])) ? htmlspecialchars( $HTTP_POST_VARS['em_pass_confirm']) : '' ;
	$em_version = (isset($HTTP_POST_VARS['em_version'])) ? htmlspecialchars( $HTTP_POST_VARS['em_version']) : '' ;

	// file access settings
	$read = (isset($HTTP_POST_VARS['sel_read'])) ? htmlspecialchars( $HTTP_POST_VARS['sel_read']) : '' ;
	$write = (isset($HTTP_POST_VARS['sel_write'])) ? htmlspecialchars( $HTTP_POST_VARS['sel_write']) : '' ;
	$move = (isset($HTTP_POST_VARS['sel_move'])) ? htmlspecialchars( $HTTP_POST_VARS['sel_move']) : '' ;

	// ftp settings
	$ftp_user = (isset($HTTP_POST_VARS['ftp_user'])) ? htmlspecialchars( $HTTP_POST_VARS['ftp_user']) : '' ;
	$ftp_pass = (isset($HTTP_POST_VARS['ftp_pass'])) ? htmlspecialchars( $HTTP_POST_VARS['ftp_pass']) : '' ;
	$ftp_host = (isset($HTTP_POST_VARS['ftp_host'])) ? htmlspecialchars( $HTTP_POST_VARS['ftp_host']) : '' ;
	$ftp_port = (isset($HTTP_POST_VARS['ftp_port'])) ? intval( $HTTP_POST_VARS['ftp_port']) : 0 ;
	$ftp_type = (isset($HTTP_POST_VARS['ftp_type'])) ? htmlspecialchars( $HTTP_POST_VARS['ftp_type']) : 'fsock' ;
	$ftp_cache = (isset($HTTP_POST_VARS['ftp_cache'])) ? intval( $HTTP_POST_VARS['ftp_cache']) : 0 ;
	$ftp_dir = (isset($HTTP_POST_VARS['ftp_dir'])) ? htmlspecialchars( $HTTP_POST_VARS['ftp_dir']) : '/' ;
	$ftp_dir == ( $ftp_dir == '') ? '/' : $ftp_dir ;

	// confirm passwords match and update pw if needed
	if ( $em_pass == $em_pass_confirm)
	{
		// update the password; starting with 0.0.11 store as MD5 hash
		em_db_update( 'EM_password', md5($em_pass)) ;
		$pass_msg = ($em_pass == '') ? $lang['EM_pass_disabled'] : $lang['EM_pass_updated'] ;
		$force_ftp_pass = true;
	}
	// the confirm is empty so they are not trying to update the pw, so don't
	else if ( $em_pass_confirm == '')
	{
		$pass_msg = $lang['EM_pass_not_updated'] ;
		$force_ftp_pass = false;
	}
	// passwords do not match so throw an error
	else if ( $em_pass != $em_pass_confirm)
	{
		message_die( GENERAL_ERROR, $lang['EM_err_set_pw']) ;
	}


	// update the settings
	em_db_update( 'EM_read', $read) ;
	em_db_update( 'EM_write', $write) ;
	em_db_update( 'EM_move', $move) ;
	em_db_update( 'EM_ftp_dir', $ftp_dir) ;
	em_db_update( 'EM_ftp_user', $ftp_user) ;
	
	if ( $force_ftp_pass || !empty($ftp_pass) )
	{
		// decrypt the FTP password
		include($phpbb_root_path . '/admin/em_includes/em_cipher.php') ;
		$cipher = new Cipher_BlockMode_cbc();
		$cipher->blowfish->setKey( $em_pass);
		$ftp_pass = $cipher->encrypt( $ftp_pass) ;
		
		em_db_update( 'EM_ftp_pass', $ftp_pass) ;
	}
	
	em_db_update( 'EM_ftp_host', $ftp_host) ;
	em_db_update( 'EM_ftp_port', $ftp_port) ;
	em_db_update( 'EM_ftp_type', $ftp_type) ;
	em_db_update( 'EM_ftp_cache', $ftp_cache) ;
	em_db_update( 'EM_version', $em_version) ;

	message_die( GENERAL_MESSAGE, '<br />' . $lang['EM_settings_success'] . " $pass_msg<br /><br />") ;
}


//
// history
//
else if ($mode == 'history')
{
	// load the history page template
	$template->set_filenames(array(
		"body" => "admin/mod_history.tpl")
	);


	$template->assign_vars(array(
		'L_INSTALLED' => $lang['EM_Installed'],
		'L_INSTALLED_DESC' => $lang['EM_installed_desc'],
		'L_INSTALL_DATE' => $lang['EM_install_date'],
		'L_MOD_NAME' => $lang['EM_Mod'],
		'L_FILE' => $lang['EM_File'],
		'L_VERSION' => $lang['EM_Version'],
		'L_AUTHOR' => $lang['EM_Author'],
		'L_DESCRIPTION' => $lang['EM_Description'],
		'L_DATE' => $lang['EM_Process_Date'],
		'L_PHPBB_VER' => $lang['EM_phpBB_Version'],
		'L_THEMES' => $lang['EM_Themes'],
		'L_LANGUAGES' => $lang['EM_Languages'],
		'L_NONE_INSTALLED' => $lang['EM_none_installed'],
		'S_DETAILS' => $lang['EM_details'])
	);



	$sql = "SELECT *
		FROM " . EASYMOD_TABLE . " 
		ORDER BY mod_id DESC" ;
	if( !$result = $db->sql_query($sql) )
	{
	   message_die(GENERAL_ERROR, $lang['EM_err_em_info'], '', __LINE__, __FILE__, $sql);
	}

	$i = 0 ;
	while( $row = $db->sql_fetchrow($result) )
	{
		$row_class = ( !($i % 2) ) ? $theme['td_class1'] : $theme['td_class2'];
		$template->assign_block_vars('install', array(
			'ROW_CLASS' => $row_class,
			'INSTALL_DATE' => create_date($board_config['default_dateformat'], $row['mod_process_date'], $board_config['board_timezone']),
			'TITLE' => $row['mod_title'],
			'VERSION' => $row['mod_version'],
			'AUTHOR' => $row['mod_author_handle'],
			'URL' => $row['mod_author_url'],
			'PHPBB_VER' => $row['mod_phpBB_version'],

			'S_ACTION' => append_sid('admin_easymod.' . $phpEx),
			'S_HIDDEN_FIELDS' => '<input type="hidden" name="mod_id" value="' . $row['mod_id'] . '"><input type="hidden" name="mode" value="history_details"><input type="hidden" name="password" value="' . $password . '">',

/////////////////
///////////////// blah, what about schema name?
/////////////////
			'THEMES' => $row['mod_processed_themes'],
			'LANGS' => $row['mod_processed_langs'])
		);
		$i++ ;
	}
	if ( $i == 0 )
	{
		$template->assign_block_vars('no_install', array()) ;
	}
}

//
// history details
//
else if ( $mode == 'history_details' )
{
	// get the mod id
	if ( isset($HTTP_POST_VARS['mod_id']) )
	{
		$mod_id = intval($HTTP_POST_VARS['mod_id']);
	}
	else
	{
		message_die(GENERAL_ERROR, $lang['EM_No_mod_selected']);
	}

	// load the template
	$template->set_filenames(array(
		"body" => "admin/mod_history_details.tpl")
	);

	$template->assign_vars(array(
		'L_MOD_DATA' => $lang['EM_Mod_Data'],
		'L_MOD_TITLE' => $lang['EM_Mod_Title'],
		'L_MOD_DESCRIPTION' => $lang['EM_Description'],
		'L_AUTHOR' => $lang['EM_Author'],
		'L_INSTALL_DATE' => $lang['EM_install_date'],
		'L_PHPBB_VER' => $lang['EM_phpBB_Version'],
		'L_THEMES' => $lang['EM_Proc_Themes'],
		'L_LANGUAGES' => $lang['EM_Proc_Languages'],
		'L_FILES' => $lang['EM_Files'],
		'L_DB_ALTS' => $lang['EM_db_alt'],
		'L_ADDED' => $lang['EM_tables_added'],
		'L_ALTERED' => $lang['EM_tables_altered'],
		'L_INSERTED' => $lang['EM_rows_added'],
		
		'L_DELETE_FILES' => $lang['EM_del_files'],
		'L_DELETE_RECORD' => $lang['EN_del_record'],
		'L_INSTALL_LANG' => $lang['EM_install_new_lang'],
		'L_INSTALL_THEMES' => $lang['EM_install_new_themes'],
		'L_RESTORE_BACKUPS' => $lang['EM_restore_backups'],
		'L_UNISTALL' => $lang['EM_uninstall'],
		'L_GO' => $lang['Go'],
			
		'S_ACTION' => append_sid($phpbb_root_path . 'admin/admin_easymod.'.$phpEx),
		'S_HIDDEN_FIELDS' => '<input type="hidden" name="mod_id" value="' . $mod_id . '"><input type="hidden" name="password" value="' . $password . '">')
	);

	$sql = "SELECT * FROM " . EASYMOD_TABLE . "
		WHERE mod_id = $mod_id
		LIMIT 0, 1";

	if( !$result = $db->sql_query($sql) )
	{
	   message_die(GENERAL_ERROR, $lang['EM_err_em_info'], '', __LINE__, __FILE__, $sql);
	}

	$row = $db->sql_fetchrow($result);

	// file
	$file = explode('/', $row['mod_file']);

	if ( file_exists('./mods/' . $row['mod_file']) )
	{
		$temp_url = $phpbb_root_path . 'admin/mods/' . $row['mod_file'];
		$mod_file = '<a href="' . $temp_url . '" class="gen" target="_blank">' . $file[1] . '</a>';

		$template->assign_block_vars('switch_install_file', array());
	}
	else
	{
		$mod_file = $file[1];
	}

	// see what files are there so we can work with them
	if ( file_exists('./mods/' . $file[0] . '/processed/') || file_exists('./mods/' . $file[0]. '/backups/') )
	{
		$template->assign_block_vars('switch_files', array());
	}
	// see if backups are there so we can give them the option to restore them
	if ( file_exists('./mods/' . $file[0]. '/backups/') )
	{
		$template->assign_block_vars('switch_backups', array());
	}

	$template->assign_vars(array(
		'TITLE' => $row['mod_title'],
		'VERSION' => $row['mod_version'],
		'MOD_FILE' => $mod_file,
		'DESCRIPTION' => $row['mod_description'],
		'AUTHOR' => $row['mod_author_handle'],
		'EMAIL' => $row['mod_author_email'],
		'REAL_NAME' => $row['mod_author_name'],
		'URL' => $row['mod_author_url'],
		'DATE' => create_date($board_config['default_dateformat'], $row['mod_process_date'], $board_config['board_timezone']),
		'PHPBB_VERSION' => $row['mod_phpBB_version'],
		'THEMES' => $row['mod_processed_themes'],
		'LANGUAGES' => $row['mod_processed_langs'],
		'FILES' => $row['mod_files_edited'],
		'ADDED' => $row['mod_tables_added'],
		'ALTERED' => $row['mod_tables_altered'],
		'INSERTED' => $row['mod_rows_inserted'])
	);

}

//
// delete MOD files
//
else if ( $mode == 'del_files' )
{
	// display which folders to delete, either
	// processed, backups, or the complete folder
	message_die(GENERAL_MESSAGE, $lang['Coming_soon']);

}

//
// delete MOD record
//
else if ( $mode == 'del_record' )
{
	// display confirm and delete sql entry
	message_die(GENERAL_MESSAGE, $lang['Coming_soon']);

}

//
// Restore Backups
//
else if ( $mode == 'restore_backups' )
{
	// display confirm and move the backups into place
	message_die(GENERAL_ERROR, $lang['Coming_soon']);

}

//
// Install MOD on new Languages
//
else if ( $mode == 'install_lang' )
{
	// list which languages so user can choose and go through install process
	message_die(GENERAL_ERROR, $lang['Coming_soon']);

}

//
// Install MOD on new themes
//
else if ( $mode == 'install_themes' )
{
	// list which themes so user can choose and go through install process
	message_die(GENERAL_ERROR, $lang['Coming_soon']);

} 

//
// uninstall the mod
//
else if ( $mode == 'unistall_mod' )
{
	message_die(GENERAL_MESSAGE, $lang['Coming_soon']);
}

//
// display install MOD page
//
else if ( $mode == 'install')
{
	// load the install page template
	$template->set_filenames(array(
		'body' => 'admin/mod_install.tpl')
	);

	$template->assign_vars(array(
		'L_EM_INTRO' => $lang['EM_Intro'],

		'L_UNPROCESSED' => $lang['EM_Unprocessed'],
		'L_UNPROCESSED_DESC' => $lang['EM_unprocessed_mods'],

		'L_MOD' => $lang['EM_Mod'],
		'L_AUTHOR' => $lang['EM_Author'],
		'L_SUPPORT' => $lang['EM_support_thread'],
		'L_DESCRIPTION' => $lang['EM_Description'],
		'L_EMC' => $lang['EM_EMC'],
		'L_PROCESS' => $lang['EM_process'],
		'L_PREVIEW' => $lang['EM_preview'],
		'L_ALL_PROCESSED' => $lang['EM_All_Processed'],

		'EM_PASS' => $password)
	);



	$phpbb_version = get_phpbb_version() ;
	if ($phpbb_version == '')
	{
		message_die( GENERAL_ERROR, $lang['EM_err_phpbb_ver']);
	}

	// parse the "mods" directory, looking for newly extracted mods, or mod updates
	$top_handle = opendir('./mods');
	$i = 0 ;
	while (false !== ($dir = readdir($top_handle)))
	{
		// only want the subdirectories (but not . and ..)
		if ( (is_dir('./mods/' . $dir) ) && ($dir != '.') && ($dir != '..'))
		{
			$path = './mods/' . $dir ;
			$dir_handle = opendir( $path);
			// loop through the subdirs, looking for mod files
			while (false !== ($file = readdir($dir_handle)))
			{
				$file_path =  $path . '/' . $file ;
				// make sure it is not a dir, and that it ends with .txt or .mod
				if ( !is_dir( $file_path) && ( (eregi(".txt$", $file_path)) || (eregi(".mod$", $file_path))))
				{
					$mod_title = '' ;
					$mod_author_handle = '' ;
					$mod_author_email = '' ;
					$mod_author_name = '' ;
					$mod_author_url = '' ;
					$mod_description = '' ;
					$mod_version = '' ;
					$compliant = false ;

					$is_mod = get_mod_properties( $file_path, $mod_title, $mod_author_handle, $mod_author_email, $mod_author_name, $mod_author_url, $mod_description, $mod_version, $compliant) ;

					// if it is a MOD and has not been processed yet then add it to the list
					if (($is_mod) && ( is_unprocessed( $db, $mod_title, $mod_version, $phpbb_version)))
					{
						$row_class = ( !($i % 2) ) ? $theme['td_class1'] : $theme['td_class2'];
						$template->assign_block_vars('unprocessed', array(
							'ROW_CLASS' => $row_class,
							'MOD_TITLE' => $mod_title,
							'MOD_AUTHOR' => $mod_author_handle,
							'MOD_URL' => $mod_author_url,
							'MOD_VERSION' => $mod_version,
							'MOD_DESC' => $mod_description,
							'MOD_EMC' => ($compliant) ? '<img src="../templates/subSilver/images/emc.gif">' : $lang['No'],
							'MOD_PATH' => $path . '/',
							'MOD_FILE' => $file,
							'MOD_FILE_URL' => $path . '/' . $file)
						);
						$i++ ;
					}
				}
			}
		}
	}

	// didn't find any MODs we can process
	if ( $i == 0 )
	{
		$template->assign_block_vars('no_unprocessed', array()) ;
	}
}


//
// preview the changes EM will be making to files
//
else if ($preview)
{
	$files = array() ;
	$f_mod_script = fopen ( $install_path . $install_file, 'r');
	while (!feof ($f_mod_script))
	{
		$buffer = fgets($f_mod_script, 4096);

		// if the line starts with #, this is either a comment or an action command

		// after obtaining the command, skip any comments until we reach the command body
		if (($buffer[0] == '#') && ($in_header))
		{
			// do nothing until we are out of the command header!!
		}

		// not in a header so this comment is either a random comment or start of a command header
		else if ($buffer[0] == '#')
		{
			// if we find [ and ] and OPEN on this line, then we can be reasonably sure we've got an OPEN command
			if ((strstr($buffer, '[')) && (strstr($buffer, ']')) && (strstr($buffer, 'OPEN')))
			{
				// get us past any remaining # lines
				$buffer = fgets($f_mod_script, 4096);
				while ($buffer[0] == '#')
				{
					if ( feof($f_mod_script))
					{
						break ;
					}
					$buffer = fgets($f_mod_script, 4096);
				}

				// loop until we get a filename (a non-whitespace line) or the next # line
				while (!feof($f_mod_script))
				{
					// got a line with some text not starting with #, so we're calling this a filename ;)
					if ((strlen(trim($buffer)) > 0) && ($buffer[0] != '#'))
					{
						$files[] = trim($buffer) ;
						break ;
					}

					// we found a # so get us out of here
					else if ($buffer[0] == '#')
					{
						break ;
					}

					$buffer = fgets($f_mod_script, 4096);
				}

				// if we hit eof, then get us out of here
				if (feof($f_mod_script))
				{
					break ;
				}
			}
		}

		// not a comment or command so this is the body of the command
		else
		{
			$in_header = false ;
		}
	}
	fclose($f_mod_script);


	// Show the preview page
	$template->set_filenames(array(
		'body' => 'admin/mod_preview.tpl')
	);

	$template->assign_vars(array(
		'L_HEADER' => $lang['EM_preview_mode'],
		'L_PREVIEW_DESC' => $lang['EM_preview_desc'],
		'L_FILENAME' => $lang['EM_preview_filename'],
		'L_VIEW' => $lang['EM_preview_view'])
	);


	// load in the filename and link info
	for ($i=0; $i<count($files); $i++)
	{
		$link = append_sid('admin_easymod.' . $phpEx) . '&mode=display_file&file=../../../' . $files[$i] . "&password=$password&install_file=$install_file&install_path=$install_path" ;

		$template->assign_block_vars('files', array(
			'NAME' => $files[$i],
			'URL' => $link)
		);

	}

	// if there are no files to be modified, then display the message
	if ( count($files) == 0)
	{
		$template->assign_block_vars('nofiles', array(
			'L_NO_FILES' => $lang['EM_preview_nofile'])
		);

	}
}


//
// download or display a backup of the core phpBB file
//
else if (($mode == 'display_backup') || ($mode == 'download_backup'))
{
	// open the core file
	if (!$read_file = fopen ( $process_file, 'r'))
	{
		// gotta echo out the message since message_die is not an option
		echo sprintf( $lang['EM_err_backup_open'], $process_file) . "\n" ;
		exit ;
	}

	// write out the lines
	while (!feof($read_file))
	{
		$newline = fgets( $read_file, 4096);
		if ($mode == 'download_backup')
		{
			echo $newline ;
		}
		else
		{
			echo htmlspecialchars($newline) ;
		}
	}
	fclose( $read_file) ;

	// finish the PRE formatting tag
	if ($mode == 'display_backup')
	{
		echo "</PRE>\n" ;
	}

	// done! done! done!
	exit ;
}


//
// process the MOD script and modify the files
//
else if (($mode == 'process' ) || ($mode == 'display_file') || ($mode == 'download_file'))
{
	// 0.0.11 preview mode
	$preview = (isset($HTTP_POST_VARS['preview'])) ? 1 : ($mode == 'display_file') ? 1 : 0 ;

	$current_command = '' ;
	$commands = array() ;
	$body = array() ;

	$in_header = false ;		// in the header of the command (the ## section)
	$line_num = 0 ;			// line number in the MOD script we are parsing

	$found_file = false ;		// only for the special cases


	//
	// open the mod script and load an array with commands to execute
	//

	$f_mod_script = fopen ( $install_path . '/' . $install_file, 'r');
	while (!feof ($f_mod_script))
	{
		$buffer = fgets($f_mod_script, 4096);
		$line_num++ ;

		// if the line starts with #, this is either a comment or an action command; will also tell us when
		//    we've hit the last search line of the target content for this command (meaning we've reached the
		//    next command)

		// after obtaining the command, skip any comments until we reach the command body
		if (($buffer[0] == '#') && ($in_header))
		{
			// do nothing until we are out of the command header!!
		}

		// not in a header so this comment is either a random comment or start of a command header
		else if ($buffer[0] == '#')
		{
			// done with last command now that we've hit a comment (regardless if a new command or just a comment)
			if ( $current_command != '')
			{
				$current_command = '' ;
			}

			// if we find [ and ] on this line, then we can be reasonably sure it is an action command
			if ((strstr($buffer, '[')) && (strstr($buffer, ']')))
			{

				//
				// we know it's an action, take appropriate steps for the action; see if the current command
				//   is found on our list;  NOTE: since we are using strstr, it is important to keep the
				//   IN-LINE commands listed before thier similarly named cousins
				//

				if (strstr($buffer, 'OPEN'))
				{
					$current_command = 'OPEN' ;
				}
				else if (strstr($buffer, 'IN-LINE FIND'))
				{
					$current_command = 'IN-LINE FIND' ;
				}
				else if (strstr($buffer, 'FIND'))
				{
					$current_command = 'FIND' ;
				}
				else if (strstr($buffer, 'IN-LINE AFTER, ADD'))
				{
					$current_command = 'IN-LINE AFTERADD' ;
				}
				else if (strstr($buffer, 'AFTER, ADD'))
				{
					$current_command = 'AFTERADD' ;
				}
				else if (strstr($buffer, 'IN-LINE BEFORE, ADD'))
				{
					$current_command = 'IN-LINE BEFOREADD' ;
				}
				else if (strstr($buffer, 'BEFORE, ADD'))
				{
					$current_command = 'BEFOREADD' ;
				}
				else if (strstr($buffer, 'IN-LINE REPLACE'))
				{
					$current_command = 'IN-LINE REPLACE' ;
				}
				else if (strstr($buffer, 'REPLACE'))
				{
					$current_command = 'REPLACE' ;
				}
				else if (strstr($buffer, 'COPY'))
				{
					$current_command = 'COPY' ;
				}
				else if (strstr($buffer, 'SQL'))
				{
					$current_command = 'SQL' ;
				}
				else if ( strstr($buffer, 'DIY INSTRUCTIONS') )
				{
					$current_command = 'DIY INSTRUCTIONS';
				}
				else if ( strstr($buffer, 'INCREMENT') )
				{
					$current_command = 'INCREMENT';
				}
				else if (strstr($buffer, 'SAVE/CLOSE'))
				{
					$current_command = 'CLOSE' ;
				}

				// not a known command, let see if it is unrecognized command or just a comment
				else
				{
					$left_bracket = strpos( $buffer, '[') ;
					$right_bracket = strpos( $buffer, ']') ;
					$left_of_bracket = substr($buffer, 0, $left_bracket) ;
					$right_of_bracket = substr($buffer, $right_bracket) ;

					// if there is no "--" both before and after the brackets, this must be a comment
					if (( $left_bracket < $right_bracket) && (strstr( $left_of_bracket, '--')) && (strstr( $right_of_bracket, '--')))
					{
						$current_command = trim( substr($buffer, $left_bracket+1, (($right_bracket-1)-($left_bracket+1)))) ;
					}
				}

				// handle special cases when we display or download the file; we are looking for the commands
				//   for one file ONLY, so skip commands until we find the corresponding OPEN
				if (($mode == 'display_file') || ($mode == 'download_file'))
				{
					if ( $current_command != '')
					{
						// not found found file yet so this is a possible canidate
						if ((!$found_file) && ($current_command == 'OPEN'))
						{
							$in_header = true ;
						}

						// ignore all other commands until we have our file
						else if ((!$found_file) && ($current_command != 'OPEN'))
						{
							$current_command = '' ;
						}

						// after found, once we hit another OPEN or the CLOSE, then we are done
						else if ((($found_file) && ($current_command == 'OPEN') && (!$in_header)) || ($current_command == 'CLOSE'))
						{
							$current_command = '' ;
							break ;
						}

						// allow processing of this command
						else
						{
							$in_header = true ;
							$commands[] = array( 'command' => $current_command, 'line' => $line_num) ;
							$body[] = array() ;
						}
					}
				}

				// normal command processing
				else if ( $current_command != '')
				{
					$in_header = true ;
					$commands[] = array( 'command' => $current_command, 'line' => $line_num) ;
					$body[] = array() ;
				}
			}
		}

		// not a comment or command so this is the body of the command
		else if ( $current_command != '')
		{
			// handle special cases; make sure this is for the specific file we are looking for
			if (($mode == 'display_file') || ($mode == 'download_file'))
			{
				// not found found file yet so see if this is it
				if ((!$found_file) && ($current_command == 'OPEN'))
				{
					// found the file, excellent!
					if (trim($buffer) == $process_file)
					{
						$commands[] = array( 'command' => $current_command, 'line' => $line_num) ;
						$body[] = array() ;
						$body[ count($body)-1 ][] = $buffer ;
						$found_file = true ;
					}
				}

				// haven't found the file yet, so don't process this command (should never get in here)
				else if (!$found_file)
				{
					$current_command = '' ;
				}

				// this command relates to the file we are looking for, so go ahead
				else
				{
					$body[ count($body)-1 ][] = $buffer ;
				}
				$in_header = false ;
			}

			// store this as this body of our command
			else
			{
				$in_header = false ;
				$body[ count($body)-1 ][] = $buffer ;
			}
		}
	}
	fclose($f_mod_script);

	// load the process mod template unless we are in special case mode
	if (($mode != 'display_file') && ($mode != 'download_file'))
	{
		// set the template
		$template->set_filenames(array(
			'body' => 'admin/mod_process.tpl')
		);
	}



	$file_list = array() ;

	$search_array = array() ;		// what we are searching for
	$search_fragment = '' ;			// the IN-LINE FIND fragment we are looking for
	$find_array = array() ;			// contains lines from a FIND which potentially contain our search target

	$files_edited = 0 ;
	$num_processed = 0 ;
	$num_unprocessed = 0 ;

	$failed = true ;
	$exec_close = false ;			// did we hit the close command?

	// grab the EM settings and open the command file
	$command_file = get_em_settings( 'post_process.sh', '', $password, $preview) ;

	// this is really more about moving the other files than is about the command file; establish the FTP connection
	//  for moving files if necessary
	if (!$command_file->modio_prep('move'))
	{
		$command_file->err_msg = $lang['EM_trace'] . ': main[1]->' . $command_file->err_msg ;
		message_die( GENERAL_ERROR, '<b>' . $lang['EM_err_critical_error'] . ':</b><br />' . $command_file->err_msg . '<br />') ;
	}


////////////////////
//////////////////// emcopy - to be fixed and removed in 0.0.11
////////////////////
	$display_copy_warning = false ;
	$display_sql_warning = false ;
	$sql = array() ;


	//
	// now that we have the commands all set let's start to process them
	//

	// loop through the command and knock 'em out ;-)
	for ($i=0; $i<count($commands); $i++)
	{
		// a catch all at the end will switch to false if we fail to process
		$processed = true ;
		$bad_command = false;

		// protect against malformed script that didn't perform a FIND first; this acts as a gatekeeper to ensure
		//   that the find_array is being managed correctly; OPEN and FIND write out any remenants of find_array; AFTER
		//   and REPLACE destroy the array while BEFORE and the IN-LINE's preserve it to be used again
		if ((count($find_array) == 0 ) && (($commands[$i]['command'] == 'BEFOREADD') || (strstr($commands[$i]['command'], 'IN-LINE'))))
		{
			display_error( '<b>' . $lang['EM_err_critical_error'] . "</b><br /><br />\n" . $commands[$i]['command'] . $lang['EM_err_no_find'] . "<br />\n" . $lang['EM_line_num'] . $commands[$i]['line']) ;
			break ;
		}


		//
		// open phpBB core file
		//
		if ($commands[$i]['command'] == 'OPEN')
		{
			// if we were doing an BEFORE or an IN-LINE command we need to write out the find_array
			//   also, see if we need to write the lines in preview format
			if ($i>0)
			{
				$do_preview = ((strstr($commands[$i-1]['command'], 'IN-LINE')) && ($preview)) ? true : false ;
			}
			else
			{
				$do_preview = false ;
			}

			write_find_array( $find_array, $file_list, $do_preview) ;
			$find_array = array() ;

			// if we already had a file open, close it now
			if (!complete_file_reproduction( $file_list))
			{
				// close failed; throw errors and halt
				for ($errs=0; $errs<count($file_list); $errs++)
				{
					display_error( '<b>' . $lang['EM_err_critical_error'] . "</b><br /><br />\n" . $file_list[$errs]->err_msg . "<br />\n" . $lang['EM_line_num'] . $commands[$i]['line']) ;
				}

				// halt processing
				break ;
			}

			// strip the body of whitespace down and down to a single line
			$body[$i] = strip_whitespace( $body[$i], true) ;

			// if there is not exactly 1 line then throw a critical error
			if ( count($body[$i]) != 1)
			{
				display_error( '<b>' . $lang['EM_err_critical_error'] . "</b><br /><br />\n" . $lang['EM_err_comm_open'] . "<br />\n" . $lang['EM_line_num'] . $commands[$i]['line']) ;
				break ;
			}

			// strip off the path and get the file name
			$splitarray = explode('/', trim($body[$i][0])) ;
			$filename = $splitarray[count($splitarray)-1] ;

			// now get the path
			$path = '' ;
			for ($k=0; $k<count($splitarray)-1; $k++)
			{
				$path .= $splitarray[$k] . '/' ;
			}


			// open the file(s)
			$file_list = array() ;
			$result = open_files( $filename, $path, $file_list, $command_file) ;

			// display any errors; if it was critical, terminate processing; if warn, remove file from list
			if ( handle_error( $result, $file_list, $commands[$i]['line']))
			{
				break ;
			}

			// increment our count
			$files_edited += count($file_list) ;
		}

		//
		// find a string or sequential group of strings in the file
		//
		else if ($commands[$i]['command'] == 'FIND')
		{
			// if we were doing an BEFORE or an IN-LINE command we need to write out the find_array
			//   also, see if we need to write the lines in preview format
			$do_preview = ((strstr($commands[$i-1]['command'], 'IN-LINE')) && ($preview)) ? true : false ;
			write_find_array( $find_array, $file_list, $do_preview) ;

			// reinit key vars
			$find_array = array() ;
			$search_fragment = '' ;

			// strip the body of whitespace lines; allow multiple lines
			$body[$i] = strip_whitespace( $body[$i], false) ;


			// make sure we have something to search for; throw a warning if not
			$search_array = $body[$i] ;
			if ( count($search_array) == 0 )
			{
				display_error( '<b>' . $lang['EM_err_critical_error'] . "</b><br /><br />\n" . $lang['EM_err_comm_find'] . "<br />\n" . $lang['EM_line_num'] . $commands[$i]['line']) ;
				break ;
			}

			// do the find and see what happens
			$result = perform_find( $file_list, $find_array, $search_array) ;

			// display any errors; if it was critical, terminate processing; if warn, remove file from list
			//   the command will also close the files that we were writing
			if ( handle_error( $result, $file_list, $commands[$i]['line'], true))
			{
				break ;
			}
		}

		//
		// write out the find array then write the body
		//
		else if ($commands[$i]['command'] == 'AFTERADD')
		{
			$insert_string = '' ;
			for ($j=0; $j<count($body[$i]); $j++)
			{
				$insert_string .= $body[$i][$j] ;
			}

			// if we are preview mode, then mark these effect lines as special
			if ($mode == 'display_file')
			{
				$insert_string = 'EM>>' . $insert_string ;
			}

			// see if we need to write the lines in preview format
			$do_preview = ((strstr($commands[$i-1]['command'], 'IN-LINE')) && ($preview)) ? true : false ;

			write_find_array( $find_array, $file_list, $do_preview) ;
			write_files( $file_list, $insert_string) ;

			// we've written the find array already so we can no longer operate on it
			$find_array = array() ;
		}

		//
		// write the body then write out the find array
		//
		else if ($commands[$i]['command'] == 'BEFOREADD')
		{
			$insert_string = '' ;
			for ($j=0; $j<count($body[$i]); $j++)
			{
				$insert_string .= $body[$i][$j] ;
			}

			// if we are preview mode, then mark these effect lines as special
			if ($mode == 'display_file')
			{
				$insert_string = 'EM>>' . $insert_string ;
			}

			write_files( $file_list, $insert_string) ;

			// NOTE: since we have not modified the find_array in any way we can still perform operations on it
			//   so do not write it out
		}

		//
		// write the body then throw out the find array!
		//
		else if ($commands[$i]['command'] == 'REPLACE')
		{
			// is this a totally easy command or what!?!?!  That's why it is soooo dangerous to use.  Another
			//   mod will never be able to work again if it needs to FIND what we just replaced	

			// write the replace lines and notice how we never will write the find_array lines
			for ($j=0; $j<count($body[$i]); $j++)
			{
				// if we are preview mode, then mark these effect lines as special
				if ($mode == 'display_file')
				{
					write_files( $file_list, 'EM>>' . $body[$i][$j]) ;
				}
				else
				{
					write_files( $file_list, $body[$i][$j]) ;
				}
			}

			// we've obliterated the find array already so we can no longer operate on it
			$find_array = array() ;
		}

		else if ($commands[$i]['command'] == 'INCREMENT')
		{
			// strip the body of whitespace down and down to a single line
			$body[$i] = strip_whitespace( $body[$i], true) ;

			// if there is not exactly 1 line then throw a critical error
			if ( count($body[$i]) != 1)
			{
				display_error( '<b>' . $lang['EM_err_critical_error'] . "</b><br /><br />\n" . $commands[$i]['command'] . $lang['EM_err_increment_body'] . "<br />\n" . $lang['EM_line_num'] . $commands[$i]['line']) ;
				break ;
			}

			// parse the increment command
			$inc_data = array();
			if (!preg_match('#(%\:\d+)\s*([\+\-]\d+)?#',trim($body[$i][0]),$inc_data))
			{
				display_error( '<b>' . $lang['EM_err_critical_error'] . "</b><br /><br />\n" . $commands[$i]['command'] . $lang['EM_err_increment_body'] . "<br />\n" . $lang['EM_line_num'] . $commands[$i]['line']) ;
				break;
			}
			$inc_data[1] = '{'.$inc_data[1].'}';
			$inc_data[2] = isset($inc_data[2]) ? $inc_data[2] : 1;

			// perform the increment as appropriate
			for ( $file = 0; $file < count($file_list); $file++ )
			{
				for ( $j = 0; $j < count($find_array); $j++ )
				{
					$increment_search = ($search_fragment != '') ? $search_fragment : $search_array[$j];
					$find_array[$file][$j] = increment_wildcard($inc_data[1], $inc_data[2], $increment_search, $find_array[$file][$j]);
				}
			}
		}

		//
		// IN-LINE commands; perform precision operations on a single line
		//
		else if (strstr($commands[$i]['command'], 'IN-LINE'))
		{
/////////////////////
///////////////////// wasn't there something about not trimming the left side?
/////////////////////
			// strip the body of whitespace down and down to a single line
			$body[$i] = strip_whitespace( $body[$i], true) ;

			// if there is not exactly 1 line then throw a critical error
			if ( count($body[$i]) != 1)
			{
				display_error( '<b>' . $lang['EM_err_critical_error'] . "</b><br /><br />\n" . $commands[$i]['command'] . $lang['EM_err_inline_body'] . "<br />\n" . $lang['EM_line_num'] . $commands[$i]['line']) ;
				break ;
			}

			// if there is no search fragment for an AFTER, BEFORE, or REPLACE then throw a crit error
			if (($search_fragment == '') && ($commands[$i]['command'] != 'IN-LINE FIND'))
			{
				display_error( '<b>' . $lang['EM_err_critical_error'] . "</b><br /><br />\n" . $commands[$i]['command'] . $lang['EM_err_no_ifind'] . "<br />\n" . $lang['EM_line_num'] .$commands[$i]['line']);
				break ;
			}


			// make the actual alteration for after, before, and replace
			if ($commands[$i]['command'] == 'IN-LINE AFTERADD')
			{
				$result = perform_inline_add( $find_array, $file_list, $search_fragment, $body[$i][0], 'after');
			}
			else if ($commands[$i]['command'] == 'IN-LINE BEFOREADD')
			{
				$result = perform_inline_add( $find_array, $file_list, $search_fragment, $body[$i][0], 'before') ;
			}
			else if ($commands[$i]['command'] == 'IN-LINE REPLACE')
			{
				$result = perform_inline_add( $find_array, $file_list, $search_fragment, $body[$i][0], 'replace') ;
			}
			// strip off white space and get our search fragment (we already know it is not an empty string)
			else if ($commands[$i]['command'] == 'IN-LINE FIND')
			{
				$search_fragment = trim($body[$i][0]) ;
			}
			else
			{
				$bad_command = true;
			}

			// display any errors; if it was critical, terminate processing; if warn, remove file from list
			//   the command will also close the files that we were writing
			if ( handle_error( $result, $file_list, $commands[$i]['line'], true, $find_array))
			{
				break ;
			}
		}

		else if ($commands[$i]['command'] == 'SQL')
		{
			$sql[] = $body[$i] ;
		}

		else if ( $commands[$i]['command'] == 'DIY INSTRUCTIONS')
		{
			$diy[] = $body[$i];
		}

		//
		// setup the copying of files from the mod directory to core directories
		//
		else if ($commands[$i]['command'] == 'COPY')
		{
			// strip the body of whitespace lines; allow multiple lines
			$body[$i] = strip_whitespace( $body[$i], false) ;

/*
//////////////////////////////////////////////////////////////////////////////
// this COPY command was mostly written by Ptirhiik and integrated by me.  It's not perfect yet, and I can't remember why
//   since it's been soooooo long since I worked on the dang thing!  Will fine tune it later.  
//////////////////////////////////////////////////////////////////////////////


////////// yeah.... can't remember what most of these notes mean ;-)

copy to *.*
copy *.*
copy templates/*.*				to foo
copy includes/functions?.* to foo
copy templates/subSilver/images/icon*.gif to foo
copy templates/sub* to templates/sav
copy ind*.php to sav*.?u?

copy foo_body.tpl to templates/subSilver/foo_body.tpl 
copy foo_body.tpl to templates/subSilver/ 
copy *.* to templates/subSilver/ 

want to work:
copy admin_flags.php to admin/admin_flags.php				// basic
copy admin_flags.php 		to 	admin/admin_flags.php		// basic with tabs
copy admin_flags.php		to	admin/				// to a dir with trailing slash
copy admin_flags.php		to	admin					// to a dir without trailing slash
copy admin_flags.php		to	admin/*.*				// to a dir as *.*
copy admin_flags.?h?		to	admin					// from with ? wildcards
copy admin_flags.*		to	admin					// from with * wildcard
copy a*.*				to	admin					// from with * wildcards
copy *.*				to	admin					// from as *.*

on the bubble:
copy admin_flags.php		to	admin/*				// to a dir as *
copy a*s.*				to	admin					// from with * wildcards
copy templates/sub* to templates/sav			// wow!!!
copy ind*.php to sav*.?u?					// the heck??



#copy admin_flags.php		to	admin/
#copy admin_flags.php		to	admin/*.*
#copy admin_flags.?h?		to	admin
#copy admin_flags.*		to	admin
#copy admin_flags.*		to	admin/
#copy a*.*			to	admin/
#copy a*.*			to	admin/xxx		// sends files to admin/xxx/ directory
#copy admin_flags.php		to	admin			// careful! Will create a FILE named admin!!
#copy *.*			to	admin
#copy flags/a*.*		to	admin
#copy admin_flags.php		to	admin/*			// careful! file named 'admin_flags' w/o .php!
#copy admin_flags.php		to	admin/*.sfdg
#copy a*s.*				to	admin
#copy processed/templates/sub* to templates/sav
#copy a*.php to sav*.?u?


*/

			// multiple copies : from
			$tmp_mult['from_path'] = array();
			$tmp_mult['from_file'] = array();
			$tmp_mult['to_path'] = array();
			$tmp_mult['to_file'] = array();


			//
			// first pass : split qualified copies from masked copies
			//
			$bad_copy = false ;
			for ( $j = 0; $j < count($body[$i]); $j++ )
			{
				$split_line = array();
				// make sure the command is in proper format "copy x to y"
				if ( !$split_line = copy_check_basic_form( $body[$i][$j]))
				{
//echo "1<br>\n" ;
					display_error( '<b>' . $lang['EM_err_critical_error'] . "</b><br /><br />\n" . $lang['EM_err_copy_format'] . '<br />' . trim($body[$i][$j]) . "<br />\n" . $lang['EM_line_num'] .$commands[$i]['line']);
					$bad_copy = true ;
					break ;
				}

				// makes sure the filename+path are ok and do a little formatting
				if ((!$targ = copy_check_file( trim( $split_line[1]))) || 
					(!$dest = copy_check_file( trim( $split_line[3]))))
				{
//echo "2<br>\n" ;
					display_error( '<b>' . $lang['EM_err_critical_error'] . "</b><br /><br />\n" . $lang['EM_err_copy_format'] . '<br />' . trim($body[$i][$j]) . "<br />\n" . $lang['EM_line_num'] .$commands[$i]['line']);
					$bad_copy = true ;
					break ;
				}

				// final format check, make sure we have a muli dest if we have a multi targ
				if ( strstr( $targ['file'], '*') || strstr( $targ['file'], '?') )
				{
					// force this to be a multi dest listing if not so already
					if ((!strstr( $dest['file'], '*')) && (!strstr( $dest['file'], '?')) )
					{
						$dest['path'] .= $dest['file'] . '/' ;
						$dest['file'] = '*.*' ;
					}
				}				
				else
				{
					// check to see if the file exists
					if ( !file_exists($install_path . $targ['path'] . $targ['file']) )
					{
						display_error( '<b>' . $lang['EM_err_critical_error'] . "</b><br /><br />\n" . sprintf($lang['EM_err_comm_copy'], $install_path . $targ['path'], $targ['file']) . '<br />' . trim($body[$i][$j]) . "<br />\n" . $lang['EM_line_num'] .$commands[$i]['line']);
						$bad_copy = true ;					
					}

				}

				// store
				$tmp_mult['from_path'][] = $targ['path'] ;
				$tmp_mult['from_file'][] = $targ['file'];
				$tmp_mult['to_path'][] = $dest['path'] ;
				$tmp_mult['to_file'][] = $dest['file'] ;
			}


			// if we failed then halt processing
			if ($bad_copy)
			{
				break ;
			}


			//
			// second pass : get the relevant files with the mask
			//
			for ( $j = 0; $j < count($tmp_mult['from_path']); $j++ )
			{
				if ($bad_copy)
				{
					break ;
				}
				$tmp_from_path = $tmp_mult['from_path'][$j];
				$tmp_from_file = $tmp_mult['from_file'][$j];
				$tmp_to_path = $tmp_mult['to_path'][$j];
				$tmp_to_file = $tmp_mult['to_file'][$j];

				// from mask
				$tmp_all = ($tmp_from_file == '*.*');
				$tmp_from_mask = '^' . str_replace( array('*', '?'), array('(.+)', '(.)'), $tmp_from_file . '$');

				// to maks
				$tmp_to_mask = $tmp_to_file;
				$tmp_pos = strrpos($tmp_to_mask, '.');
				if ( $tmp_pos === false )
				{
					$tmp_to_ext = '';
					$tmp_to_base = $tmp_to_file;
				}
				else
				{
					$tmp_to_ext = substr( $tmp_to_file, $tmp_pos+1 );
					$tmp_to_base = substr( $tmp_to_file, 0, $tmp_pos );
				}

				// stack of subdirs
				$tmp_dirs_from = array();
				$tmp_dirs_to = array();

				// init with the asked dir
				array_push($tmp_dirs_from, $tmp_from_path);
				array_push($tmp_dirs_to, $tmp_to_path);

				// let's go
				$first_pass = true;
				while ( !empty($tmp_dirs_from) )
				{
					// get the dir
					$tmp_from_dir = array_pop($tmp_dirs_from);
					$tmp_to_dir = array_pop($tmp_dirs_to);

					// we are no more on the main dir, so accept all files and sub dirs
					if ( !$first_pass )
					{
						$tmp_all = true;
					}
					$first_pass = false;

					// another one bites the dust
					if ( !$tmp_handle = @opendir( $install_path . $tmp_from_dir ) )
					{
//echo "3 [$install_path][$tmp_from_dir]<br>\n" ;
						display_error( '<b>' . $lang['EM_err_critical_error'] . "</b><br /><br />\n" . $lang['EM_err_copy_format'] . '<br />' . trim($body[$i][$j]) . "<br />\n" . $lang['EM_line_num'] .$commands[$i]['line']);
						$bad_copy = true ;
						break ;
					}

					while ( $tmp_file = readdir($tmp_handle) )
					{
						// don't take care of . & ..
						if ( in_array($tmp_file, array('.', '..')) )
						{
							continue ;
						}
						// check if relevant name
						else if ( !$tmp_all && !ereg($tmp_from_mask, $tmp_file) )
						{
							continue ;
						}

						// if we keep the full name or are in sub-dirs, don't bother to filter the dest mask
						$tmp_to_file = $tmp_file;
						if ( !$tmp_all )
						{
							// split in basename + ext
							$tmp_pos = strrpos($tmp_file, '.');
							$tmp_from_ext = '';
							$tmp_from_base = $tmp_file;
							if ( $tmp_pos)
							{
								$tmp_from_ext = substr( $tmp_file, $tmp_pos+1 );
								$tmp_from_base = substr( $tmp_file, 0, $tmp_pos );
							}

							$w_base = process_file_split( $tmp_to_base, $tmp_from_base) ;
							$w_ext = process_file_split( $tmp_to_ext, $tmp_from_ext) ;

							// get the final result
							$tmp_to_file = $w_base . ( empty($w_ext) ? '' : '.' . $w_ext );
						}


						// if we are on a dir, push it
						if ( is_dir($install_path . $tmp_from_dir . $tmp_file) )
						{
							array_push($tmp_dirs_from, $tmp_from_dir . $tmp_file . '/');
							array_push($tmp_dirs_to, $tmp_to_dir . $tmp_to_file . '/');
						}
						// we are on a file
						else
						{
							$final = array() ;
							$final = final_formatting( $tmp_to_dir, $tmp_to_file, $tmp_from_dir, $tmp_file) ;
							for ($x=0; $x<count($final); $x++)
							{
								//$command_file->modio_mkdirs_copy( $final[$x]['to_path']) ;
								$command_file->afile[] = 'copy ' . $final[$x]['from_path'] . $final[$x]['from_file'] . ' ../../../' . $final[$x]['to_path'] . $final[$x]['to_file'] ;

//echo 'copy ' . $final[$x]['from_path'] . $final[$x]['from_file'] . ' ../../../' . $final[$x]['to_path'] . $final[$x]['to_file'] . "<br>\n" ;
							}
						}
					}
				}
			}


			// if we failed then halt processing
			if ($bad_copy)
			{
				break ;
			}
		}


		//
		// we are done!  close up shop and stop processing
		//
		else if ($commands[$i]['command'] == 'CLOSE')
		{
			// if we haven't dumped the find_array, then do it now
			if (count($find_array) != 0)
			{
				//   also, see if we need to write the lines in preview format
				$do_preview = ((strstr($commands[$i-1]['command'], 'IN-LINE')) && ($preview)) ? true : false ;
				write_find_array( $find_array, $file_list, $do_preview) ;
				$find_array = array() ;
			}

			// if we have a file open, close it now
			if (!complete_file_reproduction( $file_list))
			{
				// close failed; throw errors and halt
				for ($errs=0; $errs<count($file_list); $errs++)
				{
					display_error( '<b>' . $lang['EM_err_critical_error'] . "</b><br /><br />\n" . $file_list[$errs]->err_msg . "<br />\n" . $lang['EM_line_num'] . $commands[$i]['line']) ;
				}

				// halt processing
				break ;
			}

			$body[$i] = array() ;
			$failed = false ;
			$exec_close = true ;
		}
		else
		{
			$bad_command = true;
		}

		//
		// where unloved commands go ;-)
		//
		if ($bad_command)
		{
			$processed = false ;
			$num_unprocessed++ ;
			if ($mode == 'process')
			{
				display_unprocessed_line( $commands[$i], $body[$i]) ;
			}
		}


		// we processed the command, increase our count and display command info on screen
		if (($processed) && ($mode == 'process'))
		{
			$num_processed++ ;
			display_line( $commands[$i], $body[$i]) ;
		}
	}

	// close the ftp connection
	$command_file->modio_cleanup('move') ;

	//
	// we will now finish up the download or display file if that's what we're doing
	//
	if (($mode == 'display_file') || ($mode == 'download_file'))
	{
		// if we have a file open, close it now
		if (!$exec_close)
		{
			// if we haven't dumped the find_array, then do it now
			if (count($find_array) != 0)
			{
				//   also, see if we need to write the lines in preview format
				$do_preview = (strstr($commands[$i-1]['command'], 'IN-LINE')) ? true : false ;
				write_find_array( $find_array, $file_list, $do_preview) ;
			}

			// not likely a close error will be thrown
			complete_file_reproduction( $file_list) ;
		}

		// make sure we have the right file
		for ($file=0; $file<count($file_list); $file++)
		{
			// make sure this is what we are looking for, otherwise keep looking
			if ($orig_file != ($file_list[$file]->path . $file_list[$file]->filename))
			{
				continue ;
			}

			// write out the lines
			$preview_display = false ;
			for ($i=0; $i<count($file_list[$file]->afile); $i++)
			{
				// writing to file, so do NOT use htmlspecial chars
				if ($mode == 'download_file')
				{
					echo $file_list[$file]->afile[$i] ;
				}

				// writing to screen so you damn well better use htmlspecial chars!
				else
				{
					// if we encountered a line with the designated EM preview symbol then make it stand out
					if (substr($file_list[$file]->afile[$i], 0, 4) == 'EM>>')
					{
						// the first line of a preview display, being bolding
						if (!$preview_display)
						{
							echo '</PRE><b class="preview"><PRE>' . htmlspecialchars(substr($file_list[$file]->afile[$i], 4) ) ;
						}

						// special case: the very last line of the file, end the bolding
						else if ($i == (count($file_list[$file]->afile)-1))
						{
							echo htmlspecialchars(substr($file_list[$file]->afile[$i], 4) ) . '</PRE></b><PRE>' ;
						}

						// a middle line of the preview display, just print the line
						else
						{
							echo htmlspecialchars(substr($file_list[$file]->afile[$i], 4) ) ;
						}

						$preview_display = true ;
					}

					// first line following a preview display line, end the bolding and then carry on
					else if ($preview_display)
					{
						echo '</PRE></b><PRE>' . htmlspecialchars($file_list[$file]->afile[$i]) ;
						$preview_display = false ;
					}

					// normal line
					else
					{
						echo htmlspecialchars($file_list[$file]->afile[$i]) ;
					}
				}
			}

			// finish the html tag
			if ($mode == 'display_file')
			{
				echo "</PRE>\n" ;
			}

			// done! done! done!
			exit ;
		}

		// didn't find the file!  OH CRAP!
		echo sprintf($lang['EM_err_modify'], $orig_file)  . "\n" ;
		exit ;
	}


	//
	// fill in the template info
	//
	$mod_title = '' ;
	$mod_author_handle = '' ;
	$mod_author_email = '' ;
	$mod_author_name = '' ;
	$mod_author_url = '' ;
	$mod_description = '' ;
	$mod_version = '' ;
	$compliant = false ;

	// get the properties of the MOD so we can display them nicely
	get_mod_properties( $install_path . '/' . $install_file, $mod_title, $mod_author_handle, $mod_author_email, $mod_author_name, $mod_author_url, $mod_description, $mod_version, $compliant) ;

	$mod_themes = get_themes() ;
	if ( $mod_themes == '')
	{
		message_die( CRITICAL_ERROR, $lang['EM_err_theme_info']) ;
	}
	$mod_langs = get_languages('../language') ;

	$mod_title = str_replace("'", "''", $mod_title) ;
	$mod_version = str_replace("'", "''", $mod_version) ;
	$mod_author_handle = str_replace("'", "''", $mod_author_handle) ;
	$mod_author_email = str_replace("'", "''", $mod_author_email) ;
	$mod_author_name = str_replace("'", "''", $mod_author_name) ;
	$mod_author_url = str_replace("'", "''", $mod_author_url) ;
	$mod_description = str_replace("'", "''", $mod_description) ;
	$phpbb_version = get_phpbb_version() ;
	if ($phpbb_version == '')
	{
		message_die( GENERAL_ERROR, $lang['EM_err_phpbb_ver']);
	}
	$print_path = 'admin' . substr($install_path, 1) ;

	// fill in the template with all our info
	$template->assign_vars(array(
		'S_ACTION' => append_sid('admin_easymod.' . $phpEx),
		'L_MOD_DATA' => $lang['EM_Mod_Data'],
		'L_MOD_TITLE' => $lang['EM_Mod_Title'],
		'L_AUTHOR' => $lang['EM_Author'],
		'L_THEMES' => $lang['EM_Proc_Themes'],
		'L_LANGUAGES' => $lang['EM_Proc_Languages'],
		'L_FILES' => $lang['EM_Files'],
		'L_UNPROCESSED' => $lang['EM_unprocessed_commands'],
		'L_UNPROCESSED_DESC' => $lang['EM_unprocessed_desc'],
		'L_PROCESSED' => $lang['EM_processed_commands'],
		'L_PROCESSED_DESC' => $lang['EM_processed_desc'],

		'INSTALL_PATH' => $print_path,
		'TITLE' => $mod_title,
		'VERSION' => $mod_version,
		'MOD_FILE' => $install_file,
		'AUTHOR' => $mod_author_handle,
		'EMAIL' => $mod_author_email,
		'REAL_NAME' => $mod_author_name,
		'URL' => $mod_author_url,

		'THEMES' => $mod_themes,
		'LANGUAGES' => $mod_langs,
		'FILES' => $files_edited,
		'PROCESSED' => $num_processed,
		'UNPROCESSED' => $num_unprocessed,
		'PREVIEW' => $preview,
		'EM_PASS' => $password)
	);


	// if we succeed, tell them where to go from here (1 step down, 2 more to go)
	if ( !$failed)
	{
		// we'll want to remember the command file steps, so pass them along
		$hidden = '' ;
		for ($i=0; $i<count( $command_file->afile); $i++)
		{
			$hidden .= '<input type="hidden" name="command_step'.$i.'" value="' . $command_file->afile[$i] . "\">\n";
		}
		$hidden .= '<input type="hidden" name="num_command_steps" value="' . $i . "\">\n" ;

		// load up any SQL commands into hidden fields as well
		for ($i=0; $i<count( $sql); $i++)
		{
			$line = '' ;
			for ($j=0; $j<count($sql[$i]); $j++)
			{
				$line .= $sql[$i][$j] ;
			}
			$hidden .= '<input type="hidden" name="SQL'.$i.'" value="' . $line . "\">\n";
		}
		$hidden .= '<input type="hidden" name="num_sql_steps" value="' . $i . "\">\n" ;

		// put DIY INSTRUCTIONS in hidden fields
		for($i = 0; $i < count($diy); $i++ )
		{
			$line = '' ;
			for ($j=0; $j<count($diy[$i]); $j++)
			{
				$line .= $diy[$i][$j] ;
			}
			$hidden .= '<input type="hidden" name="diy_array[]" value="' . htmlspecialchars($line) . "\" />\n";
		}

		$template->assign_block_vars('success', array(
			'L_STEP' => $lang['EM_proc_step1'],
			'L_COMPLETE' => $lang['EM_proc_complete'],
			'L_DESC' => $lang['EM_proc_desc'],
			'L_NEXT_STEP' => $lang['EM_next_step'],

			'TITLE' => $mod_title,
			'INSTALL_PATH' => $print_path,

			'HIDDEN' => $hidden,
			'MOD_FILE' => $install_file,
			'MOD_PATH' => $install_path)
		) ;
	}

	// if we failed, then we'll report the bad news and what to do
	else
	{
		$template->assign_block_vars('fail', array(
			'L_TITLE' => $lang['EM_error_detail'],
			'L_FAILED' => $lang['EM_proc_failed'],
			'L_FAILED_DESC' => $lang['EM_proc_failed_desc'],
			'ERROR_MESSAGE' => $fail_message)
		) ;
	}
}

//
// setup the SQL processing - skip this step in preview mode!
//
else if (($mode == 'SQL_view') && (!$preview))
{
	// get the vars we are passing along
	$themes = (isset($HTTP_POST_VARS['themes'])) ? htmlspecialchars($HTTP_POST_VARS['themes']) : '' ;
	$languages = (isset($HTTP_POST_VARS['languages'])) ? htmlspecialchars($HTTP_POST_VARS['languages']) : '' ;
	$files = (isset($HTTP_POST_VARS['files'])) ? intval($HTTP_POST_VARS['files']) : 0 ;
	$num_proc = (isset($HTTP_POST_VARS['num_proc'])) ? intval($HTTP_POST_VARS['num_proc']) : 0 ;
	$num_unproc = (isset($HTTP_POST_VARS['num_unproc'])) ? intval($HTTP_POST_VARS['num_unproc']) : 0 ;
	$diy = (isset($HTTP_POST_VARS['diy_array'])) ? $HTTP_POST_VARS['diy_array'] : array();

	// get the post process operations and prepare to send them to the next step
	$num_command_steps = (isset($HTTP_POST_VARS['num_command_steps'])) ? intval($HTTP_POST_VARS['num_command_steps']) :0;
	$hidden = '' ;
	for ( $i=0; $i<$num_command_steps; $i++)
	{
		$var_name = 'command_step' . $i ;
		if ( isset($HTTP_POST_VARS[$var_name]))
		{
			$hidden .= '<input type="hidden" name="command_step'.$i.'" value="' . $HTTP_POST_VARS[$var_name]."\">\n";
		}
	}
	$hidden .= '<input type="hidden" name="num_command_steps" value="' . $i . "\">\n" ;

	// put DIY instructions in hidden vars
	for($i = 0; $i < count($diy); $i++ )
	{
		$hidden .= '<input type="hidden" name="diy_array[]" value="' . stripslashes(htmlspecialchars($diy[$i])) . "\" />\n";
	}

	// get the SQL commands we are going to translate
	$sql = array() ;
	$num_sql_steps = (isset($HTTP_POST_VARS['num_sql_steps'])) ? intval($HTTP_POST_VARS['num_sql_steps']) : 0 ;
	for ( $i=0; $i<$num_sql_steps; $i++)
	{
		$var_name = 'SQL' . $i ;
		if ( isset($HTTP_POST_VARS[$var_name]))
		{
			if (isset($HTTP_POST_VARS[$var_name]))
			{
				$sql[] = trim(stripslashes($HTTP_POST_VARS[$var_name])) ;
			}
		}
	}

	// Show the SQL template
	$template->set_filenames(array(
		'body' => 'admin/mod_sql_body.tpl')
	);


	// turn the psuedo mysql into SQL for this user's DB type
	include($phpbb_root_path . 'admin/em_includes/em_schema.' . $phpEx) ;
	$formatted_sql = array() ;
	$error = '' ;
	for ($i=0; $i<count($sql); $i++)
	{
		$return_sql = handle_db_alteration( $sql[$i], $error ) ;
		if ( $error != '')
		{
			$template->assign_block_vars( 'error', array('ERROR_MSG' => $error));
			break ;
		}

		for ($j=0; $j<count($return_sql); $j++)
		{
			$formatted_sql[] = $return_sql[$j] ;
		}
	}

	// print message if there is no SQL to worry about
	if (count($sql) == 0)
	{
		$template->assign_block_vars( 'no_sql', array());
		$template->assign_vars(array('L_NO_SQL' => $lang['EM_no_sql']));
		$error = 'none' ;
	}

	// display the list of SQL to generate and give use the option to not run them; display warnings if needed
	$drop_warning = false ;
	$steps = 0 ;
	for ($i=0; $i<count($formatted_sql); $i++)
	{
		// if there is an error, then skip this
		if ( $error != '')
		{
			break ;
		}

		$row_class = ( !($i % 2) ) ? $theme['td_class1'] : $theme['td_class2'];

		// see if this is the warning about dropping columns in postgresql
		$split = explode(' ', $formatted_sql[$i]) ;
		$hidden_sql = '' ;
		if ($split[0] == 'ABORTED:')
		{
			$formatted_sql[$i] = '<b>' . $formatted_sql[$i] . '</b>' ;
			$hidden_sql = '' ;
			$check = '' ;
		}
		else
		{
//////////////// WHAT IF THERE IS HTML IN THE SQL??
			$hidden_sql = '<input type="hidden" name="SQL' . $steps . '" value="' . $formatted_sql[$i] . '">' ;
			$check = '<input type="checkbox" name="check_SQL' . $steps . '" checked="checked">' ;
			$steps++ ;
		}

		// see if there are any DROP's we should warn the user about; we only want to display the warning once
		if ((!$drop_warning) && ((strtoupper($split[0]) == 'DROP') || (strtoupper($split[3]) == 'DROP')))
		{
			$template->assign_block_vars( 'drop_warning', array());
			$template->assign_vars(array(
				'L_SQL_DROP_WARN' => $lang['EM_sql_drop_warning'],
				'L_URGENT_WARNING' => $lang['EM_urgent_warning'])
			);
			$drop_warning = true ;
		}
		

		$template->assign_block_vars( 'sql_row', array(
			'ROW_CLASS' => $row_class,
			'HIDDEN_SQL' => $hidden_sql,
			'CHECK' => $check,
			'DISPLAY_SQL' => $formatted_sql[$i])
		);
	}
	$hidden .= '<input type="hidden" name="num_sql_steps" value="' . $steps . "\">\n" ;

	// if it's postgre or mssql, let them know I don't have things quite right yet!
	if (( $error == '') && ((SQL_LAYER == 'mssql') || (SQL_LAYER == 'postgresql')))
	{
		$link = 'http://area51.phpbb.com/phpBB/viewtopic.php?t=' ;
		$link .= (SQL_LAYER == 'postgresql') ? '15388' : '15389' ;

		$template->assign_block_vars('experimental', array());
		$template->assign_vars(array(
			'L_EXPERIMENTAL_EXPLAIN' => sprintf($lang['EM_experimental_explain'], SQL_LAYER, $link))
		);
	}

	// if it's msaccess, let them know that we can't add defaults :(
	if (( $error == '') && (SQL_LAYER == 'msaccess'))
	{
		$template->assign_block_vars( 'msaccess', array());
		$template->assign_vars(array('L_SQL_MSACCESS_WARN' => $lang['EM_sql_msaccess_warning']));
	}


	// fill the template
	$template->assign_vars(array(
		'S_ACTION' => append_sid($phpbb_root_path . 'admin/admin_easymod.'.$phpEx),

		'L_STEP' => $lang['EM_sql_step2'],
		'L_SQL_ALPHA2' => $lang['EM_SQL_Alpha2'],
		'L_SQL_INTRO' => $lang['EM_sql_intro_explain'],
		'L_ALTERATIONS' => $lang['EM_Alterations'],
		'L_PSEUDO' => sprintf($lang['EM_proposed_alerations'], SQL_LAYER),
		'L_ALLOW' => $lang['EM_Allow'],
		'L_PERFORM' => $lang['EM_Perform'],
		'L_COMPLETE' => $lang['EM_complete_install'],
		'L_NOTICE' => $lang['EM_notice'],

		'L_SQL_PROCESS_ERROR' => $lang['EM_sql_process_error'],
		'L_NO_SQL_PREFORMED' => $lang['EM_no_sql_preformed'],
		'L_FOLLOWING_ERROR' => $lang['EM_following_error'],

		'THEMES' => $themes,
		'LANGUAGES' => $languages,
		'FILES' => $files,
		'PROCESSED' => $num_proc,
		'UNPROCESSED' => $num_unproc,
		'SQL_LINES' => $num_sql_lines,
		'MOD_FILE' => $install_file,
		'MOD_PATH' => $install_path,
		'MODE' => ($error == '') ? 'SQL_execute' : 'post_process',
		'HIDDEN' => $hidden,
		'EM_PASS' => $password)
	);
}

else if ( $mode == 'SQL_execute' )
{
	// get the vars we are passing along
	$themes = (isset($HTTP_POST_VARS['themes'])) ? htmlspecialchars($HTTP_POST_VARS['themes']) : '' ;
	$languages = (isset($HTTP_POST_VARS['languages'])) ? htmlspecialchars($HTTP_POST_VARS['languages']) : '' ;
	$files = (isset($HTTP_POST_VARS['files'])) ? intval($HTTP_POST_VARS['files']) : 0 ;
	$num_proc = (isset($HTTP_POST_VARS['num_proc'])) ? intval($HTTP_POST_VARS['num_proc']) : 0 ;
	$num_unproc = (isset($HTTP_POST_VARS['num_unproc'])) ? intval($HTTP_POST_VARS['num_unproc']) : 0 ;
	$diy = (isset($HTTP_POST_VARS['diy_array'])) ? $HTTP_POST_VARS['diy_array'] : array();

	// get the post process operations and prepare to send them to the next step
	$num_command_steps = (isset($HTTP_POST_VARS['num_command_steps'])) ? intval($HTTP_POST_VARS['num_command_steps']) :0;
	$hidden = '' ;
	for ( $i=0; $i<$num_command_steps; $i++)
	{
		$var_name = 'command_step' . $i ;
		if ( isset($HTTP_POST_VARS[$var_name]))
		{
			$hidden .= '<input type="hidden" name="command_step'.$i.'" value="' . $HTTP_POST_VARS[$var_name]."\">\n";
		}
	}
	$hidden .= '<input type="hidden" name="num_command_steps" value="' . $i . "\">\n" ;

	// put DIY instructions in hidden vars
	for($i = 0; $i < count($diy); $i++ )
	{
		$hidden .= '<input type="hidden" name="diy_array[]" value="' . stripslashes(htmlspecialchars($diy[$i])) . "\" />\n";
	}

	// get the SQL commands we are going to execute
	$num_sql_steps = (isset($HTTP_POST_VARS['num_sql_steps'])) ? intval($HTTP_POST_VARS['num_sql_steps']) : 0 ;
	$sql = array() ;
	$failure = false ;
	for ($i=0; $i<$num_sql_steps; $i++)
	{
		$sql_name = 'SQL' . $i ;
		$sql_check = 'check_' . $sql_name ;
		$sql_line = ( !empty($HTTP_POST_VARS[$sql_name]) ) ? stripslashes(trim($HTTP_POST_VARS[$sql_name])) : '';
		$sql_allow = ( isset($HTTP_POST_VARS[$sql_check])) ? ( ($HTTP_POST_VARS[$sql_check]) ? TRUE : 0 ) : 0	 ;

		if ($failure)
		{
			$sql[] = array('command' => $sql_line, 'status' => '<b>' . $lang['EM_not_attempted'] . '</b>') ;
		}
		else if ($sql_allow)
		{

			if( !($result = $db->sql_query($sql_line)) )
			{
				// set the status
				$sql[] = array('command' => $sql_line, 'status' => '<b>' . $lang['EM_failed'] . '</b>') ;
				$failure = true ;

				$error = $db->sql_error() ;
//echo "[" . $error['message'] . "][" . $error['code'] . "]<br>\n" ;
//exit ;
				// load up an error message
				$template->assign_block_vars( 'sql_error', array(
					'LINE' => $sql_line,
					'ERROR_CODE' => $error['code'],
					'ERROR_MSG' => $error['message'])
				);
				$template->assign_vars(array(
					'L_SQL_ERROR' => $lang['EM_sql_error'],
					'L_SQL_ERROR_EXPLAIN' => $lang['EM_sql_error_explain'],
					'L_FAILED_LINE' => $lang['EM_failed_line'],
					'L_SQL_HALTED' => $lang['EM_sql_halted'])
				);
			}
			else
			{
				$sql[] = array('command' => $sql_line, 'status' => $lang['EM_success']) ;
			}
		}
		else
		{
			$sql[] = array('command' => $sql_line, 'status' => '<b>' . $lang['EM_skipped'] . '</b>') ;
		}
	}


	// Show the SQL template
	$template->set_filenames(array(
		'body' => 'admin/mod_sql_body.tpl')
	);

	// display the list of SQL to generate and give use the option to not run them; display warnings if needed
	$drop_warning = false ;
	$steps = 0 ;
	for ($i=0; $i<count($sql); $i++)
	{
		$row_class = ( !($i % 2) ) ? $theme['td_class1'] : $theme['td_class2'];
		$template->assign_block_vars( 'sql_row', array(
			'ROW_CLASS' => $row_class,
			'HIDDEN' => '',
			'CHECK' => $sql[$i]['status'],
			'DISPLAY_SQL' => $sql[$i]['command'])
		);
	}
	$sql_intro = $lang['EM_line_results'];
	$sql_intro .= (!$failure) ? ' - <b>' . $lang['EM_all_lines_successfull'] . '</b>' : ' - <b>' . $lang['EM_errors_detected'] . '</b>' ;

	// fill the template
	$template->assign_vars(array(
		'L_STEP' => $lang['EM_sql_step2'],
		'L_SQL_ALPHA2' => $lang['EM_SQL_Alpha2'],
		'L_SQL_INTRO' => $sql_intro,
		'L_ALTERATIONS' => $lang['EM_processing_results'],
		'L_PSEUDO' => $lang['EM_sql_attempted'],
		'L_ALLOW' => $lang['EM_Allow'],
		'L_PERFORM' => $lang['EM_Perform'],
		'L_COMPLETE' => $lang['EM_complete_install'],

		'THEMES' => $themes,
		'LANGUAGES' => $languages,
		'FILES' => $files,
		'PROCESSED' => $num_proc,
		'UNPROCESSED' => $num_unproc,
//		'SQL_LINES' => $i,
		'SQL_LINES' => $num_sql_lines,
		'MOD_FILE' => $install_file,
		'MOD_PATH' => $install_path,
		'MODE' => 'post_process',
		'HIDDEN' => $hidden,
		'EM_PASS' => $password)
	);
}

//
// last step!  move the files into place - force this step if in preview mode
//
else if (($mode == 'post_process') || ($preview))
{
	// get the info we are passing along
	$themes = (isset($HTTP_POST_VARS['themes'])) ? htmlspecialchars($HTTP_POST_VARS['themes']) : '' ;
	$languages = (isset($HTTP_POST_VARS['languages'])) ? htmlspecialchars($HTTP_POST_VARS['languages']) : '' ;
	$files = (isset($HTTP_POST_VARS['files'])) ? intval($HTTP_POST_VARS['files']) : 0 ;
	$num_proc = (isset($HTTP_POST_VARS['num_proc'])) ? intval($HTTP_POST_VARS['num_proc']) : 0 ;
	$num_unproc = (isset($HTTP_POST_VARS['num_unproc'])) ? intval($HTTP_POST_VARS['num_unproc']) : 0 ;
	$diy = (isset($HTTP_POST_VARS['diy_array'])) ? $HTTP_POST_VARS['diy_array'] : array();

	$hidden = '';

	// explode each new line so they can have their own bullet
	if ( count($diy) )
	{
		$template->assign_block_vars('diy_switch', array(
			'MODE'		=> 'diy_process',
			'U_ACTION'	=> $phpbb_root_path . 'admin/admin_easymod.'.$phpEx,
			'EM_PASS' => $password)
		);

		$diy_process = array();
		for( $i = 0; $i < count($diy); $i++ )
		{
			$diy_process = array_merge($diy_process, explode("\n", $diy[$i]));
		}

		for( $i = 0; $i < count($diy_process); $i++ )
		{
			$diy_process[$i] = trim($diy_process[$i]);
			if ( !empty($diy_process[$i]) )
			{
				$hidden .= '<input type="hidden" name="diy_array[]" value="' . stripslashes(htmlspecialchars($diy_process[$i])) . "\" />\n";

				$template->assign_block_vars('diy_switch.diyrow', array(
					'INSTRUCTIONS'	=> stripslashes(htmlspecialchars($diy_process[$i])))
				);
			}
		}
	}

	// get the post process operations
	$num_command_steps = (isset($HTTP_POST_VARS['num_command_steps'])) ? intval($HTTP_POST_VARS['num_command_steps']) :0;
	$command = array() ;
	for ( $i=0; $i<$num_command_steps; $i++)
	{
		$var_name = 'command_step' . $i ;
		if ( isset($HTTP_POST_VARS[$var_name]))
		{
			$command[] = htmlspecialchars( $HTTP_POST_VARS[$var_name]) ;
		}
	}


	// Show the post process page
	$template->set_filenames(array(
		'body' => 'admin/mod_complete.tpl')
	);


	// write the command files
	$command_file = get_em_settings( 'post_process.sh', '', $password, $preview) ;
	$command_bat = new mod_io( 'post_process.bat', '', $command_file->read_method, $command_file->write_method, $command_file->move_method, $command_file->ftp_user, $command_file->ftp_pass, $command_file->ftp_path, $command_file->ftp_host, $command_file->ftp_port, $command_file->ftp_type, $command_file->ftp_cache) ;

	// open the command file: config=true,command=true
	if (( !$command_file->modio_open(true)) || ( !$command_bat->modio_open(true)))
	{
		$command_file->err_msg = $lang['EM_trace'] . ':<br /> main[2]->' . $command_file->err_msg ;
		message_die( GENERAL_ERROR, '<br />' . $lang['EM_err_open_pp'] . '<br />' . $lang['EM_err_cwd'] . ': ' . getcwd() . '<br />') ;
	}

	// this is really more about moving the other files than is about the command file; establish the FTP connection
	//  for moving files if necessary
	if (!$command_file->modio_prep('move'))
	{
		$command_file->err_msg = $lang['EM_trace'] . ': main[3]->' . $command_file->err_msg ;
		message_die( GENERAL_ERROR, '<b>' . $lang['EM_err_critical_error'] . ':</b><br /> ' . $command_file->err_msg . '<br />') ;
	}
	// share FTP attributes with the bat file
	$command_bat->emftp = $command_file->emftp ;


////////////////////
////////////////////
////////////////////-md5
////////////////////
////////////////////
//	$em_pass = get_em_pw() ;
	$em_pass = $password ;

	// execute the move!
	$mod_count = 0 ;
	for ($i=0; $i<$num_command_steps; $i++)
	{
/////////BUG: if there is a dir with spaces in the name that is going to cause problems
		$parms = explode(' ', $command[$i]) ;
		if ( $parms[0] == 'copy')
		{
			// write to the post-process script
			$command_file->modio_write( 'cp ' . $parms[1] . ' ' . $parms[2] . "\n") ;
			$command_bat->modio_write( str_replace('/', "\\", $command[$i]) . "\r\n") ;

			$split_from = explode('/', $parms[1]) ;
			$split_to = explode('/', $parms[2]) ;

			// set vars depending if this is a backup or a download file
			if ($split_to[0] == 'backups')
			{
				$from = $parms[1] ;
				$to = $parms[2] ;
				$type = $lang['EM_pp_backup'] ;
				$is_backup = true ;
				$link = append_sid('admin_easymod.' . $phpEx) . '&mode=display_backup&file=' . $parms[1] . "&password=$em_pass" ;
			}
			else
			{
				$from = $parms[1] ;
				$to = $parms[2] ;
				$type = $lang['EM_pp_download'] ;
				$is_backup = false ;
				$link = append_sid('admin_easymod.' . $phpEx) . '&mode=display_file&file=' . $parms[2] . "&password=$em_pass&install_file=$install_file&install_path=$install_path" ;
			}

			// create the directory before moving files into it
			// could be optimized such that modio_mkdirs_copy is only called once per
			// new directory, as opposed to once per original COPY action, but oh well...
			if ((substr($parms[1],0,9) != "processed") && (substr($parms[1],0,9) != "../../../"))
			{
				$command_file->modio_mkdirs_copy( substr(dirname($parms[2]),9).'/' ) ;
			}

			// now the magic happens ;-)
			$ret_value = $command_file->modio_move( $parms[2], $parms[1], $mod_count, $link, $type) ;
			$mod_count++ ;

			// if there is no return value then that means it didn't work; print the err_msg and bail
			if ($ret_value == '')
			{
				message_die( GENERAL_ERROR, '<b>' . $lang['EM_err_critical_error'] . ':</b> ' . $command_file->err_msg . '<br />' . $lang['EM_err_attempt_remainder'] . '<br />') ;
			}

			// move was a success, display the output
			else
			{
				// if the destination is a backup, then put in the backup listing
				if ($is_backup)
				{
					$template->assign_block_vars('backups', array(
						'FROM' => ((substr($from, 0, 9) == '../../../') ? substr($from, 9) : $from),
						'TO' => $ret_value)
					);
				}

				// put in the move list
				else
				{
					if (!(strstr($parms[1], 'processed/')) && ($ret_value != '<b>' . $lang['EM_pp_complete'] . '</b>') && ($ret_value != '<b>' . $lang['EM_pp_ready'] . '</b>'))
					{
						$ret_value = '<b>' . $lang['EM_pp_manual'] . '</b>' ;
					}

					$template->assign_block_vars('files', array(
						'FROM' => $from,
						'TO' => ((substr($to, 0, 9) == '../../../') ? substr($to, 9) : $to),
						'COMPLETED' => $ret_value)
					);
				}
			}
		}
	}

	$mod_title = '' ;
	$mod_author_handle = '' ;
	$mod_author_email = '' ;
	$mod_author_name = '' ;
	$mod_author_url = '' ;
	$mod_description = '' ;
	$mod_version = '' ;
	$compliant = false ;
	get_mod_properties( $install_path . '/' . $install_file, $mod_title, $mod_author_handle, $mod_author_email, $mod_author_name, $mod_author_url, $mod_description, $mod_version, $compliant) ;

	$template->assign_vars(array(
		'S_ACTION' => append_sid('admin_easymod.' . $phpEx),

		'L_STEP' => $lang['EM_pp_step3'],
		'L_COMPLETE' => $lang['EM_pp_install_comp'],
		'L_COMP_DESC' => $lang['EM_pp_comp_desc'],
		'L_COPY_TO' => $lang['EM_pp_to'],
		'L_COPY_STATUS' => $lang['EM_pp_status'],
		'L_COPY_FROM' => sprintf( $lang['EM_pp_from'], $install_path . 'processed/'),
		'L_MAKING_BACKUPS' => sprintf( $lang['EM_pp_backups'], $install_path . 'backups/'),

		'L_MOD_DATA' => $lang['EM_Mod_Data'],
		'L_MOD_TITLE' => $lang['EM_Mod_Title'],
		'L_AUTHOR' => $lang['EM_Author'],
		'L_THEMES' => $lang['EM_Proc_Themes'],
		'L_LANGUAGES' => $lang['EM_Proc_Languages'],
		'L_FILES' => $lang['EM_Files'],
		'L_PROCESSED' => $lang['EM_processed_commands'],
		'L_UNPROCESSED' => $lang['EM_unprocessed_commands'],
		'L_DB_ALTERATIONS' => $lang['EM_database_alterations'],
		'L_TABLES_ADDED' => $lang['EM_tables_added'],
		'L_TABLES_ALTERED' => $lang['EM_tables_altered'],
		'L_ROWS_ADDED' => $lang['EM_rows_added'],
		'L_DEPENDS_ON_MOVE' => $lang['EM_text_depend_move'],

		'L_DIY_INSTRUCTIONS' => $lang['DIY_Instructions'],
		'L_DIY_INTRO' => $lang['DIY_intro'],
		'L_FINAL_INSTALL_STEP' => $lang['Final_install_step'],

		'INSTALL_PATH' => $print_path,
		'TITLE' => $mod_title,
		'VERSION' => $mod_version,
		'MOD_FILE' => $install_file,
		'AUTHOR' => $mod_author_handle,
		'EMAIL' => $mod_author_email,
		'REAL_NAME' => $mod_author_name,
		'URL' => $mod_author_url,

		'MOD_FILE' => $install_file,
		'MOD_PATH' => $install_path,
		'MOD_COUNT' => $mod_count,
		'THEMES' => $themes,
		'LANGUAGES' => $languages,
		'FILES' => $files,
		'PROCESSED' => $num_proc,
		'UNPROCESSED' => $num_unproc,
		
		'HIDDEN'	=> $hidden)
	);


	// finish the script generation
	if ((!$command_file->modio_close(true)) || (!$command_bat->modio_close(true)))
	{
		message_die( GENERAL_ERROR, '<br />' . $lang['EM_err_write_pp'] . '<br />' . $lang['EM_err_cwd'] . ': ' . getcwd() . '<br />') ;
	}

	// closs the FTP session
	$command_file->modio_cleanup('move') ;	


	$phpbb_version = get_phpbb_version() ;
	$mod_title = str_replace("'", "''", substr( $mod_title, 0, 255)) ;
	$mod_author_handle = str_replace("'", "''", substr( $mod_author_handle, 0, 25)) ;
	$mod_author_email = str_replace("'", "''", substr( $mod_author_email, 0, 100)) ;
	$mod_author_name = str_replace("'", "''", substr( $mod_author_name, 0, 100)) ;
	$mod_author_url = str_replace("'", "''", substr( $mod_author_url, 0, 100)) ;
	$mod_description = str_replace("'", "''", $mod_description) ;
	$mod_version = str_replace("'", "''", substr( $mod_version, 0, 15)) ;

	$sql = 'INSERT INTO ' . EASYMOD_TABLE . " ( mod_file, mod_title, mod_version, mod_author_handle, mod_author_email, mod_author_url, mod_author_name, mod_description, mod_process_date, mod_phpBB_version, mod_processed_themes, mod_processed_langs, mod_files_edited)
		VALUES ( '" . substr($install_path, 7) . $install_file . "', '$mod_title', '$mod_version', '$mod_author_handle', '$mod_author_email', '$mod_author_url', '$mod_author_name', '$mod_description', " . time() . ", '" . $phpbb_version . "', '" . $themes . "', '" . $languages . "', $files)";


	if ($preview)
	{
		// do not update the DB while in preview mode
	}
	else if ( !($result = $db->sql_query($sql)) )
	{
		message_die(GENERAL_ERROR, $lang['EM_err_em_info'], '', __LINE__, __FILE__, $sql);
	}
}

//
// show the DIY instructions
// move below post_process?
//
else if ( $mode == 'diy_process' )
{
	$diy = (isset($HTTP_POST_VARS['diy_array'])) ? $HTTP_POST_VARS['diy_array'] : array();

	// explode each new line so they can have their own bullet
	$diy_process = array();
	for( $i = 0; $i < count($diy); $i++ )
	{
		$diy_process = array_merge($diy_process, explode("\n", $diy[$i]));
	}

	for( $i = 0; $i < count($diy_process); $i++ )
	{
		$diy_process[$i] = trim($diy_process[$i]);
		if ( !empty($diy_process[$i]) )
		{
			$template->assign_block_vars('diyrow', array(
				'INSTRUCTIONS'	=> stripslashes(htmlspecialchars($diy_process[$i])))
			);
		}
	}

	// Show the SQL template
	$template->set_filenames(array(
		'body' => 'admin/mod_diy_body.tpl')
	);

	// fill the template
	$template->assign_vars(array(
		'L_STEP' => $lang['DIY_final'],
		'L_COMPLETE' => $lang['DIY_Instructions'],
		'L_DIY_INTRO' => $lang['DIY_intro'],
		'L_INSTALL_COMPLETE' => $lang['Install_complete'])
	);

}
	

// actually outputs the template date we've built
$template->pparse('body');

// output the footer
include('page_footer_admin.'.$phpEx);

?>
