function parseBoardMod($file, $testing = true, $undo = false, $theme_paths = array()) { global $boarddir, $sourcedir, $settings, $txt, $modSettings; @set_time_limit(600); $file = strtr($file, array("\r" => '')); $working_file = null; $working_search = null; $working_data = ''; $replace_with = null; $actions = array(); $everything_found = true; // This holds all the template changes in the standard mod file. $template_changes = array(); // This is just the temporary file. $temp_file = $file; // This holds the actual changes on a step counter basis. $temp_changes = array(); $counter = 0; $step_counter = 0; // Before we do *anything*, let's build a list of what we're editing, as it's going to be used for other theme edits. while (preg_match('~<(edit file|file|search|search for|add|add after|replace|add before|add above|above|before)>\\n(.*?)\\n</\\1>~is', $temp_file, $code_match) != 0) { $counter++; // Get rid of the old stuff. $temp_file = substr_replace($temp_file, '', strpos($temp_file, $code_match[0]), strlen($code_match[0])); // No interest to us? if ($code_match[1] != 'edit file' && $code_match[1] != 'file') { // It's a step, let's add that to the current steps. if (isset($temp_changes[$step_counter])) { $temp_changes[$step_counter]['changes'][] = $code_match[0]; } continue; } // We've found a new edit - let's make ourself heard, kind of. $step_counter = $counter; $temp_changes[$step_counter] = array('title' => $code_match[0], 'changes' => array()); $filename = parse_path($code_match[2]); // Now, is this a template file, and if so, which? foreach ($theme_paths as $id => $theme) { // If this filename is relative, if so take a guess at what it should be. if (strpos($filename, 'Themes') === 0) { $filename = $boarddir . '/' . $filename; } if (strpos($filename, $theme['theme_dir']) === 0) { $template_changes[$id][$counter] = substr($filename, strlen($theme['theme_dir']) + 1); } } } // Anything above $counter must be for custom themes. $custom_template_begin = $counter; // Reference for what theme ID this action belongs to. $theme_id_ref = array(); // Now we know what templates we need to touch, cycle through each theme and work out what we need to edit. if (!empty($template_changes[1])) { foreach ($theme_paths as $id => $theme) { // Don't do default, it means nothing to me. if ($id == 1) { continue; } // Now, for each file do we need to edit it? foreach ($template_changes[1] as $pos => $template_file) { // It does? Add it to the list darlin'. if (file_exists($theme['theme_dir'] . '/' . $template_file) && (!isset($template_changes[$id][$pos]) || !in_array($template_file, $template_changes[$id][$pos]))) { // Actually add it to the mod file too, so we can see that it will work ;) if (!empty($temp_changes[$pos]['changes'])) { $file .= "\n\n" . '<edit file>' . "\n" . $theme['theme_dir'] . '/' . $template_file . "\n" . '</edit file>' . "\n\n" . implode("\n\n", $temp_changes[$pos]['changes']); $theme_id_ref[$counter] = $id; $counter += 1 + count($temp_changes[$pos]['changes']); } } } } } $counter = 0; $is_custom = 0; while (preg_match('~<(edit file|file|search|search for|add|add after|replace|add before|add above|above|before)>\\n(.*?)\\n</\\1>~is', $file, $code_match) != 0) { // This is for working out what we should be editing. $counter++; // Edit a specific file. if ($code_match[1] == 'file' || $code_match[1] == 'edit file') { // Backup the old file. if ($working_file !== null) { package_chmod($working_file); // Don't even dare. if (basename($working_file) == 'Settings_bak.php') { continue; } if (!is_writable($working_file)) { $actions[] = array('type' => 'chmod', 'filename' => $working_file); } if (!$testing && !empty($modSettings['package_make_backups']) && file_exists($working_file)) { if (basename($working_file) == 'Settings.php') { @copy($working_file, dirname($working_file) . '/Settings_bak.php'); } else { @copy($working_file, $working_file . '~'); } } package_put_contents($working_file, $working_data, $testing); } if ($working_file !== null) { $actions[] = array('type' => 'saved', 'filename' => $working_file, 'is_custom' => $is_custom); } // Is this "now working on" file a theme specific one? $is_custom = isset($theme_id_ref[$counter - 1]) ? $theme_id_ref[$counter - 1] : 0; // Make sure the file exists! $working_file = parse_path($code_match[2]); if ($working_file[0] != '/' && $working_file[1] != ':') { trigger_error('parseBoardMod(): The filename \'' . $working_file . '\' is not a full path!', E_USER_WARNING); $working_file = $boarddir . '/' . $working_file; } if (!file_exists($working_file)) { $places_to_check = array($boarddir, $sourcedir, $settings['default_theme_dir'], $settings['default_theme_dir'] . '/languages'); foreach ($places_to_check as $place) { if (file_exists($place . '/' . $working_file)) { $working_file = $place . '/' . $working_file; break; } } } if (file_exists($working_file)) { // Load the new file. $working_data = str_replace("\r", '', package_get_contents($working_file)); $actions[] = array('type' => 'opened', 'filename' => $working_file); } else { $actions[] = array('type' => 'missing', 'filename' => $working_file); $working_file = null; $everything_found = false; } // Can't be searching for something... $working_search = null; } elseif (($code_match[1] == 'search' || $code_match[1] == 'search for') && $working_file !== null) { if ($working_search !== null) { $actions[] = array('type' => 'error', 'filename' => $working_file); $everything_found = false; } $working_search = $code_match[2]; } elseif ($working_search !== null) { // This is the base string.... $replace_with = $code_match[2]; // Add this afterward... if ($code_match[1] == 'add' || $code_match[1] == 'add after') { $replace_with = $working_search . "\n" . $replace_with; } elseif ($code_match[1] == 'before' || $code_match[1] == 'add before' || $code_match[1] == 'above' || $code_match[1] == 'add above') { $replace_with .= "\n" . $working_search; } // Otherwise.. replace with $replace_with ;). } // If we have a search string, replace string, and open file.. if ($working_search !== null && $replace_with !== null && $working_file !== null) { // Make sure it's somewhere in the string. if ($undo) { $temp = $replace_with; $replace_with = $working_search; $working_search = $temp; } if (strpos($working_data, $working_search) !== false) { $working_data = str_replace($working_search, $replace_with, $working_data); $actions[] = array('type' => 'replace', 'filename' => $working_file, 'search' => $working_search, 'replace' => $replace_with, 'search_original' => $working_search, 'replace_original' => $replace_with, 'position' => $code_match[1] == 'replace' ? 'replace' : ($code_match[1] == 'add' || $code_match[1] == 'add after' ? 'before' : 'after'), 'is_custom' => $is_custom, 'failed' => false); } else { $actions[] = array('type' => 'failure', 'filename' => $working_file, 'search' => $working_search, 'is_custom' => $is_custom, 'search_original' => $working_search, 'replace_original' => $replace_with, 'position' => $code_match[1] == 'replace' ? 'replace' : ($code_match[1] == 'add' || $code_match[1] == 'add after' ? 'before' : 'after'), 'is_custom' => $is_custom, 'failed' => true); $everything_found = false; } // These don't hold any meaning now. $working_search = null; $replace_with = null; } // Get rid of the old tag. $file = substr_replace($file, '', strpos($file, $code_match[0]), strlen($code_match[0])); } // Backup the old file. if ($working_file !== null) { package_chmod($working_file); if (!is_writable($working_file)) { $actions[] = array('type' => 'chmod', 'filename' => $working_file); } if (!$testing && !empty($modSettings['package_make_backups']) && file_exists($working_file)) { if (basename($working_file) == 'Settings.php') { @copy($working_file, dirname($working_file) . '/Settings_bak.php'); } else { @copy($working_file, $working_file . '~'); } } package_put_contents($working_file, $working_data, $testing); } if ($working_file !== null) { $actions[] = array('type' => 'saved', 'filename' => $working_file, 'is_custom' => $is_custom); } $actions[] = array('type' => 'result', 'status' => $everything_found); return $actions; }
function parseBoardMod($file, $testing = true, $undo = false) { global $boarddir, $sourcedir, $settings, $txt, $modSettings; @set_time_limit(600); $file = strtr($file, array("\r" => '')); $working_file = null; $working_search = null; $working_data = ''; $replace_with = null; $actions = array(); $everything_found = true; while (preg_match('~<(edit file|file|search|search for|add|add after|replace|add before|add above|above|before)>\\n(.*?)\\n</\\1>~is', $file, $code_match) != 0) { // Edit a specific file. if ($code_match[1] == 'file' || $code_match[1] == 'edit file') { // Backup the old file. if ($working_file !== null) { package_chmod($working_file); // Don't even dare. if (basename($working_file) == 'Settings_bak.php') { continue; } if (!is_writable($working_file)) { $actions[] = array('type' => 'chmod', 'filename' => $working_file); } if (!$testing && !empty($modSettings['package_make_backups']) && file_exists($working_file)) { if (basename($working_file) == 'Settings.php') { @copy($working_file, dirname($working_file) . '/Settings_bak.php'); } else { @copy($working_file, $working_file . '~'); } } package_put_contents($working_file, $working_data, $testing); } if ($working_file !== null) { $actions[] = array('type' => 'saved', 'filename' => $working_file); } // Make sure the file exists! $working_file = parse_path($code_match[2]); if ($working_file[0] != '/' && $working_file[1] != ':') { trigger_error('parseBoardMod(): The filename \'' . $working_file . '\' is not a full path!', E_USER_WARNING); $working_file = $boarddir . '/' . $working_file; } if (!file_exists($working_file)) { $places_to_check = array($boarddir, $sourcedir, $settings['default_theme_dir'], $settings['default_theme_dir'] . '/languages'); foreach ($places_to_check as $place) { if (file_exists($place . '/' . $working_file)) { $working_file = $place . '/' . $working_file; break; } } } if (file_exists($working_file)) { // Load the new file. $working_data = str_replace("\r", '', package_get_contents($working_file)); $actions[] = array('type' => 'opened', 'filename' => $working_file); } else { $actions[] = array('type' => 'missing', 'filename' => $working_file); $working_file = null; $everything_found = false; } // Can't be searching for something... $working_search = null; } elseif (($code_match[1] == 'search' || $code_match[1] == 'search for') && $working_file !== null) { if ($working_search !== null) { $actions[] = array('type' => 'error', 'filename' => $working_file); $everything_found = false; } $working_search = $code_match[2]; } elseif ($working_search !== null) { // This is the base string.... $replace_with = $code_match[2]; // Add this afterward... if ($code_match[1] == 'add' || $code_match[1] == 'add after') { $replace_with = $working_search . "\n" . $replace_with; } elseif ($code_match[1] == 'before' || $code_match[1] == 'add before' || $code_match[1] == 'above' || $code_match[1] == 'add above') { $replace_with .= "\n" . $working_search; } // Otherwise.. replace with $replace_with ;). } // If we have a search string, replace string, and open file.. if ($working_search !== null && $replace_with !== null && $working_file !== null) { // Make sure it's somewhere in the string. if ($undo) { $temp = $replace_with; $replace_with = $working_search; $working_search = $temp; } if (strpos($working_data, $working_search) !== false) { $working_data = str_replace($working_search, $replace_with, $working_data); $actions[] = array('type' => 'replace', 'filename' => $working_file, 'search' => $working_search, 'replace' => $replace_with); } else { $actions[] = array('type' => 'failure', 'filename' => $working_file, 'search' => $working_search); $everything_found = false; } // These don't hold any meaning now. $working_search = null; $replace_with = null; } // Get rid of the old tag. $file = substr_replace($file, '', strpos($file, $code_match[0]), strlen($code_match[0])); } // Backup the old file. if ($working_file !== null) { package_chmod($working_file); if (!is_writable($working_file)) { $actions[] = array('type' => 'chmod', 'filename' => $working_file); } if (!$testing && !empty($modSettings['package_make_backups']) && file_exists($working_file)) { if (basename($working_file) == 'Settings.php') { @copy($working_file, dirname($working_file) . '/Settings_bak.php'); } else { @copy($working_file, $working_file . '~'); } } package_put_contents($working_file, $working_data, $testing); } if ($working_file !== null) { $actions[] = array('type' => 'saved', 'filename' => $working_file); } $actions[] = array('type' => 'result', 'status' => $everything_found); return $actions; }