PageRenderTime 64ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/phpmyadmin/libraries/common.lib.php

https://bitbucket.org/DenizYldrm/openemr
PHP | 2367 lines | 1394 code | 200 blank | 773 comment | 353 complexity | 1bc5e5f686ab67e428d7770cdec0e54a MD5 | raw file
Possible License(s): AGPL-1.0, GPL-2.0, MPL-2.0, LGPL-2.1
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Misc functions used all over the scripts.
  5. *
  6. * @version $Id$
  7. */
  8. /**
  9. * Exponential expression / raise number into power
  10. *
  11. * @uses function_exists()
  12. * @uses bcpow()
  13. * @uses gmp_pow()
  14. * @uses gmp_strval()
  15. * @uses pow()
  16. * @param number $base
  17. * @param number $exp
  18. * @param string pow function use, or false for auto-detect
  19. * @return mixed string or float
  20. */
  21. function PMA_pow($base, $exp, $use_function = false)
  22. {
  23. static $pow_function = null;
  24. if ($exp < 0) {
  25. return false;
  26. }
  27. if (null == $pow_function) {
  28. if (function_exists('bcpow')) {
  29. // BCMath Arbitrary Precision Mathematics Function
  30. $pow_function = 'bcpow';
  31. } elseif (function_exists('gmp_pow')) {
  32. // GMP Function
  33. $pow_function = 'gmp_pow';
  34. } else {
  35. // PHP function
  36. $pow_function = 'pow';
  37. }
  38. }
  39. if (! $use_function) {
  40. $use_function = $pow_function;
  41. }
  42. switch ($use_function) {
  43. case 'bcpow' :
  44. //bcscale(10);
  45. $pow = bcpow($base, $exp);
  46. break;
  47. case 'gmp_pow' :
  48. $pow = gmp_strval(gmp_pow($base, $exp));
  49. break;
  50. case 'pow' :
  51. $base = (float) $base;
  52. $exp = (int) $exp;
  53. $pow = pow($base, $exp);
  54. break;
  55. default:
  56. $pow = $use_function($base, $exp);
  57. }
  58. return $pow;
  59. }
  60. /**
  61. * string PMA_getIcon(string $icon)
  62. *
  63. * @uses $GLOBALS['pmaThemeImage']
  64. * @param $icon name of icon
  65. * @return html img tag
  66. */
  67. function PMA_getIcon($icon, $alternate = '')
  68. {
  69. if ($GLOBALS['cfg']['PropertiesIconic']) {
  70. return '<img src="' . $GLOBALS['pmaThemeImage'] . $icon . '"'
  71. . ' title="' . $alternate . '" alt="' . $alternate . '"'
  72. . ' class="icon" width="16" height="16" />';
  73. } else {
  74. return $alternate;
  75. }
  76. }
  77. /**
  78. * Displays the maximum size for an upload
  79. *
  80. * @uses $GLOBALS['strMaximumSize']
  81. * @uses PMA_formatByteDown()
  82. * @uses sprintf()
  83. * @param integer the size
  84. *
  85. * @return string the message
  86. *
  87. * @access public
  88. */
  89. function PMA_displayMaximumUploadSize($max_upload_size)
  90. {
  91. list($max_size, $max_unit) = PMA_formatByteDown($max_upload_size);
  92. return '(' . sprintf($GLOBALS['strMaximumSize'], $max_size, $max_unit) . ')';
  93. }
  94. /**
  95. * Generates a hidden field which should indicate to the browser
  96. * the maximum size for upload
  97. *
  98. * @param integer the size
  99. *
  100. * @return string the INPUT field
  101. *
  102. * @access public
  103. */
  104. function PMA_generateHiddenMaxFileSize($max_size)
  105. {
  106. return '<input type="hidden" name="MAX_FILE_SIZE" value="' .$max_size . '" />';
  107. }
  108. /**
  109. * Add slashes before "'" and "\" characters so a value containing them can
  110. * be used in a sql comparison.
  111. *
  112. * @uses str_replace()
  113. * @param string the string to slash
  114. * @param boolean whether the string will be used in a 'LIKE' clause
  115. * (it then requires two more escaped sequences) or not
  116. * @param boolean whether to treat cr/lfs as escape-worthy entities
  117. * (converts \n to \\n, \r to \\r)
  118. *
  119. * @param boolean whether this function is used as part of the
  120. * "Create PHP code" dialog
  121. *
  122. * @return string the slashed string
  123. *
  124. * @access public
  125. */
  126. function PMA_sqlAddslashes($a_string = '', $is_like = false, $crlf = false, $php_code = false)
  127. {
  128. if ($is_like) {
  129. $a_string = str_replace('\\', '\\\\\\\\', $a_string);
  130. } else {
  131. $a_string = str_replace('\\', '\\\\', $a_string);
  132. }
  133. if ($crlf) {
  134. $a_string = str_replace("\n", '\n', $a_string);
  135. $a_string = str_replace("\r", '\r', $a_string);
  136. $a_string = str_replace("\t", '\t', $a_string);
  137. }
  138. if ($php_code) {
  139. $a_string = str_replace('\'', '\\\'', $a_string);
  140. } else {
  141. $a_string = str_replace('\'', '\'\'', $a_string);
  142. }
  143. return $a_string;
  144. } // end of the 'PMA_sqlAddslashes()' function
  145. /**
  146. * Add slashes before "_" and "%" characters for using them in MySQL
  147. * database, table and field names.
  148. * Note: This function does not escape backslashes!
  149. *
  150. * @uses str_replace()
  151. * @param string the string to escape
  152. *
  153. * @return string the escaped string
  154. *
  155. * @access public
  156. */
  157. function PMA_escape_mysql_wildcards($name)
  158. {
  159. $name = str_replace('_', '\\_', $name);
  160. $name = str_replace('%', '\\%', $name);
  161. return $name;
  162. } // end of the 'PMA_escape_mysql_wildcards()' function
  163. /**
  164. * removes slashes before "_" and "%" characters
  165. * Note: This function does not unescape backslashes!
  166. *
  167. * @uses str_replace()
  168. * @param string $name the string to escape
  169. * @return string the escaped string
  170. * @access public
  171. */
  172. function PMA_unescape_mysql_wildcards($name)
  173. {
  174. $name = str_replace('\\_', '_', $name);
  175. $name = str_replace('\\%', '%', $name);
  176. return $name;
  177. } // end of the 'PMA_unescape_mysql_wildcards()' function
  178. /**
  179. * removes quotes (',",`) from a quoted string
  180. *
  181. * checks if the sting is quoted and removes this quotes
  182. *
  183. * @uses str_replace()
  184. * @uses substr()
  185. * @param string $quoted_string string to remove quotes from
  186. * @param string $quote type of quote to remove
  187. * @return string unqoted string
  188. */
  189. function PMA_unQuote($quoted_string, $quote = null)
  190. {
  191. $quotes = array();
  192. if (null === $quote) {
  193. $quotes[] = '`';
  194. $quotes[] = '"';
  195. $quotes[] = "'";
  196. } else {
  197. $quotes[] = $quote;
  198. }
  199. foreach ($quotes as $quote) {
  200. if (substr($quoted_string, 0, 1) === $quote
  201. && substr($quoted_string, -1, 1) === $quote) {
  202. $unquoted_string = substr($quoted_string, 1, -1);
  203. // replace escaped quotes
  204. $unquoted_string = str_replace($quote . $quote, $quote, $unquoted_string);
  205. return $unquoted_string;
  206. }
  207. }
  208. return $quoted_string;
  209. }
  210. /**
  211. * format sql strings
  212. *
  213. * @todo move into PMA_Sql
  214. * @uses PMA_SQP_isError()
  215. * @uses PMA_SQP_formatHtml()
  216. * @uses PMA_SQP_formatNone()
  217. * @uses is_array()
  218. * @param mixed pre-parsed SQL structure
  219. *
  220. * @return string the formatted sql
  221. *
  222. * @global array the configuration array
  223. * @global boolean whether the current statement is a multiple one or not
  224. *
  225. * @access public
  226. *
  227. * @author Robin Johnson <robbat2@users.sourceforge.net>
  228. */
  229. function PMA_formatSql($parsed_sql, $unparsed_sql = '')
  230. {
  231. global $cfg;
  232. // Check that we actually have a valid set of parsed data
  233. // well, not quite
  234. // first check for the SQL parser having hit an error
  235. if (PMA_SQP_isError()) {
  236. return $parsed_sql;
  237. }
  238. // then check for an array
  239. if (!is_array($parsed_sql)) {
  240. // We don't so just return the input directly
  241. // This is intended to be used for when the SQL Parser is turned off
  242. $formatted_sql = '<pre>' . "\n"
  243. . (($cfg['SQP']['fmtType'] == 'none' && $unparsed_sql != '') ? $unparsed_sql : $parsed_sql) . "\n"
  244. . '</pre>';
  245. return $formatted_sql;
  246. }
  247. $formatted_sql = '';
  248. switch ($cfg['SQP']['fmtType']) {
  249. case 'none':
  250. if ($unparsed_sql != '') {
  251. $formatted_sql = "<pre>\n" . PMA_SQP_formatNone(array('raw' => $unparsed_sql)) . "\n</pre>";
  252. } else {
  253. $formatted_sql = PMA_SQP_formatNone($parsed_sql);
  254. }
  255. break;
  256. case 'html':
  257. $formatted_sql = PMA_SQP_formatHtml($parsed_sql, 'color');
  258. break;
  259. case 'text':
  260. //$formatted_sql = PMA_SQP_formatText($parsed_sql);
  261. $formatted_sql = PMA_SQP_formatHtml($parsed_sql, 'text');
  262. break;
  263. default:
  264. break;
  265. } // end switch
  266. return $formatted_sql;
  267. } // end of the "PMA_formatSql()" function
  268. /**
  269. * Displays a link to the official MySQL documentation
  270. *
  271. * @uses $cfg['MySQLManualType']
  272. * @uses $cfg['MySQLManualBase']
  273. * @uses $cfg['ReplaceHelpImg']
  274. * @uses $GLOBALS['mysql_4_1_doc_lang']
  275. * @uses $GLOBALS['mysql_5_1_doc_lang']
  276. * @uses $GLOBALS['mysql_5_0_doc_lang']
  277. * @uses $GLOBALS['strDocu']
  278. * @uses $GLOBALS['pmaThemeImage']
  279. * @uses PMA_MYSQL_INT_VERSION
  280. * @uses strtolower()
  281. * @uses str_replace()
  282. * @param string chapter of "HTML, one page per chapter" documentation
  283. * @param string contains name of page/anchor that is being linked
  284. * @param bool whether to use big icon (like in left frame)
  285. *
  286. * @return string the html link
  287. *
  288. * @access public
  289. */
  290. function PMA_showMySQLDocu($chapter, $link, $big_icon = false)
  291. {
  292. global $cfg;
  293. if ($cfg['MySQLManualType'] == 'none' || empty($cfg['MySQLManualBase'])) {
  294. return '';
  295. }
  296. // Fixup for newly used names:
  297. $chapter = str_replace('_', '-', strtolower($chapter));
  298. $link = str_replace('_', '-', strtolower($link));
  299. switch ($cfg['MySQLManualType']) {
  300. case 'chapters':
  301. if (empty($chapter)) {
  302. $chapter = 'index';
  303. }
  304. $url = $cfg['MySQLManualBase'] . '/' . $chapter . '.html#' . $link;
  305. break;
  306. case 'big':
  307. $url = $cfg['MySQLManualBase'] . '#' . $link;
  308. break;
  309. case 'searchable':
  310. if (empty($link)) {
  311. $link = 'index';
  312. }
  313. $url = $cfg['MySQLManualBase'] . '/' . $link . '.html';
  314. break;
  315. case 'viewable':
  316. default:
  317. if (empty($link)) {
  318. $link = 'index';
  319. }
  320. $mysql = '5.0';
  321. $lang = 'en';
  322. if (defined('PMA_MYSQL_INT_VERSION')) {
  323. if (PMA_MYSQL_INT_VERSION < 50000) {
  324. $mysql = '4.1';
  325. if (!empty($GLOBALS['mysql_4_1_doc_lang'])) {
  326. $lang = $GLOBALS['mysql_4_1_doc_lang'];
  327. }
  328. } elseif (PMA_MYSQL_INT_VERSION >= 50100) {
  329. $mysql = '5.1';
  330. if (!empty($GLOBALS['mysql_5_1_doc_lang'])) {
  331. $lang = $GLOBALS['mysql_5_1_doc_lang'];
  332. }
  333. } elseif (PMA_MYSQL_INT_VERSION >= 50000) {
  334. $mysql = '5.0';
  335. if (!empty($GLOBALS['mysql_5_0_doc_lang'])) {
  336. $lang = $GLOBALS['mysql_5_0_doc_lang'];
  337. }
  338. }
  339. }
  340. $url = $cfg['MySQLManualBase'] . '/' . $mysql . '/' . $lang . '/' . $link . '.html';
  341. break;
  342. }
  343. if ($big_icon) {
  344. return '<a href="' . $url . '" target="mysql_doc"><img class="icon" src="' . $GLOBALS['pmaThemeImage'] . 'b_sqlhelp.png" width="16" height="16" alt="' . $GLOBALS['strDocu'] . '" title="' . $GLOBALS['strDocu'] . '" /></a>';
  345. } elseif ($GLOBALS['cfg']['ReplaceHelpImg']) {
  346. return '<a href="' . $url . '" target="mysql_doc"><img class="icon" src="' . $GLOBALS['pmaThemeImage'] . 'b_help.png" width="11" height="11" alt="' . $GLOBALS['strDocu'] . '" title="' . $GLOBALS['strDocu'] . '" /></a>';
  347. } else {
  348. return '[<a href="' . $url . '" target="mysql_doc">' . $GLOBALS['strDocu'] . '</a>]';
  349. }
  350. } // end of the 'PMA_showMySQLDocu()' function
  351. /**
  352. * Displays a hint icon, on mouse over show the hint
  353. *
  354. * @uses $GLOBALS['pmaThemeImage']
  355. * @uses PMA_jsFormat()
  356. * @param string the error message
  357. *
  358. * @access public
  359. */
  360. function PMA_showHint($hint_message)
  361. {
  362. //return '<img class="lightbulb" src="' . $GLOBALS['pmaThemeImage'] . 'b_tipp.png" width="16" height="16" border="0" alt="' . $hint_message . '" title="' . $hint_message . '" align="middle" onclick="alert(\'' . PMA_jsFormat($hint_message, false) . '\');" />';
  363. return '<img class="lightbulb" src="' . $GLOBALS['pmaThemeImage']
  364. . 'b_tipp.png" width="16" height="16" alt="Tip" title="Tip" onmouseover="pmaTooltip(\''
  365. . PMA_jsFormat($hint_message, false) . '\'); return false;" onmouseout="swapTooltip(\'default\'); return false;" />';
  366. }
  367. /**
  368. * Displays a MySQL error message in the right frame.
  369. *
  370. * @uses footer.inc.php
  371. * @uses header.inc.php
  372. * @uses $GLOBALS['sql_query']
  373. * @uses $GLOBALS['strError']
  374. * @uses $GLOBALS['strSQLQuery']
  375. * @uses $GLOBALS['pmaThemeImage']
  376. * @uses $GLOBALS['strEdit']
  377. * @uses $GLOBALS['strMySQLSaid']
  378. * @uses $GLOBALS['cfg']['PropertiesIconic']
  379. * @uses $GLOBALS['cfg']['MaxCharactersInDisplayedSQL']
  380. * @uses PMA_backquote()
  381. * @uses PMA_DBI_getError()
  382. * @uses PMA_formatSql()
  383. * @uses PMA_generate_common_hidden_inputs()
  384. * @uses PMA_generate_common_url()
  385. * @uses PMA_showMySQLDocu()
  386. * @uses PMA_sqlAddslashes()
  387. * @uses PMA_SQP_isError()
  388. * @uses PMA_SQP_parse()
  389. * @uses PMA_SQP_getErrorString()
  390. * @uses strtolower()
  391. * @uses urlencode()
  392. * @uses str_replace()
  393. * @uses nl2br()
  394. * @uses substr()
  395. * @uses preg_replace()
  396. * @uses preg_match()
  397. * @uses explode()
  398. * @uses implode()
  399. * @uses is_array()
  400. * @uses function_exists()
  401. * @uses htmlspecialchars()
  402. * @uses trim()
  403. * @uses strstr()
  404. * @param string the error message
  405. * @param string the sql query that failed
  406. * @param boolean whether to show a "modify" link or not
  407. * @param string the "back" link url (full path is not required)
  408. * @param boolean EXIT the page?
  409. *
  410. * @global string the curent table
  411. * @global string the current db
  412. *
  413. * @access public
  414. */
  415. function PMA_mysqlDie($error_message = '', $the_query = '',
  416. $is_modify_link = true, $back_url = '', $exit = true)
  417. {
  418. global $table, $db;
  419. /**
  420. * start http output, display html headers
  421. */
  422. require_once './libraries/header.inc.php';
  423. if (!$error_message) {
  424. $error_message = PMA_DBI_getError();
  425. }
  426. if (!$the_query && !empty($GLOBALS['sql_query'])) {
  427. $the_query = $GLOBALS['sql_query'];
  428. }
  429. // --- Added to solve bug #641765
  430. // Robbat2 - 12 January 2003, 9:46PM
  431. // Revised, Robbat2 - 13 January 2003, 2:59PM
  432. if (!function_exists('PMA_SQP_isError') || PMA_SQP_isError()) {
  433. $formatted_sql = htmlspecialchars($the_query);
  434. } elseif (empty($the_query) || trim($the_query) == '') {
  435. $formatted_sql = '';
  436. } else {
  437. if (strlen($the_query) > $GLOBALS['cfg']['MaxCharactersInDisplayedSQL']) {
  438. $formatted_sql = substr($the_query, 0, $GLOBALS['cfg']['MaxCharactersInDisplayedSQL']) . '[...]';
  439. } else {
  440. $formatted_sql = PMA_formatSql(PMA_SQP_parse($the_query), $the_query);
  441. }
  442. }
  443. // ---
  444. echo "\n" . '<!-- PMA-SQL-ERROR -->' . "\n";
  445. echo ' <div class="error"><h1>' . $GLOBALS['strError'] . '</h1>' . "\n";
  446. // if the config password is wrong, or the MySQL server does not
  447. // respond, do not show the query that would reveal the
  448. // username/password
  449. if (!empty($the_query) && !strstr($the_query, 'connect')) {
  450. // --- Added to solve bug #641765
  451. // Robbat2 - 12 January 2003, 9:46PM
  452. // Revised, Robbat2 - 13 January 2003, 2:59PM
  453. if (function_exists('PMA_SQP_isError') && PMA_SQP_isError()) {
  454. echo PMA_SQP_getErrorString() . "\n";
  455. echo '<br />' . "\n";
  456. }
  457. // ---
  458. // modified to show me the help on sql errors (Michael Keck)
  459. echo ' <p><strong>' . $GLOBALS['strSQLQuery'] . ':</strong>' . "\n";
  460. if (strstr(strtolower($formatted_sql), 'select')) { // please show me help to the error on select
  461. echo PMA_showMySQLDocu('SQL-Syntax', 'SELECT');
  462. }
  463. if ($is_modify_link && strlen($db)) {
  464. if (strlen($table)) {
  465. $doedit_goto = '<a href="tbl_sql.php?' . PMA_generate_common_url($db, $table) . '&amp;sql_query=' . urlencode($the_query) . '&amp;show_query=1">';
  466. } else {
  467. $doedit_goto = '<a href="db_sql.php?' . PMA_generate_common_url($db) . '&amp;sql_query=' . urlencode($the_query) . '&amp;show_query=1">';
  468. }
  469. if ($GLOBALS['cfg']['PropertiesIconic']) {
  470. echo $doedit_goto
  471. . '<img class="icon" src=" '. $GLOBALS['pmaThemeImage'] . 'b_edit.png" width="16" height="16" alt="' . $GLOBALS['strEdit'] .'" />'
  472. . '</a>';
  473. } else {
  474. echo ' ['
  475. . $doedit_goto . $GLOBALS['strEdit'] . '</a>'
  476. . ']' . "\n";
  477. }
  478. } // end if
  479. echo ' </p>' . "\n"
  480. .' <p>' . "\n"
  481. .' ' . $formatted_sql . "\n"
  482. .' </p>' . "\n";
  483. } // end if
  484. $tmp_mysql_error = ''; // for saving the original $error_message
  485. if (!empty($error_message)) {
  486. $tmp_mysql_error = strtolower($error_message); // save the original $error_message
  487. $error_message = htmlspecialchars($error_message);
  488. $error_message = preg_replace("@((\015\012)|(\015)|(\012)){3,}@", "\n\n", $error_message);
  489. }
  490. // modified to show me the help on error-returns (Michael Keck)
  491. // (now error-messages-server)
  492. echo '<p>' . "\n"
  493. . ' <strong>' . $GLOBALS['strMySQLSaid'] . '</strong>'
  494. . PMA_showMySQLDocu('Error-messages-server', 'Error-messages-server')
  495. . "\n"
  496. . '</p>' . "\n";
  497. // The error message will be displayed within a CODE segment.
  498. // To preserve original formatting, but allow wordwrapping, we do a couple of replacements
  499. // Replace all non-single blanks with their HTML-counterpart
  500. $error_message = str_replace(' ', '&nbsp;&nbsp;', $error_message);
  501. // Replace TAB-characters with their HTML-counterpart
  502. $error_message = str_replace("\t", '&nbsp;&nbsp;&nbsp;&nbsp;', $error_message);
  503. // Replace linebreaks
  504. $error_message = nl2br($error_message);
  505. echo '<code>' . "\n"
  506. . $error_message . "\n"
  507. . '</code><br />' . "\n";
  508. echo '</div>';
  509. echo '<fieldset class="tblFooters">';
  510. if (!empty($back_url) && $exit) {
  511. $goto_back_url='<a href="' . (strstr($back_url, '?') ? $back_url . '&amp;no_history=true' : $back_url . '?no_history=true') . '">';
  512. echo '[ ' . $goto_back_url . $GLOBALS['strBack'] . '</a> ]';
  513. }
  514. echo ' </fieldset>' . "\n\n";
  515. if ($exit) {
  516. /**
  517. * display footer and exit
  518. */
  519. require_once './libraries/footer.inc.php';
  520. }
  521. } // end of the 'PMA_mysqlDie()' function
  522. /**
  523. * Returns a string formatted with CONVERT ... USING
  524. * if MySQL supports it
  525. *
  526. * @uses PMA_MYSQL_INT_VERSION
  527. * @uses $GLOBALS['collation_connection']
  528. * @uses explode()
  529. * @param string the string itself
  530. * @param string the mode: quoted or unquoted (this one by default)
  531. *
  532. * @return the formatted string
  533. *
  534. * @access private
  535. */
  536. function PMA_convert_using($string, $mode='unquoted', $force_utf8 = false)
  537. {
  538. if ($mode == 'quoted') {
  539. $possible_quote = "'";
  540. } else {
  541. $possible_quote = "";
  542. }
  543. if (PMA_MYSQL_INT_VERSION >= 40100) {
  544. if ($force_utf8) {
  545. $charset = 'utf8';
  546. $collate = ' COLLATE utf8_bin';
  547. } else {
  548. list($charset) = explode('_', $GLOBALS['collation_connection']);
  549. $collate = '';
  550. }
  551. $converted_string = "CONVERT(" . $possible_quote . $string . $possible_quote . " USING " . $charset . ")" . $collate;
  552. } else {
  553. $converted_string = $possible_quote . $string . $possible_quote;
  554. }
  555. return $converted_string;
  556. } // end function
  557. /**
  558. * Send HTTP header, taking IIS limits into account (600 seems ok)
  559. *
  560. * @uses PMA_IS_IIS
  561. * @uses PMA_COMING_FROM_COOKIE_LOGIN
  562. * @uses PMA_get_arg_separator()
  563. * @uses SID
  564. * @uses strlen()
  565. * @uses strpos()
  566. * @uses header()
  567. * @uses session_write_close()
  568. * @uses headers_sent()
  569. * @uses function_exists()
  570. * @uses debug_print_backtrace()
  571. * @uses trigger_error()
  572. * @uses defined()
  573. * @param string $uri the header to send
  574. * @return boolean always true
  575. */
  576. function PMA_sendHeaderLocation($uri)
  577. {
  578. if (PMA_IS_IIS && strlen($uri) > 600) {
  579. echo '<html><head><title>- - -</title>' . "\n";
  580. echo '<meta http-equiv="expires" content="0">' . "\n";
  581. echo '<meta http-equiv="Pragma" content="no-cache">' . "\n";
  582. echo '<meta http-equiv="Cache-Control" content="no-cache">' . "\n";
  583. echo '<meta http-equiv="Refresh" content="0;url=' .$uri . '">' . "\n";
  584. echo '<script type="text/javascript">' . "\n";
  585. echo '//<![CDATA[' . "\n";
  586. echo 'setTimeout("window.location = unescape(\'"' . $uri . '"\')", 2000);' . "\n";
  587. echo '//]]>' . "\n";
  588. echo '</script>' . "\n";
  589. echo '</head>' . "\n";
  590. echo '<body>' . "\n";
  591. echo '<script type="text/javascript">' . "\n";
  592. echo '//<![CDATA[' . "\n";
  593. echo 'document.write(\'<p><a href="' . $uri . '">' . $GLOBALS['strGo'] . '</a></p>\');' . "\n";
  594. echo '//]]>' . "\n";
  595. echo '</script></body></html>' . "\n";
  596. } else {
  597. if (SID) {
  598. if (strpos($uri, '?') === false) {
  599. header('Location: ' . $uri . '?' . SID);
  600. } else {
  601. $separator = PMA_get_arg_separator();
  602. header('Location: ' . $uri . $separator . SID);
  603. }
  604. } else {
  605. session_write_close();
  606. if (headers_sent()) {
  607. if (function_exists('debug_print_backtrace')) {
  608. echo '<pre>';
  609. debug_print_backtrace();
  610. echo '</pre>';
  611. }
  612. trigger_error('PMA_sendHeaderLocation called when headers are already sent!', E_USER_ERROR);
  613. }
  614. // bug #1523784: IE6 does not like 'Refresh: 0', it
  615. // results in a blank page
  616. // but we need it when coming from the cookie login panel)
  617. if (PMA_IS_IIS && defined('PMA_COMING_FROM_COOKIE_LOGIN')) {
  618. header('Refresh: 0; ' . $uri);
  619. } else {
  620. header('Location: ' . $uri);
  621. }
  622. }
  623. }
  624. }
  625. /**
  626. * returns array with tables of given db with extended information and grouped
  627. *
  628. * @uses $cfg['LeftFrameTableSeparator']
  629. * @uses $cfg['LeftFrameTableLevel']
  630. * @uses $cfg['ShowTooltipAliasTB']
  631. * @uses $cfg['NaturalOrder']
  632. * @uses PMA_backquote()
  633. * @uses count()
  634. * @uses array_merge
  635. * @uses uksort()
  636. * @uses strstr()
  637. * @uses explode()
  638. * @param string $db name of db
  639. * @param string $tables name of tables
  640. * return array (recursive) grouped table list
  641. */
  642. function PMA_getTableList($db, $tables = null, $limit_offset = 0, $limit_count = false)
  643. {
  644. $sep = $GLOBALS['cfg']['LeftFrameTableSeparator'];
  645. if (null === $tables) {
  646. $tables = PMA_DBI_get_tables_full($db, false, false, null, $limit_offset, $limit_count);
  647. if ($GLOBALS['cfg']['NaturalOrder']) {
  648. uksort($tables, 'strnatcasecmp');
  649. }
  650. }
  651. if (count($tables) < 1) {
  652. return $tables;
  653. }
  654. $default = array(
  655. 'Name' => '',
  656. 'Rows' => 0,
  657. 'Comment' => '',
  658. 'disp_name' => '',
  659. );
  660. $table_groups = array();
  661. foreach ($tables as $table_name => $table) {
  662. // check for correct row count
  663. if (null === $table['Rows']) {
  664. // Do not check exact row count here,
  665. // if row count is invalid possibly the table is defect
  666. // and this would break left frame;
  667. // but we can check row count if this is a view,
  668. // since PMA_Table::countRecords() returns a limited row count
  669. // in this case.
  670. // set this because PMA_Table::countRecords() can use it
  671. $tbl_is_view = PMA_Table::isView($db, $table['Name']);
  672. if ($tbl_is_view) {
  673. $table['Rows'] = PMA_Table::countRecords($db, $table['Name'],
  674. $return = true);
  675. }
  676. }
  677. // in $group we save the reference to the place in $table_groups
  678. // where to store the table info
  679. if ($GLOBALS['cfg']['LeftFrameDBTree']
  680. && $sep && strstr($table_name, $sep))
  681. {
  682. $parts = explode($sep, $table_name);
  683. $group =& $table_groups;
  684. $i = 0;
  685. $group_name_full = '';
  686. while ($i < count($parts) - 1
  687. && $i < $GLOBALS['cfg']['LeftFrameTableLevel']) {
  688. $group_name = $parts[$i] . $sep;
  689. $group_name_full .= $group_name;
  690. if (!isset($group[$group_name])) {
  691. $group[$group_name] = array();
  692. $group[$group_name]['is' . $sep . 'group'] = true;
  693. $group[$group_name]['tab' . $sep . 'count'] = 1;
  694. $group[$group_name]['tab' . $sep . 'group'] = $group_name_full;
  695. } elseif (!isset($group[$group_name]['is' . $sep . 'group'])) {
  696. $table = $group[$group_name];
  697. $group[$group_name] = array();
  698. $group[$group_name][$group_name] = $table;
  699. unset($table);
  700. $group[$group_name]['is' . $sep . 'group'] = true;
  701. $group[$group_name]['tab' . $sep . 'count'] = 1;
  702. $group[$group_name]['tab' . $sep . 'group'] = $group_name_full;
  703. } else {
  704. $group[$group_name]['tab' . $sep . 'count']++;
  705. }
  706. $group =& $group[$group_name];
  707. $i++;
  708. }
  709. } else {
  710. if (!isset($table_groups[$table_name])) {
  711. $table_groups[$table_name] = array();
  712. }
  713. $group =& $table_groups;
  714. }
  715. if ($GLOBALS['cfg']['ShowTooltipAliasTB']
  716. && $GLOBALS['cfg']['ShowTooltipAliasTB'] !== 'nested') {
  717. // switch tooltip and name
  718. $table['Comment'] = $table['Name'];
  719. $table['disp_name'] = $table['Comment'];
  720. } else {
  721. $table['disp_name'] = $table['Name'];
  722. }
  723. $group[$table_name] = array_merge($default, $table);
  724. }
  725. return $table_groups;
  726. }
  727. /* ----------------------- Set of misc functions ----------------------- */
  728. /**
  729. * Adds backquotes on both sides of a database, table or field name.
  730. * and escapes backquotes inside the name with another backquote
  731. *
  732. * example:
  733. * <code>
  734. * echo PMA_backquote('owner`s db'); // `owner``s db`
  735. *
  736. * </code>
  737. *
  738. * @uses PMA_backquote()
  739. * @uses is_array()
  740. * @uses strlen()
  741. * @uses str_replace()
  742. * @param mixed $a_name the database, table or field name to "backquote"
  743. * or array of it
  744. * @param boolean $do_it a flag to bypass this function (used by dump
  745. * functions)
  746. * @return mixed the "backquoted" database, table or field name if the
  747. * current MySQL release is >= 3.23.6, the original one
  748. * else
  749. * @access public
  750. */
  751. function PMA_backquote($a_name, $do_it = true)
  752. {
  753. if (! $do_it) {
  754. return $a_name;
  755. }
  756. if (is_array($a_name)) {
  757. $result = array();
  758. foreach ($a_name as $key => $val) {
  759. $result[$key] = PMA_backquote($val);
  760. }
  761. return $result;
  762. }
  763. // '0' is also empty for php :-(
  764. if (strlen($a_name) && $a_name !== '*') {
  765. return '`' . str_replace('`', '``', $a_name) . '`';
  766. } else {
  767. return $a_name;
  768. }
  769. } // end of the 'PMA_backquote()' function
  770. /**
  771. * Defines the <CR><LF> value depending on the user OS.
  772. *
  773. * @uses PMA_USR_OS
  774. * @return string the <CR><LF> value to use
  775. *
  776. * @access public
  777. */
  778. function PMA_whichCrlf()
  779. {
  780. $the_crlf = "\n";
  781. // The 'PMA_USR_OS' constant is defined in "./libraries/Config.class.php"
  782. // Win case
  783. if (PMA_USR_OS == 'Win') {
  784. $the_crlf = "\r\n";
  785. }
  786. // Others
  787. else {
  788. $the_crlf = "\n";
  789. }
  790. return $the_crlf;
  791. } // end of the 'PMA_whichCrlf()' function
  792. /**
  793. * Reloads navigation if needed.
  794. *
  795. * @uses $GLOBALS['reload']
  796. * @uses $GLOBALS['db']
  797. * @uses PMA_generate_common_url()
  798. * @global array configuration
  799. *
  800. * @access public
  801. */
  802. function PMA_reloadNavigation()
  803. {
  804. global $cfg;
  805. // Reloads the navigation frame via JavaScript if required
  806. if (isset($GLOBALS['reload']) && $GLOBALS['reload']) {
  807. // one of the reasons for a reload is when a table is dropped
  808. // in this case, get rid of the table limit offset, otherwise
  809. // we have a problem when dropping a table on the last page
  810. // and the offset becomes greater than the total number of tables
  811. unset($_SESSION['userconf']['table_limit_offset']);
  812. echo "\n";
  813. $reload_url = './navigation.php?' . PMA_generate_common_url($GLOBALS['db'], '', '&');
  814. ?>
  815. <script type="text/javascript">
  816. //<![CDATA[
  817. if (typeof(window.parent) != 'undefined'
  818. && typeof(window.parent.frame_navigation) != 'undefined') {
  819. window.parent.goTo('<?php echo $reload_url; ?>');
  820. }
  821. //]]>
  822. </script>
  823. <?php
  824. unset($GLOBALS['reload']);
  825. }
  826. }
  827. /**
  828. * displays the message and the query
  829. * usually the message is the result of the query executed
  830. *
  831. * @param string $message the message to display
  832. * @param string $sql_query the query to display
  833. * @global array the configuration array
  834. * @uses $cfg
  835. * @access public
  836. */
  837. function PMA_showMessage($message, $sql_query = null)
  838. {
  839. global $cfg;
  840. $query_too_big = false;
  841. if (null === $sql_query) {
  842. if (! empty($GLOBALS['display_query'])) {
  843. $sql_query = $GLOBALS['display_query'];
  844. } elseif ($cfg['SQP']['fmtType'] == 'none' && ! empty($GLOBALS['unparsed_sql'])) {
  845. $sql_query = $GLOBALS['unparsed_sql'];
  846. } elseif (! empty($GLOBALS['sql_query'])) {
  847. $sql_query = $GLOBALS['sql_query'];
  848. } else {
  849. $sql_query = '';
  850. }
  851. }
  852. // Corrects the tooltip text via JS if required
  853. // @todo this is REALLY the wrong place to do this - very unexpected here
  854. if (strlen($GLOBALS['table']) && $cfg['ShowTooltip']) {
  855. $result = PMA_DBI_try_query('SHOW TABLE STATUS FROM ' . PMA_backquote($GLOBALS['db']) . ' LIKE \'' . PMA_sqlAddslashes($GLOBALS['table'], true) . '\'');
  856. if ($result) {
  857. $tbl_status = PMA_DBI_fetch_assoc($result);
  858. $tooltip = (empty($tbl_status['Comment']))
  859. ? ''
  860. : $tbl_status['Comment'] . ' ';
  861. $tooltip .= '(' . PMA_formatNumber($tbl_status['Rows'], 0) . ' ' . $GLOBALS['strRows'] . ')';
  862. PMA_DBI_free_result($result);
  863. $uni_tbl = PMA_jsFormat($GLOBALS['db'] . '.' . $GLOBALS['table'], false);
  864. echo "\n";
  865. echo '<script type="text/javascript">' . "\n";
  866. echo '//<![CDATA[' . "\n";
  867. echo "window.parent.updateTableTitle('" . $uni_tbl . "', '" . PMA_jsFormat($tooltip, false) . "');" . "\n";
  868. echo '//]]>' . "\n";
  869. echo '</script>' . "\n";
  870. } // end if
  871. } // end if ... elseif
  872. // Checks if the table needs to be repaired after a TRUNCATE query.
  873. // @todo what about $GLOBALS['display_query']???
  874. // @todo this is REALLY the wrong place to do this - very unexpected here
  875. if (strlen($GLOBALS['table'])
  876. && $GLOBALS['sql_query'] == 'TRUNCATE TABLE ' . PMA_backquote($GLOBALS['table'])) {
  877. if (!isset($tbl_status)) {
  878. $result = @PMA_DBI_try_query('SHOW TABLE STATUS FROM ' . PMA_backquote($GLOBALS['db']) . ' LIKE \'' . PMA_sqlAddslashes($GLOBALS['table'], true) . '\'');
  879. if ($result) {
  880. $tbl_status = PMA_DBI_fetch_assoc($result);
  881. PMA_DBI_free_result($result);
  882. }
  883. }
  884. if (isset($tbl_status) && (int) $tbl_status['Index_length'] > 1024) {
  885. PMA_DBI_try_query('REPAIR TABLE ' . PMA_backquote($GLOBALS['table']));
  886. }
  887. }
  888. unset($tbl_status);
  889. echo '<br />' . "\n";
  890. echo '<div align="' . $GLOBALS['cell_align_left'] . '">' . "\n";
  891. if (!empty($GLOBALS['show_error_header'])) {
  892. echo '<div class="error">' . "\n";
  893. echo '<h1>' . $GLOBALS['strError'] . '</h1>' . "\n";
  894. }
  895. echo '<div class="notice">';
  896. echo PMA_sanitize($message);
  897. if (isset($GLOBALS['special_message'])) {
  898. echo PMA_sanitize($GLOBALS['special_message']);
  899. unset($GLOBALS['special_message']);
  900. }
  901. echo '</div>';
  902. if (!empty($GLOBALS['show_error_header'])) {
  903. echo '</div>';
  904. }
  905. if ($cfg['ShowSQL'] == true && ! empty($sql_query)) {
  906. // Basic url query part
  907. $url_qpart = '?' . PMA_generate_common_url($GLOBALS['db'], $GLOBALS['table']);
  908. // Html format the query to be displayed
  909. // The nl2br function isn't used because its result isn't a valid
  910. // xhtml1.0 statement before php4.0.5 ("<br>" and not "<br />")
  911. // If we want to show some sql code it is easiest to create it here
  912. /* SQL-Parser-Analyzer */
  913. if (!empty($GLOBALS['show_as_php'])) {
  914. $new_line = '\'<br />' . "\n" . '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. \' ';
  915. }
  916. if (isset($new_line)) {
  917. /* SQL-Parser-Analyzer */
  918. $query_base = PMA_sqlAddslashes(htmlspecialchars($sql_query), false, false, true);
  919. /* SQL-Parser-Analyzer */
  920. $query_base = preg_replace("@((\015\012)|(\015)|(\012))+@", $new_line, $query_base);
  921. } else {
  922. $query_base = $sql_query;
  923. }
  924. if (strlen($query_base) > $cfg['MaxCharactersInDisplayedSQL']) {
  925. $query_too_big = true;
  926. $query_base = nl2br(htmlspecialchars($sql_query));
  927. unset($GLOBALS['parsed_sql']);
  928. }
  929. // Parse SQL if needed
  930. // (here, use "! empty" because when deleting a bookmark,
  931. // $GLOBALS['parsed_sql'] is set but empty
  932. if (! empty($GLOBALS['parsed_sql']) && $query_base == $GLOBALS['parsed_sql']['raw']) {
  933. $parsed_sql = $GLOBALS['parsed_sql'];
  934. } else {
  935. // when the query is large (for example an INSERT of binary
  936. // data), the parser chokes; so avoid parsing the query
  937. if (! $query_too_big) {
  938. $parsed_sql = PMA_SQP_parse($query_base);
  939. }
  940. }
  941. // Analyze it
  942. if (isset($parsed_sql)) {
  943. $analyzed_display_query = PMA_SQP_analyze($parsed_sql);
  944. }
  945. // Here we append the LIMIT added for navigation, to
  946. // enable its display. Adding it higher in the code
  947. // to $sql_query would create a problem when
  948. // using the Refresh or Edit links.
  949. // Only append it on SELECTs.
  950. /**
  951. * @todo what would be the best to do when someone hits Refresh:
  952. * use the current LIMITs ?
  953. */
  954. if (isset($analyzed_display_query[0]['queryflags']['select_from'])
  955. && isset($GLOBALS['sql_limit_to_append'])) {
  956. $query_base = $analyzed_display_query[0]['section_before_limit'] . "\n" . $GLOBALS['sql_limit_to_append'] . $analyzed_display_query[0]['section_after_limit'];
  957. // Need to reparse query
  958. $parsed_sql = PMA_SQP_parse($query_base);
  959. }
  960. if (!empty($GLOBALS['show_as_php'])) {
  961. $query_base = '$sql = \'' . $query_base;
  962. } elseif (!empty($GLOBALS['validatequery'])) {
  963. $query_base = PMA_validateSQL($query_base);
  964. } else {
  965. if (isset($parsed_sql)) {
  966. $query_base = PMA_formatSql($parsed_sql, $query_base);
  967. }
  968. }
  969. // Prepares links that may be displayed to edit/explain the query
  970. // (don't go to default pages, we must go to the page
  971. // where the query box is available)
  972. $edit_target = strlen($GLOBALS['db']) ? (strlen($GLOBALS['table']) ? 'tbl_sql.php' : 'db_sql.php') : 'server_sql.php';
  973. if (isset($cfg['SQLQuery']['Edit'])
  974. && ($cfg['SQLQuery']['Edit'] == true)
  975. && (!empty($edit_target))
  976. && ! $query_too_big) {
  977. if ($cfg['EditInWindow'] == true) {
  978. $onclick = 'window.parent.focus_querywindow(\'' . PMA_jsFormat($sql_query, false) . '\'); return false;';
  979. } else {
  980. $onclick = '';
  981. }
  982. $edit_link = $edit_target
  983. . $url_qpart
  984. . '&amp;sql_query=' . urlencode($sql_query)
  985. . '&amp;show_query=1#querybox';
  986. $edit_link = ' [' . PMA_linkOrButton($edit_link, $GLOBALS['strEdit'], array('onclick' => $onclick)) . ']';
  987. } else {
  988. $edit_link = '';
  989. }
  990. // Want to have the query explained (Mike Beck 2002-05-22)
  991. // but only explain a SELECT (that has not been explained)
  992. /* SQL-Parser-Analyzer */
  993. if (isset($cfg['SQLQuery']['Explain'])
  994. && $cfg['SQLQuery']['Explain'] == true
  995. && ! $query_too_big) {
  996. // Detect if we are validating as well
  997. // To preserve the validate uRL data
  998. if (!empty($GLOBALS['validatequery'])) {
  999. $explain_link_validate = '&amp;validatequery=1';
  1000. } else {
  1001. $explain_link_validate = '';
  1002. }
  1003. $explain_link = 'import.php'
  1004. . $url_qpart
  1005. . $explain_link_validate
  1006. . '&amp;sql_query=';
  1007. if (preg_match('@^SELECT[[:space:]]+@i', $sql_query)) {
  1008. $explain_link .= urlencode('EXPLAIN ' . $sql_query);
  1009. $message = $GLOBALS['strExplain'];
  1010. } elseif (preg_match('@^EXPLAIN[[:space:]]+SELECT[[:space:]]+@i', $sql_query)) {
  1011. $explain_link .= urlencode(substr($sql_query, 8));
  1012. $message = $GLOBALS['strNoExplain'];
  1013. } else {
  1014. $explain_link = '';
  1015. }
  1016. if (!empty($explain_link)) {
  1017. $explain_link = ' [' . PMA_linkOrButton($explain_link, $message) . ']';
  1018. }
  1019. } else {
  1020. $explain_link = '';
  1021. } //show explain
  1022. // Also we would like to get the SQL formed in some nice
  1023. // php-code (Mike Beck 2002-05-22)
  1024. if (isset($cfg['SQLQuery']['ShowAsPHP'])
  1025. && $cfg['SQLQuery']['ShowAsPHP'] == true
  1026. && ! $query_too_big) {
  1027. $php_link = 'import.php'
  1028. . $url_qpart
  1029. . '&amp;show_query=1'
  1030. . '&amp;sql_query=' . urlencode($sql_query)
  1031. . '&amp;show_as_php=';
  1032. if (!empty($GLOBALS['show_as_php'])) {
  1033. $php_link .= '0';
  1034. $message = $GLOBALS['strNoPhp'];
  1035. } else {
  1036. $php_link .= '1';
  1037. $message = $GLOBALS['strPhp'];
  1038. }
  1039. $php_link = ' [' . PMA_linkOrButton($php_link, $message) . ']';
  1040. if (isset($GLOBALS['show_as_php'])) {
  1041. $runquery_link
  1042. = 'import.php'
  1043. . $url_qpart
  1044. . '&amp;show_query=1'
  1045. . '&amp;sql_query=' . urlencode($sql_query);
  1046. $php_link .= ' [' . PMA_linkOrButton($runquery_link, $GLOBALS['strRunQuery']) . ']';
  1047. }
  1048. } else {
  1049. $php_link = '';
  1050. } //show as php
  1051. // Refresh query
  1052. if (isset($cfg['SQLQuery']['Refresh'])
  1053. && $cfg['SQLQuery']['Refresh']
  1054. && preg_match('@^(SELECT|SHOW)[[:space:]]+@i', $sql_query)) {
  1055. $refresh_link = 'import.php'
  1056. . $url_qpart
  1057. . '&amp;show_query=1'
  1058. . '&amp;sql_query=' . urlencode($sql_query);
  1059. $refresh_link = ' [' . PMA_linkOrButton($refresh_link, $GLOBALS['strRefresh']) . ']';
  1060. } else {
  1061. $refresh_link = '';
  1062. } //show as php
  1063. if (isset($cfg['SQLValidator']['use'])
  1064. && $cfg['SQLValidator']['use'] == true
  1065. && isset($cfg['SQLQuery']['Validate'])
  1066. && $cfg['SQLQuery']['Validate'] == true) {
  1067. $validate_link = 'import.php'
  1068. . $url_qpart
  1069. . '&amp;show_query=1'
  1070. . '&amp;sql_query=' . urlencode($sql_query)
  1071. . '&amp;validatequery=';
  1072. if (!empty($GLOBALS['validatequery'])) {
  1073. $validate_link .= '0';
  1074. $validate_message = $GLOBALS['strNoValidateSQL'] ;
  1075. } else {
  1076. $validate_link .= '1';
  1077. $validate_message = $GLOBALS['strValidateSQL'] ;
  1078. }
  1079. $validate_link = ' [' . PMA_linkOrButton($validate_link, $validate_message) . ']';
  1080. } else {
  1081. $validate_link = '';
  1082. } //validator
  1083. // why this?
  1084. //unset($sql_query);
  1085. // Displays the message
  1086. echo '<fieldset class="">' . "\n";
  1087. echo ' <legend>' . $GLOBALS['strSQLQuery'] . ':</legend>';
  1088. echo ' <div>';
  1089. // when uploading a 700 Kio binary file into a LONGBLOB,
  1090. // I get a white page, strlen($query_base) is 2 x 700 Kio
  1091. // so put a hard limit here (let's say 1000)
  1092. if ($query_too_big) {
  1093. echo ' ' . substr($query_base, 0, $cfg['MaxCharactersInDisplayedSQL']) . '[...]';
  1094. } else {
  1095. echo ' ' . $query_base;
  1096. }
  1097. //Clean up the end of the PHP
  1098. if (!empty($GLOBALS['show_as_php'])) {
  1099. echo '\';';
  1100. }
  1101. echo ' </div>';
  1102. echo '</fieldset>' . "\n";
  1103. if (!empty($edit_target)) {
  1104. echo '<fieldset class="tblFooters">';
  1105. // avoid displaying a Profiling checkbox that could
  1106. // be checked, which would reexecute an INSERT, for example
  1107. if (! empty($refresh_link)) {
  1108. PMA_profilingCheckbox($sql_query);
  1109. }
  1110. echo $edit_link . $explain_link . $php_link . $refresh_link . $validate_link;
  1111. echo '</fieldset>';
  1112. }
  1113. }
  1114. echo '</div><br />' . "\n";
  1115. } // end of the 'PMA_showMessage()' function
  1116. /**
  1117. * Verifies if current MySQL server supports profiling
  1118. *
  1119. * @access public
  1120. * @return boolean whether profiling is supported
  1121. *
  1122. * @author Marc Delisle
  1123. */
  1124. function PMA_profilingSupported() {
  1125. // 5.0.37 has profiling but for example, 5.1.20 does not
  1126. // (avoid a trip to the server for MySQL before 5.0.37)
  1127. // and do not set a constant as we might be switching servers
  1128. if (defined('PMA_MYSQL_INT_VERSION') && PMA_MYSQL_INT_VERSION >= 50037 && PMA_DBI_fetch_value("SHOW VARIABLES LIKE 'profiling'")) {
  1129. return true;
  1130. } else {
  1131. return false;
  1132. }
  1133. }
  1134. /**
  1135. * Displays a form with the Profiling checkbox
  1136. *
  1137. * @param string $sql_query
  1138. * @access public
  1139. *
  1140. * @author Marc Delisle
  1141. */
  1142. function PMA_profilingCheckbox($sql_query) {
  1143. if (PMA_profilingSupported()) {
  1144. echo '<form action="sql.php" method="post">' . "\n";
  1145. echo PMA_generate_common_hidden_inputs($GLOBALS['db'], $GLOBALS['table']);
  1146. echo '<input type="hidden" name="sql_query" value="' . htmlspecialchars($sql_query) . '" />' . "\n";
  1147. echo '<input type="hidden" name="profiling_form" value="1" />' . "\n";
  1148. echo '<input type="checkbox" name="profiling" id="profiling"' . (isset($_SESSION['profiling']) ? ' checked="checked"' : '') . ' onclick="this.form.submit();" /><label for="profiling">' . $GLOBALS['strProfiling'] . '</label>' . "\n";
  1149. echo '<noscript><input type="submit" value="' . $GLOBALS['strGo'] . '" /></noscript>' . "\n";
  1150. echo '</form>' . "\n";
  1151. }
  1152. }
  1153. /**
  1154. * Displays the results of SHOW PROFILE
  1155. *
  1156. * @param array the results
  1157. * @access public
  1158. *
  1159. * @author Marc Delisle
  1160. */
  1161. function PMA_profilingResults($profiling_results) {
  1162. echo '<fieldset><legend>' . $GLOBALS['strProfiling'] . '</legend>' . "\n";
  1163. echo '<table>' . "\n";
  1164. echo ' <tr>' . "\n";
  1165. echo ' <th>' . $GLOBALS['strStatus'] . '</th>' . "\n";
  1166. echo ' <th>' . $GLOBALS['strTime'] . '</th>' . "\n";
  1167. echo ' </tr>' . "\n";
  1168. foreach($profiling_results as $one_result) {
  1169. echo ' <tr>' . "\n";
  1170. echo '<td>' . $one_result['Status'] . '</td>' . "\n";
  1171. echo '<td>' . $one_result['Duration'] . '</td>' . "\n";
  1172. }
  1173. echo '</table>' . "\n";
  1174. echo '</fieldset>' . "\n";
  1175. }
  1176. /**
  1177. * Formats $value to byte view
  1178. *
  1179. * @param double the value to format
  1180. * @param integer the sensitiveness
  1181. * @param integer the number of decimals to retain
  1182. *
  1183. * @return array the formatted value and its unit
  1184. *
  1185. * @access public
  1186. *
  1187. * @author staybyte
  1188. * @version 1.2 - 18 July 2002
  1189. */
  1190. function PMA_formatByteDown($value, $limes = 6, $comma = 0)
  1191. {
  1192. $dh = PMA_pow(10, $comma);
  1193. $li = PMA_pow(10, $limes);
  1194. $return_value = $value;
  1195. $unit = $GLOBALS['byteUnits'][0];
  1196. for ($d = 6, $ex = 15; $d >= 1; $d--, $ex-=3) {
  1197. if (isset($GLOBALS['byteUnits'][$d]) && $value >= $li * PMA_pow(10, $ex)) {
  1198. // use 1024.0 to avoid integer overflow on 64-bit machines
  1199. $value = round($value / (PMA_pow(1024, $d) / $dh)) /$dh;
  1200. $unit = $GLOBALS['byteUnits'][$d];
  1201. break 1;
  1202. } // end if
  1203. } // end for
  1204. if ($unit != $GLOBALS['byteUnits'][0]) {
  1205. // if the unit is not bytes (as represented in current language)
  1206. // reformat with max length of 5
  1207. // 4th parameter=true means do not reformat if value < 1
  1208. $return_value = PMA_formatNumber($value, 5, $comma, true);
  1209. } else {
  1210. // do not reformat, just handle the locale
  1211. $return_value = PMA_formatNumber($value, 0);
  1212. }
  1213. return array($return_value, $unit);
  1214. } // end of the 'PMA_formatByteDown' function
  1215. /**
  1216. * Formats $value to the given length and appends SI prefixes
  1217. * $comma is not substracted from the length
  1218. * with a $length of 0 no truncation occurs, number is only formated
  1219. * to the current locale
  1220. *
  1221. * examples:
  1222. * <code>
  1223. * echo PMA_formatNumber(123456789, 6); // 123,457 k
  1224. * echo PMA_formatNumber(-123456789, 4, 2); // -123.46 M
  1225. * echo PMA_formatNumber(-0.003, 6); // -3 m
  1226. * echo PMA_formatNumber(0.003, 3, 3); // 0.003
  1227. * echo PMA_formatNumber(0.00003, 3, 2); // 0.03 m
  1228. * echo PMA_formatNumber(0, 6); // 0
  1229. *
  1230. * </code>
  1231. * @param double $value the value to format
  1232. * @param integer $length the max length
  1233. * @param integer $comma the number of decimals to retain
  1234. * @param boolean $only_down do not reformat numbers below 1
  1235. *
  1236. * @return string the formatted value and its unit
  1237. *
  1238. * @access public
  1239. *
  1240. * @author staybyte, sebastian mendel
  1241. * @version 1.1.0 - 2005-10-27
  1242. */
  1243. function PMA_formatNumber($value, $length = 3, $comma = 0, $only_down = false)
  1244. {
  1245. //number_format is not multibyte safe, str_replace is safe
  1246. if ($length === 0) {
  1247. return str_replace(array(',', '.'),
  1248. array($GLOBALS['number_thousands_separator'], $GLOBALS['number_decimal_separator']),
  1249. number_format($value, $comma));
  1250. }
  1251. // this units needs no translation, ISO
  1252. $units = array(
  1253. -8 => 'y',
  1254. -7 => 'z',
  1255. -6 => 'a',
  1256. -5 => 'f',
  1257. -4 => 'p',
  1258. -3 => 'n',
  1259. -2 => '&micro;',
  1260. -1 => 'm',
  1261. 0 => ' ',
  1262. 1 => 'k',
  1263. 2 => 'M',
  1264. 3 => 'G',
  1265. 4 => 'T',
  1266. 5 => 'P',
  1267. 6 => 'E',
  1268. 7 => 'Z',
  1269. 8 => 'Y'
  1270. );
  1271. // we need at least 3 digits to be displayed
  1272. if (3 > $length + $comma) {
  1273. $length = 3 - $comma;
  1274. }
  1275. // check for negative value to retain sign
  1276. if ($value < 0) {
  1277. $sign = '-';
  1278. $value = abs($value);
  1279. } else {
  1280. $sign = '';
  1281. }
  1282. $dh = PMA_pow(10, $comma);
  1283. $li = PMA_pow(10, $length);
  1284. $unit = $units[0];
  1285. if ($value >= 1) {
  1286. for ($d = 8; $d >= 0; $d--) {
  1287. if (isset($units[$d]) && $value >= $li * PMA_pow(1000, $d-1)) {
  1288. $value = round($value / (PMA_pow(1000, $d) / $dh)) /$dh;
  1289. $unit = $units[$d];
  1290. break 1;
  1291. } // end if
  1292. } // end for
  1293. } elseif (!$only_down && (float) $value !== 0.0) {
  1294. for ($d = -8; $d <= 8; $d++) {
  1295. if (isset($units[$d]) && $value <= $li * PMA_pow(1000, $d-1)) {
  1296. $value = round($value / (PMA_pow(1000, $d) / $dh)) /$dh;
  1297. $unit = $units[$d];
  1298. break 1;
  1299. } // end if
  1300. } // end for
  1301. } // end if ($value >= 1) elseif (!$only_down && (float) $value !== 0.0)
  1302. //number_format is not multibyte safe, str_replace is safe
  1303. $value = str_replace(array(',', '.'),
  1304. array($GLOBALS['number_thousands_separator'], $GLOBALS['number_decimal_separator']),
  1305. number_format($value, $comma));
  1306. return $sign . $value . ' ' . $unit;
  1307. } // end of the 'PMA_formatNumber' function
  1308. /**
  1309. * Extracts ENUM / SET options from a type definition string
  1310. *
  1311. * @param string The column type definition
  1312. *
  1313. * @return array The options or
  1314. * boolean false in case of an error.
  1315. *
  1316. * @author rabus
  1317. */
  1318. function PMA_getEnumSetOptions($type_def)
  1319. {
  1320. $open = strpos($type_def, '(');
  1321. $close = strrpos($type_def, ')');
  1322. if (!$open || !$close) {
  1323. return false;
  1324. }
  1325. $options = substr($type_def, $open + 2, $close - $open - 3);
  1326. $options = explode('\',\'', $options);
  1327. return $options;
  1328. } // end of the 'PMA_getEnumSetOptions' function
  1329. /**
  1330. * Writes localised date
  1331. *
  1332. * @param string the current timestamp
  1333. *
  1334. * @return string the formatted date
  1335. *
  1336. * @access public
  1337. */
  1338. function PMA_localisedDate($timestamp = -1, $format = '')
  1339. {
  1340. global $datefmt, $month, $day_of_week;
  1341. if ($format == '') {
  1342. $format = $datefmt;
  1343. }
  1344. if ($timestamp == -1) {
  1345. $timestamp = time();
  1346. }
  1347. $date = preg_replace('@%[aA]@', $day_of_week[(int)strftime('%w', $timestamp)], $format);
  1348. $date = preg_replace('@%[bB]@', $month[(int)strftime('%m', $timestamp)-1], $date);
  1349. return strftime($date, $timestamp);
  1350. } // end of the 'PMA_localisedDate()' function
  1351. /**
  1352. * returns a tab for tabbed navigation.
  1353. * If the variables $link and $args ar left empty, an inactive tab is created
  1354. *
  1355. * @uses $GLOBALS['PMA_PHP_SELF']
  1356. * @uses $GLOBALS['strEmpty']
  1357. * @uses $GLOBALS['strDrop']
  1358. * @uses $GLOBALS['active_page']
  1359. * @uses $GLOBALS['url_query']
  1360. * @uses $cfg['MainPageIconic']
  1361. * @uses $GLOBALS['pmaThemeImage']
  1362. * @uses PMA_generate_common_url()
  1363. * @uses E_USER_NOTICE
  1364. * @uses htmlentities()
  1365. * @uses urlencode()
  1366. * @uses sprintf()
  1367. * @uses trigger_error()
  1368. * @uses array_merge()
  1369. * @uses basename()
  1370. * @param array $tab array with all options
  1371. * @return string html code for one tab, a link if valid otherwise a span
  1372. * @access public
  1373. */
  1374. function PMA_getTab($tab)
  1375. {
  1376. // default values
  1377. $defaults = array(
  1378. 'text' => '',
  1379. 'class' => '',
  1380. 'active' => false,
  1381. 'link' => '',
  1382. 'sep' => '?',
  1383. 'attr' => '',
  1384. 'args' => '',
  1385. 'warning' => '',
  1386. 'fragment' => '',
  1387. );
  1388. $tab = array_merge($defaults, $tab);
  1389. // determine additionnal style-class
  1390. if (empty($tab['class'])) {
  1391. if ($tab['text'] == $GLOBALS['strEmpty']
  1392. || $tab['text'] == $GLOBALS['strDrop']) {
  1393. $tab['class'] = 'caution';
  1394. } elseif (!empty($tab['active'])
  1395. || (isset($GLOBALS['active_page'])
  1396. && $GLOBALS['active_page'] == $tab['link'])
  1397. || (basename($GLOBALS['PMA_PHP_SELF']) == $tab['link'] && empty($tab['warning'])))
  1398. {
  1399. $tab['class'] = 'active';
  1400. }
  1401. }
  1402. if (!empty($tab['warning'])) {
  1403. $tab['class'] .= ' warning';
  1404. $tab['attr'] .= ' title="' . htmlspecialchars($tab['warning']) . '"';
  1405. }
  1406. // build the link
  1407. if (!empty($tab['link'])) {
  1408. $tab['link'] = htmlentities($tab['link']);
  1409. $tab['link'] = $tab['link'] . $tab['sep']
  1410. .(empty($GLOBALS['url_query']) ?
  1411. PMA_generate_common_url() : $GLOBALS['url_query']);
  1412. if (!empty($tab['args'])) {
  1413. foreach ($tab['args'] as $param => $value) {
  1414. $tab['link'] .= '&amp;' . urlencode($param) . '='
  1415. . urlencode($value);
  1416. }
  1417. }
  1418. }
  1419. if (! empty($tab['fragment'])) {
  1420. $tab['link'] .= $tab['fragment'];
  1421. }
  1422. // display icon, even if iconic is disabled but the link-text is missing
  1423. if (($GLOBALS['cfg']['MainPageIconic'] || empty($tab['text']))
  1424. && isset($tab['icon'])) {
  1425. // avoid generating an alt tag, because it only illustrates
  1426. // the text that follows and if browser does not display
  1427. // images, the text is duplicated
  1428. $image = '<img class="icon" src="' . htmlentities($GLOBALS['pmaThemeImage'])
  1429. .'%1$s" width="16" height="16" alt="" />%2$s';
  1430. $tab['text'] = sprintf($image, htmlentities($tab['icon']), $tab['text']);
  1431. }
  1432. // check to not display an empty link-text
  1433. elseif (empty($tab['text'])) {
  1434. $tab['text'] = '?';
  1435. trigger_error('empty linktext in function ' . __FUNCTION__ . '()',
  1436. E_USER_NOTICE);
  1437. }
  1438. $out = '<li' . ($tab['class'] == 'active' ? ' class="active"' : '') . '>';
  1439. if (!empty($tab['link'])) {
  1440. $out .= '<a class="tab' . htmlentities($tab['class']) . '"'
  1441. .' href="' . $tab['link'] . '" ' . $tab['attr'] . '>'
  1442. . $tab['text'] . '</a>';
  1443. } else {
  1444. $out .= '<span class="tab' . htmlentities($tab['class']) . '">'
  1445. . $tab['text'] . '</span>';
  1446. }
  1447. $out .= '</li>';
  1448. return $out;
  1449. } // end of the 'PMA_getTab()' function
  1450. /**
  1451. * returns html-code for a tab navigation
  1452. *
  1453. * @uses PMA_getTab()
  1454. * @uses htmlentities()
  1455. * @param array $tabs one element per tab
  1456. * @param string $tag_id id used for the html-tag
  1457. * @return string html-code for tab-navigation
  1458. */
  1459. function PMA_getTabs($tabs, $tag_id = 'topmenu')
  1460. {
  1461. $tab_navigation =
  1462. '<div id="' . htmlentities($tag_id) . 'container">' . "\n"
  1463. .'<ul id="' . htmlentities($tag_id) . '">' . "\n";
  1464. foreach ($tabs as $tab) {
  1465. $tab_navigation .= PMA_getTab($tab) . "\n";
  1466. }
  1467. $tab_navigation .=
  1468. '</ul>' . "\n"
  1469. .'<div class="clearfloat"></div>'
  1470. .'</div>' . "\n";
  1471. return $tab_navigation;
  1472. }
  1473. /**
  1474. * Displays a link, or a button if the link's URL is too large, to
  1475. * accommodate some browsers' limitations
  1476. *
  1477. * @param string the URL
  1478. * @param string the link message
  1479. * @param mixed $tag_params string: js confirmation
  1480. * array: additional tag params (f.e. style="")
  1481. * @param boolean $new_form we set this to false when we are already in
  1482. * a form, to avoid generating nested forms
  1483. *
  1484. * @return string the results to be echoed or saved in an array
  1485. */
  1486. function PMA_linkOrButton($url, $message, $tag_params = array(),
  1487. $new_form = true, $strip_img = false, $target = '')
  1488. {
  1489. if (! is_array($tag_params)) {
  1490. $tmp = $tag_params;
  1491. $tag_params = array();
  1492. if (!empty($tmp)) {
  1493. $tag_params['onclick'] = 'return confirmLink(this, \'' . $tmp . '\')';
  1494. }
  1495. unset($tmp);
  1496. }
  1497. if (! empty($target)) {
  1498. $tag_params['target'] = htmlentities($target);
  1499. }
  1500. $tag_params_strings = array();
  1501. foreach ($tag_params as $par_name => $par_value) {
  1502. // htmlspecialchars() only on non javascript
  1503. $par_value = substr($par_name, 0, 2) == 'on'
  1504. ? $par_value
  1505. : htmlspecialchars($par_value);
  1506. $tag_params_strings[] = $par_name . '="' . $par_value . '"';
  1507. }
  1508. // previously the limit was set to 2047, it seems 1000 is better
  1509. if (strlen($url) <= 1000) {
  1510. // no whitespace within an <a> else Safari will make it part of the link
  1511. $ret = "\n" . '<a href="' . $url . '" '
  1512. . implode(' ', $tag_params_strings) . '>'
  1513. . $message . '</a>' . "\n";
  1514. } else {
  1515. // no spaces (linebreaks) at all
  1516. // or after the hidden fields
  1517. // IE will display them all
  1518. // add class=link to submit button
  1519. if (empty($tag_params['class'])) {
  1520. $tag_params['class'] = 'link';
  1521. }
  1522. // decode encoded url separators
  1523. $separator = PMA_get_arg_separator();
  1524. // on most places separator is still hard coded ...
  1525. if ($separator !== '&') {
  1526. // ... so always replace & with $separator
  1527. $url = str_replace(htmlentities('&'), $separator, $url);
  1528. $url = str_replace('&', $separator, $url);
  1529. }
  1530. $url = str_replace(htmlentities($separator), $separator, $url);
  1531. // end decode
  1532. $url_parts = parse_url($url);
  1533. $query_parts = explode($separator, $url_parts['query']);
  1534. if ($new_form) {
  1535. $ret = '<form action="' . $url_parts['path'] . '" class="link"'
  1536. . ' method="post"' . $target . ' style="display: inline;">';
  1537. $subname_open = '';
  1538. $subname_close = '';
  1539. $submit_name = '';
  1540. } else {
  1541. $query_parts[] = 'redirect=' . $url_parts['path'];
  1542. if (empty($GLOBALS['subform_counter'])) {
  1543. $GLOBALS['subform_counter'] = 0;
  1544. }
  1545. $GLOBALS['subform_counter']++;
  1546. $ret = '';
  1547. $subname_open = 'subform[' . $GLOBALS['subform_counter'] . '][';
  1548. $subname_close = ']';
  1549. $submit_name = ' name="usesubform[' . $GLOBALS['subform_counter'] . ']"';
  1550. }
  1551. foreach ($query_parts as $query_pair) {
  1552. list($eachvar, $eachval) = explode('=', $query_pair);
  1553. $ret .= '<input type="hidden" name="' . $subname_open . $eachvar
  1554. . $subname_close . '" value="'
  1555. . htmlspecialchars(urldecode($eachval)) . '" />';
  1556. } // end while
  1557. if (stristr($message, '<img')) {
  1558. if ($strip_img) {
  1559. $message = trim(strip_tags($message));
  1560. $ret .= '<input type="submit"' . $submit_name . ' '
  1561. . implode(' ', $tag_params_strings)
  1562. . ' value="' . htmlspecialchars($message) . '" />';
  1563. } else {
  1564. $ret .= '<input type="image"' . $submit_name . ' '
  1565. . implode(' ', $tag_params_strings)
  1566. . ' src="' . preg_replace(
  1567. '/^.*\ssrc="([^"]*)".*$/si', '\1', $message) . '"'
  1568. . ' value="' . htmlspecialchars(
  1569. preg_replace('/^.*\salt="([^"]*)".*$/si', '\1',
  1570. $message))
  1571. . '" />';
  1572. }
  1573. } else {
  1574. $message = trim(strip_tags($message));
  1575. $ret .= '<input type="submit"' . $submit_name . ' '
  1576. . implode(' ', $tag_params_strings)
  1577. . ' value="' . htmlspecialchars($message) . '" />';
  1578. }
  1579. if ($new_form) {
  1580. $ret .= '</form>';
  1581. }
  1582. } // end if... else...
  1583. return $ret;
  1584. } // end of the 'PMA_linkOrButton()' function
  1585. /**
  1586. * Returns a given timespan value in a readable format.
  1587. *
  1588. * @uses $GLOBALS['timespanfmt']
  1589. * @uses sprintf()
  1590. * @uses floor()
  1591. * @param int the timespan
  1592. *
  1593. * @return string the formatted value
  1594. */
  1595. function PMA_timespanFormat($seconds)
  1596. {
  1597. $return_string = '';
  1598. $days = floor($seconds / 86400);
  1599. if ($days > 0) {
  1600. $seconds -= $days * 86400;
  1601. }
  1602. $hours = floor($seconds / 3600);
  1603. if ($days > 0 || $hours > 0) {
  1604. $seconds -= $hours * 3600;
  1605. }
  1606. $minutes = floor($seconds / 60);
  1607. if ($days > 0 || $hours > 0 || $minutes > 0) {
  1608. $seconds -= $minutes * 60;
  1609. }
  1610. return sprintf($GLOBALS['timespanfmt'], (string)$days, (string)$hours, (string)$minutes, (string)$seconds);
  1611. }
  1612. /**
  1613. * Takes a string and outputs each character on a line for itself. Used
  1614. * mainly for horizontalflipped display mode.
  1615. * Takes care of special html-characters.
  1616. * Fulfills todo-item
  1617. * http://sf.net/tracker/?func=detail&aid=544361&group_id=23067&atid=377411
  1618. *
  1619. * @todo add a multibyte safe function PMA_STR_split()
  1620. * @uses strlen
  1621. * @param string The string
  1622. * @param string The Separator (defaults to "<br />\n")
  1623. *
  1624. * @access public
  1625. * @author Garvin Hicking <me@supergarv.de>
  1626. * @return string The flipped string
  1627. */
  1628. function PMA_flipstring($string, $Separator = "<br />\n")
  1629. {
  1630. $format_string = '';
  1631. $charbuff = false;
  1632. for ($i = 0; $i < strlen($string); $i++) {
  1633. $char = $string{$i};
  1634. $append = false;
  1635. if ($char == '&') {
  1636. $format_string .= $charbuff;
  1637. $charbuff = $char;
  1638. $append = true;
  1639. } elseif (!empty($charbuff)) {
  1640. $charbuff .= $char;
  1641. } elseif ($char == ';' && !empty($charbuff)) {
  1642. $format_string .= $charbuff;
  1643. $charbuff = false;
  1644. $append = true;
  1645. } else {
  1646. $format_string .= $char;
  1647. $append = true;
  1648. }
  1649. if ($append && ($i != strlen($string))) {
  1650. $format_string .= $Separator;
  1651. }
  1652. }
  1653. return $format_string;
  1654. }
  1655. /**
  1656. * Function added to avoid path disclosures.
  1657. * Called by each script that needs parameters, it displays
  1658. * an error message and, by default, stops the execution.
  1659. *
  1660. * Not sure we could use a strMissingParameter message here,
  1661. * would have to check if the error message file is always available
  1662. *
  1663. * @todo localize error message
  1664. * @todo use PMA_fatalError() if $die === true?
  1665. * @uses PMA_getenv()
  1666. * @uses header_meta_style.inc.php
  1667. * @uses $GLOBALS['PMA_PHP_SELF']
  1668. * basename
  1669. * @param array The names of the parameters needed by the calling
  1670. * script.
  1671. * @param boolean Stop the execution?
  1672. * (Set this manually to false in the calling script
  1673. * until you know all needed parameters to check).
  1674. * @param boolean Whether to include this list in checking for special params.
  1675. * @global string path to current script
  1676. * @global boolean flag whether any special variable was required
  1677. *
  1678. * @access public
  1679. * @author Marc Delisle (lem9@users.sourceforge.net)
  1680. */
  1681. function PMA_checkParameters($params, $die = true, $request = true)
  1682. {
  1683. global $checked_special;
  1684. if (!isset($checked_special)) {
  1685. $checked_special = false;
  1686. }
  1687. $reported_script_name = basename($GLOBALS['PMA_PHP_SELF']);
  1688. $found_error = false;
  1689. $error_message = '';
  1690. foreach ($params as $param) {
  1691. if ($request && $param != 'db' && $param != 'table') {
  1692. $checked_special = true;
  1693. }
  1694. if (!isset($GLOBALS[$param])) {
  1695. $error_message .= $reported_script_name
  1696. . ': Missing parameter: ' . $param
  1697. . ' <a href="./Documentation.html#faqmissingparameters"'
  1698. . ' target="documentation"> (FAQ 2.8)</a><br />';
  1699. $found_error = true;
  1700. }
  1701. }
  1702. if ($found_error) {
  1703. /**
  1704. * display html meta tags
  1705. */
  1706. require_once './libraries/header_meta_style.inc.php';
  1707. echo '</head><body><p>' . $error_message . '</p></body></html>';
  1708. if ($die) {
  1709. exit();
  1710. }
  1711. }
  1712. } // end function
  1713. /**
  1714. * Function to generate unique condition for specified row.
  1715. *
  1716. * @uses PMA_MYSQL_INT_VERSION
  1717. * @uses $GLOBALS['analyzed_sql'][0]
  1718. * @uses PMA_DBI_field_flags()
  1719. * @uses PMA_backquote()
  1720. * @uses PMA_sqlAddslashes()
  1721. * @uses stristr()
  1722. * @uses bin2hex()
  1723. * @uses preg_replace()
  1724. * @param resource $handle current query result
  1725. * @param integer $fields_cnt number of fields
  1726. * @param array $fields_meta meta information about fields
  1727. * @param array $row current row
  1728. * @param boolean $force_unique generate condition only on pk or unique
  1729. *
  1730. * @access public
  1731. * @author Michal Cihar (michal@cihar.com) and others...
  1732. * @return string calculated condition
  1733. */
  1734. function PMA_getUniqueCondition($handle, $fields_cnt, $fields_meta, $row, $force_unique=false)
  1735. {
  1736. $primary_key = '';
  1737. $unique_key = '';
  1738. $nonprimary_condition = '';
  1739. $preferred_condition = '';
  1740. for ($i = 0; $i < $fields_cnt; ++$i) {
  1741. $condition = '';
  1742. $field_flags = PMA_DBI_field_flags($handle, $i);
  1743. $meta = $fields_meta[$i];
  1744. // do not use a column alias in a condition
  1745. if (! isset($meta->orgname) || ! strlen($meta->orgname)) {
  1746. $meta->orgname = $meta->name;
  1747. if (isset($GLOBALS['analyzed_sql'][0]['select_expr'])
  1748. && is_array($GLOBALS['analyzed_sql'][0]['select_expr'])) {
  1749. foreach ($GLOBALS['analyzed_sql'][0]['select_expr']
  1750. as $select_expr) {
  1751. // need (string) === (string)
  1752. // '' !== 0 but '' == 0
  1753. if ((string) $select_expr['alias'] === (string) $meta->name) {
  1754. $meta->orgname = $select_expr['column'];
  1755. break;
  1756. } // end if
  1757. } // end foreach
  1758. }
  1759. }
  1760. // Do not use a table alias in a condition.
  1761. // Test case is:
  1762. // select * from galerie x WHERE
  1763. //(select count(*) from galerie y where y.datum=x.datum)>1
  1764. //
  1765. // But orgtable is present only with mysqli extension so the
  1766. // fix is only for mysqli.
  1767. if (isset($meta->orgtable) && $meta->table != $meta->orgtable) {
  1768. $meta->table = $meta->orgtable;
  1769. }
  1770. // to fix the bug where float fields (primary or not)
  1771. // can't be matched because of the imprecision of
  1772. // floating comparison, use CONCAT
  1773. // (also, the syntax "CONCAT(field) IS NULL"
  1774. // that we need on the next "if" will work)
  1775. if ($meta->type == 'real') {
  1776. $condition = ' CONCAT(' . PMA_backquote($meta->table) . '.'
  1777. . PMA_backquote($meta->orgname) . ') ';
  1778. } else {
  1779. // string and blob fields have to be converted using
  1780. // the system character set (always utf8) since
  1781. // mysql4.1 can use different charset for fields.
  1782. if (PMA_MYSQL_INT_VERSION >= 40100
  1783. && ($meta->type == 'string' || $meta->type == 'blob')) {
  1784. $condition = ' CONVERT(' . PMA_backquote($meta->table) . '.'
  1785. . PMA_backquote($meta->orgname) . ' USING utf8) ';
  1786. } else {
  1787. $condition = ' ' . PMA_backquote($meta->table) . '.'
  1788. . PMA_backquote($meta->orgname) . ' ';
  1789. }
  1790. } // end if... else...
  1791. if (!isset($row[$i]) || is_null($row[$i])) {
  1792. $condition .= 'IS NULL AND';
  1793. } else {
  1794. // timestamp is numeric on some MySQL 4.1
  1795. if ($meta->numeric && $meta->type != 'timestamp') {
  1796. $condition .= '= ' . $row[$i] . ' AND';
  1797. } elseif (($meta->type == 'blob' || $meta->type == 'string')
  1798. // hexify only if this is a true not empty BLOB or a BINARY
  1799. && stristr($field_flags, 'BINARY')
  1800. && !empty($row[$i])) {
  1801. // do not waste memory building a too big condition
  1802. if (strlen($row[$i]) < 1000) {
  1803. if (PMA_MYSQL_INT_VERSION < 40002) {
  1804. $condition .= 'LIKE 0x' . bin2hex($row[$i]) . ' AND';
  1805. } else {
  1806. // use a CAST if possible, to avoid problems
  1807. // if the field contains wildcard characters % or _
  1808. $condition .= '= CAST(0x' . bin2hex($row[$i])
  1809. . ' AS BINARY) AND';
  1810. }
  1811. } else {
  1812. // this blob won't be part of the final condition
  1813. $condition = '';
  1814. }
  1815. } else {
  1816. $condition .= '= \''
  1817. . PMA_sqlAddslashes($row[$i], false, true) . '\' AND';
  1818. }
  1819. }
  1820. if ($meta->primary_key > 0) {
  1821. $primary_key .= $condition;
  1822. } elseif ($meta->unique_key > 0) {
  1823. $unique_key .= $condition;
  1824. }
  1825. $nonprimary_condition .= $condition;
  1826. } // end for
  1827. // Correction University of Virginia 19991216:
  1828. // prefer primary or unique keys for condition,
  1829. // but use conjunction of all values if no primary key
  1830. if ($primary_key) {
  1831. $preferred_condition = $primary_key;
  1832. } elseif ($unique_key) {
  1833. $preferred_condition = $unique_key;
  1834. } elseif (! $force_unique) {
  1835. $preferred_condition = $nonprimary_condition;
  1836. }
  1837. return preg_replace('|\s?AND$|', '', $preferred_condition);
  1838. } // end function
  1839. /**
  1840. * Generate a button or image tag
  1841. *
  1842. * @uses PMA_USR_BROWSER_AGENT
  1843. * @uses $GLOBALS['pmaThemeImage']
  1844. * @uses $GLOBALS['cfg']['PropertiesIconic']
  1845. * @param string name of button element
  1846. * @param string class of button element
  1847. * @param string name of image element
  1848. * @param string text to display
  1849. * @param string image to display
  1850. *
  1851. * @access public
  1852. * @author Michal Cihar (michal@cihar.com)
  1853. */
  1854. function PMA_buttonOrImage($button_name, $button_class, $image_name, $text,
  1855. $image)
  1856. {
  1857. /* Opera has trouble with <input type="image"> */
  1858. /* IE has trouble with <button> */
  1859. if (PMA_USR_BROWSER_AGENT != 'IE') {
  1860. echo '<button class="' . $button_class . '" type="submit"'
  1861. .' name="' . $button_name . '" value="' . $text . '"'
  1862. .' title="' . $text . '">' . "\n"
  1863. .'<img class="icon" src="' . $GLOBALS['pmaThemeImage'] . $image . '"'
  1864. .' title="' . $text . '" alt="' . $text . '" width="16"'
  1865. .' height="16" />'
  1866. .($GLOBALS['cfg']['PropertiesIconic'] === 'both' ? '&nbsp;' . $text : '') . "\n"
  1867. .'</button>' . "\n";
  1868. } else {
  1869. echo '<input type="image" name="' . $image_name . '" value="'
  1870. . $text . '" title="' . $text . '" src="' . $GLOBALS['pmaThemeImage']
  1871. . $image . '" />'
  1872. . ($GLOBALS['cfg']['PropertiesIconic'] === 'both' ? '&nbsp;' . $text : '') . "\n";
  1873. }
  1874. } // end function
  1875. /**
  1876. * Generate a pagination selector for browsing resultsets
  1877. *
  1878. * @uses $GLOBALS['strPageNumber']
  1879. * @uses range()
  1880. * @param string URL for the JavaScript
  1881. * @param string Number of rows in the pagination set
  1882. * @param string current page number
  1883. * @param string number of total pages
  1884. * @param string If the number of pages is lower than this
  1885. * variable, no pages will be ommitted in
  1886. * pagination
  1887. * @param string How many rows at the beginning should always
  1888. * be shown?
  1889. * @param string How many rows at the end should always
  1890. * be shown?
  1891. * @param string Percentage of calculation page offsets to
  1892. * hop to a next page
  1893. * @param string Near the current page, how many pages should
  1894. * be considered "nearby" and displayed as
  1895. * well?
  1896. * @param string The prompt to display (sometimes empty)
  1897. *
  1898. * @access public
  1899. * @author Garvin Hicking (pma@supergarv.de)
  1900. */
  1901. function PMA_pageselector($url, $rows, $pageNow = 1, $nbTotalPage = 1,
  1902. $showAll = 200, $sliceStart = 5, $sliceEnd = 5, $percent = 20,
  1903. $range = 10, $prompt = '')
  1904. {
  1905. $gotopage = $prompt
  1906. . ' <select name="pos" onchange="goToUrl(this, \''
  1907. . $url . '\');">' . "\n";
  1908. if ($nbTotalPage < $showAll) {
  1909. $pages = range(1, $nbTotalPage);
  1910. } else {
  1911. $pages = array();
  1912. // Always show first X pages
  1913. for ($i = 1; $i <= $sliceStart; $i++) {
  1914. $pages[] = $i;
  1915. }
  1916. // Always show last X pages
  1917. for ($i = $nbTotalPage - $sliceEnd; $i <= $nbTotalPage; $i++) {
  1918. $pages[] = $i;
  1919. }
  1920. // garvin: Based on the number of results we add the specified
  1921. // $percent percentate to each page number,
  1922. // so that we have a representing page number every now and then to
  1923. // immideately jump to specific pages.
  1924. // As soon as we get near our currently chosen page ($pageNow -
  1925. // $range), every page number will be
  1926. // shown.
  1927. $i = $sliceStart;
  1928. $x = $nbTotalPage - $sliceEnd;
  1929. $met_boundary = false;
  1930. while ($i <= $x) {
  1931. if ($i >= ($pageNow - $range) && $i <= ($pageNow + $range)) {
  1932. // If our pageselector comes near the current page, we use 1
  1933. // counter increments
  1934. $i++;
  1935. $met_boundary = true;
  1936. } else {
  1937. // We add the percentate increment to our current page to
  1938. // hop to the next one in range
  1939. $i = $i + floor($nbTotalPage / $percent);
  1940. // Make sure that we do not cross our boundaries.
  1941. if ($i > ($pageNow - $range) && !$met_boundary) {
  1942. $i = $pageNow - $range;
  1943. }
  1944. }
  1945. if ($i > 0 && $i <= $x) {
  1946. $pages[] = $i;
  1947. }
  1948. }
  1949. // Since because of ellipsing of the current page some numbers may be double,
  1950. // we unify our array:
  1951. sort($pages);
  1952. $pages = array_unique($pages);
  1953. }
  1954. foreach ($pages as $i) {
  1955. if ($i == $pageNow) {
  1956. $selected = 'selected="selected" style="font-weight: bold"';
  1957. } else {
  1958. $selected = '';
  1959. }
  1960. $gotopage .= ' <option ' . $selected . ' value="' . (($i - 1) * $rows) . '">' . $i . '</option>' . "\n";
  1961. }
  1962. $gotopage .= ' </select><noscript><input type="submit" value="' . $GLOBALS['strGo'] . '" /></noscript>';
  1963. return $gotopage;
  1964. } // end function
  1965. /**
  1966. * Generate navigation for a list
  1967. *
  1968. * @todo use $pos from $_url_params
  1969. * @uses $GLOBALS['strPageNumber']
  1970. * @uses range()
  1971. * @param integer number of elements in the list
  1972. * @param integer current position in the list
  1973. * @param array url parameters
  1974. * @param string script name for form target
  1975. * @param string target frame
  1976. * @param integer maximum number of elements to display from the list
  1977. *
  1978. * @access public
  1979. */
  1980. function PMA_listNavigator($count, $pos, $_url_params, $script, $frame, $max_count) {
  1981. if ($max_count < $count) {
  1982. echo 'frame_navigation' == $frame ? '<div id="navidbpageselector">' . "\n" : '';
  1983. echo $GLOBALS['strPageNumber'];
  1984. echo 'frame_navigation' == $frame ? '<br />' : ' ';
  1985. // Move to the beginning or to the previous page
  1986. if ($pos > 0) {
  1987. // loic1: patch #474210 from Gosha Sakovich - part 1
  1988. if ($GLOBALS['cfg']['NavigationBarIconic']) {
  1989. $caption1 = '&lt;&lt;';
  1990. $caption2 = ' &lt; ';
  1991. $title1 = ' title="' . $GLOBALS['strPos1'] . '"';
  1992. $title2 = ' title="' . $GLOBALS['strPrevious'] . '"';
  1993. } else {
  1994. $caption1 = $GLOBALS['strPos1'] . ' &lt;&lt;';
  1995. $caption2 = $GLOBALS['strPrevious'] . ' &lt;';
  1996. $title1 = '';
  1997. $title2 = '';
  1998. } // end if... else...
  1999. $_url_params['pos'] = 0;
  2000. echo '<a' . $title1 . ' href="' . $script
  2001. . PMA_generate_common_url($_url_params) . '" target="' . $frame . '">'
  2002. . $caption1 . '</a>';
  2003. $_url_params['pos'] = $pos - $max_count;
  2004. echo '<a' . $title2 . ' href="' . $script
  2005. . PMA_generate_common_url($_url_params) . '" target="' . $frame . '">'
  2006. . $caption2 . '</a>';
  2007. }
  2008. echo "\n", '<form action="./', basename($script), '" method="post" target="', $frame, '">', "\n";
  2009. echo PMA_generate_common_hidden_inputs($_url_params);
  2010. echo PMA_pageselector(
  2011. $script . PMA_generate_common_url($_url_params) . '&',
  2012. $max_count,
  2013. floor(($pos + 1) / $max_count) + 1,
  2014. ceil($count / $max_count));
  2015. echo '</form>';
  2016. if ($pos + $max_count < $count) {
  2017. if ($GLOBALS['cfg']['NavigationBarIconic']) {
  2018. $caption3 = ' &gt; ';
  2019. $caption4 = '&gt;&gt;';
  2020. $title3 = ' title="' . $GLOBALS['strNext'] . '"';
  2021. $title4 = ' title="' . $GLOBALS['strEnd'] . '"';
  2022. } else {
  2023. $caption3 = '&gt; ' . $GLOBALS['strNext'];
  2024. $caption4 = '&gt;&gt; ' . $GLOBALS['strEnd'];
  2025. $title3 = '';
  2026. $title4 = '';
  2027. } // end if... else...
  2028. $_url_params['pos'] = $pos + $max_count;
  2029. echo '<a' . $title3 . ' href="' . $script
  2030. . PMA_generate_common_url($_url_params) . '" target="' . $frame . '">'
  2031. . $caption3 . '</a>';
  2032. $_url_params['pos'] = floor($count / $max_count) * $max_count;
  2033. if ($_url_params['pos'] == $count) {
  2034. $_url_params['pos'] = $count - $max_count;
  2035. }
  2036. echo '<a' . $title4 . ' href="' . $script
  2037. . PMA_generate_common_url($_url_params) . '" target="' . $frame . '">'
  2038. . $caption4 . '</a>';
  2039. }
  2040. echo "\n";
  2041. if ('frame_navigation' == $frame) {
  2042. echo '</div>' . "\n";
  2043. }
  2044. }
  2045. }
  2046. /**
  2047. * replaces %u in given path with current user name
  2048. *
  2049. * example:
  2050. * <code>
  2051. * $user_dir = PMA_userDir('/var/pma_tmp/%u/'); // '/var/pma_tmp/root/'
  2052. *
  2053. * </code>
  2054. * @uses $cfg['Server']['user']
  2055. * @uses substr()
  2056. * @uses str_replace()
  2057. * @param string $dir with wildcard for user
  2058. * @return string per user directory
  2059. */
  2060. function PMA_userDir($dir)
  2061. {
  2062. // add trailing slash
  2063. if (substr($dir, -1) != '/') {
  2064. $dir .= '/';
  2065. }
  2066. return str_replace('%u', $GLOBALS['cfg']['Server']['user'], $dir);
  2067. }
  2068. /**
  2069. * returns html code for db link to default db page
  2070. *
  2071. * @uses $cfg['DefaultTabDatabase']
  2072. * @uses $GLOBALS['db']
  2073. * @uses $GLOBALS['strJumpToDB']
  2074. * @uses PMA_generate_common_url()
  2075. * @uses PMA_unescape_mysql_wildcards()
  2076. * @uses strlen()
  2077. * @uses sprintf()
  2078. * @uses htmlspecialchars()
  2079. * @param string $database
  2080. * @return string html link to default db page
  2081. */
  2082. function PMA_getDbLink($database = null)
  2083. {
  2084. if (!strlen($database)) {
  2085. if (!strlen($GLOBALS['db'])) {
  2086. return '';
  2087. }
  2088. $database = $GLOBALS['db'];
  2089. } else {
  2090. $database = PMA_unescape_mysql_wildcards($database);
  2091. }
  2092. return '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?' . PMA_generate_common_url($database) . '"'
  2093. .' title="' . sprintf($GLOBALS['strJumpToDB'], htmlspecialchars($database)) . '">'
  2094. .htmlspecialchars($database) . '</a>';
  2095. }
  2096. /**
  2097. * Displays a lightbulb hint explaining a known external bug
  2098. * that affects a functionality
  2099. *
  2100. * @uses PMA_MYSQL_INT_VERSION
  2101. * @uses $GLOBALS['strKnownExternalBug']
  2102. * @uses PMA_showHint()
  2103. * @uses sprintf()
  2104. * @param string $functionality localized message explaining the func.
  2105. * @param string $component 'mysql' (eventually, 'php')
  2106. * @param string $minimum_version of this component
  2107. * @param string $bugref bug reference for this component
  2108. */
  2109. function PMA_externalBug($functionality, $component, $minimum_version, $bugref)
  2110. {
  2111. if ($component == 'mysql' && PMA_MYSQL_INT_VERSION < $minimum_version) {
  2112. echo PMA_showHint(sprintf($GLOBALS['strKnownExternalBug'], $functionality, 'http://bugs.mysql.com/' . $bugref));
  2113. }
  2114. }
  2115. /**
  2116. * Converts a bit value to printable format;
  2117. * in MySQL a BIT field can be from 1 to 64 bits so we need this
  2118. * function because in PHP, decbin() supports only 32 bits
  2119. *
  2120. * @uses ceil()
  2121. * @uses decbin()
  2122. * @uses ord()
  2123. * @uses substr()
  2124. * @uses sprintf()
  2125. * @param numeric $value coming from a BIT field
  2126. * @param integer $length
  2127. * @return string the printable value
  2128. */
  2129. function PMA_printable_bit_value($value, $length) {
  2130. $printable = '';
  2131. for ($i = 0; $i < ceil($length / 8); $i++) {
  2132. $printable .= sprintf('%08d', decbin(ord(substr($value, $i, 1))));
  2133. }
  2134. $printable = substr($printable, -$length);
  2135. return $printable;
  2136. }
  2137. /**
  2138. * Extracts the true field type and length from a field type spec
  2139. *
  2140. * @uses strpos()
  2141. * @uses chop()
  2142. * @uses substr()
  2143. * @param string $fieldspec
  2144. * @return array associative array containing the type and length
  2145. */
  2146. function PMA_extract_type_length($fieldspec) {
  2147. $first_bracket_pos = strpos($fieldspec, '(');
  2148. if ($first_bracket_pos) {
  2149. $length = chop(substr($fieldspec, $first_bracket_pos + 1, (strpos($fieldspec, ')') - $first_bracket_pos - 1)));
  2150. $type = chop(substr($fieldspec, 0, $first_bracket_pos));
  2151. } else {
  2152. $type = $fieldspec;
  2153. $length = '';
  2154. }
  2155. return array(
  2156. 'type' => $type,
  2157. 'length' => $length
  2158. );
  2159. }
  2160. ?>