Url.php 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. <?php
  2. /**
  3. * Static methods for URL/hidden inputs generating
  4. */
  5. declare(strict_types=1);
  6. namespace PhpMyAdmin;
  7. use function htmlentities;
  8. use function htmlspecialchars;
  9. use function http_build_query;
  10. use function ini_get;
  11. use function is_array;
  12. use function mb_strpos;
  13. use function strlen;
  14. /**
  15. * Static methods for URL/hidden inputs generating
  16. */
  17. class Url
  18. {
  19. /**
  20. * Generates text with hidden inputs.
  21. *
  22. * @see Url::getCommon()
  23. *
  24. * @param string|array $db optional database name
  25. * (can also be an array of parameters)
  26. * @param string $table optional table name
  27. * @param int $indent indenting level
  28. * @param string|array $skip do not generate a hidden field for this parameter
  29. * (can be an array of strings)
  30. *
  31. * @return string string with input fields
  32. *
  33. * @access public
  34. */
  35. public static function getHiddenInputs(
  36. $db = '',
  37. $table = '',
  38. $indent = 0,
  39. $skip = []
  40. ) {
  41. global $PMA_Config;
  42. if (is_array($db)) {
  43. $params =& $db;
  44. } else {
  45. $params = [];
  46. if (strlen((string) $db) > 0) {
  47. $params['db'] = $db;
  48. }
  49. if (strlen((string) $table) > 0) {
  50. $params['table'] = $table;
  51. }
  52. }
  53. if (! empty($GLOBALS['server'])
  54. && $GLOBALS['server'] != $GLOBALS['cfg']['ServerDefault']
  55. ) {
  56. $params['server'] = $GLOBALS['server'];
  57. }
  58. if (empty($PMA_Config->getCookie('pma_lang')) && ! empty($GLOBALS['lang'])) {
  59. $params['lang'] = $GLOBALS['lang'];
  60. }
  61. if (! is_array($skip)) {
  62. if (isset($params[$skip])) {
  63. unset($params[$skip]);
  64. }
  65. } else {
  66. foreach ($skip as $skipping) {
  67. if (! isset($params[$skipping])) {
  68. continue;
  69. }
  70. unset($params[$skipping]);
  71. }
  72. }
  73. return self::getHiddenFields($params);
  74. }
  75. /**
  76. * create hidden form fields from array with name => value
  77. *
  78. * <code>
  79. * $values = array(
  80. * 'aaa' => aaa,
  81. * 'bbb' => array(
  82. * 'bbb_0',
  83. * 'bbb_1',
  84. * ),
  85. * 'ccc' => array(
  86. * 'a' => 'ccc_a',
  87. * 'b' => 'ccc_b',
  88. * ),
  89. * );
  90. * echo Url::getHiddenFields($values);
  91. *
  92. * // produces:
  93. * <input type="hidden" name="aaa" Value="aaa">
  94. * <input type="hidden" name="bbb[0]" Value="bbb_0">
  95. * <input type="hidden" name="bbb[1]" Value="bbb_1">
  96. * <input type="hidden" name="ccc[a]" Value="ccc_a">
  97. * <input type="hidden" name="ccc[b]" Value="ccc_b">
  98. * </code>
  99. *
  100. * @param array $values hidden values
  101. * @param string $pre prefix
  102. * @param bool $is_token if token already added in hidden input field
  103. *
  104. * @return string form fields of type hidden
  105. */
  106. public static function getHiddenFields(array $values, $pre = '', $is_token = false)
  107. {
  108. $fields = '';
  109. /* Always include token in plain forms */
  110. if ($is_token === false) {
  111. $values['token'] = $_SESSION[' PMA_token '];
  112. }
  113. foreach ($values as $name => $value) {
  114. if (! empty($pre)) {
  115. $name = $pre . '[' . $name . ']';
  116. }
  117. if (is_array($value)) {
  118. $fields .= self::getHiddenFields($value, $name, true);
  119. } else {
  120. // do not generate an ending "\n" because
  121. // Url::getHiddenInputs() is sometimes called
  122. // from a JS document.write()
  123. $fields .= '<input type="hidden" name="' . htmlspecialchars((string) $name)
  124. . '" value="' . htmlspecialchars((string) $value) . '">';
  125. }
  126. }
  127. return $fields;
  128. }
  129. /**
  130. * Generates text with URL parameters.
  131. *
  132. * <code>
  133. * $params['myparam'] = 'myvalue';
  134. * $params['db'] = 'mysql';
  135. * $params['table'] = 'rights';
  136. * // note the missing ?
  137. * echo 'script.php' . Url::getCommon($params);
  138. * // produces with cookies enabled:
  139. * // script.php?myparam=myvalue&db=mysql&table=rights
  140. * // with cookies disabled:
  141. * // script.php?server=1&lang=en&myparam=myvalue&db=mysql
  142. * // &table=rights
  143. *
  144. * // note the missing ?
  145. * echo 'script.php' . Url::getCommon();
  146. * // produces with cookies enabled:
  147. * // script.php
  148. * // with cookies disabled:
  149. * // script.php?server=1&lang=en
  150. * </code>
  151. *
  152. * @param array<string,int|string|bool> $params optional, Contains an associative array with url params
  153. * @param string $divider optional character to use instead of '?'
  154. *
  155. * @return string string with URL parameters
  156. *
  157. * @access public
  158. */
  159. public static function getCommon(array $params = [], $divider = '?')
  160. {
  161. return self::getCommonRaw($params, $divider);
  162. }
  163. /**
  164. * Generates text with URL parameters.
  165. *
  166. * <code>
  167. * $params['myparam'] = 'myvalue';
  168. * $params['db'] = 'mysql';
  169. * $params['table'] = 'rights';
  170. * // note the missing ?
  171. * echo 'script.php' . Url::getCommon($params);
  172. * // produces with cookies enabled:
  173. * // script.php?myparam=myvalue&db=mysql&table=rights
  174. * // with cookies disabled:
  175. * // script.php?server=1&lang=en&myparam=myvalue&db=mysql
  176. * // &table=rights
  177. *
  178. * // note the missing ?
  179. * echo 'script.php' . Url::getCommon();
  180. * // produces with cookies enabled:
  181. * // script.php
  182. * // with cookies disabled:
  183. * // script.php?server=1&lang=en
  184. * </code>
  185. *
  186. * @param array<string|int,int|string|bool> $params optional, Contains an associative array with url params
  187. * @param string $divider optional character to use instead of '?'
  188. *
  189. * @return string string with URL parameters
  190. *
  191. * @access public
  192. */
  193. public static function getCommonRaw(array $params = [], $divider = '?')
  194. {
  195. global $PMA_Config;
  196. $separator = self::getArgSeparator();
  197. // avoid overwriting when creating navigation panel links to servers
  198. if (isset($GLOBALS['server'])
  199. && $GLOBALS['server'] != $GLOBALS['cfg']['ServerDefault']
  200. && ! isset($params['server'])
  201. && ! $PMA_Config->get('is_setup')
  202. ) {
  203. $params['server'] = $GLOBALS['server'];
  204. }
  205. // Can be null when the user is missing an extension.
  206. // See: Core::checkExtensions()
  207. if ($PMA_Config !== null && empty($PMA_Config->getCookie('pma_lang')) && ! empty($GLOBALS['lang'])) {
  208. $params['lang'] = $GLOBALS['lang'];
  209. }
  210. $query = http_build_query($params, '', $separator);
  211. if (($divider !== '?' && $divider !== '&') || strlen($query) > 0) {
  212. return $divider . $query;
  213. }
  214. return '';
  215. }
  216. /**
  217. * Returns url separator
  218. *
  219. * extracted from arg_separator.input as set in php.ini
  220. * we do not use arg_separator.output to avoid problems with & and &
  221. *
  222. * @param string $encode whether to encode separator or not,
  223. * currently 'none' or 'html'
  224. *
  225. * @return string character used for separating url parts usually ; or &
  226. *
  227. * @access public
  228. */
  229. public static function getArgSeparator($encode = 'none')
  230. {
  231. static $separator = null;
  232. static $html_separator = null;
  233. if ($separator === null) {
  234. // use separators defined by php, but prefer ';'
  235. // as recommended by W3C
  236. // (see https://www.w3.org/TR/1999/REC-html401-19991224/appendix
  237. // /notes.html#h-B.2.2)
  238. $arg_separator = (string) ini_get('arg_separator.input');
  239. if (mb_strpos($arg_separator, ';') !== false) {
  240. $separator = ';';
  241. } elseif (strlen($arg_separator) > 0) {
  242. $separator = $arg_separator[0];
  243. } else {
  244. $separator = '&';
  245. }
  246. $html_separator = htmlentities($separator);
  247. }
  248. switch ($encode) {
  249. case 'html':
  250. return $html_separator;
  251. case 'text':
  252. case 'none':
  253. default:
  254. return $separator;
  255. }
  256. }
  257. /**
  258. * @param string $route Route to use
  259. * @param array $additionalParameters Additional URL parameters
  260. */
  261. public static function getFromRoute(string $route, array $additionalParameters = []): string
  262. {
  263. return 'index.php?route=' . $route . self::getCommon($additionalParameters, '&');
  264. }
  265. }