home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / phpMyAdmin / libraries / List_Database.class.php < prev    next >
Encoding:
PHP Script  |  2008-06-23  |  18.5 KB  |  542 lines

  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4.  * holds the PMA_List_Database class
  5.  *
  6.  * @version $Id: List_Database.class.php 10913 2007-11-09 21:24:40Z cybot_tm $
  7.  */
  8.  
  9. /**
  10.  * the list base class
  11.  */
  12. require_once './libraries/List.class.php';
  13.  
  14. /**
  15.  * handles database lists
  16.  *
  17.  * <code>
  18.  * $PMA_List_Database = new PMA_List_Database($userlink, $controllink);
  19.  * </code>
  20.  *
  21.  * @todo this object should be attached to the PMA_Server object
  22.  * @todo ? make use of INFORMATION_SCHEMA
  23.  * @todo ? support --skip-showdatabases and user has only global rights
  24.  * @access public
  25.  * @since phpMyAdmin 2.9.10
  26.  */
  27. /*public*/ class PMA_List_Database extends PMA_List
  28. {
  29.     /**
  30.      * @var mixed   database link resource|object to be used
  31.      * @access protected
  32.      */
  33.     var $_db_link = null;
  34.  
  35.     /**
  36.      * @var mixed   user database link resource|object
  37.      * @access protected
  38.      */
  39.     var $_db_link_user = null;
  40.  
  41.     /**
  42.      * @var mixed   controluser database link resource|object
  43.      * @access protected
  44.      */
  45.     var $_db_link_control = null;
  46.  
  47.     /**
  48.      * @var boolean whether SHOW DATABASES is disabled or not
  49.      * @access protected
  50.      */
  51.     var $_show_databases_disabled = false;
  52.  
  53.     /**
  54.      * Constructor
  55.      *
  56.      * @uses    PMA_List_Database::$_db_link
  57.      * @uses    PMA_List_Database::$_db_link_user
  58.      * @uses    PMA_List_Database::$_db_link_control
  59.      * @uses    PMA_List_Database::build()
  60.      * @param   mixed   $db_link_user       user database link resource|object
  61.      * @param   mixed   $db_link_control    control database link resource|object
  62.      */
  63.     function __construct($db_link_user = null, $db_link_control = null) {
  64.         $this->_db_link = $db_link_user;
  65.         $this->_db_link_user = $db_link_user;
  66.         $this->_db_link_control = $db_link_control;
  67.  
  68.         $this->build();
  69.     }
  70.  
  71.     /**
  72.      * old PHP 4 style constructor
  73.      *
  74.      * @see PMA_List_Database::__construct()
  75.      */
  76.     function PMA_List_Database($db_link_user = null, $db_link_control = null) {
  77.         $this->__construct($db_link_user, $db_link_control);
  78.     }
  79.  
  80.     /**
  81.      * removes all databases not accessible by current user from list
  82.      *
  83.      * @access  protected
  84.      * @uses    PMA_List_Database::$items
  85.      * @uses    PMA_List_Database::$_db_link_user
  86.      * @uses    PMA_List_Database::$_need_to_reindex to set it if reuqired
  87.      * @uses    PMA_DBI_select_db()
  88.      */
  89.     function _checkAccess()
  90.     {
  91.         foreach ($this->items as $key => $db) {
  92.             if (! @PMA_DBI_select_db($db, $this->_db_link_user)) {
  93.                 unset($this->items[$key]);
  94.             }
  95.         }
  96.  
  97.         // re-index values
  98.         $this->_need_to_reindex = true;
  99.     }
  100.  
  101.     /**
  102.      * checks if the configuration wants to hide some databases
  103.      *
  104.      * @todo temporaly use this docblock to test how to doc $GLOBALS
  105.      * @access  protected
  106.      * @uses    PMA_List_Database::$items
  107.      * @uses    PMA_List_Database::$_need_to_reindex to set it if reuqired
  108.      * @uses    preg_match()
  109.      * @uses    $cfg['Server']['hide_db']
  110.      */
  111.     function _checkHideDatabase()
  112.     {
  113.         if (empty($GLOBALS['cfg']['Server']['hide_db'])) {
  114.             return;
  115.         }
  116.  
  117.         foreach ($this->items as $key => $db) {
  118.             if (preg_match('/' . $GLOBALS['cfg']['Server']['hide_db'] . '/', $db)) {
  119.                 unset($this->items[$key]);
  120.             }
  121.         }
  122.         // re-index values
  123.         $this->_need_to_reindex = true;
  124.     }
  125.  
  126.     /**
  127.      * retrieves database list from server
  128.      *
  129.      * @todo    we could also search mysql tables if all fail?
  130.      * @access  protected
  131.      * @uses    PMA_List_Database::$_show_databases_disabled for not retrying if SHOW DATABASES is disabled
  132.      * @uses    PMA_List_Database::$_db_link
  133.      * @uses    PMA_List_Database::$_db_link_control in case of SHOW DATABASES is disabled for userlink
  134.      * @uses    PMA_DBI_fetch_result()
  135.      * @uses    PMA_DBI_getError()
  136.      * @uses    $GLOBALS['error_showdatabases']
  137.      * @uses    $GLOBALS['errno']
  138.      * @param   string  $like_db_name   usally a db_name containing wildcards
  139.      */
  140.     function _retrieve($like_db_name = '')
  141.     {
  142.         if ($this->_show_databases_disabled) {
  143.             return array();
  144.         }
  145.  
  146.         if (! empty($like_db_name)) {
  147.             $like = " LIKE '" . $like_db_name . "';";
  148.         } else {
  149.             $like = ";";
  150.         }
  151.  
  152.         $database_list = PMA_DBI_fetch_result('SHOW DATABASES' . $like, null, null, $this->_db_link);
  153.         PMA_DBI_getError();
  154.  
  155.         if ($GLOBALS['errno'] !== 0) {
  156.             // failed to get database list, try the control user
  157.             // (hopefully there is one and he has SHOW DATABASES right)
  158.             $this->_db_link = $this->_db_link_control;
  159.             $database_list = PMA_DBI_fetch_result('SHOW DATABASES' . $like, null, null, $this->_db_link);
  160.  
  161.             PMA_DBI_getError();
  162.  
  163.             if ($GLOBALS['errno'] !== 0) {
  164.                 // failed! we will display a warning that phpMyAdmin could not safely
  165.                 // retrieve database list, the admin has to setup a control user or
  166.                 // allow SHOW DATABASES
  167.                 $GLOBALS['error_showdatabases'] = true;
  168.                 $this->_show_databases_disabled = true;
  169.             }
  170.         }
  171.  
  172.         return $database_list;
  173.     }
  174.  
  175.     /**
  176.      * builds up the list
  177.      *
  178.      * @uses    PMA_List_Database::$items to initialize it
  179.      * @uses    PMA_List_Database::$_need_to_reindex
  180.      * @uses    PMA_List_Database::_checkOnlyDatabase()
  181.      * @uses    PMA_List_Database::_retrieve()
  182.      * @uses    PMA_List_Database::_checkHideDatabase()
  183.      * @uses    PMA_List_Database::_checkAccess()
  184.      * @uses    PMA_MYSQL_INT_VERSION
  185.      * @uses    array_values()
  186.      * @uses    natsort()
  187.      * @uses    $cfg['NaturalOrder']
  188.      */
  189.     function build()
  190.     {
  191.         $this->items = array();
  192.  
  193.         if (! $this->_checkOnlyDatabase()) {
  194.             $this->items = $this->_retrieve();
  195.             if ($GLOBALS['cfg']['NaturalOrder']) {
  196.                 natsort($this->items);
  197.                 $this->_need_to_reindex = true;
  198.             }
  199.         }
  200.  
  201.         $this->_checkHideDatabase();
  202.  
  203.         // Before MySQL 4.0.2, SHOW DATABASES could send the
  204.         // whole list, so check if we really have access:
  205.         if (PMA_MYSQL_INT_VERSION < 40002) {
  206.             $this->_checkAccess();
  207.         }
  208.  
  209.         if ($this->_need_to_reindex) {
  210.             $this->items = array_values($this->items);
  211.         }
  212.     }
  213.  
  214.     /**
  215.      * checks the only_db configuration
  216.      *
  217.      * @uses    PMA_List_Database::$_show_databases_disabled
  218.      * @uses    PMA_List_Database::$items
  219.      * @uses    PMA_List_Database::_retrieve()
  220.      * @uses    PMA_unescape_mysql_wildcards()
  221.      * @uses    preg_match()
  222.      * @uses    array_diff()
  223.      * @uses    array_merge()
  224.      * @uses    is_array()
  225.      * @uses    strlen()
  226.      * @uses    is_string()
  227.      * @uses    $cfg['Server']['only_db']
  228.      * @return  boolean false if there is no only_db, otherwise true
  229.      */
  230.     function _checkOnlyDatabase()
  231.     {
  232.         if (is_string($GLOBALS['cfg']['Server']['only_db'])
  233.          && strlen($GLOBALS['cfg']['Server']['only_db'])) {
  234.             $GLOBALS['cfg']['Server']['only_db'] = array(
  235.                 $GLOBALS['cfg']['Server']['only_db']
  236.             );
  237.         }
  238.  
  239.         if (! is_array($GLOBALS['cfg']['Server']['only_db'])) {
  240.             return false;
  241.         }
  242.  
  243.         foreach ($GLOBALS['cfg']['Server']['only_db'] as $each_only_db) {
  244.             if ($each_only_db === '*' && ! $this->_show_databases_disabled) {
  245.                 // append all not already listed dbs to the list
  246.                 $this->items = array_merge($this->items,
  247.                     array_diff($this->_retrieve(), $this->items));
  248.                 // there can only be one '*', and this can only be last
  249.                 break;
  250.             }
  251.  
  252.             // check if the db name contains wildcard,
  253.             // thus containing not escaped _ or %
  254.             if (! preg_match('/(^|[^\\\\])(_|%)/', $each_only_db)) {
  255.                 // ... not contains wildcard
  256.                 $this->items[] = PMA_unescape_mysql_wildcards($each_only_db);
  257.                 continue;
  258.             }
  259.  
  260.             if (! $this->_show_databases_disabled) {
  261.                 $this->items = array_merge($this->items, $this->_retrieve($each_only_db));
  262.                 continue;
  263.             }
  264.  
  265.             // @todo induce error, about not using wildcards with SHOW DATABASE disabled?
  266.         }
  267.  
  268.         return true;
  269.     }
  270.  
  271.     /**
  272.      * returns default item
  273.      *
  274.      * @uses    PMA_List::getEmpty()
  275.      * @uses    $GLOBALS['db']
  276.      * @uses    strlen()
  277.      * @return  string  default item
  278.      */
  279.     function getDefault()
  280.     {
  281.         if (strlen($GLOBALS['db'])) {
  282.             return $GLOBALS['db'];
  283.         }
  284.  
  285.         return $this->getEmpty();
  286.     }
  287.  
  288.     /**
  289.      * returns array with dbs grouped with extended infos
  290.      *
  291.      * @uses    $GLOBALS['PMA_List_Database']
  292.      * @uses    $GLOBALS['cfgRelation']['commwork']
  293.      * @uses    $cfg['ShowTooltip']
  294.      * @uses    $cfg['LeftFrameDBTree']
  295.      * @uses    $cfg['LeftFrameDBSeparator']
  296.      * @uses    $cfg['ShowTooltipAliasDB']
  297.      * @uses    PMA_getTableCount()
  298.      * @uses    PMA_getComments()
  299.      * @uses    is_array()
  300.      * @uses    implode()
  301.      * @uses    strstr()
  302.      * @uses    explode()
  303.      * @param   integer $offset
  304.      * @param   integer $count
  305.      * @return  array   db list
  306.      */
  307.     function getGroupedDetails($offset, $count)
  308.     {
  309.         $dbgroups   = array();
  310.         $parts      = array();
  311.         foreach ($this->getLimitedItems($offset, $count) as $key => $db) {
  312.             // garvin: Get comments from PMA comments table
  313.             $db_tooltip = '';
  314.             if ($GLOBALS['cfg']['ShowTooltip']
  315.               && $GLOBALS['cfgRelation']['commwork']) {
  316.                 $_db_tooltip = PMA_getComments($db);
  317.                 if (is_array($_db_tooltip)) {
  318.                     $db_tooltip = implode(' ', $_db_tooltip);
  319.                 }
  320.             }
  321.  
  322.             if ($GLOBALS['cfg']['LeftFrameDBTree']
  323.                 && $GLOBALS['cfg']['LeftFrameDBSeparator']
  324.                 && strstr($db, $GLOBALS['cfg']['LeftFrameDBSeparator']))
  325.             {
  326.                 // use strpos instead of strrpos; it seems more common to
  327.                 // have the db name, the separator, then the rest which
  328.                 // might contain a separator
  329.                 // like dbname_the_rest
  330.                 $pos            = strpos($db, $GLOBALS['cfg']['LeftFrameDBSeparator']);
  331.                 $group          = substr($db, 0, $pos);
  332.                 $disp_name_cut  = substr($db, $pos);
  333.             } else {
  334.                 $group          = $db;
  335.                 $disp_name_cut  = $db;
  336.             }
  337.  
  338.             $disp_name  = $db;
  339.             if ($db_tooltip && $GLOBALS['cfg']['ShowTooltipAliasDB']) {
  340.                 $disp_name      = $db_tooltip;
  341.                 $disp_name_cut  = $db_tooltip;
  342.                 $db_tooltip     = $db;
  343.             }
  344.  
  345.             $dbgroups[$group][$db] = array(
  346.                 'name'          => $db,
  347.                 'disp_name_cut' => $disp_name_cut,
  348.                 'disp_name'     => $disp_name,
  349.                 'comment'       => $db_tooltip,
  350.                 'num_tables'    => PMA_getTableCount($db),
  351.             );
  352.         } // end foreach ($GLOBALS['PMA_List_Database']->items as $db)
  353.         return $dbgroups;
  354.     }
  355.  
  356.     /**
  357.      * returns a part of the items 
  358.      *
  359.      * @uses    PMA_List_Database::$items
  360.      * @uses    array_slice()
  361.      * @param   integer $offset
  362.      * @param   integer $count
  363.      * @return  array  some items 
  364.      */
  365.     function getLimitedItems($offset, $count)
  366.     {
  367.         return(array_slice($this->items, $offset, $count));
  368.     }
  369.  
  370.     /**
  371.      * returns html code for list with dbs
  372.      *
  373.      * @return  string  html code list
  374.      */
  375.     function getHtmlListGrouped($selected = '', $offset, $count)
  376.     {
  377.         if (true === $selected) {
  378.             $selected = $this->getDefault();
  379.         }
  380.  
  381.         $return = '<ul id="databaseList" xml:lang="en" dir="ltr">' . "\n";
  382.         foreach ($this->getGroupedDetails($offset, $count) as $group => $dbs) {
  383.             if (count($dbs) > 1) {
  384.                 $return .= '<li>' . htmlspecialchars($group) . '<ul>' . "\n";
  385.                 // wether display db_name cuted by the group part
  386.                 $cut = true;
  387.             } else {
  388.                 // .. or full
  389.                 $cut = false;
  390.             }
  391.             foreach ($dbs as $db) {
  392.                 $return .= '<li';
  393.                 if ($db['name'] == $selected) {
  394.                     $return .= ' class="selected"';
  395.                 }
  396.                 $return .= '><a';
  397.                 if (! empty($db['comment'])) {
  398.                     $return .= ' title="' . htmlspecialchars($db['comment']) . '"';
  399.                 }
  400.                 $return .= ' href="index.php?' . PMA_generate_common_url($db['name'])
  401.                     . '" target="_parent">';
  402.                 if ($cut) {
  403.                     $return .= htmlspecialchars($db['disp_name_cut']);
  404.                 } else {
  405.                     $return .= htmlspecialchars($db['disp_name']);
  406.                 }
  407.                 $return .= ' (' . $db['num_tables'] . ')';
  408.                 $return .= '</a></li>' . "\n";
  409.             }
  410.             if (count($dbs) > 1) {
  411.                 $return .= '</ul></li>' . "\n";
  412.             }
  413.         }
  414.         $return .= '</ul>';
  415.  
  416.         return $return;
  417.     }
  418.  
  419.     /**
  420.      * returns html code for select form element with dbs
  421.      *
  422.      * @todo IE can not handle different text directions in select boxes so,
  423.      * as mostly names will be in english, we set the whole selectbox to LTR
  424.      * and EN
  425.      *
  426.      * @return  string  html code select
  427.      */
  428.     function getHtmlSelectGrouped($selected = '', $offset, $count)
  429.     {
  430.         if (true === $selected) {
  431.             $selected = $this->getDefault();
  432.         }
  433.  
  434.         $return = '<select name="db" id="lightm_db" xml:lang="en" dir="ltr"'
  435.             . ' onchange="if (this.value != \'\') window.parent.openDb(this.value);">' . "\n"
  436.             . '<option value="" dir="' . $GLOBALS['text_dir'] . '">'
  437.             . '(' . $GLOBALS['strDatabases'] . ') ...</option>' . "\n";
  438.         foreach ($this->getGroupedDetails($offset, $count) as $group => $dbs) {
  439.             if (count($dbs) > 1) {
  440.                 $return .= '<optgroup label="' . htmlspecialchars($group)
  441.                     . '">' . "\n";
  442.                 // wether display db_name cuted by the group part
  443.                 $cut = true;
  444.             } else {
  445.                 // .. or full
  446.                 $cut = false;
  447.             }
  448.             foreach ($dbs as $db) {
  449.                 $return .= '<option value="' . htmlspecialchars($db['name']) . '"'
  450.                     .' title="' . htmlspecialchars($db['comment']) . '"';
  451.                 if ($db['name'] == $selected) {
  452.                     $return .= ' selected="selected"';
  453.                 }
  454.                 $return .= '>' . htmlspecialchars($cut ? $db['disp_name_cut'] : $db['disp_name'])
  455.                     .' (' . $db['num_tables'] . ')</option>' . "\n";
  456.             }
  457.             if (count($dbs) > 1) {
  458.                 $return .= '</optgroup>' . "\n";
  459.             }
  460.         }
  461.         $return .= '</select>';
  462.  
  463.         return $return;
  464.     }
  465.  
  466.     /**
  467.      * this is just a backup, if all is fine this can be deleted later
  468.      *
  469.      * @deprecated
  470.      * @access protected
  471.      */
  472.     function _checkAgainstPrivTables()
  473.     {
  474.         // 1. get allowed dbs from the "mysql.db" table
  475.         // lem9: User can be blank (anonymous user)
  476.         $local_query = "
  477.             SELECT DISTINCT `Db` FROM `mysql`.`db`
  478.             WHERE `Select_priv` = 'Y'
  479.             AND `User`
  480.             IN ('" . PMA_sqlAddslashes($GLOBALS['cfg']['Server']['user']) . "', '')";
  481.         $tmp_mydbs = PMA_DBI_fetch_result($local_query, null, null,
  482.             $GLOBALS['controllink']);
  483.         if ($tmp_mydbs) {
  484.             // Will use as associative array of the following 2 code
  485.             // lines:
  486.             //   the 1st is the only line intact from before
  487.             //     correction,
  488.             //   the 2nd replaces $dblist[] = $row['Db'];
  489.  
  490.             // Code following those 2 lines in correction continues
  491.             // populating $dblist[], as previous code did. But it is
  492.             // now populated with actual database names instead of
  493.             // with regular expressions.
  494.             var_dump($tmp_mydbs);
  495.             $tmp_alldbs = PMA_DBI_query('SHOW DATABASES;', $GLOBALS['controllink']);
  496.             // loic1: all databases cases - part 2
  497.             if (isset($tmp_mydbs['%'])) {
  498.                 while ($tmp_row = PMA_DBI_fetch_row($tmp_alldbs)) {
  499.                     $dblist[] = $tmp_row[0];
  500.                 } // end while
  501.             } else {
  502.                 while ($tmp_row = PMA_DBI_fetch_row($tmp_alldbs)) {
  503.                     $tmp_db = $tmp_row[0];
  504.                     if (isset($tmp_mydbs[$tmp_db]) && $tmp_mydbs[$tmp_db] == 1) {
  505.                         $dblist[]           = $tmp_db;
  506.                         $tmp_mydbs[$tmp_db] = 0;
  507.                     } elseif (!isset($dblist[$tmp_db])) {
  508.                         foreach ($tmp_mydbs as $tmp_matchpattern => $tmp_value) {
  509.                             // loic1: fixed bad regexp
  510.                             // TODO: db names may contain characters
  511.                             //       that are regexp instructions
  512.                             $re        = '(^|(\\\\\\\\)+|[^\])';
  513.                             $tmp_regex = ereg_replace($re . '%', '\\1.*', ereg_replace($re . '_', '\\1.{1}', $tmp_matchpattern));
  514.                             // Fixed db name matching
  515.                             // 2000-08-28 -- Benjamin Gandon
  516.                             if (ereg('^' . $tmp_regex . '$', $tmp_db)) {
  517.                                 $dblist[] = $tmp_db;
  518.                                 break;
  519.                             }
  520.                         } // end while
  521.                     } // end if ... elseif ...
  522.                 } // end while
  523.             } // end else
  524.             PMA_DBI_free_result($tmp_alldbs);
  525.             unset($tmp_mydbs);
  526.         } // end if
  527.  
  528.         // 2. get allowed dbs from the "mysql.tables_priv" table
  529.         $local_query = 'SELECT DISTINCT Db FROM mysql.tables_priv WHERE Table_priv LIKE \'%Select%\' AND User = \'' . PMA_sqlAddslashes($GLOBALS['cfg']['Server']['user']) . '\'';
  530.         $rs          = PMA_DBI_try_query($local_query, $GLOBALS['controllink']);
  531.         if ($rs && @PMA_DBI_num_rows($rs)) {
  532.             while ($row = PMA_DBI_fetch_assoc($rs)) {
  533.                 if (!in_array($row['Db'], $dblist)) {
  534.                     $dblist[] = $row['Db'];
  535.                 }
  536.             } // end while
  537.             PMA_DBI_free_result($rs);
  538.         } // end if
  539.     }
  540. }
  541. ?>
  542.