/forum/includes/mod_parser.php
PHP | 833 lines | 593 code | 114 blank | 126 comment | 90 complexity | 7d5e9991dbc1545f40779018a4438395 MD5 | raw file
Possible License(s): AGPL-1.0, LGPL-3.0, MPL-2.0-no-copyleft-exception
- <?php
- /**
- *
- * @package automod
- * @version $Id: mod_parser.php 242 2010-04-29 00:56:35Z jelly_doughnut $
- * @copyright (c) 2008 phpBB Group
- * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
- *
- */
- /**
- */
- if (!defined('IN_PHPBB'))
- {
- exit;
- }
- /**
- * MOD Parser class
- * Basic wrapper to run individual parser functions
- * Also contains some parsing functions that are global (i.e. needed for all parsers)
- * @package automod
- *
- * Each parser requires the following functions:
- * ~ set_file($path_to_mod_file)
- * ~ a means of setting the data to be acted upon
- * ~ get_details()
- * ~ returns an array of information about the MOD
- * ~ get_actions()
- * ~ returns an array of the MODs actions
- * ~ get_modx_version
- * ~ returns the MODX version of the MOD being looked at
- *
- */
- class parser
- {
- var $parser;
- /**
- * constructor, sets type of parser
- */
- function parser($ext)
- {
- switch ($ext)
- {
- case 'xml':
- default:
- $this->parser = new parser_xml();
- break;
- }
- }
- function set_file($file)
- {
- $this->parser->set_file($file);
- }
- function get_details()
- {
- return $this->parser->get_details();
- }
- function get_actions()
- {
- return $this->parser->get_actions();
- }
- function get_modx_version()
- {
- if (!$this->parser->modx_version)
- {
- $this->get_details();
- }
- return $this->parser->modx_version;
- }
- /**
- * Returns the needed sql query to reverse the actions taken by the given query
- * @todo: Add more
- */
- function reverse_query($orig_query)
- {
- if (preg_match('#ALTER TABLE\s([a-z_]+)\sADD(COLUMN|)\s([a-z_]+)#i', $orig_query, $matches))
- {
- return "ALTER TABLE {$matches[1]} DROP COLUMN {$matches[3]};";
- }
- else if (preg_match('#CREATE TABLE\s([a-z_])+#i', $orig_query, $matches))
- {
- return "DROP TABLE {$matches[1]};";
- }
- return false;
- }
- /**
- * Parse sql
- *
- * @param array $sql_query
- */
- function parse_sql(&$sql_query)
- {
- global $dbms, $table_prefix;
- if (!function_exists('get_available_dbms'))
- {
- global $phpbb_root_path, $phpEx;
- include($phpbb_root_path . 'includes/functions_install.' . $phpEx);
- }
- static $available_dbms;
- if (!isset($available_dbms))
- {
- $available_dbms = get_available_dbms($dbms);
- }
- $remove_remarks = $available_dbms[$dbms]['COMMENTS'];
- $delimiter = $available_dbms[$dbms]['DELIM'];
- if (sizeof($sql_query) == 1)
- {
- // do some splitting here
- $sql_query = preg_replace('#phpbb_#i', $table_prefix, $sql_query);
- $remove_remarks($sql_query[0]);
- $sql_query = split_sql_file($sql_query[0], $delimiter);
- }
- else
- {
- $query_count = sizeof($sql_query);
- for ($i = 0; $i < $query_count; $i++)
- {
- $sql_query[$i] = preg_replace('#phpbb_#i', $table_prefix, $sql_query[$i]);
- $remove_remarks($sql_query[$i]);
- }
- }
- //return $sql_query;
- }
- /**
- * Returns the edits array, but now filled with edits to reverse the given array
- * @todo: Add more
- */
- function reverse_edits($actions)
- {
- $reverse_edits = array();
- foreach ($actions['EDITS'] as $file => $edit_ary)
- {
- foreach ($edit_ary as $edit_id => $edit)
- {
- foreach ($edit as $find => $action_ary)
- {
- foreach ($action_ary as $type => $command)
- {
- // it is possible for a single edit in the install process
- // to become more than one in the uninstall process
- while (isset($reverse_edits['EDITS'][$file][$edit_id]))
- {
- $edit_id++;
- }
- switch (strtoupper($type))
- {
- // for before and after adds, we use the find as a tool for more precise finds
- // this isn't perfect, but it seems better than having
- // finds of only a couple characters, like "/*"
- case 'AFTER ADD':
- $total_find = rtrim($find, "\n") . "\n" . trim($command, "\n");
- $reverse_edits['EDITS'][$file][$edit_id][$total_find]['replace with'] = $find;
- break;
- case 'BEFORE ADD':
- $total_find = rtrim($command, "\n") . "\n" . trim($find, "\n");
- // replace with the find
- $reverse_edits['EDITS'][$file][$edit_id][$total_find]['replace with'] = $find;
- break;
- case 'REPLACE WITH':
- case 'REPLACE, WITH':
- case 'REPLACE-WITH':
- case 'REPLACE':
- // replace $command (new code) with $find (original code)
- $reverse_edits['EDITS'][$file][$edit_id][$command]['replace with'] = $find;
- break;
- case 'IN-LINE-EDIT':
- $action_id = 0;
- // build the reverse just like the normal action
- foreach ($command as $inline_find => $inline_action_ary)
- {
- foreach ($inline_action_ary as $inline_action => $inline_command)
- {
- $inline_command = $inline_command[0];
- switch (strtoupper($inline_action))
- {
- case 'IN-LINE-AFTER-ADD':
- case 'IN-LINE-BEFORE-ADD':
- // Replace with a blank string
- $reverse_edits['EDITS'][$file][$edit_id][$find]['in-line-edit'][$action_id][$inline_command]['in-line-replace'][] = '';
- break;
-
- case 'IN-LINE-REPLACE':
- // replace with the inline find
- $reverse_edits['EDITS'][$file][$edit_id][$find]['in-line-edit'][$action_id][$inline_command][$inline_action][] = $inline_find;
- break;
-
- default:
- // For the moment, we do nothing. What about increment?
- break;
- }
- $action_id++;
- }
- }
- break;
- default:
- // again, increment
- break;
- }
- }
- }
- }
- }
- if (empty($actions['SQL']))
- {
- return $reverse_edits;
- }
- if (sizeof($actions['SQL']) == 1)
- {
- $actions['SQL'] = explode("\n", $actions['SQL'][0]);
- }
- foreach ($actions['SQL'] as $query)
- {
- $reverse_edits['SQL'][] = parser::reverse_query($query);
- }
- return $reverse_edits;
- }
- }
- /**
- * XML parser
- * @package automod
- */
- class parser_xml
- {
- var $data;
- var $file;
- var $modx_version;
- /**
- * set data to read from
- */
- function set_file($file)
- {
- // Shouldn't ever happen since the master class reads file names from
- // the file system and lists them
- if (!file_exists($file))
- {
- trigger_error('Cannot locate File: ' . $file);
- }
- $this->file = $file;
- $this->data = trim(@file_get_contents($file));
- $this->data = str_replace(array("\r\n", "\r"), "\n", $this->data);
- $XML = new xml_array();
- $this->data = $XML->parse($this->file, $this->data);
- return;
- }
- /**
- * return array of the basic MOD details
- */
- function get_details()
- {
- global $user;
- if (empty($this->data))
- {
- $this->set_file($this->file);
- }
- $header = array(
- 'MOD-VERSION' => array(0 => array('children' => array())),
- 'INSTALLATION' => array(0 => array('children' => array('TARGET-VERSION' => array(0 => array('data' => ''))))),
- 'AUTHOR-GROUP' => array(0 => array('children' => array('AUTHOR' => array()))),
- 'HISTORY' => array(0 => array('children' => array('ENTRY' => array()))),
- );
- $version = $phpbb_version = '';
- $header = $this->data[0]['children']['HEADER'][0]['children'];
- // get MOD version information
- // This is also our first opportunity to differentiate MODX 1.0.x from
- // MODX 1.2.0.
- if (isset($header['MOD-VERSION'][0]['children']))
- {
- $this->modx_version = 1.0;
- $version_info = $header['MOD-VERSION'][0]['children'];
- $version = (isset($version_info['MAJOR'][0]['data'])) ? trim($version_info['MAJOR'][0]['data']) : 0;
- $version .= '.' . ((isset($version_info['MINOR'][0]['data'])) ? trim($version_info['MINOR'][0]['data']) : 0);
- $version .= '.' . ((isset($version_info['REVISION'][0]['data'])) ? trim($version_info['REVISION'][0]['data']) : 0);
- $version .= (isset($version_info['RELEASE'][0]['data'])) ? trim($version_info['RELEASE'][0]['data']) : '';
- }
- else
- {
- $this->modx_version = 1.2;
- $version = trim($header['MOD-VERSION'][0]['data']);
- }
- // get phpBB version recommendation
- switch ($this->modx_version)
- {
- case 1.0:
- if (isset($header['INSTALLATION'][0]['children']['TARGET-VERSION'][0]['children']))
- {
- $version_info = $header['INSTALLATION'][0]['children']['TARGET-VERSION'][0]['children'];
- $phpbb_version = (isset($version_info['MAJOR'][0]['data'])) ? trim($version_info['MAJOR'][0]['data']) : 0;
- $phpbb_version .= '.' . ((isset($version_info['MINOR'][0]['data'])) ? trim($version_info['MINOR'][0]['data']) : 0);
- $phpbb_version .= '.' . ((isset($version_info['REVISION'][0]['data'])) ? trim($version_info['REVISION'][0]['data']) : 0);
- $phpbb_version .= (isset($version_info['RELEASE'][0]['data'])) ? trim($version_info['RELEASE'][0]['data']) : '';
- }
- break;
- case 1.2:
- default:
- $phpbb_version = (isset($header['INSTALLATION'][0]['children']['TARGET-VERSION'][0]['data'])) ? $header['INSTALLATION'][0]['children']['TARGET-VERSION'][0]['data'] : 0;
- break;
- }
- $author_info = $header['AUTHOR-GROUP'][0]['children']['AUTHOR'];
- $author_details = array();
- for ($i = 0; $i < sizeof($author_info); $i++)
- {
- $author_details[] = array(
- 'AUTHOR_NAME' => isset($author_info[$i]['children']['USERNAME'][0]['data']) ? trim($author_info[$i]['children']['USERNAME'][0]['data']) : '',
- 'AUTHOR_EMAIL' => isset($author_info[$i]['children']['EMAIL'][0]['data']) ? trim($author_info[$i]['children']['EMAIL'][0]['data']) : '',
- 'AUTHOR_REALNAME' => isset($author_info[$i]['children']['REALNAME'][0]['data']) ? trim($author_info[$i]['children']['REALNAME'][0]['data']) : '',
- 'AUTHOR_WEBSITE' => isset($author_info[$i]['children']['HOMEPAGE'][0]['data']) ? trim($author_info[$i]['children']['HOMEPAGE'][0]['data']) : '',
- );
- }
- // history
- $history_info = (!empty($header['HISTORY'][0]['children']['ENTRY'])) ? $header['HISTORY'][0]['children']['ENTRY'] : array();
- $history_size = sizeof($history_info);
- $mod_history = array();
- for ($i = 0; $i < $history_size; $i++)
- {
- $changes = array();
- $entry = $history_info[$i]['children'];
- $changelog = isset($entry['CHANGELOG']) ? $entry['CHANGELOG'] : array();
- $changelog_size = sizeof($changelog);
- $changelog_id = 0;
- for ($j = 0; $j < $changelog_size; $j++)
- {
- // Ignore changelogs in foreign languages except in the case that there is no
- // match for the current user's language
- // TODO: Look at modifying localise_tags() for use here.
- if (match_language($user->data['user_lang'], $changelog[$j]['attrs']['LANG']))
- {
- $changelog_id = $j;
- }
- }
- $change_count = isset($changelog[$changelog_id]['children']['CHANGE']) ? sizeof($changelog[$changelog_id]['children']['CHANGE']) : 0;
- for ($j = 0; $j < $change_count; $j++)
- {
- $changes[] = $changelog[$changelog_id]['children']['CHANGE'][$j]['data'];
- }
- switch ($this->modx_version)
- {
- case 1.0:
- $changelog_version_ary = (isset($entry['REV-VERSION'][0]['children'])) ? $entry['REV-VERSION'][0]['children'] : array();
- $changelog_version = (isset($changelog_version_ary['MAJOR'][0]['data'])) ? trim($changelog_version_ary['MAJOR'][0]['data']) : 0;
- $changelog_version .= '.' . ((isset($changelog_version_ary['MINOR'][0]['data'])) ? trim($changelog_version_ary['MINOR'][0]['data']) : 0);
- $changelog_version .= '.' . ((isset($changelog_version_ary['REVISION'][0]['data'])) ? trim($changelog_version_ary['REVISION'][0]['data']) : 0);
- $changelog_version .= (isset($changelog_version_ary['RELEASE'][0]['data'])) ? trim($changelog_version_ary['RELEASE'][0]['data']) : '';
- break;
- case 1.2:
- default:
- $changelog_version = (isset($entry['REV-VERSION'][0]['data'])) ? $entry['REV-VERSION'][0]['data'] : '0.0.0';
- break;
- }
- $mod_history[] = array(
- 'DATE' => $entry['DATE'][0]['data'],
- 'VERSION' => $changelog_version,
- 'CHANGES' => $changes,
- );
- }
- $children = array();
- // Parse links
- if ($this->modx_version == 1.2)
- {
- $link_group = (isset($header['LINK-GROUP'][0]['children'])) ? $header['LINK-GROUP'][0]['children'] : array();
- if (isset($link_group['LINK']))
- {
- for ($i = 0, $size = sizeof($link_group['LINK']); $i <= $size; $i++)
- {
- // do some stuff with attrs
- // commented out due to a possible PHP bug. When using this,
- // sizeof($link_group) changed each time ...
- // $attrs = &$link_group[$i]['attrs'];
-
- if (!isset($link_group['LINK'][$i]))
- {
- continue;
- }
- if ($link_group['LINK'][$i]['attrs']['TYPE'] == 'text')
- {
- continue;
- }
- $children[$link_group['LINK'][$i]['attrs']['TYPE']][] = array(
- 'href' => $link_group['LINK'][$i]['attrs']['HREF'],
- 'realname' => isset($link_group['LINK'][$i]['attrs']['REALNAME']) ? $link_group['LINK'][$i]['attrs']['REALNAME'] : core_basename($link_group['LINK'][$i]['attrs']['HREF']),
- 'title' => localise_tags($link_group, 'LINK', $i),
- );
- }
- }
- }
- // try not to hardcode schema?
- $details = array(
- 'MOD_PATH' => $this->file,
- 'MOD_NAME' => localise_tags($header, 'TITLE'),
- 'MOD_DESCRIPTION' => nl2br(localise_tags($header, 'DESCRIPTION')),
- 'MOD_VERSION' => htmlspecialchars(trim($version)),
- // 'MOD_DEPENDENCIES' => (isset($header['TITLE'][0]['data'])) ? htmlspecialchars(trim($header['TITLE'][0]['data'])) : '',
- 'AUTHOR_DETAILS' => $author_details,
- 'AUTHOR_NOTES' => nl2br(localise_tags($header, 'AUTHOR-NOTES')),
- 'MOD_HISTORY' => $mod_history,
- 'PHPBB_VERSION' => $phpbb_version,
- 'CHILDREN' => $children,
- );
- return $details;
- }
- /**
- * returns complex array containing all mod actions
- */
- function get_actions()
- {
- global $db, $user;
- $actions = array();
- $xml_actions = $this->data[0]['children']['ACTION-GROUP'][0]['children'];
- // sql
- $actions['SQL'] = array();
- $sql_info = (!empty($xml_actions['SQL'])) ? $xml_actions['SQL'] : array();
- $match_dbms = array();
- switch ($db->sql_layer)
- {
- case 'firebird':
- case 'oracle':
- case 'postgres':
- case 'sqlite':
- case 'mssql':
- case 'db2':
- $match_dbms = array($db->sql_layer);
- break;
- case 'mssql_odbc':
- $match_dbms = array('mssql');
- break;
- // and now for the MySQL fun
- // This will generate an array of things we can probably use, but
- // will not have any priority
- case 'mysqli':
- $match_dbms = array('mysql_41', 'mysqli', 'mysql');
- break;
- case 'mysql4':
- case 'mysql':
- if (version_compare($db->sql_server_info(true), '4.1.3', '>='))
- {
- $match_dbms = array('mysql_41', 'mysql4', 'mysql', 'mysqli');
- }
- else if (version_compare($db->sql_server_info(true), '4.0.0', '>='))
- {
- $match_dbms = array('mysql_40', 'mysql4', 'mysql', 'mysqli');
- }
- else
- {
- $match_dbms = array('mysql');
- }
- break;
- // Should never happen
- default:
- break;
- }
- for ($i = 0; $i < sizeof($sql_info); $i++)
- {
- if ($this->modx_version == 1.0)
- {
- $actions['SQL'][] = (!empty($sql_info[$i]['data'])) ? trim($sql_info[$i]['data']) : '';
- }
- else if ($this->modx_version == 1.2)
- {
- // Make a slightly shorter name.
- $xml_dbms = &$sql_info[$i]['attrs']['DBMS'];
- if (!isset($sql_info[$i]['attrs']['DBMS']) || in_array($xml_dbms, $match_dbms))
- {
- $actions['SQL'][] = (!empty($sql_info[$i]['data'])) ? trim($sql_info[$i]['data']) : '';
- }
- else
- {
- // NOTE: skipped SQL is not currently useful
- $sql_skipped = true;
- }
- }
- }
- // new files
- $new_files_info = (!empty($xml_actions['COPY'])) ? $xml_actions['COPY'] : array();
- for ($i = 0; $i < sizeof($new_files_info); $i++)
- {
- $new_files = $new_files_info[$i]['children']['FILE'];
- for ($j = 0; $j < sizeof($new_files); $j++)
- {
- $from = str_replace('\\', '/', $new_files[$j]['attrs']['FROM']);
- $to = str_replace('\\', '/', $new_files[$j]['attrs']['TO']);
- $actions['NEW_FILES'][$from] = $to;
- }
- }
- $delete_files_info = (!empty($xml_actions['DELETE'])) ? $xml_actions['DELETE'] : array();
- for ($i = 0; $i < sizeof($delete_files_info); $i++)
- {
- $delete_files = $delete_files_info[$i]['children']['FILE'];
- for ($j = 0; $j < sizeof($delete_files); $j++)
- {
- $name = str_replace('\\', '/', $delete_files[$j]['attrs']['NAME']);
- $actions['DELETE_FILES'][] = $name;
- }
- }
- // open
- $open_info = (!empty($xml_actions['OPEN'])) ? $xml_actions['OPEN'] : array();
- for ($i = 0; $i < sizeof($open_info); $i++)
- {
- $current_file = str_replace('\\', '/', trim($open_info[$i]['attrs']['SRC']));
- $actions['EDITS'][$current_file] = array();
- $edit_info = (!empty($open_info[$i]['children']['EDIT'])) ? $open_info[$i]['children']['EDIT'] : array();
- // find, after add, before add, replace with
- for ($j = 0; $j < sizeof($edit_info); $j++)
- {
- $action_info = (!empty($edit_info[$j]['children'])) ? $edit_info[$j]['children'] : array();
- // store some array information to help decide what kind of operation we're doing
- $action_count = $total_action_count = $remove_count = $find_count = 0;
- if (isset($action_info['ACTION']))
- {
- $action_count += sizeof($action_info['ACTION']);
- }
- if (isset($action_info['INLINE-EDIT']))
- {
- $total_action_count += sizeof($action_info['INLINE-EDIT']);
- }
- if (isset($action_info['REMOVE']))
- {
- $remove_count = sizeof($action_info['REMOVE']); // should be an integer bounded between zero and one
- }
- if (isset($action_info['FIND']))
- {
- $find_count = sizeof($action_info['FIND']);
- }
- // the basic idea is to transform a "remove" tag into a replace-with action
- if ($remove_count && !$find_count)
- {
- // but we still support it if $remove_count is > 1
- for ($k = 0; $k < $remove_count; $k++)
- {
- // if there is no find tag associated, handle it directly
- $actions['EDITS'][$current_file][$j][trim($action_info['REMOVE'][$k]['data'], "\n\r")]['replace with'] = '';
- }
- }
- else if ($remove_count && $find_count)
- {
- // if there is a find and a remove, transform into a replace-with
- // action, and let the logic below sort out the relationships.
- for ($k = 0; $k < $remove_count; $k++)
- {
- $insert_index = (isset($action_info['ACTION'])) ? sizeof($action_info['ACTION']) : 0;
- $action_info['ACTION'][$insert_index] = array(
- 'data' => '',
- 'attrs' => array('TYPE' => 'replace with'),
- );
- }
- }
- else if (!$find_count)
- {
- trigger_error(sprintf($user->lang['INVALID_MOD_NO_FIND'], htmlspecialchars($action_info['ACTION'][0]['data'])), E_USER_WARNING);
- }
- // first we try all the possibilities for a FIND/ACTION combo, then look at inline possibilities.
- if (isset($action_info['ACTION']))
- {
- for ($k = 0; $k < $find_count; $k++)
- {
- // is this anything but the last iteration of the loop?
- if ($k < ($find_count - 1))
- {
- // NULL has special meaning for an action ... no action to be taken; advance pointer
- $actions['EDITS'][$current_file][$j][$action_info['FIND'][$k]['data']] = NULL;
- }
- else
- {
- // this is the last iteration, assign the action tags
-
- for ($l = 0; $l < $action_count; $l++)
- {
- $type = str_replace('-', ' ', $action_info['ACTION'][$l]['attrs']['TYPE']);
- $actions['EDITS'][$current_file][$j][trim($action_info['FIND'][$k]['data'], "\n\r")][$type] = (isset($action_info['ACTION'][$l]['data'])) ? preg_replace("#^(\s)+\n#", '', rtrim(trim($action_info['ACTION'][$l]['data'], "\n"))) : '';
- }
- }
- }
- }
- else
- {
- if (!$remove_count && !$total_action_count)
- {
- trigger_error(sprintf($user->lang['INVALID_MOD_NO_ACTION'], htmlspecialchars($action_info['FIND'][0]['data'])), E_USER_WARNING);
- }
- }
- // add comment to the actions array
- $actions['EDITS'][$current_file][$j]['comment'] = localise_tags($action_info, 'COMMENT');
- // inline
- if (isset($action_info['INLINE-EDIT']))
- {
- $inline_info = (!empty($action_info['INLINE-EDIT'])) ? $action_info['INLINE-EDIT'] : array();
- if (isset($inline_info[0]['children']['INLINE-REMOVE']) && sizeof($inline_info[0]['children']['INLINE-REMOVE']))
- {
- // overwrite the existing array with the new one
- $inline_info[0]['children'] = array(
- 'INLINE-FIND' => $inline_info[0]['children']['INLINE-REMOVE'],
- 'INLINE-ACTION' => array(
- 0 => array(
- 'attrs' => array('TYPE' => 'replace-with'),
- 'data' => '',
- ),
- ),
- );
- }
- if ($find_count > $total_action_count)
- {
- // Yeah, $k is used more than once for different information
- for ($k = 0; $k < $find_count; $k++)
- {
- // is this anything but the last iteration of the loop?
- if ($k < ($find_count - 1))
- {
- // NULL has special meaning for an action ... no action to be taken; advance pointer
- $actions['EDITS'][$current_file][$j][trim($action_info['FIND'][$k]['data'], "\r\n")] = NULL;
- }
- }
- }
- /*
- * This loop attaches the in-line information to the _last
- * find_ in the <edit> tag. This is the intended behavior
- * Any additional finds ought to be in a different edit tag
- */
- for ($k = 0; $k < sizeof($inline_info); $k++)
- {
- $inline_data = (!empty($inline_info[$k]['children'])) ? $inline_info[$k]['children'] : array();
- $inline_find_count = (isset($inline_data['INLINE-FIND'])) ? sizeof($inline_data['INLINE-FIND']) : 0;
- $inline_comment = localise_tags($inline_data, 'INLINE-COMMENT');
- $actions['EDITS'][$current_file][$j][trim($action_info['FIND'][$find_count - 1]['data'], "\r\n")]['in-line-edit']['inline-comment'] = $inline_comment;
- $inline_actions = (!empty($inline_data['INLINE-ACTION'])) ? $inline_data['INLINE-ACTION'] : array();
- if (empty($inline_actions))
- {
- trigger_error(sprintf($user->lang['INVALID_MOD_NO_ACTION'], htmlspecialchars($inline_data['INLINE-FIND'][0]['data'])), E_USER_WARNING);
- }
- if (empty($inline_find_count))
- {
- trigger_error(sprintf($user->lang['INVALID_MOD_NO_FIND'], htmlspecialchars($inline_actions[0]['data'])), E_USER_WARNING);
- }
- for ($l = 0; $l < $inline_find_count; $l++)
- {
- $inline_find = $inline_data['INLINE-FIND'][$l]['data'];
- // trying to reduce the levels of arrays without impairing features.
- // need to keep the "full" edit intact.
- //
- // inline actions must be trimmed in case the MOD author
- // inserts a new line by mistake
- if ($l < ($inline_find_count - 1))
- {
- $actions['EDITS'][$current_file][$j][trim($action_info['FIND'][$find_count - 1]['data'], "\r\n")]['in-line-edit'][$k][$inline_find]['in-line-'][] = null;
- }
- else
- {
- for ($m = 0; $m < sizeof($inline_actions); $m++)
- {
- $type = str_replace(',', '-', str_replace(' ', '', $inline_actions[$m]['attrs']['TYPE']));
- if (!empty($inline_actions[$m]['data']))
- {
- $actions['EDITS'][$current_file][$j][trim($action_info['FIND'][$find_count - 1]['data'], "\r\n")]['in-line-edit'][$k][$inline_find]['in-line-' . $type][] = trim($inline_actions[$m]['data'], "\n");
- }
- else
- {
- $actions['EDITS'][$current_file][$j][trim($action_info['FIND'][$find_count - 1]['data'], "\r\n")]['in-line-edit'][$k][$inline_find]['in-line-' . $type][] = '';
- }
- }
- }
- }
- }
- }
- }
- }
- if (!empty($xml_actions['PHP-INSTALLER']))
- {
- $actions['PHP_INSTALLER'] = $xml_actions['PHP-INSTALLER'][0]['data'];
- }
- if (!empty($xml_actions['DIY-INSTRUCTIONS']))
- {
- $actions['DIY_INSTRUCTIONS'] = localise_tags($xml_actions, 'DIY-INSTRUCTIONS');
- }
- return $actions;
- }
- }
- /**
- * XML processing
- * @package automod
- */
- class xml_array
- {
- var $output = array();
- var $parser;
- var $XML;
- function parse($file, $XML)
- {
- $this->parser = xml_parser_create();
- xml_set_object($this->parser, $this);
- xml_set_element_handler($this->parser, "tag_open", "tag_closed");
- xml_set_character_data_handler($this->parser, "tag_data");
- $this->XML = xml_parse($this->parser, $XML);
- if (!$this->XML)
- {
- die(sprintf("<strong>XML error</strong>: %s at line %d. View the file %s in a web browser for a more detailed error message.",
- xml_error_string(xml_get_error_code($this->parser)), xml_get_current_line_number($this->parser), $file));
- }
- xml_parser_free($this->parser);
- return $this->output;
- }
- function tag_open($parser, $name, $attrs)
- {
- $tag = array("name" => $name, "attrs" => $attrs);
- array_push($this->output, $tag);
- }
- function tag_data($parser, $tag_data)
- {
- if ($tag_data)
- {
- if (isset($this->output[sizeof($this->output) - 1]['data']))
- {
- $this->output[sizeof($this->output) - 1]['data'] .= $tag_data;
- }
- else
- {
- $this->output[sizeof($this->output) - 1]['data'] = $tag_data;
- }
- }
- }
- function tag_closed($parser, $name)
- {
- $this->output[sizeof($this->output) - 2]['children'][$name][] = $this->output[sizeof($this->output) - 1];
- array_pop($this->output);
- }
- }
- ?>