simple_console.php 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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. // Abort if called from a web server
  21. define('INSTALLDIR', dirname(__DIR__));
  22. define('PUBLICDIR', INSTALLDIR . DIRECTORY_SEPARATOR . 'public');
  23. $helptext = <<<ENDOFHELP
  24. console.php - provide an interactive PHP interpreter for testing
  25. ENDOFHELP;
  26. require_once INSTALLDIR.'/scripts/commandline.inc';
  27. // Assume we're on a terminal if on Windows, otherwise posix_isatty tells us.
  28. define('CONSOLE_INTERACTIVE', !function_exists('posix_isatty') || posix_isatty(0));
  29. define('CONSOLE_READLINE', CONSOLE_INTERACTIVE && function_exists('readline'));
  30. if (CONSOLE_READLINE && CONSOLE_INTERACTIVE) {
  31. define('CONSOLE_HISTORY', getenv("HOME") . "/.statusnet_console_history");
  32. if (file_exists(CONSOLE_HISTORY)) {
  33. readline_read_history(CONSOLE_HISTORY);
  34. }
  35. }
  36. function read_input_line($prompt)
  37. {
  38. if (CONSOLE_INTERACTIVE) {
  39. if (CONSOLE_READLINE) {
  40. $line = readline($prompt);
  41. if (trim($line) != '') {
  42. readline_add_history($line);
  43. if (defined('CONSOLE_HISTORY')) {
  44. // Save often; it's easy to hit fatal errors.
  45. readline_write_history(CONSOLE_HISTORY);
  46. }
  47. }
  48. return $line;
  49. } else {
  50. return readline_emulation($prompt);
  51. }
  52. } else {
  53. return fgets(STDIN);
  54. }
  55. }
  56. /**
  57. * On Unix-like systems where PHP readline extension isn't present,
  58. * -cough- Mac OS X -cough- we can shell out to bash to do it for us.
  59. * This lets us at least handle things like arrow keys, but we don't
  60. * get any entry history. :(
  61. *
  62. * Shamelessly ripped from when I wrote the same code for MediaWiki. :)
  63. * @author Brion Vibber <brion@status.net>
  64. *
  65. * @param string $prompt
  66. * @return mixed string on success, false on fail or EOF
  67. */
  68. function readline_emulation($prompt)
  69. {
  70. if (CONSOLE_INTERACTIVE && file_exists(trim(shell_exec('which bash')))) {
  71. $encPrompt = escapeshellarg($prompt);
  72. $command = "read -er -p $encPrompt && echo \"\$REPLY\"";
  73. $encCommand = escapeshellarg($command);
  74. $metaCommand = "bash -c $encCommand";
  75. // passthru passes our STDIN and TTY to the child...
  76. // We can pull the returned string via output buffering.
  77. ob_start();
  78. $retval = false;
  79. passthru($metaCommand, $retval);
  80. $line = ob_get_contents();
  81. ob_end_clean();
  82. if ($retval == 0) {
  83. return $line;
  84. } elseif ($retval == 127) {
  85. // Couldn't execute bash even though we thought we saw it.
  86. // Shell probably spit out an error message, sorry :(
  87. // Fall through to fgets()...
  88. } else {
  89. // EOF/ctrl+D
  90. return false;
  91. }
  92. }
  93. // Fallback... we'll have no editing controls, EWWW
  94. if (feof(STDIN)) {
  95. return false;
  96. }
  97. if (CONSOLE_INTERACTIVE) {
  98. print $prompt;
  99. }
  100. return fgets(STDIN);
  101. }
  102. function console_help()
  103. {
  104. print "Welcome to GNU social's interactive PHP console!\n";
  105. print "Type some PHP code and it'll execute...\n";
  106. print "\n";
  107. print "Hint: return a value of any type to output it via var_export():\n";
  108. print " \$profile = new Profile();\n";
  109. print " \$profile->find();\n";
  110. print " \$profile->fetch();\n";
  111. print " return \$profile;\n";
  112. print "\n";
  113. print "Note that PHP is cranky and you can easily kill your session by mistyping.\n";
  114. print "\n";
  115. print "Type ctrl+D or enter 'exit' to exit.\n";
  116. }
  117. if (CONSOLE_INTERACTIVE) {
  118. print "GNU social interactive PHP console... type ctrl+D or enter 'exit' to exit.\n";
  119. $prompt = common_slugify(common_config('site', 'name')) . '> ';
  120. } else {
  121. $prompt = '';
  122. }
  123. while (!feof(STDIN)) {
  124. $line = read_input_line($prompt);
  125. if ($line === false) {
  126. if (CONSOLE_INTERACTIVE) {
  127. print "\n";
  128. }
  129. break;
  130. } elseif ($line !== '') {
  131. try {
  132. if (trim($line) == 'exit') {
  133. break;
  134. } elseif (trim($line) == 'help') {
  135. console_help();
  136. continue;
  137. }
  138. // Let's do this!
  139. $result = eval($line);
  140. if ($result === false) {
  141. // parse error
  142. } elseif ($result === null) {
  143. // no return
  144. } else {
  145. // return value from eval'd code
  146. var_export($result);
  147. }
  148. } catch (Exception $e) {
  149. print get_class($e) . ": " . $e->getMessage() . "\n";
  150. }
  151. }
  152. if (CONSOLE_INTERACTIVE) {
  153. print "\n";
  154. }
  155. }