/** * Parses input setup in constructor, and creates a parse tree. */ function parse_input() { /*We need to break the $this->parsed_input[SECTION_COMMAND] up into several distinct parts: - Command - Options - Parameters - Extras (e.g. I/O redirection / pipes) i.e. chmod -R 777 ./foobar >> output.txt COMMAND OPTION PARAMETER PARAMETER EXTRA */ /*Output redirection: 2&1> output.txt 2&1 > output.txt STREAM_IDENTIFIER ASSIGNMENT REDIRECT_IDENTIFIER */ $this->parse_runtime['command_length'] = strlen($this->current_input); $this->parse_runtime['parse_position'] = 0; $this->parse_runtime['current_mode'] = MODE_NORMAL; $this->parse_runtime['escape_used'] = false; $this->parse_runtime['occle_command'] = COMMAND_NATIVE; $this->parsed_input[SECTION_COMMAND] = NULL; $this->parsed_input[SECTION_OPTIONS] = array(); $this->parsed_input[SECTION_PARAMETERS] = array(); $this->parsed_input[SECTION_EXTRAS] = array(); $this->fs = object_factory('virtual_fs'); //Start parsing with the command $this->_extract_command(); if (trim($this->parsed_input[SECTION_COMMAND]) == '') { $this->output[STREAM_STDCOMMAND] = ''; $this->output[STREAM_STDHTML] = ''; $this->output[STREAM_STDOUT] = ''; $this->output[STREAM_STDERR] = do_lang('NON_COMMAND'); return; } if ($this->parse_runtime['occle_command'] == COMMAND_NATIVE) { //Options (it's an OcCLE command; not a PHP command) $this->_extract_options(); $this->_extract_parameters(); } //Extras $this->_extract_extras(); //Pre-processing: follow any extras provided $i = 0; foreach ($this->parsed_input[SECTION_EXTRAS] as $extra) { if ($extra[ASSIGNMENT] == REDIRECT_PIPE || $extra[ASSIGNMENT] == REDIRECT_INPUT) { $replacements = 0; if ($extra[ASSIGNMENT] == REDIRECT_PIPE) { if (!isset($extra[STREAM_IDENTIFIER][0])) { $extra[STREAM_IDENTIFIER] = array(STREAM_STDOUT); } $virtual_bash = new virtual_bash($extra[REDIRECT_IDENTIFIER]); $virtual_output = $virtual_bash->return_output(); $pertinant_output = $virtual_output[$extra[STREAM_IDENTIFIER][count($extra[STREAM_IDENTIFIER]) - 1]]; if ($virtual_output[STREAM_STDERR] != '') { $this->output[STREAM_STDERR] = $virtual_output[STREAM_STDERR]; } } else { $pertinant_output = $this->fs->read_file($this->fs->_pwd_to_array($extra[REDIRECT_IDENTIFIER])); if ($pertinant_output === false) { $pertinant_output = ''; } } foreach ($this->parsed_input[SECTION_PARAMETERS] as $param_no => $parameter) { //Do we have any "{".$i."}" parameters? if ($parameter == '{' . strval($i) . '}') { //NOTE: Might want to change this somehow so that other streams can be put through $this->parsed_input[SECTION_PARAMETERS][$param_no] = $pertinant_output; $replacements++; } } if ($replacements == 0) { //Just tag the input onto the end of the parameters array //NOTE: See above $this->parsed_input[SECTION_PARAMETERS][] = $pertinant_output; } $i++; } } //Handle the command: load up the relevant hook if ($this->parse_runtime['occle_command'] == COMMAND_NATIVE) { //See if it's a lone command first $hooks = find_all_hooks('modules', 'admin_occle_commands'); $hook_return = NULL; foreach (array_keys($hooks) as $hook) { if ($hook == $this->parsed_input[SECTION_COMMAND]) { require_code('hooks/modules/admin_occle_commands/' . filter_naughty_harsh($hook)); $object = object_factory('Hook_' . filter_naughty_harsh($hook)); $hook_return = $object->run($this->parsed_input[SECTION_OPTIONS], $this->parsed_input[SECTION_PARAMETERS], $this->fs); $this->parse_runtime['occle_command'] = COMMAND_LONE; break; } } if (!is_null($hook_return)) { $this->output[STREAM_STDCOMMAND] = $hook_return[0]; if (is_object($hook_return[1])) { $this->output[STREAM_STDHTML] = $hook_return[1]->evaluate(); } else { $this->output[STREAM_STDHTML] = $hook_return[1]; } $this->output[STREAM_STDOUT] = array_key_exists(2, $hook_return) ? $hook_return[2] : ''; $this->output[STREAM_STDERR] = array_key_exists(2, $hook_return) ? $hook_return[3] : ''; } else { //It's not a lone command; see if it's a script - check first in the main script dir if (file_exists(get_custom_file_base() . '/data/modules/admin_occle/' . filter_naughty_harsh($this->parsed_input[SECTION_COMMAND], true))) { $script_file = get_custom_file_base() . '/data/modules/admin_occle/' . filter_naughty_harsh($this->parsed_input[SECTION_COMMAND]); } else { $script_file = $this->_find_script_file($this->parsed_input[SECTION_COMMAND]); } //Exhaustive search if ($script_file !== false && is_readable($script_file)) { //It *is* a script, so let's run it :) $this->parse_runtime['occle_command'] = COMMAND_SCRIPT; $script_contents = unixify_line_format(file_get_contents($script_file, FILE_TEXT)); $script_lines = explode("\n", $script_contents); foreach ($script_lines as $script_line) { if (strlen($script_line) > 0) { $virtual_bash = new virtual_bash($script_line, $this->parsed_input[SECTION_PARAMETERS]); $script_output = $virtual_bash->return_output(); $this->output = $this->_combine_streams($this->output, $script_output); } } } else { //Give up: it's not a command $this->output[STREAM_STDCOMMAND] = ''; $this->output[STREAM_STDHTML] = ''; $this->output[STREAM_STDOUT] = ''; $this->output[STREAM_STDERR] = do_lang('NON_COMMAND'); return; } } } elseif ($this->parse_runtime['occle_command'] == COMMAND_PHP) { //NOTE: This is done in a separate function to limit variable interaction (due to the PHP memory implemented) $this->_handle_php_command(); } elseif ($this->parse_runtime['occle_command'] == COMMAND_SQL) { //SQL command $GLOBALS['NO_DB_SCOPE_CHECK'] = true; $occle_output = $GLOBALS['SITE_DB']->query($this->parsed_input[SECTION_COMMAND], NULL, NULL, true); $GLOBALS['NO_DB_SCOPE_CHECK'] = false; if (count($occle_output) > 100) { $occle_output = $GLOBALS['SITE_DB']->query($this->parsed_input[SECTION_COMMAND], 100, NULL, true); $occle_output[] = array('...' => '...'); } $this->output[STREAM_STDCOMMAND] = ''; $this->output[STREAM_STDHTML] = ''; $this->output[STREAM_STDOUT] = ''; $this->output[STREAM_STDERR] = ''; if (is_null($occle_output)) { $this->output[STREAM_STDERR] = do_lang('NO_RESULTS'); } else { $this->output[STREAM_STDHTML] = $this->_array_to_html($occle_output); } } //Post-processing: follow any extras provided $old_output = $this->output; foreach ($this->parsed_input[SECTION_EXTRAS] as $extra) { if (!isset($extra[STREAM_IDENTIFIER][0])) { $extra[STREAM_IDENTIFIER] = array(STREAM_STDOUT); } if (!isset($this->output[$extra[REDIRECT_IDENTIFIER]])) { // It's a file... so read in if it exists, else blank $this->output[$extra[REDIRECT_IDENTIFIER]] = $this->fs->read_file($this->fs->_pwd_to_array($extra[REDIRECT_IDENTIFIER])); if ($this->output[$extra[REDIRECT_IDENTIFIER]] === false) { $this->output[$extra[REDIRECT_IDENTIFIER]] = ''; } } $extra[ASSIGNMENT] = intval($extra[ASSIGNMENT]); foreach ($extra[STREAM_IDENTIFIER] as $stream_identifier) { if ($extra[ASSIGNMENT] == REDIRECT_OVERWRITE) { $this->output[$stream_identifier] = ''; // Because it's been taken away from here $this->output[$extra[REDIRECT_IDENTIFIER]] = $old_output[$stream_identifier]; } elseif ($extra[ASSIGNMENT] == REDIRECT_APPEND) { $this->output[$stream_identifier] = ''; // Because it's been taken away from here if (is_object($this->output[$extra[REDIRECT_IDENTIFIER]]) && is_object($old_output[$stream_identifier])) { $this->output[$extra[REDIRECT_IDENTIFIER]]->append($old_output[$stream_identifier]); } elseif (!is_object($this->output[$extra[REDIRECT_IDENTIFIER]]) && is_object($old_output[$stream_identifier])) { $this->output[$extra[REDIRECT_IDENTIFIER]] = make_string_tempcode($this->output[$extra[REDIRECT_IDENTIFIER]]); $this->output[$extra[REDIRECT_IDENTIFIER]]->append($old_output[$stream_identifier]); $this->output[$extra[REDIRECT_IDENTIFIER]] = $this->output[$extra[REDIRECT_IDENTIFIER]]->evaluate(); } elseif (is_object($this->output[$extra[REDIRECT_IDENTIFIER]]) && !is_object($old_output[$stream_identifier])) { $old_output[$stream_identifier] = make_string_tempcode($old_output[$stream_identifier]); $this->output[$extra[REDIRECT_IDENTIFIER]]->append($old_output[$stream_identifier]); } else { $this->output[$extra[REDIRECT_IDENTIFIER]] .= $old_output[$stream_identifier]; } } } if ($extra[ASSIGNMENT] == REDIRECT_OVERWRITE || $extra[ASSIGNMENT] == REDIRECT_APPEND) { if (is_object($this->output[$extra[REDIRECT_IDENTIFIER]])) { $this->output[$extra[REDIRECT_IDENTIFIER]] = $this->output[$extra[REDIRECT_IDENTIFIER]]->evaluate(); } $this->fs->write_file($this->fs->_pwd_to_array($extra[REDIRECT_IDENTIFIER]), $this->output[$extra[REDIRECT_IDENTIFIER]]); } } }