TransformationWrapperController.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. <?php
  2. declare(strict_types=1);
  3. namespace PhpMyAdmin\Controllers;
  4. use PhpMyAdmin\Core;
  5. use PhpMyAdmin\DatabaseInterface;
  6. use PhpMyAdmin\DbTableExists;
  7. use PhpMyAdmin\Relation;
  8. use PhpMyAdmin\Response;
  9. use PhpMyAdmin\Template;
  10. use PhpMyAdmin\Transformations;
  11. use PhpMyAdmin\Util;
  12. use function define;
  13. use function htmlspecialchars;
  14. use function imagecopyresampled;
  15. use function imagecreatefromstring;
  16. use function imagecreatetruecolor;
  17. use function imagedestroy;
  18. use function imagejpeg;
  19. use function imagepng;
  20. use function imagesx;
  21. use function imagesy;
  22. use function in_array;
  23. use function intval;
  24. use function round;
  25. use function str_replace;
  26. use function stripos;
  27. use function substr;
  28. /**
  29. * Wrapper script for rendering transformations
  30. */
  31. class TransformationWrapperController extends AbstractController
  32. {
  33. /** @var Transformations */
  34. private $transformations;
  35. /** @var Relation */
  36. private $relation;
  37. /** @var DatabaseInterface */
  38. private $dbi;
  39. /**
  40. * @param Response $response
  41. * @param DatabaseInterface $dbi
  42. */
  43. public function __construct(
  44. $response,
  45. Template $template,
  46. Transformations $transformations,
  47. Relation $relation,
  48. $dbi
  49. ) {
  50. parent::__construct($response, $template);
  51. $this->transformations = $transformations;
  52. $this->relation = $relation;
  53. $this->dbi = $dbi;
  54. }
  55. public function index(): void
  56. {
  57. global $cn, $db, $table, $transform_key, $request_params, $size_params, $where_clause, $row;
  58. global $default_ct, $mime_map, $mime_options, $ct, $mime_type, $srcImage, $srcWidth, $srcHeight;
  59. global $ratioWidth, $ratioHeight, $destWidth, $destHeight, $destImage;
  60. define('IS_TRANSFORMATION_WRAPPER', true);
  61. $cfgRelation = $this->relation->getRelationsParam();
  62. DbTableExists::check();
  63. /**
  64. * Sets globals from $_REQUEST
  65. */
  66. $request_params = [
  67. 'cn',
  68. 'ct',
  69. 'sql_query',
  70. 'transform_key',
  71. 'where_clause',
  72. ];
  73. $size_params = [
  74. 'newHeight',
  75. 'newWidth',
  76. ];
  77. foreach ($request_params as $one_request_param) {
  78. if (! isset($_REQUEST[$one_request_param])) {
  79. continue;
  80. }
  81. if (in_array($one_request_param, $size_params)) {
  82. $GLOBALS[$one_request_param] = intval($_REQUEST[$one_request_param]);
  83. if ($GLOBALS[$one_request_param] > 2000) {
  84. $GLOBALS[$one_request_param] = 2000;
  85. }
  86. } else {
  87. $GLOBALS[$one_request_param] = $_REQUEST[$one_request_param];
  88. }
  89. }
  90. /**
  91. * Get the list of the fields of the current table
  92. */
  93. $this->dbi->selectDb($db);
  94. if (isset($where_clause)) {
  95. if (! Core::checkSqlQuerySignature($where_clause, $_GET['where_clause_sign'] ?? '')) {
  96. /* l10n: In case a SQL query did not pass a security check */
  97. Core::fatalError(__('There is an issue with your request.'));
  98. return;
  99. }
  100. $result = $this->dbi->query(
  101. 'SELECT * FROM ' . Util::backquote($table)
  102. . ' WHERE ' . $where_clause . ';',
  103. DatabaseInterface::CONNECT_USER,
  104. DatabaseInterface::QUERY_STORE
  105. );
  106. $row = $this->dbi->fetchAssoc($result);
  107. } else {
  108. $result = $this->dbi->query(
  109. 'SELECT * FROM ' . Util::backquote($table) . ' LIMIT 1;',
  110. DatabaseInterface::CONNECT_USER,
  111. DatabaseInterface::QUERY_STORE
  112. );
  113. $row = $this->dbi->fetchAssoc($result);
  114. }
  115. // No row returned
  116. if (! $row) {
  117. return;
  118. }
  119. $default_ct = 'application/octet-stream';
  120. if ($cfgRelation['commwork'] && $cfgRelation['mimework']) {
  121. $mime_map = $this->transformations->getMime($db, $table);
  122. if ($mime_map === null) {
  123. $mime_map = [];
  124. }
  125. $mime_options = $this->transformations->getOptions(
  126. $mime_map[$transform_key]['transformation_options'] ?? ''
  127. );
  128. foreach ($mime_options as $key => $option) {
  129. if (substr($option, 0, 10) !== '; charset=') {
  130. continue;
  131. }
  132. $mime_options['charset'] = $option;
  133. }
  134. }
  135. $this->response->getHeader()->sendHttpHeaders();
  136. // [MIME]
  137. if (isset($ct) && ! empty($ct)) {
  138. $mime_type = $ct;
  139. } else {
  140. $mime_type = (! empty($mime_map[$transform_key]['mimetype'])
  141. ? str_replace('_', '/', $mime_map[$transform_key]['mimetype'])
  142. : $default_ct)
  143. . ($mime_options['charset'] ?? '');
  144. }
  145. Core::downloadHeader($cn ?? '', $mime_type ?? '');
  146. if (! isset($_REQUEST['resize'])) {
  147. if (stripos($mime_type ?? '', 'html') === false) {
  148. echo $row[$transform_key];
  149. } else {
  150. echo htmlspecialchars($row[$transform_key]);
  151. }
  152. } else {
  153. // if image_*__inline.inc.php finds that we can resize,
  154. // it sets the resize parameter to jpeg or png
  155. $srcImage = imagecreatefromstring($row[$transform_key]);
  156. if ($srcImage === false) {
  157. return;
  158. }
  159. $srcWidth = imagesx($srcImage);
  160. $srcHeight = imagesy($srcImage);
  161. // Check to see if the width > height or if width < height
  162. // if so adjust accordingly to make sure the image
  163. // stays smaller than the new width and new height
  164. $ratioWidth = $srcWidth / $_REQUEST['newWidth'];
  165. $ratioHeight = $srcHeight / $_REQUEST['newHeight'];
  166. if ($ratioWidth < $ratioHeight) {
  167. $destWidth = intval(round($srcWidth / $ratioHeight));
  168. $destHeight = intval($_REQUEST['newHeight']);
  169. } else {
  170. $destWidth = intval($_REQUEST['newWidth']);
  171. $destHeight = intval(round($srcHeight / $ratioWidth));
  172. }
  173. if ($_REQUEST['resize']) {
  174. $destImage = imagecreatetruecolor($destWidth, $destHeight);
  175. if ($destImage === false) {
  176. imagedestroy($srcImage);
  177. return;
  178. }
  179. // ImageCopyResized($destImage, $srcImage, 0, 0, 0, 0,
  180. // $destWidth, $destHeight, $srcWidth, $srcHeight);
  181. // better quality but slower:
  182. imagecopyresampled(
  183. $destImage,
  184. $srcImage,
  185. 0,
  186. 0,
  187. 0,
  188. 0,
  189. $destWidth,
  190. $destHeight,
  191. $srcWidth,
  192. $srcHeight
  193. );
  194. if ($_REQUEST['resize'] === 'jpeg') {
  195. imagejpeg($destImage, null, 75);
  196. }
  197. if ($_REQUEST['resize'] === 'png') {
  198. imagepng($destImage);
  199. }
  200. imagedestroy($destImage);
  201. }
  202. imagedestroy($srcImage);
  203. }
  204. }
  205. }