Code: Select all
//
// 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 == 'uninstall' )
{
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' => sprintf($lang['EM_unprocessed_mods'], HOW_TO_INSTALL_MODS_URL),
'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'],
'S_ACTION' => append_sid('admin_easymod.' . $phpEx),
'EM_PASS' => htmlspecialchars($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();
check_file_scope($install_path . $install_file, $phpbb_root_path . $script_path);
$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
check_file_scope($process_file, $phpbb_root_path . $script_path, true);
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</body>\n</html>\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
//
check_file_scope($install_path . $install_file, $phpbb_root_path . $script_path);
$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') || $commands[$i-1]['command'] == 'INCREMENT') && ($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') || $commands[$i-1]['command'] == 'INCREMENT') && ($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') || $commands[$i-1]['command'] == 'INCREMENT') && ($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 / throw an error as appropriate
$err_level = FIND_OK;
for ( $file_count = 0; $file_count < count($file_list); $file_count++ )
{
for ( $j = 0; $j < count($find_array); $j++ )
{
$increment_search = ($search_fragment != '') ? $search_fragment : $search_array[$j];
$result = increment_wildcard($inc_data[1], $inc_data[2], $increment_search, $find_array[$file_count][$j]);
if ($result !== false)
{
$find_array[$file_count][$j] = $result;
break;
}
}
if ($j == count($find_array))
{
// halt if this is an english lang file
if (strstr($file_list[$file_count]->path, 'language/lang_english'))
{
$file_list[$file_count]->err_msg = '<b>' . $lang['EM_err_critical_error'] . '</b><br /><br />';
$err_level = FIND_FAIL_CRITICAL;
}
// halt if this is a subsilver style file
else if (strstr($file_list[$file_count]->path, 'templates/subSilver'))
{
$file_list[$file_count]->err_msg = '<b>' . $lang['EM_err_critical_error'] . '</b><br /><br />';
$err_level = FIND_FAIL_CRITICAL;
}
// if a different lang, then allow to continue processing
else if (strstr($file_list[$file_count]->path, 'language/lang_'))
{
$file_list[$file_count]->err_msg = '<b>' . $lang['EM_err_warning'] . '</b><br /><br />';
$err_level = FIND_FAIL_OK;
}
// if a different style file, then allow to continue processing
else if (strstr($file_list[$file_count]->path, 'templates/'))
{
$file_list[$file_count]->err_msg = '<b>' . $lang['EM_err_warning'] . '</b><br /><br />';
$err_level = FIND_FAIL_OK;
}
// any other file then halt processing
else
{
$file_list[$file_count]->err_msg = '<b>' . $lang['EM_err_critical_error'] . '</b><br /><br />';
$err_level = FIND_FAIL_CRITICAL;
}
$file_list[$file_count]->err_msg .= sprintf($lang['EM_err_ifind_fail'], $file_list[$file_count]->path . trim($file_list[$file_count]->filename)) . ':<br /><br />' . htmlspecialchars($search_fragment) . "<br />\n";
}
}
// 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($err_level, $file_list, $commands[$i]['line'], true, $find_array))
{
break;
}
}
//
// 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') || $commands[$i-1]['command'] == 'INCREMENT') && ($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') || $commands[$i-1]['command'] == 'INCREMENT') && ($preview)) ? 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;
$preview_count = count($file_list[$file]->afile);
for ($i=0; $i<$preview_count; $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><pre class="preview">' . htmlspecialchars(substr($file_list[$file]->afile[$i], 4));
}
// special case: the very last line of the file, end the bolding
else if ($i == ($preview_count-1))
{
echo htmlspecialchars(substr($file_list[$file]->afile[$i], 4));
}
// 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><pre class="normal">' . 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</body>\n</html>\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');
$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' => htmlspecialchars($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="' . htmlspecialchars($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'])) ? stripslashes($HTTP_POST_VARS['themes']) : '';
$languages = (isset($HTTP_POST_VARS['languages'])) ? stripslashes($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')
);
// Parser SQL statements, if any
$formatted_sql = array();
$sql_warnings = array();
$error = '';
if( count($sql) > 0 )
{
// Use the old SQL Parser for MS-Access, support for which has been dropped
if( SQL_LAYER == 'msaccess' )
{
// turn the psuedo mysql into SQL for this user's DB type
require($phpbb_root_path . 'admin/em_includes/em_schema.' . $phpEx);
for( $i = 0; $i < count($sql); $i++ )
{
$return_sql = handle_db_alteration($sql[$i], $error);
if (!empty($error))
{
$template->assign_block_vars('error', array('ERROR_MSG' => $error));
break;
}
for( $j = 0; $j < count($return_sql); $j++ )
{
$formatted_sql[] = $return_sql[$j];
}
}
}
// Use the new SQL Parser to deal with any other SQL server
else
{
// Load the new SQL Parser
if( @file_exists($phpbb_root_path . 'language/lang_' . $board_config['default_lang'] . '/lang_sql_parser.' . $phpEx) )
{
require($phpbb_root_path . 'language/lang_' . $board_config['default_lang'] . '/lang_sql_parser.' . $phpEx);
}
else
{
require($phpbb_root_path . 'language/lang_english/lang_sql_parser.' . $phpEx);
}
require($phpbb_root_path . 'includes/sql/sql_parser.' . $phpEx);
// Instatiate the SQL Parser object.
$sql_parser = new sql_parser();
// Parse and convert the SQL statements for this user's DB type.
$result = $sql_parser->parse_stream(implode("\n", $sql), $table_prefix);
if( $result & SQL_PARSER_ERROR )
{
$error = '<b>Error:</b><br />' . $sql_parser->error_message['message'] . '<br /><br /><b>SQL:</b><br />' . $sql_parser->sql_input[$sql_parser->sql_count];
$template->assign_block_vars('error', array('ERROR_MSG' => $error));
}
if( $result & SQL_PARSER_WARNINGS )
{
$sql_warnings = $sql_parser->warnings;
}
for( $j = 0; $j < count($sql_parser->sql_output); $j++ )
{
$formatted_sql[] = $sql_parser->sql_output[$j];
}
}
}
// print message if there is no SQL to worry about
else
{
$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 user the option to not run them; display warnings if needed
$drop_warning = false;
$steps = 0;
// if there was an error, then simply skip this
if (empty($error))
{
// Display warnings generated by the SQL Parser, if any
for( $i = 0; $i < count($sql_warnings); $i++ )
{
$sql_warnings_count = count($sql_warnings);
$template->assign_block_vars('warnings_block', array(
'TITLE' => sprintf($lang['EM_sql_warnings_reported'], $sql_warnings_count)
));
for( $j = 0; $j < $sql_warnings_count; $j++ )
{
$template->assign_block_vars('warnings_block.line', array(
'TEXT' => $sql_warnings[$j]['message']
));
}
}
// Show the mark/unmark commands
$template->assign_block_vars('sql_rows', array());
for( $i = 0; $i < count($formatted_sql); $i++ )
{
$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>' . htmlspecialchars($formatted_sql[$i]) . ';</b>';
$hidden_sql = '';
$check = '';
}
else
{
$formatted_sql[$i] = htmlspecialchars($formatted_sql[$i]) . ';';
$hidden_sql = '<input type="hidden" name="SQL' . $steps . '" value="' . htmlspecialchars($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,
'STMT_COUNT' => $i+1,
'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!
// Commented out since the new SQL Parser should process them nicely
// 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('admin_easymod.' . $phpEx),
'L_STEP' => $lang['EM_sql_step2'],
'L_SQL_INTRO' => $lang['EM_sql_intro_explain'],
'L_ALTERATIONS' => $lang['EM_Alterations'],
'L_PSEUDO' => sprintf($lang['EM_proposed_alterations'], SQL_LAYER),
'L_ALLOW' => $lang['EM_Allow'],
'L_PERFORM' => $lang['EM_Perform'],
'L_COMPLETE' => $lang['EM_complete_install'],
'L_NOTICE' => $lang['EM_notice'],
'L_MARK_ALL' => $lang['Mark_all'],
'L_UNMARK_ALL' => $lang['Unmark_all'],
'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,
'MOD_FILE' => $install_file,
'MOD_PATH' => $install_path,
'MODE' => ($error == '') ? 'SQL_execute' : 'post_process',
'HIDDEN' => $hidden,
'EM_PASS' => htmlspecialchars($password))
);
}
else if ( $mode == 'SQL_execute' )
{
// get the vars we are passing along
$themes = (isset($HTTP_POST_VARS['themes'])) ? stripslashes($HTTP_POST_VARS['themes']) : '';
$languages = (isset($HTTP_POST_VARS['languages'])) ? stripslashes($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' => htmlspecialchars($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
$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' => htmlspecialchars($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(
'S_ACTION' => append_sid('admin_easymod.' . $phpEx),
'L_STEP' => $lang['EM_sql_step2'],
'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,
'MOD_FILE' => $install_file,
'MOD_PATH' => $install_path,
'MODE' => 'post_process',
'HIDDEN' => $hidden,
'EM_PASS' => htmlspecialchars($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'])) ? stripslashes($HTTP_POST_VARS['themes']) : '';
$languages = (isset($HTTP_POST_VARS['languages'])) ? stripslashes($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',
'S_ACTION' => append_sid('admin_easymod.' . $phpEx),
'EM_PASS' => htmlspecialchars($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;
$processed_files = array();
// 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)
{
// this is relative to the phpBB directory
$from_file = (substr($from, 0, 9) == '../../../') ? substr($from, 9) : $from;
$processed_files[] = $from_file;
$template->assign_block_vars('backups', array(
'FROM' => $from_file,
'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));
$themes = str_replace("'", "''", $themes);
$languages = str_replace("'", "''", $languages);
if ($preview)
{
// do not update the DB while in preview mode
}
else
{
// We might come here from the 'Restore Backups' option, in this case we'll find the mod_id in the POST array.
if ( isset($HTTP_POST_VARS['mod_id']) && ($mod_id = intval($HTTP_POST_VARS['mod_id'])) > 0 )
{
// If we have restored backups, what we really need now is delete the MOD record.
$sql = 'DELETE FROM ' . EASYMOD_TABLE . " WHERE mod_id = $mod_id";
}
else
{
// Otherwise, we have just installed a new MOD.
$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 ( !($result = $db->sql_query($sql)) )
{
message_die(GENERAL_ERROR, $lang['EM_err_em_info'], '', __LINE__, __FILE__, $sql);
}
if( isset($mod_id) )
{
$sql = 'DELETE FROM ' . EASYMOD_PROCESSED_FILES_TABLE . " WHERE mod_id = $mod_id";
if ( !($result = $db->sql_query($sql)) )
{
message_die(GENERAL_ERROR, $lang['EM_err_em_info'], '', __LINE__, __FILE__, $sql);
}
}
else
{
// get the ID of the just installed MOD.
$mod_id = $db->sql_nextid();
for( $i = 0; $i < count($processed_files); $i++ )
{
$sql = 'INSERT INTO ' . EASYMOD_PROCESSED_FILES_TABLE . " (mod_processed_file, mod_id)
VALUES ('" . $processed_files[$i] . "', $mod_id)";
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);
?