~hexmode/+junk/main

« back to all changes in this revision

Viewing changes to install-files/apps/phpmyadmin2.10.1/libraries/common.lib.php

  • Committer: Mark A. Hershberger
  • Date: 2008-01-05 19:38:56 UTC
  • Revision ID: hershberger@spawn-xp-20080105193856-6rnzgwa4nehue3qj
initial commit

Show diffs side-by-side

added added

removed removed

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