/** * The invoking function which allows us to use fancy syntax for commands. It allows the user * and bot-system to directly invoke the object variable. * * @param Bot $pBot The bot that got the command. * @param string $sDestination The place we should send the output to. * @param string $sChannel The channel the command was received in. * @param string $sNickname The nickname of the user who executed the command. * @param array $aParams The parameters given to the command. * @param string $sMessage The complete message after the command. * @throws Exception If the command was not callable. * @return boolean Did the command execute? */ public function __invoke(Bot $pBot, $sDestination, $sChannel, $sNickname, $aParams, $sMessage) { if (!is_callable($this->m_rCachedCommand)) { /** Quite a serious problem this is. Throw an Exception. **/ throw new Exception('Command ' . $this->getCommand() . ' is not callable.'); } if ($this->getPermission() !== null && !$pBot->getSecurityManager()->hasPermission($pBot->In->User, $this->getPermission())) { return false; } if ($this->checkNetwork($pBot['Network']) && $this->checkChannel($sChannel)) { $cFunction = $this->m_rCachedCommand; $this->m_aStatistics['Executed']++; $this->m_aStatistics['LastTime'] = time(); /** Let the exception handler know where we are executing code. **/ ErrorExceptionHandler::$Source = $sDestination; /** Catch output. **/ ob_start(); $fStart = microtime(true); /** Execute the command. **/ $nReturnCode = call_user_func($cFunction, $pBot, $sDestination, $sChannel, $sNickname, $aParams, $sMessage); $this->m_aStatistics['TotalTime'] += microtime(true) - $fStart; if ($nReturnCode == null || !is_int($nReturnCode)) { $nReturnCode = self::OUTPUT_NORMAL; } switch ($nReturnCode) { default: case self::OUTPUT_NORMAL: $sCallback = 'privmsg'; break; case self::OUTPUT_ERROR: $sCallback = 'error'; break; case self::OUTPUT_INFO: $sCallback = 'info'; break; case self::OUTPUT_NOTICE: $sCallback = 'notice'; break; case self::OUTPUT_SUCCESS: $sCallback = 'success'; break; case self::OUTPUT_USAGE: $sCallback = 'usage'; break; } /** Send output to IRC. **/ $aOutput = explode("\n", trim(ob_get_clean())); if (isset($pBot) && $pBot instanceof Bot) { foreach ($aOutput as $sLine) { call_user_func(array('Command', $sCallback), $pBot, $sDestination, $sLine); } } return true; } return false; }
/** * This function will immediatly execute the evaluation that we're doing * right now. Evaluation delays are already handled by the parser. * * @param Bot $pBot Bot that should handle the evaluation. * @param string $sDestination Where should the output be redirected? * @param array $aOptions Array with the parsed options for this evaluation. */ public function doEvaluation(Bot $pBot, $sDestination, $aOptions) { ob_start(); ErrorExceptionHandler::$Source = $sDestination; switch ($aOptions['Type']) { case 'PHP': eval($aOptions['Operation']); break; case 'EXEC': $process = proc_open($aOptions['Operation'], array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes); if (is_resource($process)) { fclose($pipes[0]); $output = trim(stream_get_contents($pipes[1])); fclose($pipes[1]); $error = trim(stream_get_contents($pipes[2])); fclose($pipes[2]); $returnValue = proc_close($process); if ($output != '') { echo $output . ' '; } $haveNewLine = false; if ($error != '') { echo PHP_EOL . ModuleBase::COLOUR_RED . '* Error' . ModuleBase::CLEAR . ': ' . $error . ' '; $haveNewLine = true; } if ($returnValue !== 0) { if (!$haveNewLine) { echo PHP_EOL; } else { echo '| '; } echo ModuleBase::COLOUR_TEAL; if (!$haveNewLine) { echo '* '; } echo 'Return value' . ModuleBase::CLEAR . ': ' . $returnValue; $haveNewLine = true; } } break; case 'SQL': $pDatabase = Database::getInstance(); if ($pDatabase == null || $pDatabase->connect_error) { echo '4* Database Error: Could not connect to database'; if ($pDatabase != null) { echo ': "' . $pDatabase->connect_error . '"'; } echo '.'; break; } $pResult = $pDatabase->query($aOptions['Operation']); if ($pResult === false) { echo '4* Database Error: ' . $pDatabase->error; } else { if ($pResult->num_rows == 0) { echo '10* No rows.'; } else { $aFields = $aFieldLen = array(); foreach ($pResult->fetch_fields() as $pField) { $aFields[$pField->name] = array($pField->name); $aFieldLen[$pField->name] = strlen($pField->name); } while (($aRow = $pResult->fetch_assoc()) != null) { foreach ($aRow as $sField => $mValue) { if ($mValue == null) { $mValue = 'NULL'; } $aFields[$sField][] = $mValue; $aFieldLen[$sField] = max($aFieldLen[$sField], strlen((string) $mValue)); } } // Output is imminent. for ($i = 0; $i <= $pResult->num_rows; $i++) { // 1 extra loop for the header. foreach (array_keys($aFields) as $sField) { echo sprintf('| ' . ($i == 0 ? '' : '') . '%\'' . chr(160) . '-' . $aFieldLen[$sField] . 's' . ($i == 0 ? '' : '') . ' ', $aFields[$sField][$i]); } echo '|' . PHP_EOL; } } } break; } $aOutput = explode("\n", trim(ob_get_clean())); if (count($aOutput) > $aOptions['MaxLines'] + 1 && $aOptions['Buffering'] == true) { $nSize = count($aOutput); $aOutput = array_slice($aOutput, 0, $aOptions['MaxLines']); $aOutput[] = '10* Displayed ' . $aOptions['MaxLines'] . ' out of ' . $nSize . ' lines.'; } if (isset($pBot) && $pBot instanceof Bot) { foreach ($aOutput as $sLine) { $pBot->send('PRIVMSG ' . $sDestination . ' :' . trim($sLine), false); } } }