PageRenderTime 73ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/pma/libraries/common.lib.php

https://bitbucket.org/StasPiv/playzone
PHP | 2690 lines | 1566 code | 234 blank | 890 comment | 382 complexity | 89c9f783e6f1689a9126f9e4a72794d5 MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause, GPL-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: common.lib.php 12608 2009-06-30 10:48:08Z lem9 $
  7. * @package phpMyAdmin
  8. */
  9. /**
  10. * Exponential expression / raise number into power
  11. *
  12. * @uses function_exists()
  13. * @uses bcpow()
  14. * @uses gmp_pow()
  15. * @uses gmp_strval()
  16. * @uses pow()
  17. * @param number $base
  18. * @param number $exp
  19. * @param string pow function use, or false for auto-detect
  20. * @return mixed string or float
  21. */
  22. function PMA_pow($base, $exp, $use_function = false)
  23. {
  24. static $pow_function = null;
  25. if ($exp < 0) {
  26. return false;
  27. }
  28. if (null == $pow_function) {
  29. if (function_exists('bcpow')) {
  30. // BCMath Arbitrary Precision Mathematics Function
  31. $pow_function = 'bcpow';
  32. } elseif (function_exists('gmp_pow')) {
  33. // GMP Function
  34. $pow_function = 'gmp_pow';
  35. } else {
  36. // PHP function
  37. $pow_function = 'pow';
  38. }
  39. }
  40. if (! $use_function) {
  41. $use_function = $pow_function;
  42. }
  43. switch ($use_function) {
  44. case 'bcpow' :
  45. // bcscale() needed for testing PMA_pow() with base values < 1
  46. bcscale(10);
  47. $pow = bcpow($base, $exp);
  48. break;
  49. case 'gmp_pow' :
  50. $pow = gmp_strval(gmp_pow($base, $exp));
  51. break;
  52. case 'pow' :
  53. $base = (float) $base;
  54. $exp = (int) $exp;
  55. $pow = pow($base, $exp);
  56. break;
  57. default:
  58. $pow = $use_function($base, $exp);
  59. }
  60. return $pow;
  61. }
  62. /**
  63. * string PMA_getIcon(string $icon)
  64. *
  65. * @uses $GLOBALS['pmaThemeImage']
  66. * @uses $GLOBALS['cfg']['PropertiesIconic']
  67. * @uses htmlspecialchars()
  68. * @param string $icon name of icon file
  69. * @param string $alternate alternate text
  70. * @param boolean $container include in container
  71. * @param boolean $$force_text whether to force alternate text to be displayed
  72. * @return html img tag
  73. */
  74. function PMA_getIcon($icon, $alternate = '', $container = false, $force_text = false)
  75. {
  76. $include_icon = false;
  77. $include_text = false;
  78. $include_box = false;
  79. $alternate = htmlspecialchars($alternate);
  80. $button = '';
  81. if ($GLOBALS['cfg']['PropertiesIconic']) {
  82. $include_icon = true;
  83. }
  84. if ($force_text
  85. || ! (true === $GLOBALS['cfg']['PropertiesIconic'])
  86. || ! $include_icon) {
  87. // $cfg['PropertiesIconic'] is false or both
  88. // OR we have no $include_icon
  89. $include_text = true;
  90. }
  91. if ($include_text && $include_icon && $container) {
  92. // we have icon, text and request for container
  93. $include_box = true;
  94. }
  95. if ($include_box) {
  96. $button .= '<div class="nowrap">';
  97. }
  98. if ($include_icon) {
  99. $button .= '<img src="' . $GLOBALS['pmaThemeImage'] . $icon . '"'
  100. . ' title="' . $alternate . '" alt="' . $alternate . '"'
  101. . ' class="icon" width="16" height="16" />';
  102. }
  103. if ($include_icon && $include_text) {
  104. $button .= ' ';
  105. }
  106. if ($include_text) {
  107. $button .= $alternate;
  108. }
  109. if ($include_box) {
  110. $button .= '</div>';
  111. }
  112. return $button;
  113. }
  114. /**
  115. * Displays the maximum size for an upload
  116. *
  117. * @uses $GLOBALS['strMaximumSize']
  118. * @uses PMA_formatByteDown()
  119. * @uses sprintf()
  120. * @param integer the size
  121. *
  122. * @return string the message
  123. *
  124. * @access public
  125. */
  126. function PMA_displayMaximumUploadSize($max_upload_size)
  127. {
  128. // I have to reduce the second parameter (sensitiveness) from 6 to 4
  129. // to avoid weird results like 512 kKib
  130. list($max_size, $max_unit) = PMA_formatByteDown($max_upload_size, 4);
  131. return '(' . sprintf($GLOBALS['strMaximumSize'], $max_size, $max_unit) . ')';
  132. }
  133. /**
  134. * Generates a hidden field which should indicate to the browser
  135. * the maximum size for upload
  136. *
  137. * @param integer the size
  138. *
  139. * @return string the INPUT field
  140. *
  141. * @access public
  142. */
  143. function PMA_generateHiddenMaxFileSize($max_size)
  144. {
  145. return '<input type="hidden" name="MAX_FILE_SIZE" value="' .$max_size . '" />';
  146. }
  147. /**
  148. * Add slashes before "'" and "\" characters so a value containing them can
  149. * be used in a sql comparison.
  150. *
  151. * @uses str_replace()
  152. * @param string the string to slash
  153. * @param boolean whether the string will be used in a 'LIKE' clause
  154. * (it then requires two more escaped sequences) or not
  155. * @param boolean whether to treat cr/lfs as escape-worthy entities
  156. * (converts \n to \\n, \r to \\r)
  157. *
  158. * @param boolean whether this function is used as part of the
  159. * "Create PHP code" dialog
  160. *
  161. * @return string the slashed string
  162. *
  163. * @access public
  164. */
  165. function PMA_sqlAddslashes($a_string = '', $is_like = false, $crlf = false, $php_code = false)
  166. {
  167. if ($is_like) {
  168. $a_string = str_replace('\\', '\\\\\\\\', $a_string);
  169. } else {
  170. $a_string = str_replace('\\', '\\\\', $a_string);
  171. }
  172. if ($crlf) {
  173. $a_string = str_replace("\n", '\n', $a_string);
  174. $a_string = str_replace("\r", '\r', $a_string);
  175. $a_string = str_replace("\t", '\t', $a_string);
  176. }
  177. if ($php_code) {
  178. $a_string = str_replace('\'', '\\\'', $a_string);
  179. } else {
  180. $a_string = str_replace('\'', '\'\'', $a_string);
  181. }
  182. return $a_string;
  183. } // end of the 'PMA_sqlAddslashes()' function
  184. /**
  185. * Add slashes before "_" and "%" characters for using them in MySQL
  186. * database, table and field names.
  187. * Note: This function does not escape backslashes!
  188. *
  189. * @uses str_replace()
  190. * @param string the string to escape
  191. *
  192. * @return string the escaped string
  193. *
  194. * @access public
  195. */
  196. function PMA_escape_mysql_wildcards($name)
  197. {
  198. $name = str_replace('_', '\\_', $name);
  199. $name = str_replace('%', '\\%', $name);
  200. return $name;
  201. } // end of the 'PMA_escape_mysql_wildcards()' function
  202. /**
  203. * removes slashes before "_" and "%" characters
  204. * Note: This function does not unescape backslashes!
  205. *
  206. * @uses str_replace()
  207. * @param string $name the string to escape
  208. * @return string the escaped string
  209. * @access public
  210. */
  211. function PMA_unescape_mysql_wildcards($name)
  212. {
  213. $name = str_replace('\\_', '_', $name);
  214. $name = str_replace('\\%', '%', $name);
  215. return $name;
  216. } // end of the 'PMA_unescape_mysql_wildcards()' function
  217. /**
  218. * removes quotes (',",`) from a quoted string
  219. *
  220. * checks if the sting is quoted and removes this quotes
  221. *
  222. * @uses str_replace()
  223. * @uses substr()
  224. * @param string $quoted_string string to remove quotes from
  225. * @param string $quote type of quote to remove
  226. * @return string unqoted string
  227. */
  228. function PMA_unQuote($quoted_string, $quote = null)
  229. {
  230. $quotes = array();
  231. if (null === $quote) {
  232. $quotes[] = '`';
  233. $quotes[] = '"';
  234. $quotes[] = "'";
  235. } else {
  236. $quotes[] = $quote;
  237. }
  238. foreach ($quotes as $quote) {
  239. if (substr($quoted_string, 0, 1) === $quote
  240. && substr($quoted_string, -1, 1) === $quote) {
  241. $unquoted_string = substr($quoted_string, 1, -1);
  242. // replace escaped quotes
  243. $unquoted_string = str_replace($quote . $quote, $quote, $unquoted_string);
  244. return $unquoted_string;
  245. }
  246. }
  247. return $quoted_string;
  248. }
  249. /**
  250. * format sql strings
  251. *
  252. * @todo move into PMA_Sql
  253. * @uses PMA_SQP_isError()
  254. * @uses PMA_SQP_formatHtml()
  255. * @uses PMA_SQP_formatNone()
  256. * @uses is_array()
  257. * @param mixed pre-parsed SQL structure
  258. *
  259. * @return string the formatted sql
  260. *
  261. * @global array the configuration array
  262. * @global boolean whether the current statement is a multiple one or not
  263. *
  264. * @access public
  265. *
  266. * @author Robin Johnson <robbat2@users.sourceforge.net>
  267. */
  268. function PMA_formatSql($parsed_sql, $unparsed_sql = '')
  269. {
  270. global $cfg;
  271. // Check that we actually have a valid set of parsed data
  272. // well, not quite
  273. // first check for the SQL parser having hit an error
  274. if (PMA_SQP_isError()) {
  275. return htmlspecialchars($parsed_sql['raw']);
  276. }
  277. // then check for an array
  278. if (!is_array($parsed_sql)) {
  279. // We don't so just return the input directly
  280. // This is intended to be used for when the SQL Parser is turned off
  281. $formatted_sql = '<pre>' . "\n"
  282. . (($cfg['SQP']['fmtType'] == 'none' && $unparsed_sql != '') ? $unparsed_sql : $parsed_sql) . "\n"
  283. . '</pre>';
  284. return $formatted_sql;
  285. }
  286. $formatted_sql = '';
  287. switch ($cfg['SQP']['fmtType']) {
  288. case 'none':
  289. if ($unparsed_sql != '') {
  290. $formatted_sql = "<pre>\n" . PMA_SQP_formatNone(array('raw' => $unparsed_sql)) . "\n</pre>";
  291. } else {
  292. $formatted_sql = PMA_SQP_formatNone($parsed_sql);
  293. }
  294. break;
  295. case 'html':
  296. $formatted_sql = PMA_SQP_formatHtml($parsed_sql, 'color');
  297. break;
  298. case 'text':
  299. //$formatted_sql = PMA_SQP_formatText($parsed_sql);
  300. $formatted_sql = PMA_SQP_formatHtml($parsed_sql, 'text');
  301. break;
  302. default:
  303. break;
  304. } // end switch
  305. return $formatted_sql;
  306. } // end of the "PMA_formatSql()" function
  307. /**
  308. * Displays a link to the official MySQL documentation
  309. *
  310. * @uses $cfg['MySQLManualType']
  311. * @uses $cfg['MySQLManualBase']
  312. * @uses $cfg['ReplaceHelpImg']
  313. * @uses $GLOBALS['mysql_4_1_doc_lang']
  314. * @uses $GLOBALS['mysql_5_1_doc_lang']
  315. * @uses $GLOBALS['mysql_5_0_doc_lang']
  316. * @uses $GLOBALS['strDocu']
  317. * @uses $GLOBALS['pmaThemeImage']
  318. * @uses PMA_MYSQL_INT_VERSION
  319. * @uses strtolower()
  320. * @uses str_replace()
  321. * @param string chapter of "HTML, one page per chapter" documentation
  322. * @param string contains name of page/anchor that is being linked
  323. * @param bool whether to use big icon (like in left frame)
  324. * @param string anchor to page part
  325. *
  326. * @return string the html link
  327. *
  328. * @access public
  329. */
  330. function PMA_showMySQLDocu($chapter, $link, $big_icon = false, $anchor = '')
  331. {
  332. global $cfg;
  333. if ($cfg['MySQLManualType'] == 'none' || empty($cfg['MySQLManualBase'])) {
  334. return '';
  335. }
  336. // Fixup for newly used names:
  337. $chapter = str_replace('_', '-', strtolower($chapter));
  338. $link = str_replace('_', '-', strtolower($link));
  339. switch ($cfg['MySQLManualType']) {
  340. case 'chapters':
  341. if (empty($chapter)) {
  342. $chapter = 'index';
  343. }
  344. if (empty($anchor)) {
  345. $anchor = $link;
  346. }
  347. $url = $cfg['MySQLManualBase'] . '/' . $chapter . '.html#' . $anchor;
  348. break;
  349. case 'big':
  350. if (empty($anchor)) {
  351. $anchor = $link;
  352. }
  353. $url = $cfg['MySQLManualBase'] . '#' . $anchor;
  354. break;
  355. case 'searchable':
  356. if (empty($link)) {
  357. $link = 'index';
  358. }
  359. $url = $cfg['MySQLManualBase'] . '/' . $link . '.html';
  360. if (!empty($anchor)) {
  361. $url .= '#' . $anchor;
  362. }
  363. break;
  364. case 'viewable':
  365. default:
  366. if (empty($link)) {
  367. $link = 'index';
  368. }
  369. $mysql = '5.0';
  370. $lang = 'en';
  371. if (defined('PMA_MYSQL_INT_VERSION')) {
  372. if (PMA_MYSQL_INT_VERSION >= 50100) {
  373. $mysql = '5.1';
  374. if (!empty($GLOBALS['mysql_5_1_doc_lang'])) {
  375. $lang = $GLOBALS['mysql_5_1_doc_lang'];
  376. }
  377. } elseif (PMA_MYSQL_INT_VERSION >= 50000) {
  378. $mysql = '5.0';
  379. if (!empty($GLOBALS['mysql_5_0_doc_lang'])) {
  380. $lang = $GLOBALS['mysql_5_0_doc_lang'];
  381. }
  382. }
  383. }
  384. $url = $cfg['MySQLManualBase'] . '/' . $mysql . '/' . $lang . '/' . $link . '.html';
  385. if (!empty($anchor)) {
  386. $url .= '#' . $anchor;
  387. }
  388. break;
  389. }
  390. if ($big_icon) {
  391. 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>';
  392. } elseif ($GLOBALS['cfg']['ReplaceHelpImg']) {
  393. 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>';
  394. } else {
  395. return '[<a href="' . $url . '" target="mysql_doc">' . $GLOBALS['strDocu'] . '</a>]';
  396. }
  397. } // end of the 'PMA_showMySQLDocu()' function
  398. /**
  399. * returns HTML for a footnote marker and add the messsage to the footnotes
  400. *
  401. * @uses $GLOBALS['footnotes']
  402. * @param string the error message
  403. * @return string html code for a footnote marker
  404. * @access public
  405. */
  406. function PMA_showHint($message, $bbcode = false, $type = 'notice')
  407. {
  408. if ($message instanceof PMA_Message) {
  409. $key = $message->getHash();
  410. $type = $message->getLevel();
  411. } else {
  412. $key = md5($message);
  413. }
  414. if (! isset($GLOBALS['footnotes'][$key])) {
  415. if (empty($GLOBALS['footnotes']) || ! is_array($GLOBALS['footnotes'])) {
  416. $GLOBALS['footnotes'] = array();
  417. }
  418. $nr = count($GLOBALS['footnotes']) + 1;
  419. // this is the first instance of this message
  420. $instance = 1;
  421. $GLOBALS['footnotes'][$key] = array(
  422. 'note' => $message,
  423. 'type' => $type,
  424. 'nr' => $nr,
  425. 'instance' => $instance
  426. );
  427. } else {
  428. $nr = $GLOBALS['footnotes'][$key]['nr'];
  429. // another instance of this message (to ensure ids are unique)
  430. $instance = ++$GLOBALS['footnotes'][$key]['instance'];
  431. }
  432. if ($bbcode) {
  433. return '[sup]' . $nr . '[/sup]';
  434. }
  435. // footnotemarker used in js/tooltip.js
  436. return '<sup class="footnotemarker" id="footnote_sup_' . $nr . '_' . $instance . '">' . $nr . '</sup>';
  437. }
  438. /**
  439. * Displays a MySQL error message in the right frame.
  440. *
  441. * @uses footer.inc.php
  442. * @uses header.inc.php
  443. * @uses $GLOBALS['sql_query']
  444. * @uses $GLOBALS['strError']
  445. * @uses $GLOBALS['strSQLQuery']
  446. * @uses $GLOBALS['pmaThemeImage']
  447. * @uses $GLOBALS['strEdit']
  448. * @uses $GLOBALS['strMySQLSaid']
  449. * @uses $GLOBALS['cfg']['PropertiesIconic']
  450. * @uses $GLOBALS['cfg']['MaxCharactersInDisplayedSQL']
  451. * @uses PMA_backquote()
  452. * @uses PMA_DBI_getError()
  453. * @uses PMA_formatSql()
  454. * @uses PMA_generate_common_hidden_inputs()
  455. * @uses PMA_generate_common_url()
  456. * @uses PMA_showMySQLDocu()
  457. * @uses PMA_sqlAddslashes()
  458. * @uses PMA_SQP_isError()
  459. * @uses PMA_SQP_parse()
  460. * @uses PMA_SQP_getErrorString()
  461. * @uses strtolower()
  462. * @uses urlencode()
  463. * @uses str_replace()
  464. * @uses nl2br()
  465. * @uses substr()
  466. * @uses preg_replace()
  467. * @uses preg_match()
  468. * @uses explode()
  469. * @uses implode()
  470. * @uses is_array()
  471. * @uses function_exists()
  472. * @uses htmlspecialchars()
  473. * @uses trim()
  474. * @uses strstr()
  475. * @param string the error message
  476. * @param string the sql query that failed
  477. * @param boolean whether to show a "modify" link or not
  478. * @param string the "back" link url (full path is not required)
  479. * @param boolean EXIT the page?
  480. *
  481. * @global string the curent table
  482. * @global string the current db
  483. *
  484. * @access public
  485. */
  486. function PMA_mysqlDie($error_message = '', $the_query = '',
  487. $is_modify_link = true, $back_url = '', $exit = true)
  488. {
  489. global $table, $db;
  490. /**
  491. * start http output, display html headers
  492. */
  493. require_once './libraries/header.inc.php';
  494. if (!$error_message) {
  495. $error_message = PMA_DBI_getError();
  496. }
  497. if (!$the_query && !empty($GLOBALS['sql_query'])) {
  498. $the_query = $GLOBALS['sql_query'];
  499. }
  500. // --- Added to solve bug #641765
  501. // Robbat2 - 12 January 2003, 9:46PM
  502. // Revised, Robbat2 - 13 January 2003, 2:59PM
  503. if (!function_exists('PMA_SQP_isError') || PMA_SQP_isError()) {
  504. $formatted_sql = htmlspecialchars($the_query);
  505. } elseif (empty($the_query) || trim($the_query) == '') {
  506. $formatted_sql = '';
  507. } else {
  508. if (strlen($the_query) > $GLOBALS['cfg']['MaxCharactersInDisplayedSQL']) {
  509. $formatted_sql = substr($the_query, 0, $GLOBALS['cfg']['MaxCharactersInDisplayedSQL']) . '[...]';
  510. } else {
  511. $formatted_sql = PMA_formatSql(PMA_SQP_parse($the_query), $the_query);
  512. }
  513. }
  514. // ---
  515. echo "\n" . '<!-- PMA-SQL-ERROR -->' . "\n";
  516. echo ' <div class="error"><h1>' . $GLOBALS['strError'] . '</h1>' . "\n";
  517. // if the config password is wrong, or the MySQL server does not
  518. // respond, do not show the query that would reveal the
  519. // username/password
  520. if (!empty($the_query) && !strstr($the_query, 'connect')) {
  521. // --- Added to solve bug #641765
  522. // Robbat2 - 12 January 2003, 9:46PM
  523. // Revised, Robbat2 - 13 January 2003, 2:59PM
  524. if (function_exists('PMA_SQP_isError') && PMA_SQP_isError()) {
  525. echo PMA_SQP_getErrorString() . "\n";
  526. echo '<br />' . "\n";
  527. }
  528. // ---
  529. // modified to show me the help on sql errors (Michael Keck)
  530. echo ' <p><strong>' . $GLOBALS['strSQLQuery'] . ':</strong>' . "\n";
  531. if (strstr(strtolower($formatted_sql), 'select')) { // please show me help to the error on select
  532. echo PMA_showMySQLDocu('SQL-Syntax', 'SELECT');
  533. }
  534. if ($is_modify_link) {
  535. $_url_params = array(
  536. 'sql_query' => $the_query,
  537. 'show_query' => 1,
  538. );
  539. if (strlen($table)) {
  540. $_url_params['db'] = $db;
  541. $_url_params['table'] = $table;
  542. $doedit_goto = '<a href="tbl_sql.php?' . PMA_generate_common_url($_url_params) . '">';
  543. } elseif (strlen($db)) {
  544. $_url_params['db'] = $db;
  545. $doedit_goto = '<a href="db_sql.php?' . PMA_generate_common_url($_url_params) . '">';
  546. } else {
  547. $doedit_goto = '<a href="server_sql.php?' . PMA_generate_common_url($_url_params) . '">';
  548. }
  549. echo $doedit_goto
  550. . PMA_getIcon('b_edit.png', $GLOBALS['strEdit'])
  551. . '</a>';
  552. } // end if
  553. echo ' </p>' . "\n"
  554. .' <p>' . "\n"
  555. .' ' . $formatted_sql . "\n"
  556. .' </p>' . "\n";
  557. } // end if
  558. $tmp_mysql_error = ''; // for saving the original $error_message
  559. if (!empty($error_message)) {
  560. $tmp_mysql_error = strtolower($error_message); // save the original $error_message
  561. $error_message = htmlspecialchars($error_message);
  562. $error_message = preg_replace("@((\015\012)|(\015)|(\012)){3,}@", "\n\n", $error_message);
  563. }
  564. // modified to show me the help on error-returns (Michael Keck)
  565. // (now error-messages-server)
  566. echo '<p>' . "\n"
  567. . ' <strong>' . $GLOBALS['strMySQLSaid'] . '</strong>'
  568. . PMA_showMySQLDocu('Error-messages-server', 'Error-messages-server')
  569. . "\n"
  570. . '</p>' . "\n";
  571. // The error message will be displayed within a CODE segment.
  572. // To preserve original formatting, but allow wordwrapping, we do a couple of replacements
  573. // Replace all non-single blanks with their HTML-counterpart
  574. $error_message = str_replace(' ', '&nbsp;&nbsp;', $error_message);
  575. // Replace TAB-characters with their HTML-counterpart
  576. $error_message = str_replace("\t", '&nbsp;&nbsp;&nbsp;&nbsp;', $error_message);
  577. // Replace linebreaks
  578. $error_message = nl2br($error_message);
  579. echo '<code>' . "\n"
  580. . $error_message . "\n"
  581. . '</code><br />' . "\n";
  582. echo '</div>';
  583. if ($exit) {
  584. if (! empty($back_url)) {
  585. if (strstr($back_url, '?')) {
  586. $back_url .= '&amp;no_history=true';
  587. } else {
  588. $back_url .= '?no_history=true';
  589. }
  590. echo '<fieldset class="tblFooters">';
  591. echo '[ <a href="' . $back_url . '">' . $GLOBALS['strBack'] . '</a> ]';
  592. echo '</fieldset>' . "\n\n";
  593. }
  594. /**
  595. * display footer and exit
  596. */
  597. require_once './libraries/footer.inc.php';
  598. }
  599. } // end of the 'PMA_mysqlDie()' function
  600. /**
  601. * Send HTTP header, taking IIS limits into account (600 seems ok)
  602. *
  603. * @uses PMA_IS_IIS
  604. * @uses PMA_COMING_FROM_COOKIE_LOGIN
  605. * @uses PMA_get_arg_separator()
  606. * @uses SID
  607. * @uses strlen()
  608. * @uses strpos()
  609. * @uses header()
  610. * @uses session_write_close()
  611. * @uses headers_sent()
  612. * @uses function_exists()
  613. * @uses debug_print_backtrace()
  614. * @uses trigger_error()
  615. * @uses defined()
  616. * @param string $uri the header to send
  617. * @return boolean always true
  618. */
  619. function PMA_sendHeaderLocation($uri)
  620. {
  621. if (PMA_IS_IIS && strlen($uri) > 600) {
  622. echo '<html><head><title>- - -</title>' . "\n";
  623. echo '<meta http-equiv="expires" content="0">' . "\n";
  624. echo '<meta http-equiv="Pragma" content="no-cache">' . "\n";
  625. echo '<meta http-equiv="Cache-Control" content="no-cache">' . "\n";
  626. echo '<meta http-equiv="Refresh" content="0;url=' .$uri . '">' . "\n";
  627. echo '<script type="text/javascript">' . "\n";
  628. echo '//<![CDATA[' . "\n";
  629. echo 'setTimeout("window.location = unescape(\'"' . $uri . '"\')", 2000);' . "\n";
  630. echo '//]]>' . "\n";
  631. echo '</script>' . "\n";
  632. echo '</head>' . "\n";
  633. echo '<body>' . "\n";
  634. echo '<script type="text/javascript">' . "\n";
  635. echo '//<![CDATA[' . "\n";
  636. echo 'document.write(\'<p><a href="' . $uri . '">' . $GLOBALS['strGo'] . '</a></p>\');' . "\n";
  637. echo '//]]>' . "\n";
  638. echo '</script></body></html>' . "\n";
  639. } else {
  640. if (SID) {
  641. if (strpos($uri, '?') === false) {
  642. header('Location: ' . $uri . '?' . SID);
  643. } else {
  644. $separator = PMA_get_arg_separator();
  645. header('Location: ' . $uri . $separator . SID);
  646. }
  647. } else {
  648. session_write_close();
  649. if (headers_sent()) {
  650. if (function_exists('debug_print_backtrace')) {
  651. echo '<pre>';
  652. debug_print_backtrace();
  653. echo '</pre>';
  654. }
  655. trigger_error('PMA_sendHeaderLocation called when headers are already sent!', E_USER_ERROR);
  656. }
  657. // bug #1523784: IE6 does not like 'Refresh: 0', it
  658. // results in a blank page
  659. // but we need it when coming from the cookie login panel)
  660. if (PMA_IS_IIS && defined('PMA_COMING_FROM_COOKIE_LOGIN')) {
  661. header('Refresh: 0; ' . $uri);
  662. } else {
  663. header('Location: ' . $uri);
  664. }
  665. }
  666. }
  667. }
  668. /**
  669. * returns array with tables of given db with extended information and grouped
  670. *
  671. * @uses $cfg['LeftFrameTableSeparator']
  672. * @uses $cfg['LeftFrameTableLevel']
  673. * @uses $cfg['ShowTooltipAliasTB']
  674. * @uses $cfg['NaturalOrder']
  675. * @uses PMA_backquote()
  676. * @uses count()
  677. * @uses array_merge
  678. * @uses uksort()
  679. * @uses strstr()
  680. * @uses explode()
  681. * @param string $db name of db
  682. * @param string $tables name of tables
  683. * @param integer $limit_offset list offset
  684. * @param integer $limit_count max tables to return
  685. * return array (recursive) grouped table list
  686. */
  687. function PMA_getTableList($db, $tables = null, $limit_offset = 0, $limit_count = false)
  688. {
  689. $sep = $GLOBALS['cfg']['LeftFrameTableSeparator'];
  690. if (null === $tables) {
  691. $tables = PMA_DBI_get_tables_full($db, false, false, null, $limit_offset, $limit_count);
  692. if ($GLOBALS['cfg']['NaturalOrder']) {
  693. uksort($tables, 'strnatcasecmp');
  694. }
  695. }
  696. if (count($tables) < 1) {
  697. return $tables;
  698. }
  699. $default = array(
  700. 'Name' => '',
  701. 'Rows' => 0,
  702. 'Comment' => '',
  703. 'disp_name' => '',
  704. );
  705. $table_groups = array();
  706. // for blobstreaming - list of blobstreaming tables - rajk
  707. // load PMA configuration
  708. $PMA_Config = $_SESSION['PMA_Config'];
  709. // if PMA configuration exists
  710. if (!empty($PMA_Config))
  711. $session_bs_tables = $_SESSION['PMA_Config']->get('BLOBSTREAMING_TABLES');
  712. foreach ($tables as $table_name => $table) {
  713. // if BS tables exist
  714. if (isset($session_bs_tables))
  715. // compare table name to tables in list of blobstreaming tables
  716. foreach ($session_bs_tables as $table_key=>$table_val)
  717. // if table is in list, skip outer foreach loop
  718. if ($table_name == $table_key)
  719. continue 2;
  720. // check for correct row count
  721. if (null === $table['Rows']) {
  722. // Do not check exact row count here,
  723. // if row count is invalid possibly the table is defect
  724. // and this would break left frame;
  725. // but we can check row count if this is a view or the
  726. // information_schema database
  727. // since PMA_Table::countRecords() returns a limited row count
  728. // in this case.
  729. // set this because PMA_Table::countRecords() can use it
  730. $tbl_is_view = PMA_Table::isView($db, $table['Name']);
  731. if ($tbl_is_view || 'information_schema' == $db) {
  732. $table['Rows'] = PMA_Table::countRecords($db, $table['Name'],
  733. $return = true);
  734. }
  735. }
  736. // in $group we save the reference to the place in $table_groups
  737. // where to store the table info
  738. if ($GLOBALS['cfg']['LeftFrameDBTree']
  739. && $sep && strstr($table_name, $sep))
  740. {
  741. $parts = explode($sep, $table_name);
  742. $group =& $table_groups;
  743. $i = 0;
  744. $group_name_full = '';
  745. $parts_cnt = count($parts) - 1;
  746. while ($i < $parts_cnt
  747. && $i < $GLOBALS['cfg']['LeftFrameTableLevel']) {
  748. $group_name = $parts[$i] . $sep;
  749. $group_name_full .= $group_name;
  750. if (!isset($group[$group_name])) {
  751. $group[$group_name] = array();
  752. $group[$group_name]['is' . $sep . 'group'] = true;
  753. $group[$group_name]['tab' . $sep . 'count'] = 1;
  754. $group[$group_name]['tab' . $sep . 'group'] = $group_name_full;
  755. } elseif (!isset($group[$group_name]['is' . $sep . 'group'])) {
  756. $table = $group[$group_name];
  757. $group[$group_name] = array();
  758. $group[$group_name][$group_name] = $table;
  759. unset($table);
  760. $group[$group_name]['is' . $sep . 'group'] = true;
  761. $group[$group_name]['tab' . $sep . 'count'] = 1;
  762. $group[$group_name]['tab' . $sep . 'group'] = $group_name_full;
  763. } else {
  764. $group[$group_name]['tab' . $sep . 'count']++;
  765. }
  766. $group =& $group[$group_name];
  767. $i++;
  768. }
  769. } else {
  770. if (!isset($table_groups[$table_name])) {
  771. $table_groups[$table_name] = array();
  772. }
  773. $group =& $table_groups;
  774. }
  775. if ($GLOBALS['cfg']['ShowTooltipAliasTB']
  776. && $GLOBALS['cfg']['ShowTooltipAliasTB'] !== 'nested') {
  777. // switch tooltip and name
  778. $table['Comment'] = $table['Name'];
  779. $table['disp_name'] = $table['Comment'];
  780. } else {
  781. $table['disp_name'] = $table['Name'];
  782. }
  783. $group[$table_name] = array_merge($default, $table);
  784. }
  785. return $table_groups;
  786. }
  787. /* ----------------------- Set of misc functions ----------------------- */
  788. /**
  789. * Adds backquotes on both sides of a database, table or field name.
  790. * and escapes backquotes inside the name with another backquote
  791. *
  792. * example:
  793. * <code>
  794. * echo PMA_backquote('owner`s db'); // `owner``s db`
  795. *
  796. * </code>
  797. *
  798. * @uses PMA_backquote()
  799. * @uses is_array()
  800. * @uses strlen()
  801. * @uses str_replace()
  802. * @param mixed $a_name the database, table or field name to "backquote"
  803. * or array of it
  804. * @param boolean $do_it a flag to bypass this function (used by dump
  805. * functions)
  806. * @return mixed the "backquoted" database, table or field name if the
  807. * current MySQL release is >= 3.23.6, the original one
  808. * else
  809. * @access public
  810. */
  811. function PMA_backquote($a_name, $do_it = true)
  812. {
  813. if (! $do_it) {
  814. return $a_name;
  815. }
  816. if (is_array($a_name)) {
  817. $result = array();
  818. foreach ($a_name as $key => $val) {
  819. $result[$key] = PMA_backquote($val);
  820. }
  821. return $result;
  822. }
  823. // '0' is also empty for php :-(
  824. if (strlen($a_name) && $a_name !== '*') {
  825. return '`' . str_replace('`', '``', $a_name) . '`';
  826. } else {
  827. return $a_name;
  828. }
  829. } // end of the 'PMA_backquote()' function
  830. /**
  831. * Defines the <CR><LF> value depending on the user OS.
  832. *
  833. * @uses PMA_USR_OS
  834. * @return string the <CR><LF> value to use
  835. *
  836. * @access public
  837. */
  838. function PMA_whichCrlf()
  839. {
  840. $the_crlf = "\n";
  841. // The 'PMA_USR_OS' constant is defined in "./libraries/Config.class.php"
  842. // Win case
  843. if (PMA_USR_OS == 'Win') {
  844. $the_crlf = "\r\n";
  845. }
  846. // Others
  847. else {
  848. $the_crlf = "\n";
  849. }
  850. return $the_crlf;
  851. } // end of the 'PMA_whichCrlf()' function
  852. /**
  853. * Reloads navigation if needed.
  854. *
  855. * @uses $GLOBALS['reload']
  856. * @uses $GLOBALS['db']
  857. * @uses PMA_generate_common_url()
  858. * @global array configuration
  859. *
  860. * @access public
  861. */
  862. function PMA_reloadNavigation()
  863. {
  864. global $cfg;
  865. // Reloads the navigation frame via JavaScript if required
  866. if (isset($GLOBALS['reload']) && $GLOBALS['reload']) {
  867. // one of the reasons for a reload is when a table is dropped
  868. // in this case, get rid of the table limit offset, otherwise
  869. // we have a problem when dropping a table on the last page
  870. // and the offset becomes greater than the total number of tables
  871. unset($_SESSION['userconf']['table_limit_offset']);
  872. echo "\n";
  873. $reload_url = './navigation.php?' . PMA_generate_common_url($GLOBALS['db'], '', '&');
  874. ?>
  875. <script type="text/javascript">
  876. //<![CDATA[
  877. if (typeof(window.parent) != 'undefined'
  878. && typeof(window.parent.frame_navigation) != 'undefined'
  879. && window.parent.goTo) {
  880. window.parent.goTo('<?php echo $reload_url; ?>');
  881. }
  882. //]]>
  883. </script>
  884. <?php
  885. unset($GLOBALS['reload']);
  886. }
  887. }
  888. /**
  889. * displays the message and the query
  890. * usually the message is the result of the query executed
  891. *
  892. * @param string $message the message to display
  893. * @param string $sql_query the query to display
  894. * @param string $type the type (level) of the message
  895. * @global array the configuration array
  896. * @uses $cfg
  897. * @access public
  898. */
  899. function PMA_showMessage($message, $sql_query = null, $type = 'notice')
  900. {
  901. global $cfg;
  902. if (null === $sql_query) {
  903. if (! empty($GLOBALS['display_query'])) {
  904. $sql_query = $GLOBALS['display_query'];
  905. } elseif ($cfg['SQP']['fmtType'] == 'none' && ! empty($GLOBALS['unparsed_sql'])) {
  906. $sql_query = $GLOBALS['unparsed_sql'];
  907. } elseif (! empty($GLOBALS['sql_query'])) {
  908. $sql_query = $GLOBALS['sql_query'];
  909. } else {
  910. $sql_query = '';
  911. }
  912. }
  913. // Corrects the tooltip text via JS if required
  914. // @todo this is REALLY the wrong place to do this - very unexpected here
  915. if (strlen($GLOBALS['table']) && $cfg['ShowTooltip']) {
  916. $tooltip = PMA_Table::sGetToolTip($GLOBALS['db'], $GLOBALS['table']);
  917. $uni_tbl = PMA_jsFormat($GLOBALS['db'] . '.' . $GLOBALS['table'], false);
  918. echo "\n";
  919. echo '<script type="text/javascript">' . "\n";
  920. echo '//<![CDATA[' . "\n";
  921. echo "if (window.parent.updateTableTitle) window.parent.updateTableTitle('" . $uni_tbl . "', '" . PMA_jsFormat($tooltip, false) . "');" . "\n";
  922. echo '//]]>' . "\n";
  923. echo '</script>' . "\n";
  924. } // end if ... elseif
  925. // Checks if the table needs to be repaired after a TRUNCATE query.
  926. // @todo what about $GLOBALS['display_query']???
  927. // @todo this is REALLY the wrong place to do this - very unexpected here
  928. if (strlen($GLOBALS['table'])
  929. && $GLOBALS['sql_query'] == 'TRUNCATE TABLE ' . PMA_backquote($GLOBALS['table'])) {
  930. if (PMA_Table::sGetStatusInfo($GLOBALS['db'], $GLOBALS['table'], 'Index_length') > 1024) {
  931. PMA_DBI_try_query('REPAIR TABLE ' . PMA_backquote($GLOBALS['table']));
  932. }
  933. }
  934. unset($tbl_status);
  935. echo '<div align="' . $GLOBALS['cell_align_left'] . '">' . "\n";
  936. if ($message instanceof PMA_Message) {
  937. if (isset($GLOBALS['special_message'])) {
  938. $message->addMessage($GLOBALS['special_message']);
  939. unset($GLOBALS['special_message']);
  940. }
  941. $message->display();
  942. $type = $message->getLevel();
  943. } else {
  944. echo '<div class="' . $type . '">';
  945. echo PMA_sanitize($message);
  946. if (isset($GLOBALS['special_message'])) {
  947. echo PMA_sanitize($GLOBALS['special_message']);
  948. unset($GLOBALS['special_message']);
  949. }
  950. echo '</div>';
  951. }
  952. if ($cfg['ShowSQL'] == true && ! empty($sql_query)) {
  953. // Html format the query to be displayed
  954. // If we want to show some sql code it is easiest to create it here
  955. /* SQL-Parser-Analyzer */
  956. if (! empty($GLOBALS['show_as_php'])) {
  957. $new_line = '\\n"<br />' . "\n"
  958. . '&nbsp;&nbsp;&nbsp;&nbsp;. "';
  959. $query_base = htmlspecialchars(addslashes($sql_query));
  960. $query_base = preg_replace('/((\015\012)|(\015)|(\012))/', $new_line, $query_base);
  961. } else {
  962. $query_base = $sql_query;
  963. }
  964. $query_too_big = false;
  965. if (strlen($query_base) > $cfg['MaxCharactersInDisplayedSQL']) {
  966. // when the query is large (for example an INSERT of binary
  967. // data), the parser chokes; so avoid parsing the query
  968. $query_too_big = true;
  969. $shortened_query_base = nl2br(htmlspecialchars(substr($sql_query, 0, $cfg['MaxCharactersInDisplayedSQL']) . '[...]'));
  970. } elseif (! empty($GLOBALS['parsed_sql'])
  971. && $query_base == $GLOBALS['parsed_sql']['raw']) {
  972. // (here, use "! empty" because when deleting a bookmark,
  973. // $GLOBALS['parsed_sql'] is set but empty
  974. $parsed_sql = $GLOBALS['parsed_sql'];
  975. } else {
  976. // Parse SQL if needed
  977. $parsed_sql = PMA_SQP_parse($query_base);
  978. }
  979. // Analyze it
  980. if (isset($parsed_sql)) {
  981. $analyzed_display_query = PMA_SQP_analyze($parsed_sql);
  982. // Here we append the LIMIT added for navigation, to
  983. // enable its display. Adding it higher in the code
  984. // to $sql_query would create a problem when
  985. // using the Refresh or Edit links.
  986. // Only append it on SELECTs.
  987. /**
  988. * @todo what would be the best to do when someone hits Refresh:
  989. * use the current LIMITs ?
  990. */
  991. if (isset($analyzed_display_query[0]['queryflags']['select_from'])
  992. && isset($GLOBALS['sql_limit_to_append'])) {
  993. $query_base = $analyzed_display_query[0]['section_before_limit']
  994. . "\n" . $GLOBALS['sql_limit_to_append']
  995. . $analyzed_display_query[0]['section_after_limit'];
  996. // Need to reparse query
  997. $parsed_sql = PMA_SQP_parse($query_base);
  998. }
  999. }
  1000. if (! empty($GLOBALS['show_as_php'])) {
  1001. $query_base = '$sql = "' . $query_base;
  1002. } elseif (! empty($GLOBALS['validatequery'])) {
  1003. $query_base = PMA_validateSQL($query_base);
  1004. } elseif (isset($parsed_sql)) {
  1005. $query_base = PMA_formatSql($parsed_sql, $query_base);
  1006. }
  1007. // Prepares links that may be displayed to edit/explain the query
  1008. // (don't go to default pages, we must go to the page
  1009. // where the query box is available)
  1010. // Basic url query part
  1011. $url_params = array();
  1012. if (strlen($GLOBALS['db'])) {
  1013. $url_params['db'] = $GLOBALS['db'];
  1014. if (strlen($GLOBALS['table'])) {
  1015. $url_params['table'] = $GLOBALS['table'];
  1016. $edit_link = 'tbl_sql.php';
  1017. } else {
  1018. $edit_link = 'db_sql.php';
  1019. }
  1020. } else {
  1021. $edit_link = 'server_sql.php';
  1022. }
  1023. // Want to have the query explained (Mike Beck 2002-05-22)
  1024. // but only explain a SELECT (that has not been explained)
  1025. /* SQL-Parser-Analyzer */
  1026. $explain_link = '';
  1027. if (! empty($cfg['SQLQuery']['Explain']) && ! $query_too_big) {
  1028. $explain_params = $url_params;
  1029. // Detect if we are validating as well
  1030. // To preserve the validate uRL data
  1031. if (! empty($GLOBALS['validatequery'])) {
  1032. $explain_params['validatequery'] = 1;
  1033. }
  1034. if (preg_match('@^SELECT[[:space:]]+@i', $sql_query)) {
  1035. $explain_params['sql_query'] = 'EXPLAIN ' . $sql_query;
  1036. $_message = $GLOBALS['strExplain'];
  1037. } elseif (preg_match('@^EXPLAIN[[:space:]]+SELECT[[:space:]]+@i', $sql_query)) {
  1038. $explain_params['sql_query'] = substr($sql_query, 8);
  1039. $_message = $GLOBALS['strNoExplain'];
  1040. }
  1041. if (isset($explain_params['sql_query'])) {
  1042. $explain_link = 'import.php' . PMA_generate_common_url($explain_params);
  1043. $explain_link = ' [' . PMA_linkOrButton($explain_link, $_message) . ']';
  1044. }
  1045. } //show explain
  1046. $url_params['sql_query'] = $sql_query;
  1047. $url_params['show_query'] = 1;
  1048. if (! empty($cfg['SQLQuery']['Edit']) && ! $query_too_big) {
  1049. if ($cfg['EditInWindow'] == true) {
  1050. $onclick = 'window.parent.focus_querywindow(\'' . PMA_jsFormat($sql_query, false) . '\'); return false;';
  1051. } else {
  1052. $onclick = '';
  1053. }
  1054. $edit_link .= PMA_generate_common_url($url_params) . '#querybox';
  1055. $edit_link = ' [' . PMA_linkOrButton($edit_link, $GLOBALS['strEdit'], array('onclick' => $onclick)) . ']';
  1056. } else {
  1057. $edit_link = '';
  1058. }
  1059. $url_qpart = PMA_generate_common_url($url_params);
  1060. // Also we would like to get the SQL formed in some nice
  1061. // php-code (Mike Beck 2002-05-22)
  1062. if (! empty($cfg['SQLQuery']['ShowAsPHP']) && ! $query_too_big) {
  1063. $php_params = $url_params;
  1064. if (! empty($GLOBALS['show_as_php'])) {
  1065. $_message = $GLOBALS['strNoPhp'];
  1066. } else {
  1067. $php_params['show_as_php'] = 1;
  1068. $_message = $GLOBALS['strPhp'];
  1069. }
  1070. $php_link = 'import.php' . PMA_generate_common_url($php_params);
  1071. $php_link = ' [' . PMA_linkOrButton($php_link, $_message) . ']';
  1072. if (isset($GLOBALS['show_as_php'])) {
  1073. $runquery_link = 'import.php' . PMA_generate_common_url($url_params);
  1074. $php_link .= ' [' . PMA_linkOrButton($runquery_link, $GLOBALS['strRunQuery']) . ']';
  1075. }
  1076. } else {
  1077. $php_link = '';
  1078. } //show as php
  1079. // Refresh query
  1080. if (! empty($cfg['SQLQuery']['Refresh'])
  1081. && preg_match('@^(SELECT|SHOW)[[:space:]]+@i', $sql_query)) {
  1082. $refresh_link = 'import.php' . PMA_generate_common_url($url_params);
  1083. $refresh_link = ' [' . PMA_linkOrButton($refresh_link, $GLOBALS['strRefresh']) . ']';
  1084. } else {
  1085. $refresh_link = '';
  1086. } //show as php
  1087. if (! empty($cfg['SQLValidator']['use'])
  1088. && ! empty($cfg['SQLQuery']['Validate'])) {
  1089. $validate_params = $url_params;
  1090. if (!empty($GLOBALS['validatequery'])) {
  1091. $validate_message = $GLOBALS['strNoValidateSQL'] ;
  1092. } else {
  1093. $validate_params['validatequery'] = 1;
  1094. $validate_message = $GLOBALS['strValidateSQL'] ;
  1095. }
  1096. $validate_link = 'import.php' . PMA_generate_common_url($validate_params);
  1097. $validate_link = ' [' . PMA_linkOrButton($validate_link, $validate_message) . ']';
  1098. } else {
  1099. $validate_link = '';
  1100. } //validator
  1101. echo '<code class="sql">';
  1102. if ($query_too_big) {
  1103. echo $shortened_query_base;
  1104. } else {
  1105. echo $query_base;
  1106. }
  1107. //Clean up the end of the PHP
  1108. if (! empty($GLOBALS['show_as_php'])) {
  1109. echo '";';
  1110. }
  1111. echo '</code>';
  1112. echo '<div class="tools">';
  1113. // avoid displaying a Profiling checkbox that could
  1114. // be checked, which would reexecute an INSERT, for example
  1115. if (! empty($refresh_link)) {
  1116. PMA_profilingCheckbox($sql_query);
  1117. }
  1118. echo $edit_link . $explain_link . $php_link . $refresh_link . $validate_link;
  1119. echo '</div>';
  1120. }
  1121. echo '</div><br />' . "\n";
  1122. } // end of the 'PMA_showMessage()' function
  1123. /**
  1124. * Verifies if current MySQL server supports profiling
  1125. *
  1126. * @uses $_SESSION['profiling_supported'] for caching
  1127. * @uses $GLOBALS['server']
  1128. * @uses PMA_DBI_fetch_value()
  1129. * @uses PMA_MYSQL_INT_VERSION
  1130. * @uses defined()
  1131. * @access public
  1132. * @return boolean whether profiling is supported
  1133. *
  1134. * @author Marc Delisle
  1135. */
  1136. function PMA_profilingSupported()
  1137. {
  1138. if (! PMA_cacheExists('profiling_supported', true)) {
  1139. // 5.0.37 has profiling but for example, 5.1.20 does not
  1140. // (avoid a trip to the server for MySQL before 5.0.37)
  1141. // and do not set a constant as we might be switching servers
  1142. if (defined('PMA_MYSQL_INT_VERSION')
  1143. && PMA_MYSQL_INT_VERSION >= 50037
  1144. && PMA_DBI_fetch_value("SHOW VARIABLES LIKE 'profiling'")) {
  1145. PMA_cacheSet('profiling_supported', true, true);
  1146. } else {
  1147. PMA_cacheSet('profiling_supported', false, true);
  1148. }
  1149. }
  1150. return PMA_cacheGet('profiling_supported', true);
  1151. }
  1152. /**
  1153. * Displays a form with the Profiling checkbox
  1154. *
  1155. * @param string $sql_query
  1156. * @access public
  1157. *
  1158. * @author Marc Delisle
  1159. */
  1160. function PMA_profilingCheckbox($sql_query)
  1161. {
  1162. if (PMA_profilingSupported()) {
  1163. echo '<form action="sql.php" method="post">' . "\n";
  1164. echo PMA_generate_common_hidden_inputs($GLOBALS['db'], $GLOBALS['table']);
  1165. echo '<input type="hidden" name="sql_query" value="' . htmlspecialchars($sql_query) . '" />' . "\n";
  1166. echo '<input type="hidden" name="profiling_form" value="1" />' . "\n";
  1167. PMA_generate_html_checkbox('profiling', $GLOBALS['strProfiling'], isset($_SESSION['profiling']), true);
  1168. echo '<noscript><input type="submit" value="' . $GLOBALS['strGo'] . '" /></noscript>' . "\n";
  1169. echo '</form>' . "\n";
  1170. }
  1171. }
  1172. /**
  1173. * Displays the results of SHOW PROFILE
  1174. *
  1175. * @param array the results
  1176. * @access public
  1177. *
  1178. * @author Marc Delisle
  1179. */
  1180. function PMA_profilingResults($profiling_results)
  1181. {
  1182. echo '<fieldset><legend>' . $GLOBALS['strProfiling'] . '</legend>' . "\n";
  1183. echo '<table>' . "\n";
  1184. echo ' <tr>' . "\n";
  1185. echo ' <th>' . $GLOBALS['strStatus'] . '</th>' . "\n";
  1186. echo ' <th>' . $GLOBALS['strTime'] . '</th>' . "\n";
  1187. echo ' </tr>' . "\n";
  1188. foreach($profiling_results as $one_result) {
  1189. echo ' <tr>' . "\n";
  1190. echo '<td>' . $one_result['Status'] . '</td>' . "\n";
  1191. echo '<td>' . $one_result['Duration'] . '</td>' . "\n";
  1192. }
  1193. echo '</table>' . "\n";
  1194. echo '</fieldset>' . "\n";
  1195. }
  1196. /**
  1197. * Formats $value to byte view
  1198. *
  1199. * @param double the value to format
  1200. * @param integer the sensitiveness
  1201. * @param integer the number of decimals to retain
  1202. *
  1203. * @return array the formatted value and its unit
  1204. *
  1205. * @access public
  1206. *
  1207. * @author staybyte
  1208. * @version 1.2 - 18 July 2002
  1209. */
  1210. function PMA_formatByteDown($value, $limes = 6, $comma = 0)
  1211. {
  1212. $dh = PMA_pow(10, $comma);
  1213. $li = PMA_pow(10, $limes);
  1214. $return_value = $value;
  1215. $unit = $GLOBALS['byteUnits'][0];
  1216. for ($d = 6, $ex = 15; $d >= 1; $d--, $ex-=3) {
  1217. if (isset($GLOBALS['byteUnits'][$d]) && $value >= $li * PMA_pow(10, $ex)) {
  1218. // use 1024.0 to avoid integer overflow on 64-bit machines
  1219. $value = round($value / (PMA_pow(1024, $d) / $dh)) /$dh;
  1220. $unit = $GLOBALS['byteUnits'][$d];
  1221. break 1;
  1222. } // end if
  1223. } // end for
  1224. if ($unit != $GLOBALS['byteUnits'][0]) {
  1225. // if the unit is not bytes (as represented in current language)
  1226. // reformat with max length of 5
  1227. // 4th parameter=true means do not reformat if value < 1
  1228. $return_value = PMA_formatNumber($value, 5, $comma, true);
  1229. } else {
  1230. // do not reformat, just handle the locale
  1231. $return_value = PMA_formatNumber($value, 0);
  1232. }
  1233. return array($return_value, $unit);
  1234. } // end of the 'PMA_formatByteDown' function
  1235. /**
  1236. * Formats $value to the given length and appends SI prefixes
  1237. * $comma is not substracted from the length
  1238. * with a $length of 0 no truncation occurs, number is only formated
  1239. * to the current locale
  1240. *
  1241. * examples:
  1242. * <code>
  1243. * echo PMA_formatNumber(123456789, 6); // 123,457 k
  1244. * echo PMA_formatNumber(-123456789, 4, 2); // -123.46 M
  1245. * echo PMA_formatNumber(-0.003, 6); // -3 m
  1246. * echo PMA_formatNumber(0.003, 3, 3); // 0.003
  1247. * echo PMA_formatNumber(0.00003, 3, 2); // 0.03 m
  1248. * echo PMA_formatNumber(0, 6); // 0
  1249. *
  1250. * </code>
  1251. * @param double $value the value to format
  1252. * @param integer $length the max length
  1253. * @param integer $comma the number of decimals to retain
  1254. * @param boolean $only_down do not reformat numbers below 1
  1255. *
  1256. * @return string the formatted value and its unit
  1257. *
  1258. * @access public
  1259. *
  1260. * @author staybyte, sebastian mendel
  1261. * @version 1.1.0 - 2005-10-27
  1262. */
  1263. function PMA_formatNumber($value, $length = 3, $comma = 0, $only_down = false)
  1264. {
  1265. //number_format is not multibyte safe, str_replace is safe
  1266. if ($length === 0) {
  1267. return str_replace(array(',', '.'),
  1268. array($GLOBALS['number_thousands_separator'], $GLOBALS['number_decimal_separator']),
  1269. number_format($value, $comma));
  1270. }
  1271. // this units needs no translation, ISO
  1272. $units = array(
  1273. -8 => 'y',
  1274. -7 => 'z',
  1275. -6 => 'a',
  1276. -5 => 'f',
  1277. -4 => 'p',
  1278. -3 => 'n',
  1279. -2 => '&micro;',
  1280. -1 => 'm',
  1281. 0 => ' ',
  1282. 1 => 'k',
  1283. 2 => 'M',
  1284. 3 => 'G',
  1285. 4 => 'T',
  1286. 5 => 'P',
  1287. 6 => 'E',
  1288. 7 => 'Z',
  1289. 8 => 'Y'
  1290. );
  1291. // we need at least 3 digits to be displayed
  1292. if (3 > $length + $comma) {
  1293. $length = 3 - $comma;
  1294. }
  1295. // check for negative value to retain sign
  1296. if ($value < 0) {
  1297. $sign = '-';
  1298. $value = abs($value);
  1299. } else {
  1300. $sign = '';
  1301. }
  1302. $dh = PMA_pow(10, $comma);
  1303. $li = PMA_pow(10, $length);
  1304. $unit = $units[0];
  1305. if ($value >= 1) {
  1306. for ($d = 8; $d >= 0; $d--) {
  1307. if (isset($units[$d]) && $value >= $li * PMA_pow(1000, $d-1)) {
  1308. $value = round($value / (PMA_pow(1000, $d) / $dh)) /$dh;
  1309. $unit = $units[$d];
  1310. break 1;
  1311. } // end if
  1312. } // end for
  1313. } elseif (!$only_down && (float) $value !== 0.0) {
  1314. for ($d = -8; $d <= 8; $d++) {
  1315. if (isset($units[$d]) && $value <= $li * PMA_pow(1000, $d-1)) {
  1316. $value = round($value / (PMA_pow(1000, $d) / $dh)) /$dh;
  1317. $unit = $units[$d];
  1318. break 1;
  1319. } // end if
  1320. } // end for
  1321. } // end if ($value >= 1) elseif (!$only_down && (float) $value !== 0.0)
  1322. //number_format is not multibyte safe, str_replace is safe
  1323. $value = str_replace(array(',', '.'),
  1324. array($GLOBALS['number_thousands_separator'], $GLOBALS['number_decimal_separator']),
  1325. number_format($value, $comma));
  1326. return $sign . $value . ' ' . $unit;
  1327. } // end of the 'PMA_formatNumber' function
  1328. /**
  1329. * Writes localised date
  1330. *
  1331. * @param string the current timestamp
  1332. *
  1333. * @return string the formatted date
  1334. *
  1335. * @access public
  1336. */
  1337. function PMA_localisedDate($timestamp = -1, $format = '')
  1338. {
  1339. global $datefmt, $month, $day_of_week;
  1340. if ($format == '') {
  1341. $format = $datefmt;
  1342. }
  1343. if ($timestamp == -1) {
  1344. $timestamp = time();
  1345. }
  1346. $date = preg_replace('@%[aA]@', $day_of_week[(int)strftime('%w', $timestamp)], $format);
  1347. $date = preg_replace('@%[bB]@', $month[(int)strftime('%m', $timestamp)-1], $date);
  1348. return strftime($date, $timestamp);
  1349. } // end of the 'PMA_localisedDate()' function
  1350. /**
  1351. * returns a tab for tabbed navigation.
  1352. * If the variables $link and $args ar left empty, an inactive tab is created
  1353. *
  1354. * @uses $GLOBALS['PMA_PHP_SELF']
  1355. * @uses $GLOBALS['strEmpty']
  1356. * @uses $GLOBALS['strDrop']
  1357. * @uses $GLOBALS['active_page']
  1358. * @uses $GLOBALS['url_query']
  1359. * @uses $cfg['MainPageIconic']
  1360. * @uses $GLOBALS['pmaThemeImage']
  1361. * @uses PMA_generate_common_url()
  1362. * @uses E_USER_NOTICE
  1363. * @uses htmlentities()
  1364. * @uses urlencode()
  1365. * @uses sprintf()
  1366. * @uses trigger_error()
  1367. * @uses array_merge()
  1368. * @uses basename()
  1369. * @param array $tab array with all options
  1370. * @param array $url_params
  1371. * @return string html code for one tab, a link if valid otherwise a span
  1372. * @access public
  1373. */
  1374. function PMA_getTab($tab, $url_params = array())
  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. || PMA_isValid($GLOBALS['active_page'], 'identical', $tab['link'])) {
  1396. $tab['class'] = 'active';
  1397. } elseif (empty($GLOBALS['active_page'])
  1398. && basename($GLOBALS['PMA_PHP_SELF']) == $tab['link']
  1399. && empty($tab['warning'])) {
  1400. $tab['class'] = 'active';
  1401. }
  1402. }
  1403. if (!empty($tab['warning'])) {
  1404. $tab['class'] .= ' warning';
  1405. $tab['attr'] .= ' title="' . htmlspecialchars($tab['warning']) . '"';
  1406. }
  1407. // build the link
  1408. if (!empty($tab['link'])) {
  1409. $tab['link'] = htmlentities($tab['link']);
  1410. $tab['link'] = $tab['link'] . PMA_generate_common_url($url_params);
  1411. if (! empty($tab['args'])) {
  1412. foreach ($tab['args'] as $param => $value) {
  1413. $tab['link'] .= PMA_get_arg_separator('html') . urlencode($param) . '='
  1414. . urlencode($value);
  1415. }
  1416. }
  1417. }
  1418. if (! empty($tab['fragment'])) {
  1419. $tab['link'] .= $tab['fragment'];
  1420. }
  1421. // display icon, even if iconic is disabled but the link-text is missing
  1422. if (($GLOBALS['cfg']['MainPageIconic'] || empty($tab['text']))
  1423. && isset($tab['icon'])) {
  1424. // avoid generating an alt tag, because it only illustrates
  1425. // the text that follows and if browser does not display
  1426. // images, the text is duplicated
  1427. $image = '<img class="icon" src="' . htmlentities($GLOBALS['pmaThemeImage'])
  1428. .'%1$s" width="16" height="16" alt="" />%2$s';
  1429. $tab['text'] = sprintf($image, htmlentities($tab['icon']), $tab['text']);
  1430. }
  1431. // check to not display an empty link-text
  1432. elseif (empty($tab['text'])) {
  1433. $tab['text'] = '?';
  1434. trigger_error('empty linktext in function ' . __FUNCTION__ . '()',
  1435. E_USER_NOTICE);
  1436. }
  1437. $out = '<li' . ($tab['class'] == 'active' ? ' class="active"' : '') . '>';
  1438. if (!empty($tab['link'])) {
  1439. $out .= '<a class="tab' . htmlentities($tab['class']) . '"'
  1440. .' href="' . $tab['link'] . '" ' . $tab['attr'] . '>'
  1441. . $tab['text'] . '</a>';
  1442. } else {
  1443. $out .= '<span class="tab' . htmlentities($tab['class']) . '">'
  1444. . $tab['text'] . '</span>';
  1445. }
  1446. $out .= '</li>';
  1447. return $out;
  1448. } // end of the 'PMA_getTab()' function
  1449. /**
  1450. * returns html-code for a tab navigation
  1451. *
  1452. * @uses PMA_getTab()
  1453. * @uses htmlentities()
  1454. * @param array $tabs one element per tab
  1455. * @param string $url_params
  1456. * @return string html-code for tab-navigation
  1457. */
  1458. function PMA_getTabs($tabs, $url_params)
  1459. {
  1460. $tag_id = 'topmenu';
  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, $url_params) . "\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, $str_len = strlen($string); $i < $str_len; $i++) {
  1633. $char = $string{$i};
  1634. $append = false;
  1635. if ($char == '&') {
  1636. $format_string .= $charbuff;
  1637. $charbuff = $char;
  1638. } elseif ($char == ';' && !empty($charbuff)) {
  1639. $format_string .= $charbuff . $char;
  1640. $charbuff = false;
  1641. $append = true;
  1642. } elseif (! empty($charbuff)) {
  1643. $charbuff .= $char;
  1644. } else {
  1645. $format_string .= $char;
  1646. $append = true;
  1647. }
  1648. // do not add separator after the last character
  1649. if ($append && ($i != $str_len - 1)) {
  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 $GLOBALS['analyzed_sql'][0]
  1717. * @uses PMA_DBI_field_flags()
  1718. * @uses PMA_backquote()
  1719. * @uses PMA_sqlAddslashes()
  1720. * @uses stristr()
  1721. * @uses bin2hex()
  1722. * @uses preg_replace()
  1723. * @param resource $handle current query result
  1724. * @param integer $fields_cnt number of fields
  1725. * @param array $fields_meta meta information about fields
  1726. * @param array $row current row
  1727. * @param boolean $force_unique generate condition only on pk or unique
  1728. *
  1729. * @access public
  1730. * @author Michal Cihar (michal@cihar.com) and others...
  1731. * @return string calculated condition
  1732. */
  1733. function PMA_getUniqueCondition($handle, $fields_cnt, $fields_meta, $row, $force_unique=false)
  1734. {
  1735. $primary_key = '';
  1736. $unique_key = '';
  1737. $nonprimary_condition = '';
  1738. $preferred_condition = '';
  1739. for ($i = 0; $i < $fields_cnt; ++$i) {
  1740. $condition = '';
  1741. $field_flags = PMA_DBI_field_flags($handle, $i);
  1742. $meta = $fields_meta[$i];
  1743. // do not use a column alias in a condition
  1744. if (! isset($meta->orgname) || ! strlen($meta->orgname)) {
  1745. $meta->orgname = $meta->name;
  1746. if (isset($GLOBALS['analyzed_sql'][0]['select_expr'])
  1747. && is_array($GLOBALS['analyzed_sql'][0]['select_expr'])) {
  1748. foreach ($GLOBALS['analyzed_sql'][0]['select_expr']
  1749. as $select_expr) {
  1750. // need (string) === (string)
  1751. // '' !== 0 but '' == 0
  1752. if ((string) $select_expr['alias'] === (string) $meta->name) {
  1753. $meta->orgname = $select_expr['column'];
  1754. break;
  1755. } // end if
  1756. } // end foreach
  1757. }
  1758. }
  1759. // Do not use a table alias in a condition.
  1760. // Test case is:
  1761. // select * from galerie x WHERE
  1762. //(select count(*) from galerie y where y.datum=x.datum)>1
  1763. //
  1764. // But orgtable is present only with mysqli extension so the
  1765. // fix is only for mysqli.
  1766. // Also, do not use the original table name if we are dealing with
  1767. // a view because this view might be updatable.
  1768. // (The isView() verification should not be costly in most cases
  1769. // because there is some caching in the function).
  1770. if (isset($meta->orgtable) && $meta->table != $meta->orgtable && ! PMA_Table::isView($GLOBALS['db'], $meta->table)) {
  1771. $meta->table = $meta->orgtable;
  1772. }
  1773. // to fix the bug where float fields (primary or not)
  1774. // can't be matched because of the imprecision of
  1775. // floating comparison, use CONCAT
  1776. // (also, the syntax "CONCAT(field) IS NULL"
  1777. // that we need on the next "if" will work)
  1778. if ($meta->type == 'real') {
  1779. $condition = ' CONCAT(' . PMA_backquote($meta->table) . '.'
  1780. . PMA_backquote($meta->orgname) . ') ';
  1781. } else {
  1782. $condition = ' ' . PMA_backquote($meta->table) . '.'
  1783. . PMA_backquote($meta->orgname) . ' ';
  1784. } // end if... else...
  1785. if (!isset($row[$i]) || is_null($row[$i])) {
  1786. $condition .= 'IS NULL AND';
  1787. } else {
  1788. // timestamp is numeric on some MySQL 4.1
  1789. if ($meta->numeric && $meta->type != 'timestamp') {
  1790. $condition .= '= ' . $row[$i] . ' AND';
  1791. } elseif (($meta->type == 'blob' || $meta->type == 'string')
  1792. // hexify only if this is a true not empty BLOB or a BINARY
  1793. && stristr($field_flags, 'BINARY')
  1794. && !empty($row[$i])) {
  1795. // do not waste memory building a too big condition
  1796. if (strlen($row[$i]) < 1000) {
  1797. // use a CAST if possible, to avoid problems
  1798. // if the field contains wildcard characters % or _
  1799. $condition .= '= CAST(0x' . bin2hex($row[$i])
  1800. . ' AS BINARY) AND';
  1801. } else {
  1802. // this blob won't be part of the final condition
  1803. $condition = '';
  1804. }
  1805. } else {
  1806. $condition .= '= \''
  1807. . PMA_sqlAddslashes($row[$i], false, true) . '\' AND';
  1808. }
  1809. }
  1810. if ($meta->primary_key > 0) {
  1811. $primary_key .= $condition;
  1812. } elseif ($meta->unique_key > 0) {
  1813. $unique_key .= $condition;
  1814. }
  1815. $nonprimary_condition .= $condition;
  1816. } // end for
  1817. // Correction University of Virginia 19991216:
  1818. // prefer primary or unique keys for condition,
  1819. // but use conjunction of all values if no primary key
  1820. if ($primary_key) {
  1821. $preferred_condition = $primary_key;
  1822. } elseif ($unique_key) {
  1823. $preferred_condition = $unique_key;
  1824. } elseif (! $force_unique) {
  1825. $preferred_condition = $nonprimary_condition;
  1826. }
  1827. return trim(preg_replace('|\s?AND$|', '', $preferred_condition));
  1828. } // end function
  1829. /**
  1830. * Generate a button or image tag
  1831. *
  1832. * @uses PMA_USR_BROWSER_AGENT
  1833. * @uses $GLOBALS['pmaThemeImage']
  1834. * @uses $GLOBALS['cfg']['PropertiesIconic']
  1835. * @param string name of button element
  1836. * @param string class of button element
  1837. * @param string name of image element
  1838. * @param string text to display
  1839. * @param string image to display
  1840. *
  1841. * @access public
  1842. * @author Michal Cihar (michal@cihar.com)
  1843. */
  1844. function PMA_buttonOrImage($button_name, $button_class, $image_name, $text,
  1845. $image)
  1846. {
  1847. if (false === $GLOBALS['cfg']['PropertiesIconic']) {
  1848. echo ' <input type="submit" name="' . $button_name . '"'
  1849. .' value="' . htmlspecialchars($text) . '"'
  1850. .' title="' . htmlspecialchars($text) . '" />' . "\n";
  1851. return;
  1852. }
  1853. /* Opera has trouble with <input type="image"> */
  1854. /* IE has trouble with <button> */
  1855. if (PMA_USR_BROWSER_AGENT != 'IE') {
  1856. echo '<button class="' . $button_class . '" type="submit"'
  1857. .' name="' . $button_name . '" value="' . htmlspecialchars($text) . '"'
  1858. .' title="' . htmlspecialchars($text) . '">' . "\n"
  1859. . PMA_getIcon($image, $text)
  1860. .'</button>' . "\n";
  1861. } else {
  1862. echo '<input type="image" name="' . $image_name . '" value="'
  1863. . htmlspecialchars($text) . '" title="' . htmlspecialchars($text) . '" src="' . $GLOBALS['pmaThemeImage']
  1864. . $image . '" />'
  1865. . ($GLOBALS['cfg']['PropertiesIconic'] === 'both' ? '&nbsp;' . htmlspecialchars($text) : '') . "\n";
  1866. }
  1867. } // end function
  1868. /**
  1869. * Generate a pagination selector for browsing resultsets
  1870. *
  1871. * @todo $url is not javascript escaped!?
  1872. * @uses $GLOBALS['strPageNumber']
  1873. * @uses range()
  1874. * @param string URL for the JavaScript
  1875. * @param string Number of rows in the pagination set
  1876. * @param string current page number
  1877. * @param string number of total pages
  1878. * @param string If the number of pages is lower than this
  1879. * variable, no pages will be omitted in
  1880. * pagination
  1881. * @param string How many rows at the beginning should always
  1882. * be shown?
  1883. * @param string How many rows at the end should always
  1884. * be shown?
  1885. * @param string Percentage of calculation page offsets to
  1886. * hop to a next page
  1887. * @param string Near the current page, how many pages should
  1888. * be considered "nearby" and displayed as
  1889. * well?
  1890. * @param string The prompt to display (sometimes empty)
  1891. *
  1892. * @access public
  1893. * @author Garvin Hicking (pma@supergarv.de)
  1894. */
  1895. function PMA_pageselector($url, $rows, $pageNow = 1, $nbTotalPage = 1,
  1896. $showAll = 200, $sliceStart = 5, $sliceEnd = 5, $percent = 20,
  1897. $range = 10, $prompt = '')
  1898. {
  1899. $increment = floor($nbTotalPage / $percent);
  1900. $pageNowMinusRange = ($pageNow - $range);
  1901. $pageNowPlusRange = ($pageNow + $range);
  1902. $gotopage = $prompt
  1903. . ' <select name="pos" onchange="goToUrl(this, \''
  1904. . $url . '\');">' . "\n";
  1905. if ($nbTotalPage < $showAll) {
  1906. $pages = range(1, $nbTotalPage);
  1907. } else {
  1908. $pages = array();
  1909. // Always show first X pages
  1910. for ($i = 1; $i <= $sliceStart; $i++) {
  1911. $pages[] = $i;
  1912. }
  1913. // Always show last X pages
  1914. for ($i = $nbTotalPage - $sliceEnd; $i <= $nbTotalPage; $i++) {
  1915. $pages[] = $i;
  1916. }
  1917. // garvin: Based on the number of results we add the specified
  1918. // $percent percentage to each page number,
  1919. // so that we have a representing page number every now and then to
  1920. // immediately jump to specific pages.
  1921. // As soon as we get near our currently chosen page ($pageNow -
  1922. // $range), every page number will be shown.
  1923. $i = $sliceStart;
  1924. $x = $nbTotalPage - $sliceEnd;
  1925. $met_boundary = false;
  1926. while ($i <= $x) {
  1927. if ($i >= $pageNowMinusRange && $i <= $pageNowPlusRange) {
  1928. // If our pageselector comes near the current page, we use 1
  1929. // counter increments
  1930. $i++;
  1931. $met_boundary = true;
  1932. } else {
  1933. // We add the percentage increment to our current page to
  1934. // hop to the next one in range
  1935. $i += $increment;
  1936. // Make sure that we do not cross our boundaries.
  1937. if ($i > $pageNowMinusRange && ! $met_boundary) {
  1938. $i = $pageNowMinusRange;
  1939. }
  1940. }
  1941. if ($i > 0 && $i <= $x) {
  1942. $pages[] = $i;
  1943. }
  1944. }
  1945. // Since because of ellipsing of the current page some numbers may be double,
  1946. // we unify our array:
  1947. sort($pages);
  1948. $pages = array_unique($pages);
  1949. }
  1950. foreach ($pages as $i) {
  1951. if ($i == $pageNow) {
  1952. $selected = 'selected="selected" style="font-weight: bold"';
  1953. } else {
  1954. $selected = '';
  1955. }
  1956. $gotopage .= ' <option ' . $selected . ' value="' . (($i - 1) * $rows) . '">' . $i . '</option>' . "\n";
  1957. }
  1958. $gotopage .= ' </select><noscript><input type="submit" value="' . $GLOBALS['strGo'] . '" /></noscript>';
  1959. return $gotopage;
  1960. } // end function
  1961. /**
  1962. * Generate navigation for a list
  1963. *
  1964. * @todo use $pos from $_url_params
  1965. * @uses $GLOBALS['strPageNumber']
  1966. * @uses range()
  1967. * @param integer number of elements in the list
  1968. * @param integer current position in the list
  1969. * @param array url parameters
  1970. * @param string script name for form target
  1971. * @param string target frame
  1972. * @param integer maximum number of elements to display from the list
  1973. *
  1974. * @access public
  1975. */
  1976. function PMA_listNavigator($count, $pos, $_url_params, $script, $frame, $max_count) {
  1977. if ($max_count < $count) {
  1978. echo 'frame_navigation' == $frame ? '<div id="navidbpageselector">' . "\n" : '';
  1979. echo $GLOBALS['strPageNumber'];
  1980. echo 'frame_navigation' == $frame ? '<br />' : ' ';
  1981. // Move to the beginning or to the previous page
  1982. if ($pos > 0) {
  1983. // loic1: patch #474210 from Gosha Sakovich - part 1
  1984. if ($GLOBALS['cfg']['NavigationBarIconic']) {
  1985. $caption1 = '&lt;&lt;';
  1986. $caption2 = ' &lt; ';
  1987. $title1 = ' title="' . $GLOBALS['strPos1'] . '"';
  1988. $title2 = ' title="' . $GLOBALS['strPrevious'] . '"';
  1989. } else {
  1990. $caption1 = $GLOBALS['strPos1'] . ' &lt;&lt;';
  1991. $caption2 = $GLOBALS['strPrevious'] . ' &lt;';
  1992. $title1 = '';
  1993. $title2 = '';
  1994. } // end if... else...
  1995. $_url_params['pos'] = 0;
  1996. echo '<a' . $title1 . ' href="' . $script
  1997. . PMA_generate_common_url($_url_params) . '" target="' . $frame . '">'
  1998. . $caption1 . '</a>';
  1999. $_url_params['pos'] = $pos - $max_count;
  2000. echo '<a' . $title2 . ' href="' . $script
  2001. . PMA_generate_common_url($_url_params) . '" target="' . $frame . '">'
  2002. . $caption2 . '</a>';
  2003. }
  2004. echo "\n", '<form action="./', basename($script), '" method="post" target="', $frame, '">', "\n";
  2005. echo PMA_generate_common_hidden_inputs($_url_params);
  2006. echo PMA_pageselector(
  2007. $script . PMA_generate_common_url($_url_params) . '&amp;',
  2008. $max_count,
  2009. floor(($pos + 1) / $max_count) + 1,
  2010. ceil($count / $max_count));
  2011. echo '</form>';
  2012. if ($pos + $max_count < $count) {
  2013. if ($GLOBALS['cfg']['NavigationBarIconic']) {
  2014. $caption3 = ' &gt; ';
  2015. $caption4 = '&gt;&gt;';
  2016. $title3 = ' title="' . $GLOBALS['strNext'] . '"';
  2017. $title4 = ' title="' . $GLOBALS['strEnd'] . '"';
  2018. } else {
  2019. $caption3 = '&gt; ' . $GLOBALS['strNext'];
  2020. $caption4 = '&gt;&gt; ' . $GLOBALS['strEnd'];
  2021. $title3 = '';
  2022. $title4 = '';
  2023. } // end if... else...
  2024. $_url_params['pos'] = $pos + $max_count;
  2025. echo '<a' . $title3 . ' href="' . $script
  2026. . PMA_generate_common_url($_url_params) . '" target="' . $frame . '">'
  2027. . $caption3 . '</a>';
  2028. $_url_params['pos'] = floor($count / $max_count) * $max_count;
  2029. if ($_url_params['pos'] == $count) {
  2030. $_url_params['pos'] = $count - $max_count;
  2031. }
  2032. echo '<a' . $title4 . ' href="' . $script
  2033. . PMA_generate_common_url($_url_params) . '" target="' . $frame . '">'
  2034. . $caption4 . '</a>';
  2035. }
  2036. echo "\n";
  2037. if ('frame_navigation' == $frame) {
  2038. echo '</div>' . "\n";
  2039. }
  2040. }
  2041. }
  2042. /**
  2043. * replaces %u in given path with current user name
  2044. *
  2045. * example:
  2046. * <code>
  2047. * $user_dir = PMA_userDir('/var/pma_tmp/%u/'); // '/var/pma_tmp/root/'
  2048. *
  2049. * </code>
  2050. * @uses $cfg['Server']['user']
  2051. * @uses substr()
  2052. * @uses str_replace()
  2053. * @param string $dir with wildcard for user
  2054. * @return string per user directory
  2055. */
  2056. function PMA_userDir($dir)
  2057. {
  2058. // add trailing slash
  2059. if (substr($dir, -1) != '/') {
  2060. $dir .= '/';
  2061. }
  2062. return str_replace('%u', $GLOBALS['cfg']['Server']['user'], $dir);
  2063. }
  2064. /**
  2065. * returns html code for db link to default db page
  2066. *
  2067. * @uses $cfg['DefaultTabDatabase']
  2068. * @uses $GLOBALS['db']
  2069. * @uses $GLOBALS['strJumpToDB']
  2070. * @uses PMA_generate_common_url()
  2071. * @uses PMA_unescape_mysql_wildcards()
  2072. * @uses strlen()
  2073. * @uses sprintf()
  2074. * @uses htmlspecialchars()
  2075. * @param string $database
  2076. * @return string html link to default db page
  2077. */
  2078. function PMA_getDbLink($database = null)
  2079. {
  2080. if (!strlen($database)) {
  2081. if (!strlen($GLOBALS['db'])) {
  2082. return '';
  2083. }
  2084. $database = $GLOBALS['db'];
  2085. } else {
  2086. $database = PMA_unescape_mysql_wildcards($database);
  2087. }
  2088. return '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?' . PMA_generate_common_url($database) . '"'
  2089. .' title="' . sprintf($GLOBALS['strJumpToDB'], htmlspecialchars($database)) . '">'
  2090. .htmlspecialchars($database) . '</a>';
  2091. }
  2092. /**
  2093. * Displays a lightbulb hint explaining a known external bug
  2094. * that affects a functionality
  2095. *
  2096. * @uses PMA_MYSQL_INT_VERSION
  2097. * @uses $GLOBALS['strKnownExternalBug']
  2098. * @uses PMA_showHint()
  2099. * @uses sprintf()
  2100. * @param string $functionality localized message explaining the func.
  2101. * @param string $component 'mysql' (eventually, 'php')
  2102. * @param string $minimum_version of this component
  2103. * @param string $bugref bug reference for this component
  2104. */
  2105. function PMA_externalBug($functionality, $component, $minimum_version, $bugref)
  2106. {
  2107. if ($component == 'mysql' && PMA_MYSQL_INT_VERSION < $minimum_version) {
  2108. echo PMA_showHint(sprintf($GLOBALS['strKnownExternalBug'], $functionality, 'http://bugs.mysql.com/' . $bugref));
  2109. }
  2110. }
  2111. /**
  2112. * Generates and echoes an HTML checkbox
  2113. *
  2114. * @param string $html_field_name the checkbox HTML field
  2115. * @param string $label
  2116. * @param boolean $checked is it initially checked?
  2117. * @param boolean $onclick should it submit the form on click?
  2118. */
  2119. function PMA_generate_html_checkbox($html_field_name, $label, $checked, $onclick) {
  2120. echo '<input type="checkbox" name="' . $html_field_name . '" id="' . $html_field_name . '"' . ($checked ? ' checked="checked"' : '') . ($onclick ? ' onclick="this.form.submit();"' : '') . ' /><label for="' . $html_field_name . '">' . $label . '</label>';
  2121. }
  2122. /**
  2123. * Generates and echoes a set of radio HTML fields
  2124. *
  2125. * @uses htmlspecialchars()
  2126. * @param string $html_field_name the radio HTML field
  2127. * @param array $choices the choices values and labels
  2128. * @param string $checked_choice the choice to check by default
  2129. * @param boolean $line_break whether to add an HTML line break after a choice
  2130. * @param boolean $escape_label whether to use htmlspecialchars() on label
  2131. * @param string $class enclose each choice with a div of this class
  2132. */
  2133. function PMA_generate_html_radio($html_field_name, $choices, $checked_choice = '', $line_break = true, $escape_label = true, $class='') {
  2134. foreach ($choices as $choice_value => $choice_label) {
  2135. if (! empty($class)) {
  2136. echo '<div class="' . $class . '">';
  2137. }
  2138. $html_field_id = $html_field_name . '_' . $choice_value;
  2139. echo '<input type="radio" name="' . $html_field_name . '" id="' . $html_field_id . '" value="' . htmlspecialchars($choice_value) . '"';
  2140. if ($choice_value == $checked_choice) {
  2141. echo ' checked="checked"';
  2142. }
  2143. echo ' />' . "\n";
  2144. echo '<label for="' . $html_field_id . '">' . ($escape_label ? htmlspecialchars($choice_label) : $choice_label) . '</label>';
  2145. if ($line_break) {
  2146. echo '<br />';
  2147. }
  2148. if (! empty($class)) {
  2149. echo '</div>';
  2150. }
  2151. echo "\n";
  2152. }
  2153. }
  2154. /**
  2155. * Generates and echoes an HTML dropdown
  2156. *
  2157. * @uses htmlspecialchars()
  2158. * @param string $select_name
  2159. * @param array $choices the choices values
  2160. * @param string $active_choice the choice to select by default
  2161. * @todo support titles
  2162. */
  2163. function PMA_generate_html_dropdown($select_name, $choices, $active_choice)
  2164. {
  2165. $result = '<select name="' . htmlspecialchars($select_name) . '" id="' . htmlspecialchars($select_name) . '">"' . "\n";
  2166. foreach ($choices as $one_choice) {
  2167. $result .= '<option value="' . htmlspecialchars($one_choice) . '"';
  2168. if ($one_choice == $active_choice) {
  2169. $result .= ' selected="selected"';
  2170. }
  2171. $result .= '>' . htmlspecialchars($one_choice) . '</option>' . "\n";
  2172. }
  2173. $result .= '</select>' . "\n";
  2174. echo $result;
  2175. }
  2176. /**
  2177. * Generates a slider effect (Mootools)
  2178. * Takes care of generating the initial <div> and the link
  2179. * controlling the slider; you have to generate the </div> yourself
  2180. * after the sliding section.
  2181. *
  2182. * @uses $GLOBALS['cfg']['InitialSlidersState']
  2183. * @param string $id the id of the <div> on which to apply the effect
  2184. * @param string $message the message to show as a link
  2185. */
  2186. function PMA_generate_slider_effect($id, $message)
  2187. {
  2188. if ($GLOBALS['cfg']['InitialSlidersState'] == 'disabled') {
  2189. echo '<div id="' . $id . '">';
  2190. return;
  2191. }
  2192. ?>
  2193. <script type="text/javascript">
  2194. // <![CDATA[
  2195. window.addEvent('domready', function(){
  2196. var status = {
  2197. 'true': '- ',
  2198. 'false': '+ '
  2199. };
  2200. var anchor<?php echo $id; ?> = new Element('a', {
  2201. 'id': 'toggle_<?php echo $id; ?>',
  2202. 'href': '#',
  2203. 'events': {
  2204. 'click': function(){
  2205. mySlide<?php echo $id; ?>.toggle();
  2206. }
  2207. }
  2208. });
  2209. anchor<?php echo $id; ?>.appendText('<?php echo $message; ?>');
  2210. anchor<?php echo $id; ?>.injectBefore('<?php echo $id; ?>');
  2211. var slider_status<?php echo $id; ?> = new Element('span', {
  2212. 'id': 'slider_status_<?php echo $id; ?>'
  2213. });
  2214. slider_status<?php echo $id; ?>.appendText('<?php echo $GLOBALS['cfg']['InitialSlidersState'] == 'closed' ? '+' : '-';?> ');
  2215. slider_status<?php echo $id; ?>.injectBefore('toggle_<?php echo $id; ?>');
  2216. var mySlide<?php echo $id; ?> = new Fx.Slide('<?php echo $id; ?>');
  2217. <?php
  2218. if ($GLOBALS['cfg']['InitialSlidersState'] == 'closed') {
  2219. ?>
  2220. mySlide<?php echo $id; ?>.hide();
  2221. <?php
  2222. }
  2223. ?>
  2224. mySlide<?php echo $id; ?>.addEvent('complete', function() {
  2225. $('slider_status_<?php echo $id; ?>').set('html', status[mySlide<?php echo $id; ?>.open]);
  2226. });
  2227. $('<?php echo $id; ?>').style.display="block";
  2228. });
  2229. document.write('<div id="<?php echo $id; ?>" <?php echo $GLOBALS['cfg']['InitialSlidersState'] == 'closed' ? ' style="display: none;"' : ''; ?>>');
  2230. //]]>
  2231. </script>
  2232. <noscript>
  2233. <div id="<?php echo $id; ?>" />
  2234. </noscript>
  2235. <?php
  2236. }
  2237. /**
  2238. * Verifies if something is cached in the session
  2239. *
  2240. * @param string $var
  2241. * @param scalar $server
  2242. * @return boolean
  2243. */
  2244. function PMA_cacheExists($var, $server = 0)
  2245. {
  2246. if (true === $server) {
  2247. $server = $GLOBALS['server'];
  2248. }
  2249. return isset($_SESSION['cache']['server_' . $server][$var]);
  2250. }
  2251. /**
  2252. * Gets cached information from the session
  2253. *
  2254. * @param string $var
  2255. * @param scalar $server
  2256. * @return mixed
  2257. */
  2258. function PMA_cacheGet($var, $server = 0)
  2259. {
  2260. if (true === $server) {
  2261. $server = $GLOBALS['server'];
  2262. }
  2263. if (isset($_SESSION['cache']['server_' . $server][$var])) {
  2264. return $_SESSION['cache']['server_' . $server][$var];
  2265. } else {
  2266. return null;
  2267. }
  2268. }
  2269. /**
  2270. * Caches information in the session
  2271. *
  2272. * @param string $var
  2273. * @param mixed $val
  2274. * @param integer $server
  2275. * @return mixed
  2276. */
  2277. function PMA_cacheSet($var, $val = null, $server = 0)
  2278. {
  2279. if (true === $server) {
  2280. $server = $GLOBALS['server'];
  2281. }
  2282. $_SESSION['cache']['server_' . $server][$var] = $val;
  2283. }
  2284. /**
  2285. * Removes cached information from the session
  2286. *
  2287. * @param string $var
  2288. * @param scalar $server
  2289. */
  2290. function PMA_cacheUnset($var, $server = 0)
  2291. {
  2292. if (true === $server) {
  2293. $server = $GLOBALS['server'];
  2294. }
  2295. unset($_SESSION['cache']['server_' . $server][$var]);
  2296. }
  2297. /**
  2298. * Converts a bit value to printable format;
  2299. * in MySQL a BIT field can be from 1 to 64 bits so we need this
  2300. * function because in PHP, decbin() supports only 32 bits
  2301. *
  2302. * @uses ceil()
  2303. * @uses decbin()
  2304. * @uses ord()
  2305. * @uses substr()
  2306. * @uses sprintf()
  2307. * @param numeric $value coming from a BIT field
  2308. * @param integer $length
  2309. * @return string the printable value
  2310. */
  2311. function PMA_printable_bit_value($value, $length) {
  2312. $printable = '';
  2313. for ($i = 0, $len_ceiled = ceil($length / 8); $i < $len_ceiled; $i++) {
  2314. $printable .= sprintf('%08d', decbin(ord(substr($value, $i, 1))));
  2315. }
  2316. $printable = substr($printable, -$length);
  2317. return $printable;
  2318. }
  2319. /**
  2320. * Extracts the various parts from a field type spec
  2321. *
  2322. * @uses strpos()
  2323. * @uses chop()
  2324. * @uses substr()
  2325. * @param string $fieldspec
  2326. * @return array associative array containing type, spec_in_brackets
  2327. * and possibly enum_set_values (another array)
  2328. * @author Marc Delisle
  2329. * @author Joshua Hogendorn
  2330. */
  2331. function PMA_extractFieldSpec($fieldspec) {
  2332. $first_bracket_pos = strpos($fieldspec, '(');
  2333. if ($first_bracket_pos) {
  2334. $spec_in_brackets = chop(substr($fieldspec, $first_bracket_pos + 1, (strrpos($fieldspec, ')') - $first_bracket_pos - 1)));
  2335. // convert to lowercase just to be sure
  2336. $type = strtolower(chop(substr($fieldspec, 0, $first_bracket_pos)));
  2337. } else {
  2338. $type = $fieldspec;
  2339. $spec_in_brackets = '';
  2340. }
  2341. if ('enum' == $type || 'set' == $type) {
  2342. // Define our working vars
  2343. $enum_set_values = array();
  2344. $working = "";
  2345. $in_string = false;
  2346. $index = 0;
  2347. // While there is another character to process
  2348. while (isset($fieldspec[$index])) {
  2349. // Grab the char to look at
  2350. $char = $fieldspec[$index];
  2351. // If it is a single quote, needs to be handled specially
  2352. if ($char == "'") {
  2353. // If we are not currently in a string, begin one
  2354. if (! $in_string) {
  2355. $in_string = true;
  2356. $working = "";
  2357. // Otherwise, it may be either an end of a string, or a 'double quote' which can be handled as-is
  2358. } else {
  2359. // Check out the next character (if possible)
  2360. $has_next = isset($fieldspec[$index + 1]);
  2361. $next = $has_next ? $fieldspec[$index + 1] : null;
  2362. // If we have reached the end of our 'working' string (because there are no more chars, or the next char is not another quote)
  2363. if (! $has_next || $next != "'") {
  2364. $enum_set_values[] = $working;
  2365. $in_string = false;
  2366. // Otherwise, this is a 'double quote', and can be added to the working string
  2367. } elseif ($next == "'") {
  2368. $working .= "'";
  2369. // Skip the next char; we already know what it is
  2370. $index++;
  2371. }
  2372. }
  2373. // escaping of a quote?
  2374. } elseif ('\\' == $char && isset($fieldspec[$index + 1]) && "'" == $fieldspec[$index + 1]) {
  2375. $working .= "'";
  2376. $index++;
  2377. // Otherwise, add it to our working string like normal
  2378. } else {
  2379. $working .= $char;
  2380. }
  2381. // Increment character index
  2382. $index++;
  2383. } // end while
  2384. } else {
  2385. $enum_set_values = array();
  2386. }
  2387. return array(
  2388. 'type' => $type,
  2389. 'spec_in_brackets' => $spec_in_brackets,
  2390. 'enum_set_values' => $enum_set_values
  2391. );
  2392. }
  2393. /**
  2394. * Verifies if this table's engine supports foreign keys
  2395. *
  2396. * @uses strtoupper()
  2397. * @param string $engine
  2398. * @return boolean
  2399. */
  2400. function PMA_foreignkey_supported($engine) {
  2401. $engine = strtoupper($engine);
  2402. if ('INNODB' == $engine || 'PBXT' == $engine) {
  2403. return true;
  2404. } else {
  2405. return false;
  2406. }
  2407. }
  2408. /**
  2409. * Replaces some characters by a displayable equivalent
  2410. *
  2411. * @uses str_replace()
  2412. * @param string $content
  2413. * @return string the content with characters replaced
  2414. */
  2415. function PMA_replace_binary_contents($content) {
  2416. $result = str_replace("\x00", '\0', $content);
  2417. $result = str_replace("\x08", '\b', $result);
  2418. $result = str_replace("\x0a", '\n', $result);
  2419. $result = str_replace("\x0d", '\r', $result);
  2420. $result = str_replace("\x1a", '\Z', $result);
  2421. return $result;
  2422. }
  2423. /**
  2424. *
  2425. * If the string starts with a \r\n pair (0x0d0a) add an extra \n
  2426. *
  2427. * @uses strpos()
  2428. * @return string with the chars replaced
  2429. */
  2430. function PMA_duplicateFirstNewline($string){
  2431. $first_occurence = strpos($string, "\r\n");
  2432. if ($first_occurence === 0){
  2433. $string = "\n".$string;
  2434. }
  2435. return $string;
  2436. }
  2437. /**
  2438. * get the action word corresponding to a script name
  2439. * in order to display it as a title in navigation panel
  2440. *
  2441. * @uses $GLOBALS
  2442. * @param string a valid value for $cfg['LeftDefaultTabTable']
  2443. * or $cfg['DefaultTabTable']
  2444. * or $cfg['DefaultTabDatabase']
  2445. */
  2446. function PMA_getTitleForTarget($target) {
  2447. return $GLOBALS[$GLOBALS['cfg']['DefaultTabTranslationMapping'][$target]];
  2448. }
  2449. ?>