Rev Author Line No. Line
250 kaklik 1 <?php
2 /* $Id: common.lib.php,v 2.266.2.27.2.2 2006/08/21 11:45:16 lem9 Exp $ */
3 // vim: expandtab sw=4 ts=4 sts=4:
4  
5 /**
6 * Misc stuff and functions used by almost all the scripts.
7 * Among other things, it contains the advanced authentication work.
8 */
9  
10 /**
11 * Order of sections for common.lib.php:
12 *
13 * the include of libraries/defines_mysql.lib.php must be after the connection
14 * to db to get the MySql version
15 *
16 * the authentication libraries must be before the connection to db
17 *
18 * ... so the required order is:
19 *
20 * LABEL_definition_of_functions
21 * - definition of functions
22 * LABEL_variables_init
23 * - init some variables always needed
24 * LABEL_parsing_config_file
25 * - parsing of the config file
26 * LABEL_loading_language_file
27 * - loading language file
28 * LABEL_theme_setup
29 * - setting up themes
30 *
31 * - load of mysql extension (if necessary) label_loading_mysql
32 * - loading of an authentication library label_
33 * - db connection
34 * - authentication work
35 * - load of the libraries/defines_mysql.lib.php library to get the MySQL
36 * release number
37 */
38  
39 /**
40 * For now, avoid warnings of E_STRICT mode
41 * (this must be done before function definitions)
42 */
43  
44 if (defined('E_STRICT')) {
45 $old_error_reporting = error_reporting(0);
46 if ($old_error_reporting & E_STRICT) {
47 error_reporting($old_error_reporting ^ E_STRICT);
48 } else {
49 error_reporting($old_error_reporting);
50 }
51 unset($old_error_reporting);
52 }
53  
54 /**
55 * Avoid object cloning errors
56 */
57  
58 @ini_set('zend.ze1_compatibility_mode',false);
59  
60  
61 /******************************************************************************/
62 /* definition of functions LABEL_definition_of_functions */
63 /**
64 * Removes insecure parts in a path; used before include() or
65 * require() when a part of the path comes from an insecure source
66 * like a cookie or form.
67 *
68 * @param string The path to check
69 *
70 * @return string The secured path
71 *
72 * @access public
73 * @author Marc Delisle (lem9@users.sourceforge.net)
74 */
75 function PMA_securePath($path)
76 {
77 // change .. to .
78 $path = preg_replace('@\.\.*@', '.', $path);
79  
80 return $path;
81 } // end function
82  
83 /**
84 * returns array with dbs grouped with extended infos
85 *
86 * @uses $GLOBALS['dblist'] from PMA_availableDatabases()
87 * @uses $GLOBALS['num_dbs'] from PMA_availableDatabases()
88 * @uses $GLOBALS['cfgRelation']['commwork']
89 * @uses $GLOBALS['cfg']['ShowTooltip']
90 * @uses $GLOBALS['cfg']['LeftFrameDBTree']
91 * @uses $GLOBALS['cfg']['LeftFrameDBSeparator']
92 * @uses $GLOBALS['cfg']['ShowTooltipAliasDB']
93 * @uses PMA_availableDatabases()
94 * @uses PMA_getTableCount()
95 * @uses PMA_getComments()
96 * @uses PMA_availableDatabases()
97 * @uses is_array()
98 * @uses implode()
99 * @uses strstr()
100 * @uses explode()
101 * @return array db list
102 */
103 function PMA_getDbList()
104 {
105 if (empty($GLOBALS['dblist'])) {
106 PMA_availableDatabases();
107 }
108 $dblist = $GLOBALS['dblist'];
109 $dbgroups = array();
110 $parts = array();
111 foreach ($dblist as $key => $db) {
112 // garvin: Get comments from PMA comments table
113 $db_tooltip = '';
114 if ($GLOBALS['cfg']['ShowTooltip']
115 && $GLOBALS['cfgRelation']['commwork']) {
116 $_db_tooltip = PMA_getComments($db);
117 if (is_array($_db_tooltip)) {
118 $db_tooltip = implode(' ', $_db_tooltip);
119 }
120 }
121  
122 if ($GLOBALS['cfg']['LeftFrameDBTree']
123 && $GLOBALS['cfg']['LeftFrameDBSeparator']
124 && strstr($db, $GLOBALS['cfg']['LeftFrameDBSeparator']))
125 {
126 $pos = strrpos($db, $GLOBALS['cfg']['LeftFrameDBSeparator']);
127 $group = substr($db, 0, $pos);
128 $disp_name_cut = substr($db, $pos);
129 } else {
130 $group = $db;
131 $disp_name_cut = $db;
132 }
133  
134 $disp_name = $db;
135 if ($db_tooltip && $GLOBALS['cfg']['ShowTooltipAliasDB']) {
136 $disp_name = $db_tooltip;
137 $disp_name_cut = $db_tooltip;
138 $db_tooltip = $db;
139 }
140  
141 $dbgroups[$group][$db] = array(
142 'name' => $db,
143 'disp_name_cut' => $disp_name_cut,
144 'disp_name' => $disp_name,
145 'comment' => $db_tooltip,
146 'num_tables' => PMA_getTableCount($db),
147 );
148 } // end foreach ($dblist as $db)
149 return $dbgroups;
150 }
151  
152 /**
153 * returns html code for select form element with dbs
154 *
155 * @return string html code select
156 */
157 function PMA_getHtmlSelectDb($selected = '')
158 {
159 $dblist = PMA_getDbList();
160 // TODO: IE can not handle different text directions in select boxes
161 // so, as mostly names will be in english, we set the whole selectbox to LTR
162 // and EN
163 $return = '<select name="db" id="lightm_db" xml:lang="en" dir="ltr"'
164 .' onchange="if (this.value != \'\') window.parent.openDb(this.value);">' . "\n"
165 .'<option value="" dir="' . $GLOBALS['text_dir'] . '">(' . $GLOBALS['strDatabases'] . ') ...</option>'
166 ."\n";
167 foreach ($dblist as $group => $dbs) {
168 if (count($dbs) > 1) {
169 $return .= '<optgroup label="' . htmlspecialchars($group)
170 . '">' . "\n";
171 // wether display db_name cuted by the group part
172 $cut = true;
173 } else {
174 // .. or full
175 $cut = false;
176 }
177 foreach ($dbs as $db) {
178 $return .= '<option value="' . $db['name'] . '"'
179 .' title="' . $db['comment'] . '"';
180 if ($db['name'] == $selected) {
181 $return .= ' selected="selected"';
182 }
183 $return .= '>' . ($cut ? $db['disp_name_cut'] : $db['disp_name'])
184 .' (' . $db['num_tables'] . ')</option>' . "\n";
185 }
186 if (count($dbs) > 1) {
187 $return .= '</optgroup>' . "\n";
188 }
189 }
190 $return .= '</select>';
191  
192 return $return;
193 }
194  
195 /**
196 * returns count of tables in given db
197 *
198 * @param string $db database to count tables for
199 * @return integer count of tables in $db
200 */
201 function PMA_getTableCount($db)
202 {
203 $tables = PMA_DBI_try_query(
204 'SHOW TABLES FROM ' . PMA_backquote($db) . ';',
205 null, PMA_DBI_QUERY_STORE);
206 if ($tables) {
207 $num_tables = PMA_DBI_num_rows($tables);
208 PMA_DBI_free_result($tables);
209 } else {
210 $num_tables = 0;
211 }
212  
213 return $num_tables;
214 }
215  
216  
217 /**
218 * Get the complete list of Databases a user can access
219 *
220 * @param boolean whether to include check on failed 'only_db' operations
221 * @param resource database handle (superuser)
222 * @param integer amount of databases inside the 'only_db' container
223 * @param resource possible resource from a failed previous query
224 * @param resource database handle (user)
225 * @param array configuration
226 * @param array previous list of databases
227 *
228 * @return array all databases a user has access to
229 *
230 * @access private
231 */
232 function PMA_safe_db_list($only_db_check, $controllink, $dblist_cnt, $userlink,
233 $cfg, $dblist)
234 {
235 if ($only_db_check == false) {
236 // try to get the available dbs list
237 // use userlink by default
238 $dblist = PMA_DBI_get_dblist();
239 $dblist_cnt = count($dblist);
240  
241 // PMA_DBI_get_dblist() relies on the ability to run "SHOW DATABASES".
242 // On servers started with --skip-show-database, this is not possible
243 // so we have here a fallback method, which relies on the controluser
244 // being able to access the "mysql" db, as explained in the doc.
245  
246 if (!$dblist_cnt) {
247 $auth_query = 'SELECT User, Select_priv '
248 . 'FROM mysql.user '
249 . 'WHERE User = \'' . PMA_sqlAddslashes($cfg['Server']['user']) . '\'';
250 $rs = PMA_DBI_try_query($auth_query, $controllink);
251 } // end
252 }
253  
254 // Access to "mysql" db allowed and dblist still empty -> gets the
255 // usable db list
256 if (!$dblist_cnt && ($rs && @PMA_DBI_num_rows($rs))) {
257 $row = PMA_DBI_fetch_assoc($rs);
258 PMA_DBI_free_result($rs);
259 // Correction uva 19991215
260 // Previous code assumed database "mysql" admin table "db" column
261 // "db" contains literal name of user database, and works if so.
262 // Mysql usage generally (and uva usage specifically) allows this
263 // column to contain regular expressions (we have all databases
264 // owned by a given student/faculty/staff beginning with user i.d.
265 // and governed by default by a single set of privileges with
266 // regular expression as key). This breaks previous code.
267 // This maintenance is to fix code to work correctly for regular
268 // expressions.
269 if ($row['Select_priv'] != 'Y') {
270  
271 // 1. get allowed dbs from the "mysql.db" table
272 // lem9: User can be blank (anonymous user)
273 $local_query = 'SELECT DISTINCT Db FROM mysql.db WHERE Select_priv = \'Y\' AND (User = \'' . PMA_sqlAddslashes($cfg['Server']['user']) . '\' OR User = \'\')';
274 $rs = PMA_DBI_try_query($local_query, $controllink);
275 if ($rs && @PMA_DBI_num_rows($rs)) {
276 // Will use as associative array of the following 2 code
277 // lines:
278 // the 1st is the only line intact from before
279 // correction,
280 // the 2nd replaces $dblist[] = $row['Db'];
281 $uva_mydbs = array();
282 // Code following those 2 lines in correction continues
283 // populating $dblist[], as previous code did. But it is
284 // now populated with actual database names instead of
285 // with regular expressions.
286 while ($row = PMA_DBI_fetch_assoc($rs)) {
287 // loic1: all databases cases - part 1
288 if ( !isset($row['Db']) || ! strlen($row['Db']) || $row['Db'] == '%') {
289 $uva_mydbs['%'] = 1;
290 break;
291 }
292 // loic1: avoid multiple entries for dbs
293 if (!isset($uva_mydbs[$row['Db']])) {
294 $uva_mydbs[$row['Db']] = 1;
295 }
296 } // end while
297 PMA_DBI_free_result($rs);
298 $uva_alldbs = PMA_DBI_query('SHOW DATABASES;', $GLOBALS['controllink']);
299 // loic1: all databases cases - part 2
300 if (isset($uva_mydbs['%'])) {
301 while ($uva_row = PMA_DBI_fetch_row($uva_alldbs)) {
302 $dblist[] = $uva_row[0];
303 } // end while
304 } else {
305 while ($uva_row = PMA_DBI_fetch_row($uva_alldbs)) {
306 $uva_db = $uva_row[0];
307 if (isset($uva_mydbs[$uva_db]) && $uva_mydbs[$uva_db] == 1) {
308 $dblist[] = $uva_db;
309 $uva_mydbs[$uva_db] = 0;
310 } elseif (!isset($dblist[$uva_db])) {
311 foreach ($uva_mydbs AS $uva_matchpattern => $uva_value) {
312 // loic1: fixed bad regexp
313 // TODO: db names may contain characters
314 // that are regexp instructions
315 $re = '(^|(\\\\\\\\)+|[^\])';
316 $uva_regex = ereg_replace($re . '%', '\\1.*', ereg_replace($re . '_', '\\1.{1}', $uva_matchpattern));
317 // Fixed db name matching
318 // 2000-08-28 -- Benjamin Gandon
319 if (ereg('^' . $uva_regex . '$', $uva_db)) {
320 $dblist[] = $uva_db;
321 break;
322 }
323 } // end while
324 } // end if ... elseif ...
325 } // end while
326 } // end else
327 PMA_DBI_free_result($uva_alldbs);
328 unset($uva_mydbs);
329 } // end if
330  
331 // 2. get allowed dbs from the "mysql.tables_priv" table
332 $local_query = 'SELECT DISTINCT Db FROM mysql.tables_priv WHERE Table_priv LIKE \'%Select%\' AND User = \'' . PMA_sqlAddslashes($cfg['Server']['user']) . '\'';
333 $rs = PMA_DBI_try_query($local_query, $controllink);
334 if ($rs && @PMA_DBI_num_rows($rs)) {
335 while ($row = PMA_DBI_fetch_assoc($rs)) {
336 if (!in_array($row['Db'], $dblist)) {
337 $dblist[] = $row['Db'];
338 }
339 } // end while
340 PMA_DBI_free_result($rs);
341 } // end if
342 } // end if
343 } // end building available dbs from the "mysql" db
344  
345 return $dblist;
346 }
347  
348 /**
349 * Converts numbers like 10M into bytes
350 *
351 * @param string $size
352 * @return integer $size
353 */
354 function get_real_size($size = 0)
355 {
356 if (!$size) {
357 return 0;
358 }
359 $scan['MB'] = 1048576;
360 $scan['Mb'] = 1048576;
361 $scan['M'] = 1048576;
362 $scan['m'] = 1048576;
363 $scan['KB'] = 1024;
364 $scan['Kb'] = 1024;
365 $scan['K'] = 1024;
366 $scan['k'] = 1024;
367  
368 while (list($key) = each($scan)) {
369 if ((strlen($size) > strlen($key))
370 && (substr($size, strlen($size) - strlen($key)) == $key)) {
371 $size = substr($size, 0, strlen($size) - strlen($key)) * $scan[$key];
372 break;
373 }
374 }
375 return $size;
376 } // end function get_real_size()
377  
378 /**
379 * loads php module
380 *
381 * @uses PHP_OS
382 * @uses extension_loaded()
383 * @uses ini_get()
384 * @uses function_exists()
385 * @uses ob_start()
386 * @uses phpinfo()
387 * @uses strip_tags()
388 * @uses ob_get_contents()
389 * @uses ob_end_clean()
390 * @uses preg_match()
391 * @uses strtoupper()
392 * @uses substr()
393 * @uses dl()
394 * @param string $module name if module to load
395 * @return boolean success loading module
396 */
397 function PMA_dl($module)
398 {
399 static $dl_allowed = null;
400  
401 if (extension_loaded($module)) {
402 return true;
403 }
404  
405 if (null === $dl_allowed) {
406 if (!@ini_get('safe_mode')
407 && @ini_get('enable_dl')
408 && @function_exists('dl')) {
409 ob_start();
410 phpinfo(INFO_GENERAL); /* Only general info */
411 $a = strip_tags(ob_get_contents());
412 ob_end_clean();
413 if (preg_match('@Thread Safety[[:space:]]*enabled@', $a)) {
414 if (preg_match('@Server API[[:space:]]*\(CGI\|CLI\)@', $a)) {
415 $dl_allowed = true;
416 } else {
417 $dl_allowed = false;
418 }
419 } else {
420 $dl_allowed = true;
421 }
422 } else {
423 $dl_allowed = false;
424 }
425 }
426  
427 if (!$dl_allowed) {
428 return false;
429 }
430  
431 if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
432 $module_file = 'php_' . $module . '.dll';
433 } else {
434 $module_file = $module . '.so';
435 }
436  
437 return @dl($module_file);
438 }
439  
440 /**
441 * merges array recursive like array_merge_recursive() but keyed-values are
442 * always overwritten.
443 *
444 * array PMA_array_merge_recursive(array $array1[, array $array2[, array ...]])
445 *
446 * @see http://php.net/array_merge
447 * @see http://php.net/array_merge_recursive
448 * @uses func_num_args()
449 * @uses func_get_arg()
450 * @uses is_array()
451 * @uses call_user_func_array()
452 * @param array array to merge
453 * @param array array to merge
454 * @param array ...
455 * @return array merged array
456 */
457 function PMA_array_merge_recursive()
458 {
459 switch(func_num_args()) {
460 case 0 :
461 return false;
462 break;
463 case 1 :
464 // when does that happen?
465 return func_get_arg(0);
466 break;
467 case 2 :
468 $args = func_get_args();
469 if (!is_array($args[0]) || !is_array($args[1])) {
470 return $args[1];
471 }
472 foreach ($args[1] AS $key2 => $value2) {
473 if (isset($args[0][$key2]) && !is_int($key2)) {
474 $args[0][$key2] = PMA_array_merge_recursive($args[0][$key2],
475 $value2);
476 } else {
477 // we erase the parent array, otherwise we cannot override a directive that
478 // contains array elements, like this:
479 // (in config.default.php) $cfg['ForeignKeyDropdownOrder'] = array('id-content','content-id');
480 // (in config.inc.php) $cfg['ForeignKeyDropdownOrder'] = array('content-id');
481 if (is_int($key2) && $key2 == 0) {
482 unset($args[0]);
483 }
484 $args[0][$key2] = $value2;
485 }
486 }
487 return $args[0];
488 break;
489 default :
490 $args = func_get_args();
491 $args[1] = PMA_array_merge_recursive($args[0], $args[1]);
492 array_shift($args);
493 return call_user_func_array('PMA_array_merge_recursive', $args);
494 break;
495 }
496 }
497  
498 /**
499 * calls $function vor every element in $array recursively
500 *
501 * @param array $array array to walk
502 * @param string $function function to call for every array element
503 */
504 function PMA_arrayWalkRecursive(&$array, $function, $apply_to_keys_also = false)
505 {
506 foreach ($array as $key => $value) {
507 if (is_array($value)) {
508 PMA_arrayWalkRecursive($array[$key], $function, $apply_to_keys_also);
509 } else {
510 $array[$key] = $function($value);
511 }
512  
513 if ($apply_to_keys_also && is_string($key)) {
514 $new_key = $function($key);
515 if ($new_key != $key) {
516 $array[$new_key] = $array[$key];
517 unset($array[$key]);
518 }
519 }
520 }
521 }
522  
523 /**
524 * boolean phpMyAdmin.PMA_checkPageValidity(string &$page, array $whitelist)
525 *
526 * checks given given $page against given $whitelist and returns true if valid
527 * it ignores optionaly query paramters in $page (script.php?ignored)
528 *
529 * @uses in_array()
530 * @uses urldecode()
531 * @uses substr()
532 * @uses strpos()
533 * @param string &$page page to check
534 * @param array $whitelist whitelist to check page against
535 * @return boolean whether $page is valid or not (in $whitelist or not)
536 */
537 function PMA_checkPageValidity(&$page, $whitelist)
538 {
539 if (! isset($page)) {
540 return false;
541 }
542  
543 if (in_array($page, $whitelist)) {
544 return true;
545 } elseif (in_array(substr($page, 0, strpos($page . '?', '?')), $whitelist)) {
546 return true;
547 } else {
548 $_page = urldecode($page);
549 if (in_array(substr($_page, 0, strpos($_page . '?', '?')), $whitelist)) {
550 return true;
551 }
552 }
553 return false;
554 }
555  
556 /**
557 * trys to find the value for the given environment vriable name
558 *
559 * searchs in $_SERVER, $_ENV than trys getenv() and apache_getenv()
560 * in this order
561 *
562 * @param string $var_name variable name
563 * @return string value of $var or empty string
564 */
565 function PMA_getenv($var_name) {
566 if (isset($_SERVER[$var_name])) {
567 return $_SERVER[$var_name];
568 } elseif (isset($_ENV[$var_name])) {
569 return $_ENV[$var_name];
570 } elseif (getenv($var_name)) {
571 return getenv($var_name);
572 } elseif (function_exists('apache_getenv')
573 && apache_getenv($var_name, true)) {
574 return apache_getenv($var_name, true);
575 }
576  
577 return '';
578 }
579  
580 /**
581 * include here only libraries which contain only function definitions
582 * no code im main()!
583 */
584 /* Input sanitizing */
585 require_once './libraries/sanitizing.lib.php';
586 require_once './libraries/Theme.class.php';
587 require_once './libraries/Theme_Manager.class.php';
588 require_once './libraries/Config.class.php';
589  
590  
591  
592 if (!defined('PMA_MINIMUM_COMMON')) {
593 /**
594 * Displays the maximum size for an upload
595 *
596 * @param integer the size
597 *
598 * @return string the message
599 *
600 * @access public
601 */
602 function PMA_displayMaximumUploadSize($max_upload_size)
603 {
604 list($max_size, $max_unit) = PMA_formatByteDown($max_upload_size);
605 return '(' . sprintf($GLOBALS['strMaximumSize'], $max_size, $max_unit) . ')';
606 }
607  
608 /**
609 * Generates a hidden field which should indicate to the browser
610 * the maximum size for upload
611 *
612 * @param integer the size
613 *
614 * @return string the INPUT field
615 *
616 * @access public
617 */
618 function PMA_generateHiddenMaxFileSize($max_size)
619 {
620 return '<input type="hidden" name="MAX_FILE_SIZE" value="' .$max_size . '" />';
621 }
622  
623 /**
624 * Add slashes before "'" and "\" characters so a value containing them can
625 * be used in a sql comparison.
626 *
627 * @param string the string to slash
628 * @param boolean whether the string will be used in a 'LIKE' clause
629 * (it then requires two more escaped sequences) or not
630 * @param boolean whether to treat cr/lfs as escape-worthy entities
631 * (converts \n to \\n, \r to \\r)
632 *
633 * @param boolean whether this function is used as part of the
634 * "Create PHP code" dialog
635 *
636 * @return string the slashed string
637 *
638 * @access public
639 */
640 function PMA_sqlAddslashes($a_string = '', $is_like = false, $crlf = false, $php_code = false)
641 {
642 if ($is_like) {
643 $a_string = str_replace('\\', '\\\\\\\\', $a_string);
644 } else {
645 $a_string = str_replace('\\', '\\\\', $a_string);
646 }
647  
648 if ($crlf) {
649 $a_string = str_replace("\n", '\n', $a_string);
650 $a_string = str_replace("\r", '\r', $a_string);
651 $a_string = str_replace("\t", '\t', $a_string);
652 }
653  
654 if ($php_code) {
655 $a_string = str_replace('\'', '\\\'', $a_string);
656 } else {
657 $a_string = str_replace('\'', '\'\'', $a_string);
658 }
659  
660 return $a_string;
661 } // end of the 'PMA_sqlAddslashes()' function
662  
663  
664 /**
665 * Add slashes before "_" and "%" characters for using them in MySQL
666 * database, table and field names.
667 * Note: This function does not escape backslashes!
668 *
669 * @param string the string to escape
670 *
671 * @return string the escaped string
672 *
673 * @access public
674 */
675 function PMA_escape_mysql_wildcards($name)
676 {
677 $name = str_replace('_', '\\_', $name);
678 $name = str_replace('%', '\\%', $name);
679  
680 return $name;
681 } // end of the 'PMA_escape_mysql_wildcards()' function
682  
683 /**
684 * removes slashes before "_" and "%" characters
685 * Note: This function does not unescape backslashes!
686 *
687 * @param string $name the string to escape
688 * @return string the escaped string
689 * @access public
690 */
691 function PMA_unescape_mysql_wildcards($name)
692 {
693 $name = str_replace('\\_', '_', $name);
694 $name = str_replace('\\%', '%', $name);
695  
696 return $name;
697 } // end of the 'PMA_unescape_mysql_wildcards()' function
698  
699 /**
700 * format sql strings
701 *
702 * @param mixed pre-parsed SQL structure
703 *
704 * @return string the formatted sql
705 *
706 * @global array the configuration array
707 * @global boolean whether the current statement is a multiple one or not
708 *
709 * @access public
710 *
711 * @author Robin Johnson <robbat2@users.sourceforge.net>
712 */
713 function PMA_formatSql($parsed_sql, $unparsed_sql = '')
714 {
715 global $cfg;
716  
717 // Check that we actually have a valid set of parsed data
718 // well, not quite
719 // first check for the SQL parser having hit an error
720 if (PMA_SQP_isError()) {
721 return $parsed_sql;
722 }
723 // then check for an array
724 if (!is_array($parsed_sql)) {
725 // We don't so just return the input directly
726 // This is intended to be used for when the SQL Parser is turned off
727 $formatted_sql = '<pre>' . "\n"
728 . (($cfg['SQP']['fmtType'] == 'none' && $unparsed_sql != '') ? $unparsed_sql : $parsed_sql) . "\n"
729 . '</pre>';
730 return $formatted_sql;
731 }
732  
733 $formatted_sql = '';
734  
735 switch ($cfg['SQP']['fmtType']) {
736 case 'none':
737 if ($unparsed_sql != '') {
738 $formatted_sql = "<pre>\n" . PMA_SQP_formatNone(array('raw' => $unparsed_sql)) . "\n</pre>";
739 } else {
740 $formatted_sql = PMA_SQP_formatNone($parsed_sql);
741 }
742 break;
743 case 'html':
744 $formatted_sql = PMA_SQP_formatHtml($parsed_sql, 'color');
745 break;
746 case 'text':
747 //$formatted_sql = PMA_SQP_formatText($parsed_sql);
748 $formatted_sql = PMA_SQP_formatHtml($parsed_sql, 'text');
749 break;
750 default:
751 break;
752 } // end switch
753  
754 return $formatted_sql;
755 } // end of the "PMA_formatSql()" function
756  
757  
758 /**
759 * Displays a link to the official MySQL documentation
760 *
761 * @param string chapter of "HTML, one page per chapter" documentation
762 * @param string contains name of page/anchor that is being linked
763 * @param bool whether to use big icon (like in left frame)
764 *
765 * @return string the html link
766 *
767 * @access public
768 */
769 function PMA_showMySQLDocu($chapter, $link, $big_icon = false)
770 {
771 global $cfg;
772  
773 if ($cfg['MySQLManualType'] == 'none' || empty($cfg['MySQLManualBase'])) {
774 return '';
775 }
776  
777 // Fixup for newly used names:
778 $chapter = str_replace('_', '-', strtolower($chapter));
779 $link = str_replace('_', '-', strtolower($link));
780  
781 switch ($cfg['MySQLManualType']) {
782 case 'chapters':
783 if (empty($chapter)) {
784 $chapter = 'index';
785 }
786 $url = $cfg['MySQLManualBase'] . '/' . $chapter . '.html#' . $link;
787 break;
788 case 'big':
789 $url = $cfg['MySQLManualBase'] . '#' . $link;
790 break;
791 case 'searchable':
792 if (empty($link)) {
793 $link = 'index';
794 }
795 $url = $cfg['MySQLManualBase'] . '/' . $link . '.html';
796 break;
797 case 'viewable':
798 default:
799 if (empty($link)) {
800 $link = 'index';
801 }
802 $mysql = '5.0';
803 if (defined('PMA_MYSQL_INT_VERSION')) {
804 if (PMA_MYSQL_INT_VERSION < 50000) {
805 $mysql = '4.1';
806 } elseif (PMA_MYSQL_INT_VERSION >= 50100) {
807 $mysql = '5.1';
808 } elseif (PMA_MYSQL_INT_VERSION >= 50000) {
809 $mysql = '5.0';
810 }
811 }
812 $url = $cfg['MySQLManualBase'] . '/' . $mysql . '/en/' . $link . '.html';
813 break;
814 }
815  
816 if ($big_icon) {
817 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>';
818 } elseif ($GLOBALS['cfg']['ReplaceHelpImg']) {
819 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>';
820 } else {
821 return '[<a href="' . $url . '" target="mysql_doc">' . $GLOBALS['strDocu'] . '</a>]';
822 }
823 } // end of the 'PMA_showMySQLDocu()' function
824  
825 /**
826 * Displays a hint icon, on mouse over show the hint
827 *
828 * @param string the error message
829 *
830 * @access public
831 */
832 function PMA_showHint($hint_message)
833 {
834 //return '<img class="lightbulb" src="' . $GLOBALS['pmaThemeImage'] . 'b_tipp.png" width="16" height="16" border="0" alt="' . $hint_message . '" title="' . $hint_message . '" align="middle" onclick="alert(\'' . PMA_jsFormat($hint_message, false) . '\');" />';
835 return '<img class="lightbulb" src="' . $GLOBALS['pmaThemeImage'] . 'b_tipp.png" width="16" height="16" alt="Tip" title="Tip" onmouseover="pmaTooltip(\'' . PMA_jsFormat($hint_message, false) . '\'); return false;" onmouseout="swapTooltip(\'default\'); return false;" />';
836 }
837  
838 /**
839 * Displays a MySQL error message in the right frame.
840 *
841 * @param string the error message
842 * @param string the sql query that failed
843 * @param boolean whether to show a "modify" link or not
844 * @param string the "back" link url (full path is not required)
845 * @param boolean EXIT the page?
846 *
847 * @global array the configuration array
848 *
849 * @access public
850 */
851 function PMA_mysqlDie($error_message = '', $the_query = '',
852 $is_modify_link = true, $back_url = '',
853 $exit = true)
854 {
855 global $cfg, $table, $db, $sql_query;
856  
857 require_once './libraries/header.inc.php';
858  
859 if (!$error_message) {
860 $error_message = PMA_DBI_getError();
861 }
862 if (!$the_query && !empty($GLOBALS['sql_query'])) {
863 $the_query = $GLOBALS['sql_query'];
864 }
865  
866 // --- Added to solve bug #641765
867 // Robbat2 - 12 January 2003, 9:46PM
868 // Revised, Robbat2 - 13 January 2003, 2:59PM
869 if (!function_exists('PMA_SQP_isError') || PMA_SQP_isError()) {
870 $formatted_sql = htmlspecialchars($the_query);
871 } elseif (empty($the_query) || trim($the_query) == '') {
872 $formatted_sql = '';
873 } else {
874 $formatted_sql = PMA_formatSql(PMA_SQP_parse($the_query), $the_query);
875 }
876 // ---
877 echo "\n" . '<!-- PMA-SQL-ERROR -->' . "\n";
878 echo ' <div class="error"><h1>' . $GLOBALS['strError'] . '</h1>' . "\n";
879 // if the config password is wrong, or the MySQL server does not
880 // respond, do not show the query that would reveal the
881 // username/password
882 if (!empty($the_query) && !strstr($the_query, 'connect')) {
883 // --- Added to solve bug #641765
884 // Robbat2 - 12 January 2003, 9:46PM
885 // Revised, Robbat2 - 13 January 2003, 2:59PM
886 if (function_exists('PMA_SQP_isError') && PMA_SQP_isError()) {
887 echo PMA_SQP_getErrorString() . "\n";
888 echo '<br />' . "\n";
889 }
890 // ---
891 // modified to show me the help on sql errors (Michael Keck)
892 echo ' <p><strong>' . $GLOBALS['strSQLQuery'] . ':</strong>' . "\n";
893 if (strstr(strtolower($formatted_sql), 'select')) { // please show me help to the error on select
894 echo PMA_showMySQLDocu('SQL-Syntax', 'SELECT');
895 }
896 if ($is_modify_link && isset($db)) {
897 if (isset($table)) {
898 $doedit_goto = '<a href="tbl_properties.php?' . PMA_generate_common_url($db, $table) . '&amp;sql_query=' . urlencode($the_query) . '&amp;show_query=1">';
899 } else {
900 $doedit_goto = '<a href="db_details.php?' . PMA_generate_common_url($db) . '&amp;sql_query=' . urlencode($the_query) . '&amp;show_query=1">';
901 }
902 if ($GLOBALS['cfg']['PropertiesIconic']) {
903 echo $doedit_goto
904 . '<img class="icon" src=" '. $GLOBALS['pmaThemeImage'] . 'b_edit.png" width="16" height="16" alt="' . $GLOBALS['strEdit'] .'" />'
905 . '</a>';
906 } else {
907 echo ' ['
908 . $doedit_goto . $GLOBALS['strEdit'] . '</a>'
909 . ']' . "\n";
910 }
911 } // end if
912 echo ' </p>' . "\n"
913 .' <p>' . "\n"
914 .' ' . $formatted_sql . "\n"
915 .' </p>' . "\n";
916 } // end if
917  
918 $tmp_mysql_error = ''; // for saving the original $error_message
919 if (!empty($error_message)) {
920 $tmp_mysql_error = strtolower($error_message); // save the original $error_message
921 $error_message = htmlspecialchars($error_message);
922 $error_message = preg_replace("@((\015\012)|(\015)|(\012)){3,}@", "\n\n", $error_message);
923 }
924 // modified to show me the help on error-returns (Michael Keck)
925 echo '<p>' . "\n"
926 . ' <strong>' . $GLOBALS['strMySQLSaid'] . '</strong>'
927 . PMA_showMySQLDocu('Error-returns', 'Error-returns')
928 . "\n"
929 . '</p>' . "\n";
930  
931 // The error message will be displayed within a CODE segment.
932 // To preserve original formatting, but allow wordwrapping, we do a couple of replacements
933  
934 // Replace all non-single blanks with their HTML-counterpart
935 $error_message = str_replace(' ', '&nbsp;&nbsp;', $error_message);
936 // Replace TAB-characters with their HTML-counterpart
937 $error_message = str_replace("\t", '&nbsp;&nbsp;&nbsp;&nbsp;', $error_message);
938 // Replace linebreaks
939 $error_message = nl2br($error_message);
940  
941 echo '<code>' . "\n"
942 . $error_message . "\n"
943 . '</code><br />' . "\n";
944  
945 // feature request #1036254:
946 // Add a link by MySQL-Error #1062 - Duplicate entry
947 // 2004-10-20 by mkkeck
948 // 2005-01-17 modified by mkkeck bugfix
949 if (substr($error_message, 1, 4) == '1062') {
950 // get the duplicate entry
951  
952 // get table name
953 // TODO: what would be the best delimiter, while avoiding
954 // special characters that can become high-ascii after editing,
955 // depending upon which editor is used by the developer?
956 $error_table = array();
957 if (preg_match('@ALTER\s*TABLE\s*\`([^\`]+)\`@iu', $the_query, $error_table)) {
958 $error_table = $error_table[1];
959 } elseif (preg_match('@INSERT\s*INTO\s*\`([^\`]+)\`@iu', $the_query, $error_table)) {
960 $error_table = $error_table[1];
961 } elseif (preg_match('@UPDATE\s*\`([^\`]+)\`@iu', $the_query, $error_table)) {
962 $error_table = $error_table[1];
963 } elseif (preg_match('@INSERT\s*\`([^\`]+)\`@iu', $the_query, $error_table)) {
964 $error_table = $error_table[1];
965 }
966  
967 // get fields
968 $error_fields = array();
969 if (preg_match('@\(([^\)]+)\)@i', $the_query, $error_fields)) {
970 $error_fields = explode(',', $error_fields[1]);
971 } elseif (preg_match('@(`[^`]+`)\s*=@i', $the_query, $error_fields)) {
972 $error_fields = explode(',', $error_fields[1]);
973 }
974 if (is_array($error_table) || is_array($error_fields)) {
975  
976 // duplicate value
977 $duplicate_value = array();
978 preg_match('@\'([^\']+)\'@i', $tmp_mysql_error, $duplicate_value);
979 $duplicate_value = $duplicate_value[1];
980  
981 $sql = '
982 SELECT *
983 FROM ' . PMA_backquote($error_table) . '
984 WHERE CONCAT_WS("-", ' . implode(', ', $error_fields) . ')
985 = "' . PMA_sqlAddslashes($duplicate_value) . '"
986 ORDER BY ' . implode(', ', $error_fields);
987 unset($error_table, $error_fields, $duplicate_value);
988  
989 echo ' <form method="post" action="import.php" style="padding: 0; margin: 0">' ."\n"
990 .' <input type="hidden" name="sql_query" value="' . htmlentities($sql) . '" />' . "\n"
991 .' ' . PMA_generate_common_hidden_inputs($db, $table) . "\n"
992 .' <input type="submit" name="submit" value="' . $GLOBALS['strBrowse'] . '" />' . "\n"
993 .' </form>' . "\n";
994 unset($sql);
995 }
996 } // end of show duplicate entry
997  
998 echo '</div>';
999 echo '<fieldset class="tblFooters">';
1000  
1001 if (!empty($back_url) && $exit) {
1002 $goto_back_url='<a href="' . (strstr($back_url, '?') ? $back_url . '&amp;no_history=true' : $back_url . '?no_history=true') . '">';
1003 echo '[ ' . $goto_back_url . $GLOBALS['strBack'] . '</a> ]';
1004 }
1005 echo ' </fieldset>' . "\n\n";
1006 if ($exit) {
1007 require_once './libraries/footer.inc.php';
1008 }
1009 } // end of the 'PMA_mysqlDie()' function
1010  
1011 /**
1012 * Returns a string formatted with CONVERT ... USING
1013 * if MySQL supports it
1014 *
1015 * @param string the string itself
1016 * @param string the mode: quoted or unquoted (this one by default)
1017 *
1018 * @return the formatted string
1019 *
1020 * @access private
1021 */
1022 function PMA_convert_using($string, $mode='unquoted')
1023 {
1024 if ($mode == 'quoted') {
1025 $possible_quote = "'";
1026 } else {
1027 $possible_quote = "";
1028 }
1029  
1030 if (PMA_MYSQL_INT_VERSION >= 40100) {
1031 list($conn_charset) = explode('_', $GLOBALS['collation_connection']);
1032 $converted_string = "CONVERT(" . $possible_quote . $string . $possible_quote . " USING " . $conn_charset . ")";
1033 } else {
1034 $converted_string = $possible_quote . $string . $possible_quote;
1035 }
1036 return $converted_string;
1037 } // end function
1038  
1039 /**
1040 * Send HTTP header, taking IIS limits into account (600 seems ok)
1041 *
1042 * @param string $uri the header to send
1043 * @return boolean always true
1044 */
1045 function PMA_sendHeaderLocation($uri)
1046 {
1047 if (PMA_IS_IIS && strlen($uri) > 600) {
1048  
1049 echo '<html><head><title>- - -</title>' . "\n";
1050 echo '<meta http-equiv="expires" content="0">' . "\n";
1051 echo '<meta http-equiv="Pragma" content="no-cache">' . "\n";
1052 echo '<meta http-equiv="Cache-Control" content="no-cache">' . "\n";
1053 echo '<meta http-equiv="Refresh" content="0;url=' .$uri . '">' . "\n";
1054 echo '<script type="text/javascript" language="javascript">' . "\n";
1055 echo '//<![CDATA[' . "\n";
1056 echo 'setTimeout ("window.location = unescape(\'"' . $uri . '"\')",2000); </script>' . "\n";
1057 echo '//]]>' . "\n";
1058 echo '</head>' . "\n";
1059 echo '<body>' . "\n";
1060 echo '<script type="text/javascript" language="javascript">' . "\n";
1061 echo '//<![CDATA[' . "\n";
1062 echo 'document.write (\'<p><a href="' . $uri . '">' . $GLOBALS['strGo'] . '</a></p>\');' . "\n";
1063 echo '//]]>' . "\n";
1064 echo '</script></body></html>' . "\n";
1065  
1066 } else {
1067 if (SID) {
1068 if (strpos($uri, '?') === false) {
1069 header('Location: ' . $uri . '?' . SID);
1070 } else {
1071 // use seperators defined by php, but prefer ';'
1072 // as recommended by W3C
1073 $php_arg_separator_input = ini_get('arg_separator.input');
1074 if (strpos($php_arg_separator_input, ';') !== false) {
1075 $separator = ';';
1076 } elseif (strlen($php_arg_separator_input) > 0) {
1077 $separator = $php_arg_separator_input{0};
1078 } else {
1079 $separator = '&';
1080 }
1081 header('Location: ' . $uri . $separator . SID);
1082 }
1083 } else {
1084 session_write_close();
1085 // bug #1523784, IE6 does not like 'Refresh: 0', it
1086 // results in a blank page
1087 if (PMA_IS_IIS && defined('PMA_COMING_FROM_COOKIE_LOGIN')) {
1088 header('Refresh: 0; ' . $uri);
1089 } else {
1090 header('Location: ' . $uri);
1091 }
1092 }
1093 }
1094 }
1095  
1096 /**
1097 * Get the list and number of available databases.
1098 *
1099 * @param string the url to go back to in case of error
1100 *
1101 * @return boolean always true
1102 *
1103 * @global array the list of available databases
1104 * @global integer the number of available databases
1105 * @global array current configuration
1106 */
1107 function PMA_availableDatabases($error_url = '')
1108 {
1109 global $dblist;
1110 global $num_dbs;
1111 global $cfg;
1112  
1113 // 1. A list of allowed databases has already been defined by the
1114 // authentication process -> gets the available databases list
1115 if (count($dblist)) {
1116 foreach ($dblist as $key => $db) {
1117 if (!@PMA_DBI_select_db($db) || (!empty($GLOBALS['cfg']['Server']['hide_db']) && preg_match('/' . $GLOBALS['cfg']['Server']['hide_db'] . '/', $db))) {
1118 unset($dblist[$key]);
1119 } // end if
1120 } // end for
1121 } // end if
1122 // 2. Allowed database list is empty -> gets the list of all databases
1123 // on the server
1124 elseif (empty($cfg['Server']['only_db'])) {
1125 $dblist = PMA_DBI_get_dblist(); // needed? or PMA_mysqlDie('', 'SHOW DATABASES;', false, $error_url);
1126 } // end else
1127  
1128 $num_dbs = count($dblist);
1129  
1130 // natural order for db list; but do not sort if user asked
1131 // for a specific order with the 'only_db' mechanism
1132 if (!is_array($GLOBALS['cfg']['Server']['only_db'])
1133 && $GLOBALS['cfg']['NaturalOrder']) {
1134 natsort($dblist);
1135 }
1136  
1137 return true;
1138 } // end of the 'PMA_availableDatabases()' function
1139  
1140 /**
1141 * returns array with tables of given db with extended infomation and grouped
1142 *
1143 * @uses $GLOBALS['cfg']['LeftFrameTableSeparator']
1144 * @uses $GLOBALS['cfg']['LeftFrameTableLevel']
1145 * @uses $GLOBALS['cfg']['ShowTooltipAliasTB']
1146 * @uses $GLOBALS['cfg']['NaturalOrder']
1147 * @uses PMA_DBI_fetch_result()
1148 * @uses PMA_backquote()
1149 * @uses count()
1150 * @uses array_merge
1151 * @uses uksort()
1152 * @uses strstr()
1153 * @uses explode()
1154 * @param string $db name of db
1155 * return array (rekursive) grouped table list
1156 */
1157 function PMA_getTableList($db, $tables = null)
1158 {
1159 $sep = $GLOBALS['cfg']['LeftFrameTableSeparator'];
1160  
1161 if ( null === $tables ) {
1162 $tables = PMA_DBI_get_tables_full($db);
1163 if ($GLOBALS['cfg']['NaturalOrder']) {
1164 uksort($tables, 'strnatcasecmp');
1165 }
1166 }
1167  
1168 if (count($tables) < 1) {
1169 return $tables;
1170 }
1171  
1172 $default = array(
1173 'Name' => '',
1174 'Rows' => 0,
1175 'Comment' => '',
1176 'disp_name' => '',
1177 );
1178  
1179 $table_groups = array();
1180  
1181 foreach ($tables as $table_name => $table) {
1182  
1183 // check for correct row count
1184 if (null === $table['Rows']) {
1185 // Do not check exact row count here,
1186 // if row count is invalid possibly the table is defect
1187 // and this would break left frame;
1188 // but we can check row count if this is a view,
1189 // since PMA_countRecords() returns a limited row count
1190 // in this case.
1191  
1192 // set this because PMA_countRecords() can use it
1193 $tbl_is_view = PMA_tableIsView($db, $table['Name']);
1194  
1195 if ($tbl_is_view) {
1196 $table['Rows'] = PMA_countRecords($db, $table['Name'],
1197 $return = true);
1198 }
1199 }
1200  
1201 // in $group we save the reference to the place in $table_groups
1202 // where to store the table info
1203 if ($GLOBALS['cfg']['LeftFrameDBTree']
1204 && $sep && strstr($table_name, $sep))
1205 {
1206 $parts = explode($sep, $table_name);
1207  
1208 $group =& $table_groups;
1209 $i = 0;
1210 $group_name_full = '';
1211 while ($i < count($parts) - 1
1212 && $i < $GLOBALS['cfg']['LeftFrameTableLevel']) {
1213 $group_name = $parts[$i] . $sep;
1214 $group_name_full .= $group_name;
1215  
1216 if (!isset($group[$group_name])) {
1217 $group[$group_name] = array();
1218 $group[$group_name]['is' . $sep . 'group'] = true;
1219 $group[$group_name]['tab' . $sep . 'count'] = 1;
1220 $group[$group_name]['tab' . $sep . 'group'] = $group_name_full;
1221 } elseif (!isset($group[$group_name]['is' . $sep . 'group'])) {
1222 $table = $group[$group_name];
1223 $group[$group_name] = array();
1224 $group[$group_name][$group_name] = $table;
1225 unset($table);
1226 $group[$group_name]['is' . $sep . 'group'] = true;
1227 $group[$group_name]['tab' . $sep . 'count'] = 1;
1228 $group[$group_name]['tab' . $sep . 'group'] = $group_name_full;
1229 } else {
1230 $group[$group_name]['tab' . $sep . 'count']++;
1231 }
1232 $group =& $group[$group_name];
1233 $i++;
1234 }
1235 } else {
1236 if (!isset($table_groups[$table_name])) {
1237 $table_groups[$table_name] = array();
1238 }
1239 $group =& $table_groups;
1240 }
1241  
1242  
1243 if ($GLOBALS['cfg']['ShowTooltipAliasTB']
1244 && $GLOBALS['cfg']['ShowTooltipAliasTB'] !== 'nested') {
1245 // switch tooltip and name
1246 $table['Comment'] = $table['Name'];
1247 $table['disp_name'] = $table['Comment'];
1248 } else {
1249 $table['disp_name'] = $table['Name'];
1250 }
1251  
1252 $group[$table_name] = array_merge($default, $table);
1253 }
1254  
1255 return $table_groups;
1256 }
1257  
1258 /* ----------------------- Set of misc functions ----------------------- */
1259  
1260  
1261 /**
1262 * Adds backquotes on both sides of a database, table or field name.
1263 * and escapes backquotes inside the name with another backquote
1264 *
1265 * <code>
1266 * echo PMA_backquote('owner`s db'); // `owner``s db`
1267 * </code>
1268 *
1269 * @param mixed $a_name the database, table or field name to "backquote"
1270 * or array of it
1271 * @param boolean $do_it a flag to bypass this function (used by dump
1272 * functions)
1273 * @return mixed the "backquoted" database, table or field name if the
1274 * current MySQL release is >= 3.23.6, the original one
1275 * else
1276 * @access public
1277 */
1278 function PMA_backquote($a_name, $do_it = true)
1279 {
1280 if (! $do_it) {
1281 return $a_name;
1282 }
1283  
1284 if (is_array($a_name)) {
1285 $result = array();
1286 foreach ($a_name as $key => $val) {
1287 $result[$key] = PMA_backquote($val);
1288 }
1289 return $result;
1290 }
1291  
1292 // '0' is also empty for php :-(
1293 if (strlen($a_name) && $a_name != '*') {
1294 return '`' . str_replace('`', '``', $a_name) . '`';
1295 } else {
1296 return $a_name;
1297 }
1298 } // end of the 'PMA_backquote()' function
1299  
1300  
1301 /**
1302 * Format a string so it can be passed to a javascript function.
1303 * This function is used to displays a javascript confirmation box for
1304 * "DROP/DELETE/ALTER" queries.
1305 *
1306 * @param string the string to format
1307 * @param boolean whether to add backquotes to the string or not
1308 *
1309 * @return string the formated string
1310 *
1311 * @access public
1312 */
1313 function PMA_jsFormat($a_string = '', $add_backquotes = true)
1314 {
1315 if (is_string($a_string)) {
1316 $a_string = htmlspecialchars($a_string);
1317 $a_string = str_replace('\\', '\\\\', $a_string);
1318 $a_string = str_replace('\'', '\\\'', $a_string);
1319 $a_string = str_replace('#', '\\#', $a_string);
1320 $a_string = str_replace("\012", '\\\\n', $a_string);
1321 $a_string = str_replace("\015", '\\\\r', $a_string);
1322 }
1323  
1324 return (($add_backquotes) ? PMA_backquote($a_string) : $a_string);
1325 } // end of the 'PMA_jsFormat()' function
1326  
1327  
1328 /**
1329 * Defines the <CR><LF> value depending on the user OS.
1330 *
1331 * @return string the <CR><LF> value to use
1332 *
1333 * @access public
1334 */
1335 function PMA_whichCrlf()
1336 {
1337 $the_crlf = "\n";
1338  
1339 // The 'PMA_USR_OS' constant is defined in "./libraries/defines.lib.php"
1340 // Win case
1341 if (PMA_USR_OS == 'Win') {
1342 $the_crlf = "\r\n";
1343 }
1344 // Mac case
1345 elseif (PMA_USR_OS == 'Mac') {
1346 $the_crlf = "\r";
1347 }
1348 // Others
1349 else {
1350 $the_crlf = "\n";
1351 }
1352  
1353 return $the_crlf;
1354 } // end of the 'PMA_whichCrlf()' function
1355  
1356 /**
1357 * Checks if this "table" is a view
1358 *
1359 * @param string the database name
1360 * @param string the table name
1361 *
1362 * @return boolean whether this is a view
1363 *
1364 * @access public
1365 */
1366 function PMA_tableIsView($db, $table) {
1367 // maybe we already know if the table is a view
1368 // TODO: see what we could do with the possible existence
1369 // of $table_is_view
1370 if (isset($GLOBALS['tbl_is_view']) && $GLOBALS['tbl_is_view']) {
1371 return true;
1372 }
1373 // old MySQL version: no view
1374 if (PMA_MYSQL_INT_VERSION < 50000) {
1375 return false;
1376 }
1377 if ( false === PMA_DBI_fetch_value('SELECT TABLE_NAME FROM information_schema.VIEWS WHERE TABLE_SCHEMA = \'' . $db . '\' AND TABLE_NAME = \'' . $table . '\';')) {
1378 return false;
1379 } else {
1380 return true;
1381 }
1382 }
1383  
1384 /**
1385 * Counts and returns (or displays) the number of records in a table
1386 *
1387 * Revision 13 July 2001: Patch for limiting dump size from
1388 * vinay@sanisoft.com & girish@sanisoft.com
1389 *
1390 * @param string the current database name
1391 * @param string the current table name
1392 * @param boolean whether to retain or to displays the result
1393 * @param boolean whether to force an exact count
1394 *
1395 * @return mixed the number of records if retain is required, true else
1396 *
1397 * @access public
1398 */
1399 function PMA_countRecords($db, $table, $ret = false, $force_exact = false)
1400 {
1401 global $err_url, $cfg;
1402 if (!$force_exact) {
1403 $result = PMA_DBI_query('SHOW TABLE STATUS FROM ' . PMA_backquote($db) . ' LIKE \'' . PMA_sqlAddslashes($table, true) . '\';');
1404 $showtable = PMA_DBI_fetch_assoc($result);
1405 $num = (isset($showtable['Rows']) ? $showtable['Rows'] : 0);
1406 if ($num < $cfg['MaxExactCount']) {
1407 unset($num);
1408 }
1409 PMA_DBI_free_result($result);
1410 }
1411  
1412 $tbl_is_view = PMA_tableIsView($db, $table);
1413  
1414 if (!isset($num)) {
1415 if (! $tbl_is_view) {
1416 $num = PMA_DBI_fetch_value('SELECT COUNT(*) AS num FROM ' . PMA_backquote($db) . '.' . PMA_backquote($table));
1417 // necessary?
1418 if (! $num) {
1419 $num = 0;
1420 }
1421 // since counting all rows of a view could be too long
1422 } else {
1423 // try_query because if can fail (a VIEW was based on a
1424 // table that no longer exists)
1425 $result = PMA_DBI_try_query('SELECT 1 FROM ' . PMA_backquote($db) . '.' . PMA_backquote($table) . ' LIMIT ' . $cfg['MaxExactCount'], null, PMA_DBI_QUERY_STORE);
1426 if (!PMA_DBI_getError()) {
1427 $num = PMA_DBI_num_rows($result);
1428 } else {
1429 $num = 0;
1430 }
1431 }
1432 }
1433 if ($ret) {
1434 return $num;
1435 } else {
1436 // Note: as of PMA 2.8.0, we no longer seem to be using
1437 // PMA_countRecords() in display mode.
1438 echo number_format($num, 0, $GLOBALS['number_decimal_separator'], $GLOBALS['number_thousands_separator']);
1439 if ($tbl_is_view) {
1440 echo '&nbsp;' . sprintf($GLOBALS['strViewMaxExactCount'], $cfg['MaxExactCount'], '[a@./Documentation.html#cfg_MaxExactCount@_blank]', '[/a]');
1441 }
1442 return true;
1443 }
1444 } // end of the 'PMA_countRecords()' function
1445  
1446 /**
1447 * Reloads navigation if needed.
1448 *
1449 * @global mixed configuration
1450 * @global bool whether to reload
1451 *
1452 * @access public
1453 */
1454 function PMA_reloadNavigation()
1455 {
1456 global $cfg;
1457  
1458 // Reloads the navigation frame via JavaScript if required
1459 if (isset($GLOBALS['reload']) && $GLOBALS['reload']) {
1460 echo "\n";
1461 $reload_url = './left.php?' . PMA_generate_common_url((isset($GLOBALS['db']) ? $GLOBALS['db'] : ''), '', '&');
1462 ?>
1463 <script type="text/javascript" language="javascript">
1464 //<![CDATA[
1465 if (typeof(window.parent) != 'undefined'
1466 && typeof(window.parent.frames[0]) != 'undefined') {
1467 window.parent.goTo('<?php echo $reload_url; ?>');
1468 }
1469 //]]>
1470 </script>
1471 <?php
1472 unset($GLOBALS['reload']);
1473 }
1474 }
1475  
1476 /**
1477 * Displays a message at the top of the "main" (right) frame
1478 *
1479 * @param string the message to display
1480 *
1481 * @global array the configuration array
1482 *
1483 * @access public
1484 */
1485 function PMA_showMessage($message)
1486 {
1487 global $cfg;
1488  
1489 // Sanitizes $message
1490 $message = PMA_sanitize($message);
1491  
1492 // Corrects the tooltip text via JS if required
1493 if ( isset($GLOBALS['table']) && strlen($GLOBALS['table']) && $cfg['ShowTooltip']) {
1494 $result = PMA_DBI_try_query('SHOW TABLE STATUS FROM ' . PMA_backquote($GLOBALS['db']) . ' LIKE \'' . PMA_sqlAddslashes($GLOBALS['table'], true) . '\'');
1495 if ($result) {
1496 $tbl_status = PMA_DBI_fetch_assoc($result);
1497 $tooltip = (empty($tbl_status['Comment']))
1498 ? ''
1499 : $tbl_status['Comment'] . ' ';
1500 $tooltip .= '(' . PMA_formatNumber($tbl_status['Rows'], 0) . ' ' . $GLOBALS['strRows'] . ')';
1501 PMA_DBI_free_result($result);
1502 $uni_tbl = PMA_jsFormat($GLOBALS['db'] . '.' . $GLOBALS['table'], false);
1503 echo "\n";
1504 ?>
1505 <script type="text/javascript" language="javascript">
1506 //<![CDATA[
1507 window.parent.updateTableTitle('<?php echo $uni_tbl; ?>', '<?php echo PMA_jsFormat($tooltip, false); ?>');
1508 //]]>
1509 </script>
1510 <?php
1511 } // end if
1512 } // end if ... elseif
1513  
1514 // Checks if the table needs to be repaired after a TRUNCATE query.
1515 if (isset($GLOBALS['table']) && isset($GLOBALS['sql_query'])
1516 && $GLOBALS['sql_query'] == 'TRUNCATE TABLE ' . PMA_backquote($GLOBALS['table'])) {
1517 if (!isset($tbl_status)) {
1518 $result = @PMA_DBI_try_query('SHOW TABLE STATUS FROM ' . PMA_backquote($GLOBALS['db']) . ' LIKE \'' . PMA_sqlAddslashes($GLOBALS['table'], true) . '\'');
1519 if ($result) {
1520 $tbl_status = PMA_DBI_fetch_assoc($result);
1521 PMA_DBI_free_result($result);
1522 }
1523 }
1524 if (isset($tbl_status) && (int) $tbl_status['Index_length'] > 1024) {
1525 PMA_DBI_try_query('REPAIR TABLE ' . PMA_backquote($GLOBALS['table']));
1526 }
1527 }
1528 unset($tbl_status);
1529 ?>
1530 <br />
1531 <div align="<?php echo $GLOBALS['cell_align_left']; ?>">
1532 <?php
1533 if (!empty($GLOBALS['show_error_header'])) {
1534 ?>
1535 <div class="error">
1536 <h1><?php echo $GLOBALS['strError']; ?></h1>
1537 <?php
1538 }
1539  
1540 echo $message;
1541 if (isset($GLOBALS['special_message'])) {
1542 echo PMA_sanitize($GLOBALS['special_message']);
1543 unset($GLOBALS['special_message']);
1544 }
1545  
1546 if (!empty($GLOBALS['show_error_header'])) {
1547 echo '</div>';
1548 }
1549  
1550 if ($cfg['ShowSQL'] == true
1551 && (!empty($GLOBALS['sql_query']) || !empty($GLOBALS['display_query']))) {
1552 $local_query = !empty($GLOBALS['display_query']) ? $GLOBALS['display_query'] : (($cfg['SQP']['fmtType'] == 'none' && isset($GLOBALS['unparsed_sql']) && $GLOBALS['unparsed_sql'] != '') ? $GLOBALS['unparsed_sql'] : $GLOBALS['sql_query']);
1553 // Basic url query part
1554 $url_qpart = '?' . PMA_generate_common_url(isset($GLOBALS['db']) ? $GLOBALS['db'] : '', isset($GLOBALS['table']) ? $GLOBALS['table'] : '');
1555  
1556 // Html format the query to be displayed
1557 // The nl2br function isn't used because its result isn't a valid
1558 // xhtml1.0 statement before php4.0.5 ("<br>" and not "<br />")
1559 // If we want to show some sql code it is easiest to create it here
1560 /* SQL-Parser-Analyzer */
1561  
1562 if (!empty($GLOBALS['show_as_php'])) {
1563 $new_line = '\'<br />' . "\n" . '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. \' ';
1564 }
1565 if (isset($new_line)) {
1566 /* SQL-Parser-Analyzer */
1567 $query_base = PMA_sqlAddslashes(htmlspecialchars($local_query), false, false, true);
1568 /* SQL-Parser-Analyzer */
1569 $query_base = preg_replace("@((\015\012)|(\015)|(\012))+@", $new_line, $query_base);
1570 } else {
1571 $query_base = $local_query;
1572 }
1573  
1574 // Parse SQL if needed
1575 if (isset($GLOBALS['parsed_sql']) && $query_base == $GLOBALS['parsed_sql']['raw']) {
1576 $parsed_sql = $GLOBALS['parsed_sql'];
1577 } else {
1578 // when the query is large (for example an INSERT of binary
1579 // data), the parser chokes; so avoid parsing it
1580 if (strlen($query_base) < 1000) {
1581 $parsed_sql = PMA_SQP_parse($query_base);
1582 }
1583 }
1584  
1585 // Analyze it
1586 if (isset($parsed_sql)) {
1587 $analyzed_display_query = PMA_SQP_analyze($parsed_sql);
1588 }
1589  
1590 // Here we append the LIMIT added for navigation, to
1591 // enable its display. Adding it higher in the code
1592 // to $local_query would create a problem when
1593 // using the Refresh or Edit links.
1594  
1595 // Only append it on SELECTs.
1596  
1597 // FIXME: what would be the best to do when someone
1598 // hits Refresh: use the current LIMITs ?
1599  
1600 if (isset($analyzed_display_query[0]['queryflags']['select_from'])
1601 && isset($GLOBALS['sql_limit_to_append'])) {
1602 $query_base = $analyzed_display_query[0]['section_before_limit'] . "\n" . $GLOBALS['sql_limit_to_append'] . $analyzed_display_query[0]['section_after_limit'];
1603 // Need to reparse query
1604 $parsed_sql = PMA_SQP_parse($query_base);
1605 }
1606  
1607 if (!empty($GLOBALS['show_as_php'])) {
1608 $query_base = '$sql = \'' . $query_base;
1609 } elseif (!empty($GLOBALS['validatequery'])) {
1610 $query_base = PMA_validateSQL($query_base);
1611 } else {
1612 if (isset($parsed_sql)) {
1613 $query_base = PMA_formatSql($parsed_sql, $query_base);
1614 }
1615 }
1616  
1617 // Prepares links that may be displayed to edit/explain the query
1618 // (don't go to default pages, we must go to the page
1619 // where the query box is available)
1620 // (also, I don't see why we should check the goto variable)
1621  
1622 //if (!isset($GLOBALS['goto'])) {
1623 //$edit_target = (isset($GLOBALS['table'])) ? $cfg['DefaultTabTable'] : $cfg['DefaultTabDatabase'];
1624 $edit_target = isset($GLOBALS['db']) ? (isset($GLOBALS['table']) ? 'tbl_properties.php' : 'db_details.php') : 'server_sql.php';
1625 //} elseif ($GLOBALS['goto'] != 'main.php') {
1626 // $edit_target = $GLOBALS['goto'];
1627 //} else {
1628 // $edit_target = '';
1629 //}
1630  
1631 if (isset($cfg['SQLQuery']['Edit'])
1632 && ($cfg['SQLQuery']['Edit'] == true)
1633 && (!empty($edit_target))) {
1634  
1635 if ($cfg['EditInWindow'] == true) {
1636 $onclick = 'window.parent.focus_querywindow(\'' . urlencode($local_query) . '\'); return false;';
1637 } else {
1638 $onclick = '';
1639 }
1640  
1641 $edit_link = $edit_target
1642 . $url_qpart
1643 . '&amp;sql_query=' . urlencode($local_query)
1644 . '&amp;show_query=1#querybox';
1645 $edit_link = ' [' . PMA_linkOrButton($edit_link, $GLOBALS['strEdit'], array('onclick' => $onclick)) . ']';
1646 } else {
1647 $edit_link = '';
1648 }
1649  
1650 // Want to have the query explained (Mike Beck 2002-05-22)
1651 // but only explain a SELECT (that has not been explained)
1652 /* SQL-Parser-Analyzer */
1653 if (isset($cfg['SQLQuery']['Explain'])
1654 && $cfg['SQLQuery']['Explain'] == true) {
1655  
1656 // Detect if we are validating as well
1657 // To preserve the validate uRL data
1658 if (!empty($GLOBALS['validatequery'])) {
1659 $explain_link_validate = '&amp;validatequery=1';
1660 } else {
1661 $explain_link_validate = '';
1662 }
1663  
1664 $explain_link = 'import.php'
1665 . $url_qpart
1666 . $explain_link_validate
1667 . '&amp;sql_query=';
1668  
1669 if (preg_match('@^SELECT[[:space:]]+@i', $local_query)) {
1670 $explain_link .= urlencode('EXPLAIN ' . $local_query);
1671 $message = $GLOBALS['strExplain'];
1672 } elseif (preg_match('@^EXPLAIN[[:space:]]+SELECT[[:space:]]+@i', $local_query)) {
1673 $explain_link .= urlencode(substr($local_query, 8));
1674 $message = $GLOBALS['strNoExplain'];
1675 } else {
1676 $explain_link = '';
1677 }
1678 if (!empty($explain_link)) {
1679 $explain_link = ' [' . PMA_linkOrButton($explain_link, $message) . ']';
1680 }
1681 } else {
1682 $explain_link = '';
1683 } //show explain
1684  
1685 // Also we would like to get the SQL formed in some nice
1686 // php-code (Mike Beck 2002-05-22)
1687 if (isset($cfg['SQLQuery']['ShowAsPHP'])
1688 && $cfg['SQLQuery']['ShowAsPHP'] == true) {
1689 $php_link = 'import.php'
1690 . $url_qpart
1691 . '&amp;show_query=1'
1692 . '&amp;sql_query=' . urlencode($local_query)
1693 . '&amp;show_as_php=';
1694  
1695 if (!empty($GLOBALS['show_as_php'])) {
1696 $php_link .= '0';
1697 $message = $GLOBALS['strNoPhp'];
1698 } else {
1699 $php_link .= '1';
1700 $message = $GLOBALS['strPhp'];
1701 }
1702 $php_link = ' [' . PMA_linkOrButton($php_link, $message) . ']';
1703  
1704 if (isset($GLOBALS['show_as_php']) && $GLOBALS['show_as_php'] == '1') {
1705 $runquery_link
1706 = 'import.php'
1707 . $url_qpart
1708 . '&amp;show_query=1'
1709 . '&amp;sql_query=' . urlencode($local_query);
1710 $php_link .= ' [' . PMA_linkOrButton($runquery_link, $GLOBALS['strRunQuery']) . ']';
1711 }
1712  
1713 } else {
1714 $php_link = '';
1715 } //show as php
1716  
1717 // Refresh query
1718 if (isset($cfg['SQLQuery']['Refresh'])
1719 && $cfg['SQLQuery']['Refresh']
1720 && preg_match('@^(SELECT|SHOW)[[:space:]]+@i', $local_query)) {
1721 $refresh_link = 'import.php'
1722 . $url_qpart
1723 . '&amp;show_query=1'
1724 . (isset($_GET['pos']) ? '&amp;pos=' . $_GET['pos'] : '')
1725 . '&amp;sql_query=' . urlencode($local_query);
1726 $refresh_link = ' [' . PMA_linkOrButton($refresh_link, $GLOBALS['strRefresh']) . ']';
1727 } else {
1728 $refresh_link = '';
1729 } //show as php
1730  
1731 if (isset($cfg['SQLValidator']['use'])
1732 && $cfg['SQLValidator']['use'] == true
1733 && isset($cfg['SQLQuery']['Validate'])
1734 && $cfg['SQLQuery']['Validate'] == true) {
1735 $validate_link = 'import.php'
1736 . $url_qpart
1737 . '&amp;show_query=1'
1738 . '&amp;sql_query=' . urlencode($local_query)
1739 . '&amp;validatequery=';
1740 if (!empty($GLOBALS['validatequery'])) {
1741 $validate_link .= '0';
1742 $validate_message = $GLOBALS['strNoValidateSQL'] ;
1743 } else {
1744 $validate_link .= '1';
1745 $validate_message = $GLOBALS['strValidateSQL'] ;
1746 }
1747 $validate_link = ' [' . PMA_linkOrButton($validate_link, $validate_message) . ']';
1748 } else {
1749 $validate_link = '';
1750 } //validator
1751 unset($local_query);
1752  
1753 // Displays the message
1754 echo '<fieldset class="">' . "\n";
1755 echo ' <legend>' . $GLOBALS['strSQLQuery'] . ':</legend>';
1756 echo ' ' . $query_base;
1757  
1758 //Clean up the end of the PHP
1759 if (!empty($GLOBALS['show_as_php'])) {
1760 echo '\';';
1761 }
1762 echo '</fieldset>' . "\n";
1763  
1764 if (!empty($edit_target)) {
1765 echo '<fieldset class="tblFooters">';
1766 echo $edit_link . $explain_link . $php_link . $refresh_link . $validate_link;
1767 echo '</fieldset>';
1768 }
1769 }
1770 ?>
1771 </div><br />
1772 <?php
1773 } // end of the 'PMA_showMessage()' function
1774  
1775  
1776 /**
1777 * Formats $value to byte view
1778 *
1779 * @param double the value to format
1780 * @param integer the sensitiveness
1781 * @param integer the number of decimals to retain
1782 *
1783 * @return array the formatted value and its unit
1784 *
1785 * @access public
1786 *
1787 * @author staybyte
1788 * @version 1.2 - 18 July 2002
1789 */
1790 function PMA_formatByteDown($value, $limes = 6, $comma = 0)
1791 {
1792 $dh = pow(10, $comma);
1793 $li = pow(10, $limes);
1794 $return_value = $value;
1795 $unit = $GLOBALS['byteUnits'][0];
1796  
1797 for ($d = 6, $ex = 15; $d >= 1; $d--, $ex-=3) {
1798 if (isset($GLOBALS['byteUnits'][$d]) && $value >= $li * pow(10, $ex)) {
1799 $value = round($value / (pow(1024, $d) / $dh)) /$dh;
1800 $unit = $GLOBALS['byteUnits'][$d];
1801 break 1;
1802 } // end if
1803 } // end for
1804  
1805 if ($unit != $GLOBALS['byteUnits'][0]) {
1806 $return_value = number_format($value, $comma, $GLOBALS['number_decimal_separator'], $GLOBALS['number_thousands_separator']);
1807 } else {
1808 $return_value = number_format($value, 0, $GLOBALS['number_decimal_separator'], $GLOBALS['number_thousands_separator']);
1809 }
1810  
1811 return array($return_value, $unit);
1812 } // end of the 'PMA_formatByteDown' function
1813  
1814 /**
1815 * Formats $value to the given length and appends SI prefixes
1816 * $comma is not substracted from the length
1817 * with a $length of 0 no truncation occurs, number is only formated
1818 * to the current locale
1819 * <code>
1820 * echo PMA_formatNumber(123456789, 6); // 123,457 k
1821 * echo PMA_formatNumber(-123456789, 4, 2); // -123.46 M
1822 * echo PMA_formatNumber(-0.003, 6); // -3 m
1823 * echo PMA_formatNumber(0.003, 3, 3); // 0.003
1824 * echo PMA_formatNumber(0.00003, 3, 2); // 0.03 m
1825 * echo PMA_formatNumber(0, 6); // 0
1826 * </code>
1827 * @param double $value the value to format
1828 * @param integer $length the max length
1829 * @param integer $comma the number of decimals to retain
1830 * @param boolean $only_down do not reformat numbers below 1
1831 *
1832 * @return string the formatted value and its unit
1833 *
1834 * @access public
1835 *
1836 * @author staybyte, sebastian mendel
1837 * @version 1.1.0 - 2005-10-27
1838 */
1839 function PMA_formatNumber($value, $length = 3, $comma = 0, $only_down = false)
1840 {
1841 if ($length === 0) {
1842 return number_format($value,
1843 $comma,
1844 $GLOBALS['number_decimal_separator'],
1845 $GLOBALS['number_thousands_separator']);
1846 }
1847  
1848 // this units needs no translation, ISO
1849 $units = array(
1850 -8 => 'y',
1851 -7 => 'z',
1852 -6 => 'a',
1853 -5 => 'f',
1854 -4 => 'p',
1855 -3 => 'n',
1856 -2 => '&micro;',
1857 -1 => 'm',
1858  
1859 1 => 'k',
1860 2 => 'M',
1861 3 => 'G',
1862 4 => 'T',
1863 5 => 'P',
1864 6 => 'E',
1865 7 => 'Z',
1866 8 => 'Y'
1867 );
1868  
1869 // we need at least 3 digits to be displayed
1870 if (3 > $length + $comma) {
1871 $length = 3 - $comma;
1872 }
1873  
1874 // check for negativ value to retain sign
1875 if ($value < 0) {
1876 $sign = '-';
1877 $value = abs($value);
1878 } else {
1879 $sign = '';
1880 }
1881  
1882 $dh = pow(10, $comma);
1883 $li = pow(10, $length);
1884 $unit = $units[0];
1885  
1886 if ($value >= 1) {
1887 for ($d = 8; $d >= 0; $d--) {
1888 if (isset($units[$d]) && $value >= $li * pow(1000, $d-1)) {
1889 $value = round($value / (pow(1000, $d) / $dh)) /$dh;
1890 $unit = $units[$d];
1891 break 1;
1892 } // end if
1893 } // end for
1894 } elseif (!$only_down && (float) $value !== 0.0) {
1895 for ($d = -8; $d <= 8; $d++) {
1896 if (isset($units[$d]) && $value <= $li * pow(1000, $d-1)) {
1897 $value = round($value / (pow(1000, $d) / $dh)) /$dh;
1898 $unit = $units[$d];
1899 break 1;
1900 } // end if
1901 } // end for
1902 } // end if ($value >= 1) elseif (!$only_down && (float) $value !== 0.0)
1903  
1904 $value = number_format($value,
1905 $comma,
1906 $GLOBALS['number_decimal_separator'],
1907 $GLOBALS['number_thousands_separator']);
1908  
1909 return $sign . $value . ' ' . $unit;
1910 } // end of the 'PMA_formatNumber' function
1911  
1912 /**
1913 * Extracts ENUM / SET options from a type definition string
1914 *
1915 * @param string The column type definition
1916 *
1917 * @return array The options or
1918 * boolean false in case of an error.
1919 *
1920 * @author rabus
1921 */
1922 function PMA_getEnumSetOptions($type_def)
1923 {
1924 $open = strpos($type_def, '(');
1925 $close = strrpos($type_def, ')');
1926 if (!$open || !$close) {
1927 return false;
1928 }
1929 $options = substr($type_def, $open + 2, $close - $open - 3);
1930 $options = explode('\',\'', $options);
1931 return $options;
1932 } // end of the 'PMA_getEnumSetOptions' function
1933  
1934 /**
1935 * Writes localised date
1936 *
1937 * @param string the current timestamp
1938 *
1939 * @return string the formatted date
1940 *
1941 * @access public
1942 */
1943 function PMA_localisedDate($timestamp = -1, $format = '')
1944 {
1945 global $datefmt, $month, $day_of_week;
1946  
1947 if ($format == '') {
1948 $format = $datefmt;
1949 }
1950  
1951 if ($timestamp == -1) {
1952 $timestamp = time();
1953 }
1954  
1955 $date = preg_replace('@%[aA]@', $day_of_week[(int)strftime('%w', $timestamp)], $format);
1956 $date = preg_replace('@%[bB]@', $month[(int)strftime('%m', $timestamp)-1], $date);
1957  
1958 return strftime($date, $timestamp);
1959 } // end of the 'PMA_localisedDate()' function
1960  
1961  
1962 /**
1963 * returns a tab for tabbed navigation.
1964 * If the variables $link and $args ar left empty, an inactive tab is created
1965 *
1966 * @uses array_merge()
1967 * basename()
1968 * $GLOBALS['strEmpty']
1969 * $GLOBALS['strDrop']
1970 * $GLOBALS['active_page']
1971 * $GLOBALS['PHP_SELF']
1972 * htmlentities()
1973 * PMA_generate_common_url()
1974 * $GLOBALS['url_query']
1975 * urlencode()
1976 * $GLOBALS['cfg']['MainPageIconic']
1977 * $GLOBALS['pmaThemeImage']
1978 * sprintf()
1979 * trigger_error()
1980 * E_USER_NOTICE
1981 * @param array $tab array with all options
1982 * @return string html code for one tab, a link if valid otherwise a span
1983 * @access public
1984 */
1985 function PMA_getTab($tab)
1986 {
1987 // default values
1988 $defaults = array(
1989 'text' => '',
1990 'class' => '',
1991 'active' => false,
1992 'link' => '',
1993 'sep' => '?',
1994 'attr' => '',
1995 'args' => '',
1996 );
1997  
1998 $tab = array_merge($defaults, $tab);
1999  
2000 // determine additionnal style-class
2001 if (empty($tab['class'])) {
2002 if ($tab['text'] == $GLOBALS['strEmpty']
2003 || $tab['text'] == $GLOBALS['strDrop']) {
2004 $tab['class'] = 'caution';
2005 } elseif (!empty($tab['active'])
2006 || (isset($GLOBALS['active_page'])
2007 && $GLOBALS['active_page'] == $tab['link'])
2008 || basename(PMA_getenv('PHP_SELF')) == $tab['link'])
2009 {
2010 $tab['class'] = 'active';
2011 }
2012 }
2013  
2014 // build the link
2015 if (!empty($tab['link'])) {
2016 $tab['link'] = htmlentities($tab['link']);
2017 $tab['link'] = $tab['link'] . $tab['sep']
2018 .(empty($GLOBALS['url_query']) ?
2019 PMA_generate_common_url() : $GLOBALS['url_query']);
2020 if (!empty($tab['args'])) {
2021 foreach ($tab['args'] as $param => $value) {
2022 $tab['link'] .= '&amp;' . urlencode($param) . '='
2023 . urlencode($value);
2024 }
2025 }
2026 }
2027  
2028 // display icon, even if iconic is disabled but the link-text is missing
2029 if (($GLOBALS['cfg']['MainPageIconic'] || empty($tab['text']))
2030 && isset($tab['icon'])) {
2031 $image = '<img class="icon" src="' . htmlentities($GLOBALS['pmaThemeImage'])
2032 .'%1$s" width="16" height="16" alt="%2$s" />%2$s';
2033 $tab['text'] = sprintf($image, htmlentities($tab['icon']), $tab['text']);
2034 }
2035 // check to not display an empty link-text
2036 elseif (empty($tab['text'])) {
2037 $tab['text'] = '?';
2038 trigger_error('empty linktext in function ' . __FUNCTION__ . '()',
2039 E_USER_NOTICE);
2040 }
2041  
2042 if (!empty($tab['link'])) {
2043 $out = '<a class="tab' . htmlentities($tab['class']) . '"'
2044 .' href="' . $tab['link'] . '" ' . $tab['attr'] . '>'
2045 . $tab['text'] . '</a>';
2046 } else {
2047 $out = '<span class="tab' . htmlentities($tab['class']) . '">'
2048 . $tab['text'] . '</span>';
2049 }
2050  
2051 return $out;
2052 } // end of the 'PMA_getTab()' function
2053  
2054 /**
2055 * returns html-code for a tab navigation
2056 *
2057 * @uses PMA_getTab()
2058 * @uses htmlentities()
2059 * @param array $tabs one element per tab
2060 * @param string $tag_id id used for the html-tag
2061 * @return string html-code for tab-navigation
2062 */
2063 function PMA_getTabs($tabs, $tag_id = 'topmenu')
2064 {
2065 $tab_navigation =
2066 '<div id="' . htmlentities($tag_id) . 'container">' . "\n"
2067 .'<ul id="' . htmlentities($tag_id) . '">' . "\n";
2068  
2069 foreach ($tabs as $tab) {
2070 $tab_navigation .= '<li>' . PMA_getTab($tab) . '</li>' . "\n";
2071 }
2072  
2073 $tab_navigation .=
2074 '</ul>' . "\n"
2075 .'<div class="clearfloat"></div>'
2076 .'</div>' . "\n";
2077  
2078 return $tab_navigation;
2079 }
2080  
2081  
2082 /**
2083 * Displays a link, or a button if the link's URL is too large, to
2084 * accommodate some browsers' limitations
2085 *
2086 * @param string the URL
2087 * @param string the link message
2088 * @param mixed $tag_params string: js confirmation
2089 * array: additional tag params (f.e. style="")
2090 * @param boolean $new_form we set this to false when we are already in
2091 * a form, to avoid generating nested forms
2092 *
2093 * @return string the results to be echoed or saved in an array
2094 */
2095 function PMA_linkOrButton($url, $message, $tag_params = array(),
2096 $new_form = true, $strip_img = false, $target = '')
2097 {
2098 if (! is_array($tag_params)) {
2099 $tmp = $tag_params;
2100 $tag_params = array();
2101 if (!empty($tmp)) {
2102 $tag_params['onclick'] = 'return confirmLink(this, \'' . $tmp . '\')';
2103 }
2104 unset($tmp);
2105 }
2106 if (! empty($target)) {
2107 $tag_params['target'] = htmlentities($target);
2108 }
2109  
2110 $tag_params_strings = array();
2111 foreach ($tag_params as $par_name => $par_value) {
2112 // htmlentities() only on non javascript
2113 $par_value = substr($par_name, 0, 2) == 'on'
2114 ? $par_value
2115 : htmlentities($par_value);
2116 $tag_params_strings[] = $par_name . '="' . $par_value . '"';
2117 }
2118  
2119 // previously the limit was set to 2047, it seems 1000 is better
2120 if (strlen($url) <= 1000) {
2121 // no whitespace within an <a> else Safari will make it part of the link
2122 $ret = "\n" . '<a href="' . $url . '" '
2123 . implode(' ', $tag_params_strings) . '>'
2124 . $message . '</a>' . "\n";
2125 } else {
2126 // no spaces (linebreaks) at all
2127 // or after the hidden fields
2128 // IE will display them all
2129  
2130 // add class=link to submit button
2131 if (empty($tag_params['class'])) {
2132 $tag_params['class'] = 'link';
2133 }
2134 $url = str_replace('&amp;', '&', $url);
2135 $url_parts = parse_url($url);
2136 $query_parts = explode('&', $url_parts['query']);
2137 if ($new_form) {
2138 $ret = '<form action="' . $url_parts['path'] . '" class="link"'
2139 . ' method="post"' . $target . ' style="display: inline;">';
2140 $subname_open = '';
2141 $subname_close = '';
2142 $submit_name = '';
2143 } else {
2144 $query_parts[] = 'redirect=' . $url_parts['path'];
2145 if (empty($GLOBALS['subform_counter'])) {
2146 $GLOBALS['subform_counter'] = 0;
2147 }
2148 $GLOBALS['subform_counter']++;
2149 $ret = '';
2150 $subname_open = 'subform[' . $GLOBALS['subform_counter'] . '][';
2151 $subname_close = ']';
2152 $submit_name = ' name="usesubform[' . $GLOBALS['subform_counter'] . ']"';
2153 }
2154 foreach ($query_parts AS $query_pair) {
2155 list($eachvar, $eachval) = explode('=', $query_pair);
2156 $ret .= '<input type="hidden" name="' . $subname_open . $eachvar
2157 . $subname_close . '" value="'
2158 . htmlspecialchars(urldecode($eachval)) . '" />';
2159 } // end while
2160  
2161 if (stristr($message, '<img')) {
2162 if ($strip_img) {
2163 $message = trim(strip_tags($message));
2164 $ret .= '<input type="submit"' . $submit_name . ' '
2165 . implode(' ', $tag_params_strings)
2166 . ' value="' . htmlspecialchars($message) . '" />';
2167 } else {
2168 $ret .= '<input type="image"' . $submit_name . ' '
2169 . implode(' ', $tag_params_strings)
2170 . ' src="' . preg_replace(
2171 '/^.*\ssrc="([^"]*)".*$/si', '\1', $message) . '"'
2172 . ' value="' . htmlspecialchars(
2173 preg_replace('/^.*\salt="([^"]*)".*$/si', '\1',
2174 $message))
2175 . '" />';
2176 }
2177 } else {
2178 $message = trim(strip_tags($message));
2179 $ret .= '<input type="submit"' . $submit_name . ' '
2180 . implode(' ', $tag_params_strings)
2181 . ' value="' . htmlspecialchars($message) . '" />';
2182 }
2183 if ($new_form) {
2184 $ret .= '</form>';
2185 }
2186 } // end if... else...
2187  
2188 return $ret;
2189 } // end of the 'PMA_linkOrButton()' function
2190  
2191  
2192 /**
2193 * Returns a given timespan value in a readable format.
2194 *
2195 * @param int the timespan
2196 *
2197 * @return string the formatted value
2198 */
2199 function PMA_timespanFormat($seconds)
2200 {
2201 $return_string = '';
2202 $days = floor($seconds / 86400);
2203 if ($days > 0) {
2204 $seconds -= $days * 86400;
2205 }
2206 $hours = floor($seconds / 3600);
2207 if ($days > 0 || $hours > 0) {
2208 $seconds -= $hours * 3600;
2209 }
2210 $minutes = floor($seconds / 60);
2211 if ($days > 0 || $hours > 0 || $minutes > 0) {
2212 $seconds -= $minutes * 60;
2213 }
2214 return sprintf($GLOBALS['timespanfmt'], (string)$days, (string)$hours, (string)$minutes, (string)$seconds);
2215 }
2216  
2217 /**
2218 * Takes a string and outputs each character on a line for itself. Used
2219 * mainly for horizontalflipped display mode.
2220 * Takes care of special html-characters.
2221 * Fulfills todo-item
2222 * http://sf.net/tracker/?func=detail&aid=544361&group_id=23067&atid=377411
2223 *
2224 * @param string The string
2225 * @param string The Separator (defaults to "<br />\n")
2226 *
2227 * @access public
2228 * @author Garvin Hicking <me@supergarv.de>
2229 * @return string The flipped string
2230 */
2231 function PMA_flipstring($string, $Separator = "<br />\n")
2232 {
2233 $format_string = '';
2234 $charbuff = false;
2235  
2236 for ($i = 0; $i < strlen($string); $i++) {
2237 $char = $string{$i};
2238 $append = false;
2239  
2240 if ($char == '&') {
2241 $format_string .= $charbuff;
2242 $charbuff = $char;
2243 $append = true;
2244 } elseif (!empty($charbuff)) {
2245 $charbuff .= $char;
2246 } elseif ($char == ';' && !empty($charbuff)) {
2247 $format_string .= $charbuff;
2248 $charbuff = false;
2249 $append = true;
2250 } else {
2251 $format_string .= $char;
2252 $append = true;
2253 }
2254  
2255 if ($append && ($i != strlen($string))) {
2256 $format_string .= $Separator;
2257 }
2258 }
2259  
2260 return $format_string;
2261 }
2262  
2263  
2264 /**
2265 * Function added to avoid path disclosures.
2266 * Called by each script that needs parameters, it displays
2267 * an error message and, by default, stops the execution.
2268 *
2269 * Not sure we could use a strMissingParameter message here,
2270 * would have to check if the error message file is always available
2271 *
2272 * @param array The names of the parameters needed by the calling
2273 * script.
2274 * @param boolean Stop the execution?
2275 * (Set this manually to false in the calling script
2276 * until you know all needed parameters to check).
2277 * @param boolean Whether to include this list in checking for special params.
2278 * @global string path to current script
2279 * @global boolean flag whether any special variable was required
2280 *
2281 * @access public
2282 * @author Marc Delisle (lem9@users.sourceforge.net)
2283 */
2284 function PMA_checkParameters($params, $die = true, $request = true)
2285 {
2286 global $PHP_SELF, $checked_special;
2287  
2288 if (!isset($checked_special)) {
2289 $checked_special = false;
2290 }
2291  
2292 $reported_script_name = basename($PHP_SELF);
2293 $found_error = false;
2294 $error_message = '';
2295  
2296 foreach ($params AS $param) {
2297 if ($request && $param != 'db' && $param != 'table') {
2298 $checked_special = true;
2299 }
2300  
2301 if (!isset($GLOBALS[$param])) {
2302 $error_message .= $reported_script_name . ': Missing parameter: ' . $param . ' <a href="./Documentation.html#faqmissingparameters" target="documentation"> (FAQ 2.8)</a><br />';
2303 $found_error = true;
2304 }
2305 }
2306 if ($found_error) {
2307 require_once './libraries/header_meta_style.inc.php';
2308 echo '</head><body><p>' . $error_message . '</p></body></html>';
2309 if ($die) {
2310 exit();
2311 }
2312 }
2313 } // end function
2314  
2315 /**
2316 * Function to generate unique condition for specified row.
2317 *
2318 * @param resource handle for current query
2319 * @param integer number of fields
2320 * @param array meta information about fields
2321 * @param array current row
2322 *
2323 * @access public
2324 * @author Michal Cihar (michal@cihar.com)
2325 * @return string calculated condition
2326 */
2327 function PMA_getUvaCondition($handle, $fields_cnt, $fields_meta, $row)
2328 {
2329 $primary_key = '';
2330 $unique_key = '';
2331 $uva_nonprimary_condition = '';
2332  
2333 for ($i = 0; $i < $fields_cnt; ++$i) {
2334 $field_flags = PMA_DBI_field_flags($handle, $i);
2335 $meta = $fields_meta[$i];
2336 // do not use an alias in a condition
2337 $column_for_condition = $meta->name;
2338 if (isset($analyzed_sql[0]['select_expr']) && is_array($analyzed_sql[0]['select_expr'])) {
2339 foreach ($analyzed_sql[0]['select_expr'] AS $select_expr_position => $select_expr) {
2340 $alias = $analyzed_sql[0]['select_expr'][$select_expr_position]['alias'];
2341 if (strlen($alias)) {
2342 $true_column = $analyzed_sql[0]['select_expr'][$select_expr_position]['column'];
2343 if ($alias == $meta->name) {
2344 $column_for_condition = $true_column;
2345 } // end if
2346 } // end if
2347 } // end while
2348 }
2349  
2350 // to fix the bug where float fields (primary or not)
2351 // can't be matched because of the imprecision of
2352 // floating comparison, use CONCAT
2353 // (also, the syntax "CONCAT(field) IS NULL"
2354 // that we need on the next "if" will work)
2355 if ($meta->type == 'real') {
2356 $condition = ' CONCAT(' . PMA_backquote($column_for_condition) . ') ';
2357 } else {
2358 // string and blob fields have to be converted using
2359 // the system character set (always utf8) since
2360 // mysql4.1 can use different charset for fields.
2361 if (PMA_MYSQL_INT_VERSION >= 40100 && ($meta->type == 'string' || $meta->type == 'blob')) {
2362 $condition = ' CONVERT(' . PMA_backquote($column_for_condition) . ' USING utf8) ';
2363 } else {
2364 $condition = ' ' . PMA_backquote($column_for_condition) . ' ';
2365 }
2366 } // end if... else...
2367  
2368 if (!isset($row[$i]) || is_null($row[$i])) {
2369 $condition .= 'IS NULL AND';
2370 } else {
2371 // timestamp is numeric on some MySQL 4.1
2372 if ($meta->numeric && $meta->type != 'timestamp') {
2373 $condition .= '= ' . $row[$i] . ' AND';
2374 } elseif ($meta->type == 'blob'
2375 // hexify only if this is a true not empty BLOB
2376 && stristr($field_flags, 'BINARY')
2377 && !empty($row[$i])) {
2378 // use a CAST if possible, to avoid problems
2379 // if the field contains wildcard characters % or _
2380 if (PMA_MYSQL_INT_VERSION < 40002) {
2381 $condition .= 'LIKE 0x' . bin2hex($row[$i]). ' AND';
2382 } else {
2383 $condition .= '= CAST(0x' . bin2hex($row[$i]). ' AS BINARY) AND';
2384 }
2385 } else {
2386 $condition .= '= \'' . PMA_sqlAddslashes($row[$i], false, true) . '\' AND';
2387 }
2388 }
2389 if ($meta->primary_key > 0) {
2390 $primary_key .= $condition;
2391 } elseif ($meta->unique_key > 0) {
2392 $unique_key .= $condition;
2393 }
2394 $uva_nonprimary_condition .= $condition;
2395 } // end for
2396  
2397 // Correction uva 19991216: prefer primary or unique keys
2398 // for condition, but use conjunction of all values if no
2399 // primary key
2400 if ($primary_key) {
2401 $uva_condition = $primary_key;
2402 } elseif ($unique_key) {
2403 $uva_condition = $unique_key;
2404 } else {
2405 $uva_condition = $uva_nonprimary_condition;
2406 }
2407  
2408 return preg_replace('|\s?AND$|', '', $uva_condition);
2409 } // end function
2410  
2411 /**
2412 * Function to generate unique condition for specified row.
2413 *
2414 * @param string name of button element
2415 * @param string class of button element
2416 * @param string name of image element
2417 * @param string text to display
2418 * @param string image to display
2419 *
2420 * @access public
2421 * @author Michal Cihar (michal@cihar.com)
2422 */
2423 function PMA_buttonOrImage($button_name, $button_class, $image_name, $text,
2424 $image)
2425 {
2426 global $pmaThemeImage, $propicon;
2427  
2428 /* Opera has trouble with <input type="image"> */
2429 /* IE has trouble with <button> */
2430 if (PMA_USR_BROWSER_AGENT != 'IE') {
2431 echo '<button class="' . $button_class . '" type="submit"'
2432 .' name="' . $button_name . '" value="' . $text . '"'
2433 .' title="' . $text . '">' . "\n"
2434 .'<img class="icon" src="' . $pmaThemeImage . $image . '"'
2435 .' title="' . $text . '" alt="' . $text . '" width="16"'
2436 .' height="16" />'
2437 .($propicon == 'both' ? '&nbsp;' . $text : '') . "\n"
2438 .'</button>' . "\n";
2439 } else {
2440 echo '<input type="image" name="' . $image_name . '" value="'
2441 . $text . '" title="' . $text . '" src="' . $pmaThemeImage
2442 . $image . '" />'
2443 . ($propicon == 'both' ? '&nbsp;' . $text : '') . "\n";
2444 }
2445 } // end function
2446  
2447 /**
2448 * Generate a pagination selector for browsing resultsets
2449 *
2450 * @param string URL for the JavaScript
2451 * @param string Number of rows in the pagination set
2452 * @param string current page number
2453 * @param string number of total pages
2454 * @param string If the number of pages is lower than this
2455 * variable, no pages will be ommitted in
2456 * pagination
2457 * @param string How many rows at the beginning should always
2458 * be shown?
2459 * @param string How many rows at the end should always
2460 * be shown?
2461 * @param string Percentage of calculation page offsets to
2462 * hop to a next page
2463 * @param string Near the current page, how many pages should
2464 * be considered "nearby" and displayed as
2465 * well?
2466 *
2467 * @access public
2468 * @author Garvin Hicking (pma@supergarv.de)
2469 */
2470 function PMA_pageselector($url, $rows, $pageNow = 1, $nbTotalPage = 1,
2471 $showAll = 200, $sliceStart = 5, $sliceEnd = 5, $percent = 20,
2472 $range = 10)
2473 {
2474 $gotopage = $GLOBALS['strPageNumber']
2475 . ' <select name="goToPage" onchange="goToUrl(this, \''
2476 . $url . '\');">' . "\n";
2477 if ($nbTotalPage < $showAll) {
2478 $pages = range(1, $nbTotalPage);
2479 } else {
2480 $pages = array();
2481  
2482 // Always show first X pages
2483 for ($i = 1; $i <= $sliceStart; $i++) {
2484 $pages[] = $i;
2485 }
2486  
2487 // Always show last X pages
2488 for ($i = $nbTotalPage - $sliceEnd; $i <= $nbTotalPage; $i++) {
2489 $pages[] = $i;
2490 }
2491  
2492 // garvin: Based on the number of results we add the specified
2493 // $percent percentate to each page number,
2494 // so that we have a representing page number every now and then to
2495 // immideately jump to specific pages.
2496 // As soon as we get near our currently chosen page ($pageNow -
2497 // $range), every page number will be
2498 // shown.
2499 $i = $sliceStart;
2500 $x = $nbTotalPage - $sliceEnd;
2501 $met_boundary = false;
2502 while ($i <= $x) {
2503 if ($i >= ($pageNow - $range) && $i <= ($pageNow + $range)) {
2504 // If our pageselector comes near the current page, we use 1
2505 // counter increments
2506 $i++;
2507 $met_boundary = true;
2508 } else {
2509 // We add the percentate increment to our current page to
2510 // hop to the next one in range
2511 $i = $i + floor($nbTotalPage / $percent);
2512  
2513 // Make sure that we do not cross our boundaries.
2514 if ($i > ($pageNow - $range) && !$met_boundary) {
2515 $i = $pageNow - $range;
2516 }
2517 }
2518  
2519 if ($i > 0 && $i <= $x) {
2520 $pages[] = $i;
2521 }
2522 }
2523  
2524 // Since because of ellipsing of the current page some numbers may be double,
2525 // we unify our array:
2526 sort($pages);
2527 $pages = array_unique($pages);
2528 }
2529  
2530 foreach ($pages AS $i) {
2531 if ($i == $pageNow) {
2532 $selected = 'selected="selected" style="font-weight: bold"';
2533 } else {
2534 $selected = '';
2535 }
2536 $gotopage .= ' <option ' . $selected . ' value="' . (($i - 1) * $rows) . '">' . $i . '</option>' . "\n";
2537 }
2538  
2539 $gotopage .= ' </select>';
2540  
2541 return $gotopage;
2542 } // end function
2543  
2544 /**
2545 * @TODO add documentation
2546 */
2547 function PMA_generateFieldSpec($name, $type, $length, $attribute,
2548 $collation, $null, $default, $default_current_timestamp, $extra,
2549 $comment='', &$field_primary, $index, $default_orig = false)
2550 {
2551  
2552 // $default_current_timestamp has priority over $default
2553 // TODO: on the interface, some js to clear the default value
2554 // when the default current_timestamp is checked
2555  
2556 $query = PMA_backquote($name) . ' ' . $type;
2557  
2558 if ($length != ''
2559 && !preg_match('@^(DATE|DATETIME|TIME|TINYBLOB|TINYTEXT|BLOB|TEXT|MEDIUMBLOB|MEDIUMTEXT|LONGBLOB|LONGTEXT)$@i', $type)) {
2560 $query .= '(' . $length . ')';
2561 }
2562  
2563 if ($attribute != '') {
2564 $query .= ' ' . $attribute;
2565 }
2566  
2567 if (PMA_MYSQL_INT_VERSION >= 40100 && !empty($collation)
2568 && $collation != 'NULL'
2569 && preg_match('@^(TINYTEXT|TEXT|MEDIUMTEXT|LONGTEXT|VARCHAR|CHAR|ENUM|SET)$@i', $type)) {
2570 $query .= PMA_generateCharsetQueryPart($collation);
2571 }
2572  
2573 if (!($null === false)) {
2574 if (!empty($null)) {
2575 $query .= ' NOT NULL';
2576 } else {
2577 $query .= ' NULL';
2578 }
2579 }
2580  
2581 if ($default_current_timestamp && strpos(' ' . strtoupper($type), 'TIMESTAMP') == 1) {
2582 $query .= ' DEFAULT CURRENT_TIMESTAMP';
2583 // 0 is empty in PHP
2584 // auto_increment field cannot have a default value
2585 } elseif ($extra !== 'AUTO_INCREMENT' && (!empty($default) || $default == '0' || $default != $default_orig)) {
2586 if (strtoupper($default) == 'NULL') {
2587 $query .= ' DEFAULT NULL';
2588 } else {
2589 if (!empty($default) || $default == '0') {
2590 $query .= ' DEFAULT \'' . PMA_sqlAddslashes($default) . '\'';
2591 }
2592 }
2593 }
2594  
2595 if (!empty($extra)) {
2596 $query .= ' ' . $extra;
2597 // An auto_increment field must be use as a primary key
2598 if ($extra == 'AUTO_INCREMENT' && isset($field_primary)) {
2599 $primary_cnt = count($field_primary);
2600 for ($j = 0; $j < $primary_cnt && $field_primary[$j] != $index; $j++) {
2601 // void
2602 } // end for
2603 if (isset($field_primary[$j]) && $field_primary[$j] == $index) {
2604 $query .= ' PRIMARY KEY';
2605 unset($field_primary[$j]);
2606 } // end if
2607 } // end if (auto_increment)
2608 }
2609 if (PMA_MYSQL_INT_VERSION >= 40100 && !empty($comment)) {
2610 $query .= " COMMENT '" . PMA_sqlAddslashes($comment) . "'";
2611 }
2612 return $query;
2613 } // end function
2614  
2615 /**
2616 * @TODO add documentation
2617 */
2618 function PMA_generateAlterTable($oldcol, $newcol, $type, $length,
2619 $attribute, $collation, $null, $default, $default_current_timestamp,
2620 $extra, $comment='', $default_orig)
2621 {
2622 $empty_a = array();
2623 return PMA_backquote($oldcol) . ' '
2624 . PMA_generateFieldSpec($newcol, $type, $length, $attribute,
2625 $collation, $null, $default, $default_current_timestamp, $extra,
2626 $comment, $empty_a, -1, $default_orig);
2627 } // end function
2628  
2629 /**
2630 * @TODO add documentation
2631 */
2632 function PMA_userDir($dir)
2633 {
2634 global $cfg;
2635  
2636 if (substr($dir, -1) != '/') {
2637 $dir .= '/';
2638 }
2639  
2640 return str_replace('%u', $cfg['Server']['user'], $dir);
2641 }
2642  
2643 /**
2644 * returns html code for db link to default db page
2645 *
2646 * @uses $GLOBALS['cfg']['DefaultTabDatabase']
2647 * @uses $GLOBALS['db']
2648 * @uses $GLOBALS['strJumpToDB']
2649 * @uses PMA_generate_common_url()
2650 * @param string $database
2651 * @return string html link to default db page
2652 */
2653 function PMA_getDbLink($database = null)
2654 {
2655 if (!strlen($database)) {
2656 if (!strlen($GLOBALS['db'])) {
2657 return '';
2658 }
2659 $database = $GLOBALS['db'];
2660 }
2661  
2662 return '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?' . PMA_generate_common_url($database) . '"'
2663 .' title="' . sprintf($GLOBALS['strJumpToDB'], htmlspecialchars($database)) . '">'
2664 .htmlspecialchars($database) . '</a>';
2665 }
2666  
2667 /**
2668 * removes cookie
2669 *
2670 * @uses $GLOBALS['cookie_path']
2671 * @uses $GLOBALS['is_https']
2672 * @uses setcookie()
2673 * @uses time()
2674 * @param string $cookie name of cookie to remove
2675 * @return boolean result of setcookie()
2676 */
2677 function PMA_removeCookie($cookie)
2678 {
2679 return setcookie($cookie, '', time() - 3600,
2680 $GLOBALS['cookie_path'], '', $GLOBALS['is_https']);
2681 }
2682  
2683 /**
2684 * sets cookie if value is different from current cokkie value,
2685 * or removes if value is equal to default
2686 *
2687 * @uses $GLOBALS['cookie_path']
2688 * @uses $GLOBALS['is_https']
2689 * @uses $_COOKIE
2690 * @uses PMA_removeCookie()
2691 * @uses setcookie()
2692 * @uses time()
2693 * @param string $cookie name of cookie to remove
2694 * @param mixed $value new cookie value
2695 * @param string $default default value
2696 * @return boolean result of setcookie()
2697 */
2698 function PMA_setCookie($cookie, $value, $default = null)
2699 {
2700 if (strlen($value) && null !== $default && $value === $default) {
2701 // remove cookie, default value is used
2702 return PMA_removeCookie($cookie);
2703 }
2704  
2705 if (! strlen($value) && isset($_COOKIE[$cookie])) {
2706 // remove cookie, value is empty
2707 return PMA_removeCookie($cookie);
2708 }
2709  
2710 if (! isset($_COOKIE[$cookie]) || $_COOKIE[$cookie] !== $value) {
2711 // set cookie with new value
2712 return setcookie($cookie, $value, time() + 60*60*24*30,
2713 $GLOBALS['cookie_path'], '', $GLOBALS['is_https']);
2714 }
2715  
2716 // cookie has already $value as value
2717 return true;
2718 }
2719  
2720  
2721 /**
2722 * include here only libraries which contain only function definitions
2723 * no code im main()!
2724 */
2725 /**
2726 * Include URL/hidden inputs generating.
2727 */
2728 require_once './libraries/url_generating.lib.php';
2729  
2730 }
2731  
2732  
2733 /******************************************************************************/
2734 /* start procedural code label_start_procedural */
2735  
2736 /**
2737 * protect against older PHP versions' bug about GLOBALS overwrite
2738 * (no need to localize this message :))
2739 * but what if script.php?GLOBALS[admin]=1&GLOBALS[_REQUEST]=1 ???
2740 */
2741 if (isset($_REQUEST['GLOBALS']) || isset($_FILES['GLOBALS'])
2742 || isset($_SERVER['GLOBALS']) || isset($_COOKIE['GLOBALS'])
2743 || isset($_ENV['GLOBALS'])) {
2744 die('GLOBALS overwrite attempt');
2745 }
2746  
2747 /**
2748 * just to be sure there was no import (registering) before here
2749 * we empty the global space
2750 */
2751 $variables_whitelist = array (
2752 'GLOBALS',
2753 '_SERVER',
2754 '_GET',
2755 '_POST',
2756 '_REQUEST',
2757 '_FILES',
2758 '_ENV',
2759 '_COOKIE',
2760 '_SESSION',
2761 );
2762  
2763 foreach (get_defined_vars() as $key => $value) {
2764 if (!in_array($key, $variables_whitelist)) {
2765 unset($$key);
2766 }
2767 }
2768 unset($key, $value);
2769  
2770  
2771 /**
2772 * check if a subform is submitted
2773 */
2774 $__redirect = null;
2775 if (isset($_POST['usesubform'])) {
2776 // if a subform is present and should be used
2777 // the rest of the form is deprecated
2778 $subform_id = key($_POST['usesubform']);
2779 $subform = $_POST['subform'][$subform_id];
2780 $_POST = $subform;
2781 $_REQUEST = $subform;
2782 if (isset($_POST['redirect'])
2783 && $_POST['redirect'] != basename(PMA_getenv('PHP_SELF'))) {
2784 $__redirect = $_POST['redirect'];
2785 unset($_POST['redirect']);
2786 } // end if (isset($_POST['redirect']))
2787 unset($subform_id, $subform);
2788 } // end if (isset($_POST['usesubform']))
2789 // end check if a subform is submitted
2790  
2791 if (get_magic_quotes_gpc()) {
2792 PMA_arrayWalkRecursive($_GET, 'stripslashes', true);
2793 PMA_arrayWalkRecursive($_POST, 'stripslashes', true);
2794 PMA_arrayWalkRecursive($_COOKIE, 'stripslashes', true);
2795 PMA_arrayWalkRecursive($_REQUEST, 'stripslashes', true);
2796 }
2797  
2798 require_once './libraries/session.inc.php';
2799  
2800 /**
2801 * include deprecated grab_globals only if required
2802 */
2803 if (empty($__redirect) && !defined('PMA_NO_VARIABLES_IMPORT')) {
2804 require './libraries/grab_globals.lib.php';
2805 }
2806  
2807 /**
2808 * init some variables LABEL_variables_init
2809 */
2810  
2811 /**
2812 * @var array $GLOBALS['PMA_errors'] holds errors
2813 */
2814 $GLOBALS['PMA_errors'] = array();
2815  
2816 /**
2817 * @var array $GLOBALS['url_params'] holds params to be passed to next page
2818 */
2819 $GLOBALS['url_params'] = array();
2820  
2821 /**
2822 * @var array whitelist for $goto
2823 */
2824 $goto_whitelist = array(
2825 //'browse_foreigners.php',
2826 //'calendar.php',
2827 //'changelog.php',
2828 //'chk_rel.php',
2829 'db_create.php',
2830 'db_datadict.php',
2831 'db_details.php',
2832 'db_details_export.php',
2833 'db_details_importdocsql.php',
2834 'db_details_qbe.php',
2835 'db_details_structure.php',
2836 'db_import.php',
2837 'db_operations.php',
2838 'db_printview.php',
2839 'db_search.php',
2840 //'Documentation.html',
2841 //'error.php',
2842 'export.php',
2843 'import.php',
2844 //'index.php',
2845 //'left.php',
2846 //'license.php',
2847 'main.php',
2848 'pdf_pages.php',
2849 'pdf_schema.php',
2850 //'phpinfo.php',
2851 'querywindow.php',
2852 //'readme.php',
2853 'server_binlog.php',
2854 'server_collations.php',
2855 'server_databases.php',
2856 'server_engines.php',
2857 'server_export.php',
2858 'server_import.php',
2859 'server_privileges.php',
2860 'server_processlist.php',
2861 'server_sql.php',
2862 'server_status.php',
2863 'server_variables.php',
2864 'sql.php',
2865 'tbl_addfield.php',
2866 'tbl_alter.php',
2867 'tbl_change.php',
2868 'tbl_create.php',
2869 'tbl_import.php',
2870 'tbl_indexes.php',
2871 'tbl_move_copy.php',
2872 'tbl_printview.php',
2873 'tbl_properties.php',
2874 'tbl_properties_export.php',
2875 'tbl_properties_operations.php',
2876 'tbl_properties_structure.php',
2877 'tbl_relation.php',
2878 'tbl_replace.php',
2879 'tbl_row_action.php',
2880 'tbl_select.php',
2881 //'themes.php',
2882 'transformation_overview.php',
2883 'transformation_wrapper.php',
2884 'translators.html',
2885 'user_password.php',
2886 );
2887  
2888 /**
2889 * check $__redirect against whitelist
2890 */
2891 if (! PMA_checkPageValidity($__redirect, $goto_whitelist)) {
2892 $__redirect = null;
2893 }
2894  
2895 /**
2896 * @var string $goto holds page that should be displayed
2897 */
2898 // Security fix: disallow accessing serious server files via "?goto="
2899 if (PMA_checkPageValidity($_REQUEST['goto'], $goto_whitelist)) {
2900 $GLOBALS['goto'] = $_REQUEST['goto'];
2901 $GLOBALS['url_params']['goto'] = $_REQUEST['goto'];
2902 } else {
2903 unset($_REQUEST['goto'], $_GET['goto'], $_POST['goto'], $_COOKIE['goto']);
2904 $GLOBALS['goto'] = '';
2905 }
2906  
2907 /**
2908 * @var string $back returning page
2909 */
2910 if (PMA_checkPageValidity($_REQUEST['back'], $goto_whitelist)) {
2911 $GLOBALS['back'] = $_REQUEST['back'];
2912 } else {
2913 unset($_REQUEST['back'], $_GET['back'], $_POST['back'], $_COOKIE['back']);
2914 }
2915  
2916 /**
2917 * Check whether user supplied token is valid, if not remove any
2918 * possibly dangerous stuff from request.
2919 */
2920 if (!isset($_REQUEST['token']) || $_SESSION['PMA_token'] != $_REQUEST['token']) {
2921 /* List of parameters which are allowed from unsafe source */
2922 $allow_list = array(
2923 'db', 'table', 'lang', 'server', 'convcharset', 'collation_connection', 'target',
2924 /* Session ID */
2925 'phpMyAdmin',
2926 /* Cookie preferences */
2927 'pma_lang', 'pma_charset', 'pma_collation_connection', 'pma_convcharset',
2928 /* Possible login form */
2929 'pma_username', 'pma_password',
2930 );
2931 $keys = array_keys($_REQUEST);
2932 /* Remove any non allowed stuff from requests */
2933 foreach($keys as $key) {
2934 if (!in_array($key, $allow_list)) {
2935 unset($_REQUEST[$key]);
2936 unset($_GET[$key]);
2937 unset($_POST[$key]);
2938 unset($GLOBALS[$key]);
2939 } else {
2940 // allowed stuff could be compromised so escape it
2941 $_REQUEST[$key] = htmlspecialchars($_REQUEST[$key], ENT_QUOTES);
2942 }
2943 }
2944 }
2945  
2946 /**
2947 * @var string $convcharset
2948 * @see also select_lang.lib.php
2949 */
2950 if (isset($_REQUEST['convcharset'])) {
2951 $convcharset = strip_tags($_REQUEST['convcharset']);
2952 }
2953  
2954 /**
2955 * @var string $db current selected database
2956 */
2957 if (isset($_REQUEST['db'])) {
2958 // can we strip tags from this?
2959 // only \ and / is not allowed in db names for MySQL
2960 $GLOBALS['db'] = $_REQUEST['db'];
2961 $GLOBALS['url_params']['db'] = $GLOBALS['db'];
2962 } else {
2963 $GLOBALS['db'] = '';
2964 }
2965  
2966 /**
2967 * @var string $db current selected database
2968 */
2969 if (isset($_REQUEST['table'])) {
2970 // can we strip tags from this?
2971 // only \ and / is not allowed in table names for MySQL
2972 $GLOBALS['table'] = $_REQUEST['table'];
2973 $GLOBALS['url_params']['table'] = $GLOBALS['table'];
2974 } else {
2975 $GLOBALS['table'] = '';
2976 }
2977  
2978 /**
2979 * @var string $sql_query sql query to be executed
2980 */
2981 if (isset($_REQUEST['sql_query'])) {
2982 $GLOBALS['sql_query'] = $_REQUEST['sql_query'];
2983 }
2984  
2985 //$_REQUEST['set_theme'] // checked later in this file LABEL_theme_setup
2986 //$_REQUEST['server']; // checked later in this file
2987 //$_REQUEST['lang']; // checked by LABEL_loading_language_file
2988  
2989  
2990  
2991 /******************************************************************************/
2992 /* parsing config file LABEL_parsing_config_file */
2993  
2994 if (empty($_SESSION['PMA_Config'])) {
2995 /**
2996 * We really need this one!
2997 */
2998 if (!function_exists('preg_replace')) {
2999 header('Location: error.php'
3000 . '?lang=' . urlencode($available_languages[$lang][2])
3001 . '&char=' . urlencode($charset)
3002 . '&dir=' . urlencode($text_dir)
3003 . '&type=' . urlencode($strError)
3004 . '&error=' . urlencode(
3005 strtr(sprintf($strCantLoad, 'pcre'),
3006 array('<br />' => '[br]')))
3007 . '&' . SID
3008 );
3009 exit();
3010 }
3011  
3012 $_SESSION['PMA_Config'] = new PMA_Config('./config.inc.php');
3013  
3014 } elseif (version_compare(phpversion(), '5', 'lt')) {
3015 $_SESSION['PMA_Config']->__wakeup();
3016 }
3017  
3018 if (!defined('PMA_MINIMUM_COMMON')) {
3019 $_SESSION['PMA_Config']->checkPmaAbsoluteUri();
3020 }
3021  
3022 // BC
3023 $_SESSION['PMA_Config']->enableBc();
3024  
3025  
3026 /**
3027 * check https connection
3028 */
3029 if ($_SESSION['PMA_Config']->get('ForceSSL')
3030 && !$_SESSION['PMA_Config']->get('is_https')) {
3031 PMA_sendHeaderLocation(
3032 preg_replace('/^http/', 'https',
3033 $_SESSION['PMA_Config']->get('PmaAbsoluteUri'))
3034 . PMA_generate_common_url($_GET));
3035 exit;
3036 }
3037  
3038  
3039 /******************************************************************************/
3040 /* loading language file LABEL_loading_language_file */
3041  
3042 /**
3043 * Added messages while developing:
3044 */
3045 if (file_exists('./lang/added_messages.php')) {
3046 include './lang/added_messages.php';
3047 }
3048  
3049 /**
3050 * Includes the language file if it hasn't been included yet
3051 */
3052 require_once './libraries/select_lang.lib.php';
3053  
3054  
3055 /**
3056 * check for errors occured while loading config
3057 */
3058 if ($_SESSION['PMA_Config']->error_config_file) {
3059 $GLOBALS['PMA_errors'][] = $strConfigFileError
3060 .'<br /><br />'
3061 .'<a href="' . $_SESSION['PMA_Config']->getSource() . '"'
3062 .' target="_blank">' . $_SESSION['PMA_Config']->getSource() . '</a>';
3063 }
3064 if ($_SESSION['PMA_Config']->error_config_default_file) {
3065 $GLOBALS['PMA_errors'][] = sprintf($strConfigDefaultFileError,
3066 $_SESSION['PMA_Config']->default_source);
3067 }
3068 if ($_SESSION['PMA_Config']->error_pma_uri) {
3069 $GLOBALS['PMA_errors'][] = sprintf($strPmaUriError);
3070 }
3071  
3072 /**
3073 * Servers array fixups.
3074 * $default_server comes from PMA_Config::enableBc()
3075 * @todo merge into PMA_Config
3076 */
3077 // Do we have some server?
3078 if (!isset($cfg['Servers']) || count($cfg['Servers']) == 0) {
3079 // No server => create one with defaults
3080 $cfg['Servers'] = array(1 => $default_server);
3081 } else {
3082 // We have server(s) => apply default config
3083 $new_servers = array();
3084  
3085 foreach ($cfg['Servers'] as $server_index => $each_server) {
3086 if (!is_int($server_index) || $server_index < 1) {
3087 $GLOBALS['PMA_errors'][] = sprintf($strInvalidServerIndex, $server_index);
3088 continue;
3089 }
3090  
3091 $each_server = array_merge($default_server, $each_server);
3092  
3093 // Don't use servers with no hostname
3094 if ($each_server['connect_type'] == 'tcp' && empty($each_server['host'])) {
3095 $GLOBALS['PMA_errors'][] = sprintf($strInvalidServerHostname, $server_index);
3096 continue;
3097 }
3098  
3099 // Final solution to bug #582890
3100 // If we are using a socket connection
3101 // and there is nothing in the verbose server name
3102 // or the host field, then generate a name for the server
3103 // in the form of "Server 2", localized of course!
3104 if ($each_server['connect_type'] == 'socket' && empty($each_server['host']) && empty($each_server['verbose'])) {
3105 $each_server['verbose'] = $GLOBALS['strServer'] . $server_index;
3106 }
3107  
3108 $new_servers[$server_index] = $each_server;
3109 }
3110 $cfg['Servers'] = $new_servers;
3111 unset($new_servers, $server_index, $each_server);
3112 }
3113  
3114 // Cleanup
3115 unset($default_server);
3116  
3117  
3118 /******************************************************************************/
3119 /* setup themes LABEL_theme_setup */
3120  
3121 if (!isset($_SESSION['PMA_Theme_Manager'])) {
3122 $_SESSION['PMA_Theme_Manager'] = new PMA_Theme_Manager;
3123 } else {
3124 $_SESSION['PMA_Theme_Manager']->checkConfig();
3125 }
3126  
3127 if (isset($_REQUEST['set_theme'])) {
3128 // if user submit a theme
3129 $_SESSION['PMA_Theme_Manager']->setActiveTheme($_REQUEST['set_theme']);
3130 }
3131  
3132 $_SESSION['PMA_Theme'] = $_SESSION['PMA_Theme_Manager']->theme;
3133  
3134 // BC
3135 $GLOBALS['theme'] = $_SESSION['PMA_Theme']->getName();
3136 $GLOBALS['pmaThemePath'] = $_SESSION['PMA_Theme']->getPath();
3137 $GLOBALS['pmaThemeImage'] = $_SESSION['PMA_Theme']->getImgPath();
3138  
3139 /**
3140 * load layout file if exists
3141 */
3142 if (@file_exists($_SESSION['PMA_Theme']->getLayoutFile())) {
3143 include $_SESSION['PMA_Theme']->getLayoutFile();
3144 }
3145  
3146 if (!defined('PMA_MINIMUM_COMMON')) {
3147 /**
3148 * Charset conversion.
3149 */
3150 require_once './libraries/charset_conversion.lib.php';
3151  
3152 /**
3153 * String handling
3154 */
3155 require_once './libraries/string.lib.php';
3156  
3157 /**
3158 * @var array database list
3159 */
3160 $dblist = array();
3161  
3162 /**
3163 * If no server is selected, make sure that $cfg['Server'] is empty (so
3164 * that nothing will work), and skip server authentication.
3165 * We do NOT exit here, but continue on without logging into any server.
3166 * This way, the welcome page will still come up (with no server info) and
3167 * present a choice of servers in the case that there are multiple servers
3168 * and '$cfg['ServerDefault'] = 0' is set.
3169 */
3170 if (!empty($_REQUEST['server']) && !empty($cfg['Servers'][$_REQUEST['server']])) {
3171 $GLOBALS['server'] = $_REQUEST['server'];
3172 $cfg['Server'] = $cfg['Servers'][$GLOBALS['server']];
3173 } else {
3174 if (!empty($cfg['Servers'][$cfg['ServerDefault']])) {
3175 $GLOBALS['server'] = $cfg['ServerDefault'];
3176 $cfg['Server'] = $cfg['Servers'][$GLOBALS['server']];
3177 } else {
3178 $GLOBALS['server'] = 0;
3179 $cfg['Server'] = array();
3180 }
3181 }
3182 $GLOBALS['url_params']['server'] = $GLOBALS['server'];
3183  
3184  
3185 if (!empty($cfg['Server'])) {
3186  
3187 /**
3188 * Loads the proper database interface for this server
3189 */
3190 require_once './libraries/database_interface.lib.php';
3191  
3192 // Gets the authentication library that fits the $cfg['Server'] settings
3193 // and run authentication
3194  
3195 // (for a quick check of path disclosure in auth/cookies:)
3196 $coming_from_common = true;
3197  
3198 if (!file_exists('./libraries/auth/' . $cfg['Server']['auth_type'] . '.auth.lib.php')) {
3199 header('Location: error.php'
3200 . '?lang=' . urlencode($available_languages[$lang][2])
3201 . '&char=' . urlencode($charset)
3202 . '&dir=' . urlencode($text_dir)
3203 . '&type=' . urlencode($strError)
3204 . '&error=' . urlencode(
3205 $strInvalidAuthMethod . ' '
3206 . $cfg['Server']['auth_type'])
3207 . '&' . SID
3208 );
3209 exit();
3210 }
3211 require_once './libraries/auth/' . $cfg['Server']['auth_type'] . '.auth.lib.php';
3212 if (!PMA_auth_check()) {
3213 PMA_auth();
3214 } else {
3215 PMA_auth_set_user();
3216 }
3217  
3218 // Check IP-based Allow/Deny rules as soon as possible to reject the
3219 // user
3220 // Based on mod_access in Apache:
3221 // http://cvs.apache.org/viewcvs.cgi/httpd-2.0/modules/aaa/mod_access.c?rev=1.37&content-type=text/vnd.viewcvs-markup
3222 // Look at: "static int check_dir_access(request_rec *r)"
3223 // Robbat2 - May 10, 2002
3224 if (isset($cfg['Server']['AllowDeny'])
3225 && isset($cfg['Server']['AllowDeny']['order'])) {
3226  
3227 require_once './libraries/ip_allow_deny.lib.php';
3228  
3229 $allowDeny_forbidden = false; // default
3230 if ($cfg['Server']['AllowDeny']['order'] == 'allow,deny') {
3231 $allowDeny_forbidden = true;
3232 if (PMA_allowDeny('allow')) {
3233 $allowDeny_forbidden = false;
3234 }
3235 if (PMA_allowDeny('deny')) {
3236 $allowDeny_forbidden = true;
3237 }
3238 } elseif ($cfg['Server']['AllowDeny']['order'] == 'deny,allow') {
3239 if (PMA_allowDeny('deny')) {
3240 $allowDeny_forbidden = true;
3241 }
3242 if (PMA_allowDeny('allow')) {
3243 $allowDeny_forbidden = false;
3244 }
3245 } elseif ($cfg['Server']['AllowDeny']['order'] == 'explicit') {
3246 if (PMA_allowDeny('allow')
3247 && !PMA_allowDeny('deny')) {
3248 $allowDeny_forbidden = false;
3249 } else {
3250 $allowDeny_forbidden = true;
3251 }
3252 } // end if ... elseif ... elseif
3253  
3254 // Ejects the user if banished
3255 if ($allowDeny_forbidden) {
3256 PMA_auth_fails();
3257 }
3258 unset($allowDeny_forbidden); //Clean up after you!
3259 } // end if
3260  
3261 // is root allowed?
3262 if (!$cfg['Server']['AllowRoot'] && $cfg['Server']['user'] == 'root') {
3263 $allowDeny_forbidden = true;
3264 PMA_auth_fails();
3265 unset($allowDeny_forbidden); //Clean up after you!
3266 }
3267  
3268 // The user can work with only some databases
3269 if (isset($cfg['Server']['only_db']) && $cfg['Server']['only_db'] != '') {
3270 if (is_array($cfg['Server']['only_db'])) {
3271 $dblist = $cfg['Server']['only_db'];
3272 } else {
3273 $dblist[] = $cfg['Server']['only_db'];
3274 }
3275 } // end if
3276  
3277 $bkp_track_err = @ini_set('track_errors', 1);
3278  
3279 // Try to connect MySQL with the control user profile (will be used to
3280 // get the privileges list for the current user but the true user link
3281 // must be open after this one so it would be default one for all the
3282 // scripts)
3283 if ($cfg['Server']['controluser'] != '') {
3284 $controllink = PMA_DBI_connect($cfg['Server']['controluser'],
3285 $cfg['Server']['controlpass'], true);
3286 } else {
3287 $controllink = PMA_DBI_connect($cfg['Server']['user'],
3288 $cfg['Server']['password'], true);
3289 } // end if ... else
3290  
3291 // Pass #1 of DB-Config to read in master level DB-Config will go here
3292 // Robbat2 - May 11, 2002
3293  
3294 // Connects to the server (validates user's login)
3295 $userlink = PMA_DBI_connect($cfg['Server']['user'],
3296 $cfg['Server']['password'], false);
3297  
3298 // Pass #2 of DB-Config to read in user level DB-Config will go here
3299 // Robbat2 - May 11, 2002
3300  
3301 @ini_set('track_errors', $bkp_track_err);
3302 unset($bkp_track_err);
3303  
3304 /**
3305 * SQL Parser code
3306 */
3307 require_once './libraries/sqlparser.lib.php';
3308  
3309 /**
3310 * SQL Validator interface code
3311 */
3312 require_once './libraries/sqlvalidator.lib.php';
3313  
3314 // if 'only_db' is set for the current user, there is no need to check for
3315 // available databases in the "mysql" db
3316 $dblist_cnt = count($dblist);
3317 if ($dblist_cnt) {
3318 $true_dblist = array();
3319 $is_show_dbs = true;
3320  
3321 $dblist_asterisk_bool = false;
3322 for ($i = 0; $i < $dblist_cnt; $i++) {
3323  
3324 // The current position
3325 if ($dblist[$i] == '*' && $dblist_asterisk_bool == false) {
3326 $dblist_asterisk_bool = true;
3327 $dblist_full = PMA_safe_db_list(false, $controllink, false,
3328 $userlink, $cfg, $dblist);
3329 foreach ($dblist_full as $dbl_val) {
3330 if (!in_array($dbl_val, $dblist)) {
3331 $true_dblist[] = $dbl_val;
3332 }
3333 }
3334  
3335 continue;
3336 } elseif ($dblist[$i] == '*') {
3337 // We don't want more than one asterisk inside our 'only_db'.
3338 continue;
3339 }
3340 if ($is_show_dbs && preg_match('/(^|[^\\\\])(_|%)/', $dblist[$i])) {
3341 $local_query = 'SHOW DATABASES LIKE \'' . $dblist[$i] . '\'';
3342 // here, a PMA_DBI_query() could fail silently
3343 // if SHOW DATABASES is disabled
3344 $rs = PMA_DBI_try_query($local_query, $userlink);
3345  
3346 if ($i == 0 && ! $rs) {
3347 $error_code = substr(PMA_DBI_getError($userlink), 1, 4);
3348 if ($error_code == 1227 || $error_code == 1045) {
3349 // "SHOW DATABASES" statement is disabled or not allowed to user
3350 $true_dblist[] = str_replace('\\_', '_', str_replace('\\%', '%', $dblist[$i]));
3351 $is_show_dbs = false;
3352 }
3353 unset($error_code);
3354 }
3355 // Debug
3356 // elseif (PMA_DBI_getError($controllink)) {
3357 // PMA_mysqlDie(PMA_DBI_getError($controllink), $local_query, false);
3358 // }
3359 while ($row = @PMA_DBI_fetch_row($rs)) {
3360 $true_dblist[] = $row[0];
3361 } // end while
3362 if ($rs) {
3363 PMA_DBI_free_result($rs);
3364 }
3365 } else {
3366 $true_dblist[] = str_replace('\\_', '_',
3367 str_replace('\\%', '%', $dblist[$i]));
3368 } // end if... else...
3369 } // end for
3370 $dblist = $true_dblist;
3371 unset($true_dblist, $i, $dbl_val);
3372 $only_db_check = true;
3373 } // end if
3374  
3375 // 'only_db' is empty for the current user...
3376 else {
3377 $only_db_check = false;
3378 } // end if (!$dblist_cnt)
3379  
3380 if (isset($dblist_full) && !count($dblist_full)) {
3381 $dblist = PMA_safe_db_list($only_db_check, $controllink,
3382 $dblist_cnt, $userlink, $cfg, $dblist);
3383 }
3384 unset($only_db_check, $dblist_full);
3385  
3386 } // end server connecting
3387  
3388  
3389 // Kanji encoding convert feature appended by Y.Kawada (2002/2/20)
3390 if (@function_exists('mb_convert_encoding')
3391 && strpos(' ' . $lang, 'ja-')
3392 && file_exists('./libraries/kanji-encoding.lib.php')) {
3393 require_once './libraries/kanji-encoding.lib.php';
3394 define('PMA_MULTIBYTE_ENCODING', 1);
3395 } // end if
3396  
3397 /**
3398 * save some settings in cookies
3399 */
3400 PMA_setCookie('pma_lang', $GLOBALS['lang']);
3401 PMA_setCookie('pma_charset', $GLOBALS['convcharset']);
3402 PMA_setCookie('pma_collation_connection', $GLOBALS['collation_connection']);
3403  
3404 $_SESSION['PMA_Theme_Manager']->setThemeCookie();
3405  
3406 } // end if !defined('PMA_MINIMUM_COMMON')
3407  
3408 if (!empty($__redirect) && in_array($__redirect, $goto_whitelist)) {
3409 // to handle bug #1388167
3410 if (isset($_GET['is_js_confirmed'])) {
3411 $is_js_confirmed = 1;
3412 }
3413 require $__redirect;
3414 exit();
3415 }
3416  
3417 ?>