| 1 |
#!/usr/bin/env php |
| 2 |
<?php |
| 3 |
/* |
| 4 |
* StatusNet - the distributed open-source microblogging tool |
| 5 |
* Copyright (C) 2009, StatusNet, Inc. |
| 6 |
* |
| 7 |
* This program is free software: you can redistribute it and/or modify |
| 8 |
* it under the terms of the GNU Affero General Public License as published by |
| 9 |
* the Free Software Foundation, either version 3 of the License, or |
| 10 |
* (at your option) any later version. |
| 11 |
* |
| 12 |
* This program is distributed in the hope that it will be useful, |
| 13 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 |
* GNU Affero General Public License for more details. |
| 16 |
* |
| 17 |
* You should have received a copy of the GNU Affero General Public License |
| 18 |
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 19 |
*/ |
| 20 |
|
| 21 |
# Abort if called from a web server |
| 22 |
|
| 23 |
define('INSTALLDIR', realpath(dirname(__FILE__) . '/..')); |
| 24 |
|
| 25 |
$helptext = <<<ENDOFHELP |
| 26 |
console.php - provide an interactive PHP interpreter for testing |
| 27 |
|
| 28 |
ENDOFHELP; |
| 29 |
|
| 30 |
require_once INSTALLDIR.'/scripts/commandline.inc'; |
| 31 |
|
| 32 |
// Assume we're on a terminal if on Windows, otherwise posix_isatty tells us. |
| 33 |
define('CONSOLE_INTERACTIVE', !function_exists('posix_isatty') || posix_isatty(0)); |
| 34 |
define('CONSOLE_READLINE', CONSOLE_INTERACTIVE && function_exists('readline')); |
| 35 |
|
| 36 |
if (CONSOLE_READLINE && CONSOLE_INTERACTIVE) { |
| 37 |
define('CONSOLE_HISTORY', getenv("HOME") . "/.statusnet_console_history"); |
| 38 |
if (file_exists(CONSOLE_HISTORY)) { |
| 39 |
readline_read_history(CONSOLE_HISTORY); |
| 40 |
} |
| 41 |
} |
| 42 |
|
| 43 |
function read_input_line($prompt) |
| 44 |
{ |
| 45 |
if (CONSOLE_INTERACTIVE) { |
| 46 |
if (CONSOLE_READLINE) { |
| 47 |
$line = readline($prompt); |
| 48 |
if (trim($line) != '') { |
| 49 |
readline_add_history($line); |
| 50 |
if (defined('CONSOLE_HISTORY')) { |
| 51 |
// Save often; it's easy to hit fatal errors. |
| 52 |
readline_write_history(CONSOLE_HISTORY); |
| 53 |
} |
| 54 |
} |
| 55 |
return $line; |
| 56 |
} else { |
| 57 |
return readline_emulation($prompt); |
| 58 |
} |
| 59 |
} else { |
| 60 |
return fgets(STDIN); |
| 61 |
} |
| 62 |
} |
| 63 |
|
| 64 |
/** |
| 65 |
* On Unix-like systems where PHP readline extension isn't present, |
| 66 |
* -cough- Mac OS X -cough- we can shell out to bash to do it for us. |
| 67 |
* This lets us at least handle things like arrow keys, but we don't |
| 68 |
* get any entry history. :( |
| 69 |
* |
| 70 |
* Shamelessly ripped from when I wrote the same code for MediaWiki. :) |
| 71 |
* @author Brion Vibber <brion@status.net> |
| 72 |
* |
| 73 |
* @param string $prompt |
| 74 |
* @return mixed string on success, false on fail or EOF |
| 75 |
*/ |
| 76 |
function readline_emulation($prompt) |
| 77 |
{ |
| 78 |
if(CONSOLE_INTERACTIVE && file_exists(trim(shell_exec('which bash')))) { |
| 79 |
$encPrompt = escapeshellarg($prompt); |
| 80 |
$command = "read -er -p $encPrompt && echo \"\$REPLY\""; |
| 81 |
$encCommand = escapeshellarg($command); |
| 82 |
$metaCommand = "bash -c $encCommand"; |
| 83 |
|
| 84 |
// passthru passes our STDIN and TTY to the child... |
| 85 |
// We can pull the returned string via output buffering. |
| 86 |
ob_start(); |
| 87 |
$retval = false; |
| 88 |
passthru($metaCommand, $retval); |
| 89 |
$line = ob_get_contents(); |
| 90 |
ob_end_clean(); |
| 91 |
|
| 92 |
if ($retval == 0) { |
| 93 |
return $line; |
| 94 |
} elseif ($retval == 127) { |
| 95 |
// Couldn't execute bash even though we thought we saw it. |
| 96 |
// Shell probably spit out an error message, sorry :( |
| 97 |
// Fall through to fgets()... |
| 98 |
} else { |
| 99 |
// EOF/ctrl+D |
| 100 |
return false; |
| 101 |
} |
| 102 |
} |
| 103 |
|
| 104 |
// Fallback... we'll have no editing controls, EWWW |
| 105 |
if (feof(STDIN)) { |
| 106 |
return false; |
| 107 |
} |
| 108 |
if (CONSOLE_INTERACTIVE) { |
| 109 |
print $prompt; |
| 110 |
} |
| 111 |
return fgets(STDIN); |
| 112 |
} |
| 113 |
|
| 114 |
function console_help() |
| 115 |
{ |
| 116 |
print "Welcome to StatusNet's interactive PHP console!\n"; |
| 117 |
print "Type some PHP code and it'll execute...\n"; |
| 118 |
print "\n"; |
| 119 |
print "Hint: return a value of any type to output it via var_export():\n"; |
| 120 |
print " \$profile = new Profile();\n"; |
| 121 |
print " \$profile->find();\n"; |
| 122 |
print " \$profile->fetch();\n"; |
| 123 |
print " return \$profile;\n"; |
| 124 |
print "\n"; |
| 125 |
print "Note that PHP is cranky and you can easily kill your session by mistyping.\n"; |
| 126 |
print "\n"; |
| 127 |
print "Type ctrl+D or enter 'exit' to exit.\n"; |
| 128 |
} |
| 129 |
|
| 130 |
if (CONSOLE_INTERACTIVE) { |
| 131 |
print "StatusNet interactive PHP console... type ctrl+D or enter 'exit' to exit.\n"; |
| 132 |
$prompt = common_config('site', 'name') . '> '; |
| 133 |
} else { |
| 134 |
$prompt = ''; |
| 135 |
} |
| 136 |
while (!feof(STDIN)) { |
| 137 |
$line = read_input_line($prompt); |
| 138 |
if ($line === false) { |
| 139 |
if (CONSOLE_INTERACTIVE) { |
| 140 |
print "\n"; |
| 141 |
} |
| 142 |
break; |
| 143 |
} elseif ($line !== '') { |
| 144 |
try { |
| 145 |
if (trim($line) == 'exit') { |
| 146 |
break; |
| 147 |
} elseif (trim($line) == 'help') { |
| 148 |
console_help(); |
| 149 |
continue; |
| 150 |
} |
| 151 |
|
| 152 |
// Let's do this! |
| 153 |
$result = eval($line); |
| 154 |
if ($result === false) { |
| 155 |
// parse error |
| 156 |
} elseif ($result === null) { |
| 157 |
// no return |
| 158 |
} else { |
| 159 |
// return value from eval'd code |
| 160 |
var_export($result); |
| 161 |
} |
| 162 |
} catch(Exception $e) { |
| 163 |
print get_class($e) . ": " . $e->getMessage() . "\n"; |
| 164 |
} |
| 165 |
} |
| 166 |
if (CONSOLE_INTERACTIVE) { |
| 167 |
print "\n"; |
| 168 |
} |
| 169 |
} |