ExternalTransformationsPlugin.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. <?php
  2. /**
  3. * Abstract class for the external transformations plugins
  4. */
  5. declare(strict_types=1);
  6. namespace PhpMyAdmin\Plugins\Transformations\Abs;
  7. use PhpMyAdmin\Plugins\TransformationsPlugin;
  8. use stdClass;
  9. use const E_USER_DEPRECATED;
  10. use function count;
  11. use function fclose;
  12. use function feof;
  13. use function fgets;
  14. use function fwrite;
  15. use function htmlspecialchars;
  16. use function is_resource;
  17. use function proc_close;
  18. use function proc_open;
  19. use function sprintf;
  20. use function strlen;
  21. use function trigger_error;
  22. /**
  23. * Provides common methods for all of the external transformations plugins.
  24. */
  25. abstract class ExternalTransformationsPlugin extends TransformationsPlugin
  26. {
  27. /**
  28. * Gets the transformation description of the specific plugin
  29. *
  30. * @return string
  31. */
  32. public static function getInfo()
  33. {
  34. return __(
  35. 'LINUX ONLY: Launches an external application and feeds it the column'
  36. . ' data via standard input. Returns the standard output of the'
  37. . ' application. The default is Tidy, to pretty-print HTML code.'
  38. . ' For security reasons, you have to manually edit the file'
  39. . ' libraries/classes/Plugins/Transformations/Abs/ExternalTransformationsPlugin.php'
  40. . ' and list the tools you want to make available.'
  41. . ' The first option is then the number of the program you want to'
  42. . ' use. The second option should be blank for historical reasons.'
  43. . ' The third option, if set to 1, will convert the output using'
  44. . ' htmlspecialchars() (Default 1). The fourth option, if set to 1,'
  45. . ' will prevent wrapping and ensure that the output appears all on'
  46. . ' one line (Default 1).'
  47. );
  48. }
  49. /**
  50. * Enables no-wrapping
  51. *
  52. * @param array $options transformation options
  53. *
  54. * @return bool
  55. */
  56. public function applyTransformationNoWrap(array $options = [])
  57. {
  58. if (! isset($options[3]) || $options[3] == '') {
  59. $nowrap = true;
  60. } elseif ($options[3] == '1' || $options[3] == 1) {
  61. $nowrap = true;
  62. } else {
  63. $nowrap = false;
  64. }
  65. return $nowrap;
  66. }
  67. /**
  68. * Does the actual work of each specific transformations plugin.
  69. *
  70. * @param string $buffer text to be transformed
  71. * @param array $options transformation options
  72. * @param stdClass|null $meta meta information
  73. *
  74. * @return string
  75. */
  76. public function applyTransformation($buffer, array $options = [], ?stdClass $meta = null)
  77. {
  78. // possibly use a global transform and feed it with special options
  79. // further operations on $buffer using the $options[] array.
  80. $allowed_programs = [];
  81. // WARNING:
  82. //
  83. // It's up to administrator to allow anything here. Note that users may
  84. // specify any parameters, so when programs allow output redirection or
  85. // any other possibly dangerous operations, you should write wrapper
  86. // script that will publish only functions you really want.
  87. //
  88. // Add here program definitions like (note that these are NOT safe
  89. // programs):
  90. //
  91. //$allowed_programs[0] = '/usr/local/bin/tidy';
  92. //$allowed_programs[1] = '/usr/local/bin/validate';
  93. // no-op when no allowed programs
  94. if (count($allowed_programs) === 0) {
  95. return $buffer;
  96. }
  97. $cfg = $GLOBALS['cfg'];
  98. $options = $this->getOptions(
  99. $options,
  100. $cfg['DefaultTransformations']['External']
  101. );
  102. if (isset($allowed_programs[$options[0]])) {
  103. $program = $allowed_programs[$options[0]];
  104. } else {
  105. $program = $allowed_programs[0];
  106. }
  107. if (isset($options[1]) && strlen((string) $options[1]) > 0) {
  108. trigger_error(sprintf(
  109. __(
  110. 'You are using the external transformation command line'
  111. . ' options field, which has been deprecated for security reasons.'
  112. . ' Add all command line options directly to the definition in %s.'
  113. ),
  114. '[code]libraries/classes/Plugins/Transformations/Abs/ExternalTransformationsPlugin.php[/code]'
  115. ), E_USER_DEPRECATED);
  116. }
  117. // needs PHP >= 4.3.0
  118. $newstring = '';
  119. $descriptorspec = [
  120. 0 => [
  121. 'pipe',
  122. 'r',
  123. ],
  124. 1 => [
  125. 'pipe',
  126. 'w',
  127. ],
  128. ];
  129. $process = proc_open($program . ' ' . $options[1], $descriptorspec, $pipes);
  130. if (is_resource($process)) {
  131. fwrite($pipes[0], $buffer);
  132. fclose($pipes[0]);
  133. while (! feof($pipes[1])) {
  134. $newstring .= fgets($pipes[1], 1024);
  135. }
  136. fclose($pipes[1]);
  137. // we don't currently use the return value
  138. proc_close($process);
  139. }
  140. if ($options[2] == 1 || $options[2] == '2') {
  141. $retstring = htmlspecialchars($newstring);
  142. } else {
  143. $retstring = $newstring;
  144. }
  145. return $retstring;
  146. }
  147. /* ~~~~~~~~~~~~~~~~~~~~ Getters and Setters ~~~~~~~~~~~~~~~~~~~~ */
  148. /**
  149. * Gets the transformation name of the specific plugin
  150. *
  151. * @return string
  152. */
  153. public static function getName()
  154. {
  155. return 'External';
  156. }
  157. }