home *** CD-ROM | disk | FTP | other *** search
/ PC World 2008 February (DVD) / PCWorld_2008-02_DVD.iso / v cisle / PHP / PHP.exe / xampp-win32-1.6.5-installer.exe / phpMyAdmin / libraries / Table.class.php < prev    next >
Encoding:
PHP Script  |  2007-12-20  |  43.2 KB  |  1,059 lines

  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4.  *
  5.  * @version $Id: Table.class.php 10923 2007-11-14 18:42:47Z lem9 $
  6.  */
  7.  
  8. /**
  9.  *
  10.  */
  11. class PMA_Table {
  12.  
  13.     /**
  14.      * @var string  table name
  15.      */
  16.     var $name = '';
  17.  
  18.     /**
  19.      * @var string  database name
  20.      */
  21.     var $db_name = '';
  22.  
  23.     /**
  24.      * @var string  engine (innodb, myisam, bdb, ...)
  25.      */
  26.     var $engine = '';
  27.  
  28.     /**
  29.      * @var string  type (view, base table, system view)
  30.      */
  31.     var $type = '';
  32.  
  33.     /**
  34.      * @var array   settings
  35.      */
  36.     var $settings = array();
  37.  
  38.     /**
  39.      * @var array errors occured
  40.      */
  41.     var $errors = array();
  42.  
  43.     /**
  44.      * @var array messages
  45.      */
  46.     var $messages = array();
  47.  
  48.     /**
  49.      * Constructor
  50.      *
  51.      * @param   string  $table_name table name
  52.      * @param   string  $db_name    database name
  53.      */
  54.     function __construct($table_name, $db_name)
  55.     {
  56.         $this->setName($table_name);
  57.         $this->setDbName($db_name);
  58.     }
  59.  
  60.     /**
  61.      * @see PMA_Table::getName()
  62.      */
  63.     function __toString()
  64.     {
  65.         return $this->getName();
  66.     }
  67.  
  68.     function getLastError()
  69.     {
  70.         return end($this->errors);
  71.     }
  72.  
  73.     function getLastMessage()
  74.     {
  75.         return end($this->messages);
  76.     }
  77.  
  78.     /**
  79.      * sets table anme
  80.      *
  81.      * @uses    $this->name to set it
  82.      * @param   string  $table_name new table name
  83.      */
  84.     function setName($table_name)
  85.     {
  86.         $this->name = $table_name;
  87.     }
  88.  
  89.     /**
  90.      * returns table name
  91.      *
  92.      * @uses    $this->name as return value
  93.      * @param   boolean wether to quote name with backticks ``
  94.      * @return  string  table name
  95.      */
  96.     function getName($quoted = false)
  97.     {
  98.         if ($quoted) {
  99.             return PMA_backquote($this->name);
  100.         }
  101.         return $this->name;
  102.     }
  103.  
  104.     /**
  105.      * sets database name for this table
  106.      *
  107.      * @uses    $this->db_name  to set it
  108.      * @param   string  $db_name
  109.      */
  110.     function setDbName($db_name)
  111.     {
  112.         $this->db_name = $db_name;
  113.     }
  114.  
  115.     /**
  116.      * returns database name for this table
  117.      *
  118.      * @uses    $this->db_name  as return value
  119.      * @param   boolean wether to quote name with backticks ``
  120.      * @return  string  database name for this table
  121.      */
  122.     function getDbName($quoted = false)
  123.     {
  124.         if ($quoted) {
  125.             return PMA_backquote($this->db_name);
  126.         }
  127.         return $this->db_name;
  128.     }
  129.  
  130.     /**
  131.      * returns full name for table, including database name
  132.      *
  133.      * @param   boolean wether to quote name with backticks ``
  134.      */
  135.     function getFullName($quoted = false)
  136.     {
  137.         return $this->getDbName($quoted) . '.' . $this->getName($quoted);
  138.     }
  139.  
  140.     function isView($db = null, $table = null)
  141.     {
  142.         if (strlen($db) && strlen($table)) {
  143.             return PMA_Table::_isView($db, $table);
  144.         }
  145.  
  146.         if (isset($this) && strpos($this->get('TABLE TYPE'), 'VIEW')) {
  147.             return true;
  148.         }
  149.  
  150.         return false;
  151.     }
  152.  
  153.     /**
  154.      * sets given $value for given $param
  155.      *
  156.      * @uses    $this->settings to add or change value
  157.      * @param   string  param name
  158.      * @param   mixed   param value
  159.      */
  160.     function set($param, $value)
  161.     {
  162.         $this->settings[$param] = $value;
  163.     }
  164.  
  165.     /**
  166.      * returns value for given setting/param
  167.      *
  168.      * @uses    $this->settings to return value
  169.      * @param   string  name for value to return
  170.      * @return  mixed   value for $param
  171.      */
  172.     function get($param)
  173.     {
  174.         if (isset($this->settings[$param])) {
  175.             return $this->settings[$param];
  176.         }
  177.  
  178.         return null;
  179.     }
  180.  
  181.     /**
  182.      * loads structure data
  183.      */
  184.     function loadStructure()
  185.     {
  186.         $table_info = PMA_DBI_get_tables_full($this->getDbName(), $this->getName());
  187.  
  188.         if (false === $table_info) {
  189.             return false;
  190.         }
  191.  
  192.         $this->settings = $table_info;
  193.  
  194.         if ($this->get('TABLE_ROWS') === null) {
  195.             $this->set('TABLE_ROWS', PMA_Table::countRecords($this->getDbName(),
  196.                 $this->getName(), true, true));
  197.         }
  198.  
  199.         $create_options = explode(' ', $this->get('TABLE_ROWS'));
  200.  
  201.         // export create options by its name as variables into gloabel namespace
  202.         // f.e. pack_keys=1 becomes available as $pack_keys with value of '1'
  203.         foreach ($create_options as $each_create_option) {
  204.             $each_create_option = explode('=', $each_create_option);
  205.             if (isset($each_create_option[1])) {
  206.                 $this->set($$each_create_option[0], $each_create_option[1]);
  207.             }
  208.         }
  209.     }
  210.  
  211.     /**
  212.      * old PHP 4style constructor
  213.      *
  214.      * @see     PMA_Table::__construct()
  215.      */
  216.     function PMA_Table($table_name, $db_name)
  217.     {
  218.         $this->__construct($table_name, $db_name);
  219.     }
  220.  
  221.     /**
  222.      * Checks if this "table" is a view
  223.      *
  224.      * @deprecated
  225.      * @todo see what we could do with the possible existence of $table_is_view
  226.      * @param   string   the database name
  227.      * @param   string   the table name
  228.      *
  229.      * @return  boolean  whether this is a view
  230.      *
  231.      * @access  public
  232.      */
  233.     function _isView($db, $table) {
  234.         // maybe we already know if the table is a view
  235.         if (isset($GLOBALS['tbl_is_view']) && $GLOBALS['tbl_is_view']) {
  236.             return true;
  237.         }
  238.         // old MySQL version: no view
  239.         if (PMA_MYSQL_INT_VERSION < 50000) {
  240.             return false;
  241.         }
  242.         // This would be the correct way of doing the check but at least in
  243.         // MySQL 5.0.33 it's too slow when there are hundreds of databases
  244.         // and/or tables (more than 3 minutes for 400 tables)
  245.         /*if (false === PMA_DBI_fetch_value('SELECT TABLE_NAME FROM `information_schema`.`VIEWS` WHERE `TABLE_SCHEMA` = \'' . $db . '\' AND `TABLE_NAME` = \'' . $table . '\';')) {
  246.             return false;
  247.         } else {
  248.             return true;
  249.         } */
  250.         // A more complete verification would be to check if all columns
  251.         // from the result set are NULL except Name and Comment.
  252.         // MySQL from 5.0.0 to 5.0.12 returns 'view',
  253.         // from 5.0.13 returns 'VIEW'.
  254.         $comment = strtoupper(PMA_DBI_fetch_value('SHOW TABLE STATUS FROM ' . PMA_backquote($db) . ' LIKE \'' . $table . '\'', 0, 'Comment'));
  255.         // use substr() because the comment might contain something like:
  256.         // (VIEW 'BASE2.VTEST' REFERENCES INVALID TABLE(S) OR COLUMN(S) OR FUNCTION)
  257.         return (substr($comment, 0, 4) == 'VIEW');
  258.     }
  259.  
  260.     /**
  261.      * generates column/field specification for ALTER or CREATE TABLE syntax
  262.      *
  263.      * @todo    move into class PMA_Column
  264.      * @todo on the interface, some js to clear the default value when the default
  265.      * current_timestamp is checked
  266.      * @static
  267.      * @param   string  $name       name
  268.      * @param   string  $type       type ('INT', 'VARCHAR', 'BIT', ...)
  269.      * @param   string  $length     length ('2', '5,2', '', ...)
  270.      * @param   string  $attribute
  271.      * @param   string  $collation
  272.      * @param   string  $null       with 'NULL' or 'NOT NULL'
  273.      * @param   string  $default    default value
  274.      * @param   boolean $default_current_timestamp  whether default value is
  275.      *                                              CURRENT_TIMESTAMP or not
  276.      *                                              this overrides $default value
  277.      * @param   string  $extra      'AUTO_INCREMENT'
  278.      * @param   string  $comment    field comment
  279.      * @param   array   &$field_primary list of fields for PRIMARY KEY
  280.      * @param   string  $index
  281.      * @param   string  $default_orig
  282.      * @return  string  field specification
  283.      */
  284.     function generateFieldSpec($name, $type, $length = '', $attribute = '',
  285.         $collation = '', $null = false, $default = '',
  286.         $default_current_timestamp = false, $extra = '', $comment = '',
  287.         &$field_primary, $index, $default_orig = false)
  288.     {
  289.  
  290.         $is_timestamp = strpos(' ' . strtoupper($type), 'TIMESTAMP') == 1;
  291.  
  292.         // $default_current_timestamp has priority over $default
  293.  
  294.         /**
  295.          * @todo include db-name
  296.          */
  297.         $query = PMA_backquote($name) . ' ' . $type;
  298.  
  299.         if ($length != ''
  300.             && !preg_match('@^(DATE|DATETIME|TIME|TINYBLOB|TINYTEXT|BLOB|TEXT|MEDIUMBLOB|MEDIUMTEXT|LONGBLOB|LONGTEXT)$@i', $type)) {
  301.             $query .= '(' . $length . ')';
  302.         }
  303.  
  304.         if ($attribute != '') {
  305.             $query .= ' ' . $attribute;
  306.         }
  307.  
  308.         if (PMA_MYSQL_INT_VERSION >= 40100 && !empty($collation)
  309.           && $collation != 'NULL'
  310.           && preg_match('@^(TINYTEXT|TEXT|MEDIUMTEXT|LONGTEXT|VARCHAR|CHAR|ENUM|SET)$@i', $type)) {
  311.             $query .= PMA_generateCharsetQueryPart($collation);
  312.         }
  313.  
  314.         if ($null !== false) {
  315.             if (!empty($null)) {
  316.                 $query .= ' NOT NULL';
  317.             } else {
  318.                 $query .= ' NULL';
  319.             }
  320.         }
  321.  
  322.         if ($default_current_timestamp && $is_timestamp) {
  323.             $query .= ' DEFAULT CURRENT_TIMESTAMP';
  324.         // auto_increment field cannot have a default value
  325.         } elseif ($extra !== 'AUTO_INCREMENT'
  326.           && (strlen($default) || $default != $default_orig)) {
  327.             if (strtoupper($default) == 'NULL') {
  328.                 $query .= ' DEFAULT NULL';
  329.             } else {
  330.                 if (strlen($default)) {
  331.                     if ($is_timestamp && $default == '0') {
  332.                         // a TIMESTAMP does not accept DEFAULT '0'
  333.                         // but DEFAULT 0  works
  334.                         $query .= ' DEFAULT ' . PMA_sqlAddslashes($default);
  335.                     } elseif ($default && $type == 'BIT') {
  336.                         $query .= ' DEFAULT b\'' . preg_replace('/[^01]/', '0', $default) . '\'';
  337.                     } else {
  338.                         $query .= ' DEFAULT \'' . PMA_sqlAddslashes($default) . '\'';
  339.                     }
  340.                 }
  341.             }
  342.         }
  343.  
  344.         if (!empty($extra)) {
  345.             $query .= ' ' . $extra;
  346.             // Force an auto_increment field to be part of the primary key
  347.             // even if user did not tick the PK box; 
  348.             // but the PK could contain other columns so do not append
  349.             // a PRIMARY KEY clause, just add a member to $field_primary
  350.             if ($extra == 'AUTO_INCREMENT') {
  351.                 $primary_cnt = count($field_primary);
  352.                 $found_in_pk = false;
  353.                 for ($j = 0; $j < $primary_cnt; $j++) {
  354.                     if ($field_primary[$j] == $index) {
  355.                         $found_in_pk = true;
  356.                         break;
  357.                     }
  358.                 } // end for
  359.                 if (! $found_in_pk) {
  360.                     $field_primary[] = $index;
  361.                 }
  362.             } // end if (auto_increment)
  363.         }
  364.         if (PMA_MYSQL_INT_VERSION >= 40100 && !empty($comment)) {
  365.             $query .= " COMMENT '" . PMA_sqlAddslashes($comment) . "'";
  366.         }
  367.         return $query;
  368.     } // end function
  369.  
  370.     /**
  371.      * Counts and returns (or displays) the number of records in a table
  372.      *
  373.      * Revision 13 July 2001: Patch for limiting dump size from
  374.      * vinay@sanisoft.com & girish@sanisoft.com
  375.      *
  376.      * @param   string   the current database name
  377.      * @param   string   the current table name
  378.      * @param   boolean  whether to retain or to displays the result
  379.      * @param   boolean  whether to force an exact count
  380.      *
  381.      * @return  mixed    the number of records if retain is required, true else
  382.      *
  383.      * @access  public
  384.      */
  385.     function countRecords($db, $table, $ret = false, $force_exact = false)
  386.     {
  387.         $row_count = false;
  388.  
  389.         if (! $force_exact) {
  390.             $row_count = PMA_DBI_fetch_value(
  391.                 'SHOW TABLE STATUS FROM ' . PMA_backquote($db) . ' LIKE \''
  392.                     . PMA_sqlAddslashes($table, true) . '\';',
  393.                 0, 'Rows');
  394.         }
  395.  
  396.         $tbl_is_view = PMA_Table::isView($db, $table);
  397.  
  398.         // for a VIEW, $row_count is always false at this point
  399.         if (false === $row_count || $row_count < $GLOBALS['cfg']['MaxExactCount']) {
  400.             if (! $tbl_is_view) {
  401.                 $row_count = PMA_DBI_fetch_value(
  402.                     'SELECT COUNT(*) FROM ' . PMA_backquote($db) . '.'
  403.                     . PMA_backquote($table));
  404.             } else {
  405.                 // For complex views, even trying to get a partial record
  406.                 // count could bring down a server, so we offer an
  407.                 // alternative: setting MaxExactCountViews to 0 will bypass
  408.                 // completely the record counting for views
  409.  
  410.                 if ($GLOBALS['cfg']['MaxExactCountViews'] == 0) {
  411.                     $row_count = 0;
  412.                 } else {
  413.                     // Counting all rows of a VIEW could be too long, so use
  414.                     // a LIMIT clause.
  415.                     // Use try_query because it can fail (a VIEW is based on
  416.                     // a table that no longer exists)
  417.                     $result = PMA_DBI_try_query(
  418.                         'SELECT 1 FROM ' . PMA_backquote($db) . '.'
  419.                             . PMA_backquote($table) . ' LIMIT '
  420.                             . $GLOBALS['cfg']['MaxExactCountViews'],
  421.                             null, PMA_DBI_QUERY_STORE);
  422.                     if (!PMA_DBI_getError()) {
  423.                         $row_count = PMA_DBI_num_rows($result);
  424.                         PMA_DBI_free_result($result);
  425.                     }
  426.                 }
  427.             }
  428.         }
  429.  
  430.         if ($ret) {
  431.             return $row_count;
  432.         }
  433.  
  434.         /**
  435.          * @deprecated at the moment nowhere is $return = false used
  436.          */
  437.         // Note: as of PMA 2.8.0, we no longer seem to be using
  438.         // PMA_Table::countRecords() in display mode.
  439.         echo PMA_formatNumber($row_count, 0);
  440.         if ($tbl_is_view) {
  441.             echo ' '
  442.                 . sprintf($GLOBALS['strViewMaxExactCount'],
  443.                     $GLOBALS['cfg']['MaxExactCount'],
  444.                     '[a@./Documentation.html#cfg_MaxExactCount@_blank]', '[/a]');
  445.         }
  446.     } // end of the 'PMA_Table::countRecords()' function
  447.  
  448.     /**
  449.      * @todo    add documentation
  450.      */
  451.     function generateAlter($oldcol, $newcol, $type, $length,
  452.         $attribute, $collation, $null, $default, $default_current_timestamp,
  453.         $extra, $comment='', $default_orig)
  454.     {
  455.         $empty_a = array();
  456.         return PMA_backquote($oldcol) . ' '
  457.             . PMA_Table::generateFieldSpec($newcol, $type, $length, $attribute,
  458.                 $collation, $null, $default, $default_current_timestamp, $extra,
  459.                 $comment, $empty_a, -1, $default_orig);
  460.     } // end function
  461.  
  462.     /**
  463.      * Inserts existing entries in a PMA_* table by reading a value from an old entry
  464.      *
  465.      * @param   string  The array index, which Relation feature to check
  466.      *                  ('relwork', 'commwork', ...)
  467.      * @param   string  The array index, which PMA-table to update
  468.      *                  ('bookmark', 'relation', ...)
  469.      * @param   array   Which fields will be SELECT'ed from the old entry
  470.      * @param   array   Which fields will be used for the WHERE query
  471.      *                  (array('FIELDNAME' => 'FIELDVALUE'))
  472.      * @param   array   Which fields will be used as new VALUES. These are the important
  473.      *                  keys which differ from the old entry.
  474.      *                  (array('FIELDNAME' => 'NEW FIELDVALUE'))
  475.  
  476.      * @global  string  relation variable
  477.      *
  478.      * @author          Garvin Hicking <me@supergarv.de>
  479.      */
  480.     function duplicateInfo($work, $pma_table, $get_fields, $where_fields,
  481.       $new_fields)
  482.     {
  483.         $last_id = -1;
  484.  
  485.         if (isset($GLOBALS['cfgRelation']) && $GLOBALS['cfgRelation'][$work]) {
  486.             $select_parts = array();
  487.             $row_fields = array();
  488.             foreach ($get_fields as $get_field) {
  489.                 $select_parts[] = PMA_backquote($get_field);
  490.                 $row_fields[$get_field] = 'cc';
  491.             }
  492.  
  493.             $where_parts = array();
  494.             foreach ($where_fields as $_where => $_value) {
  495.                 $where_parts[] = PMA_backquote($_where) . ' = \''
  496.                     . PMA_sqlAddslashes($_value) . '\'';
  497.             }
  498.  
  499.             $new_parts = array();
  500.             $new_value_parts = array();
  501.             foreach ($new_fields as $_where => $_value) {
  502.                 $new_parts[] = PMA_backquote($_where);
  503.                 $new_value_parts[] = PMA_sqlAddslashes($_value);
  504.             }
  505.  
  506.             $table_copy_query = '
  507.                 SELECT ' . implode(', ', $select_parts) . '
  508.                   FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.'
  509.                   . PMA_backquote($GLOBALS['cfgRelation'][$pma_table]) . '
  510.                  WHERE ' . implode(' AND ', $where_parts);
  511.  
  512.             // must use PMA_DBI_QUERY_STORE here, since we execute another
  513.             // query inside the loop
  514.             $table_copy_rs    = PMA_query_as_cu($table_copy_query, true,
  515.                 PMA_DBI_QUERY_STORE);
  516.  
  517.             while ($table_copy_row = @PMA_DBI_fetch_assoc($table_copy_rs)) {
  518.                 $value_parts = array();
  519.                 foreach ($table_copy_row as $_key => $_val) {
  520.                     if (isset($row_fields[$_key]) && $row_fields[$_key] == 'cc') {
  521.                         $value_parts[] = PMA_sqlAddslashes($_val);
  522.                     }
  523.                 }
  524.  
  525.                 $new_table_query = '
  526.                     INSERT IGNORE INTO ' . PMA_backquote($GLOBALS['cfgRelation']['db'])
  527.                         . '.' . PMA_backquote($GLOBALS['cfgRelation'][$pma_table]) . '
  528.                     (' . implode(', ', $select_parts) . ',
  529.                      ' . implode(', ', $new_parts) . ')
  530.                     VALUES
  531.                     (\'' . implode('\', \'', $value_parts) . '\',
  532.                      \'' . implode('\', \'', $new_value_parts) . '\')';
  533.  
  534.                 PMA_query_as_cu($new_table_query);
  535.                 $last_id = PMA_DBI_insert_id();
  536.             } // end while
  537.  
  538.             PMA_DBI_free_result($table_copy_rs);
  539.  
  540.             return $last_id;
  541.         }
  542.  
  543.         return true;
  544.     } // end of 'PMA_Table::duplicateInfo()' function
  545.  
  546.  
  547.     /**
  548.      * Copies or renames table
  549.      * @todo use RENAME for move operations
  550.      *        - would work only if the databases are on the same filesystem,
  551.      *          how can we check that? try the operation and
  552.      *          catch an error?
  553.      *        - for views, only if MYSQL > 50013
  554.      *        - still have to handle pmadb synch.
  555.      *
  556.      * @author          Michal Cihar <michal@cihar.com>
  557.      */
  558.     function moveCopy($source_db, $source_table, $target_db, $target_table, $what, $move, $mode)
  559.     {
  560.         global $err_url;
  561.  
  562.         // set export settings we need
  563.         $GLOBALS['sql_backquotes'] = 1;
  564.         $GLOBALS['asfile']         = 1;
  565.  
  566.         // Ensure the target is valid
  567.         if (! $GLOBALS['PMA_List_Database']->exists($source_db, $target_db)) {
  568.             /**
  569.              * @todo exit really needed here? or just a return?
  570.              */
  571.             exit;
  572.         }
  573.  
  574.         $source = PMA_backquote($source_db) . '.' . PMA_backquote($source_table);
  575.         if (! isset($target_db) || ! strlen($target_db)) {
  576.             $target_db = $source_db;
  577.         }
  578.  
  579.         // Doing a select_db could avoid some problems with replicated databases,
  580.         // when moving table from replicated one to not replicated one
  581.         PMA_DBI_select_db($target_db);
  582.  
  583.         $target = PMA_backquote($target_db) . '.' . PMA_backquote($target_table);
  584.  
  585.         // do not create the table if dataonly
  586.         if ($what != 'dataonly') {
  587.             require_once './libraries/export/sql.php';
  588.  
  589.             $no_constraints_comments = true;
  590.             $GLOBALS['sql_constraints_query'] = '';
  591.  
  592.             $sql_structure = PMA_getTableDef($source_db, $source_table, "\n", $err_url);
  593.             unset($no_constraints_comments);
  594.             $parsed_sql =  PMA_SQP_parse($sql_structure);
  595.             $analyzed_sql = PMA_SQP_analyze($parsed_sql);
  596.             $i = 0;
  597.             if (empty($analyzed_sql[0]['create_table_fields'])) {
  598.             // this is not a CREATE TABLE, so find the first VIEW
  599.                 $target_for_view = PMA_backquote($target_db);
  600.                 while (true) {
  601.                 if ($parsed_sql[$i]['type'] == 'alpha_reservedWord' && $parsed_sql[$i]['data'] == 'VIEW') {
  602.                         break;
  603.                     }
  604.                     $i++;
  605.                 }
  606.             }
  607.             unset($analyzed_sql);
  608.  
  609.             /* nijel: Find table name in query and replace it */
  610.             while ($parsed_sql[$i]['type'] != 'quote_backtick') {
  611.                 $i++;
  612.             }
  613.  
  614.             /* no need to PMA_backquote() */
  615.             if (isset($target_for_view)) {
  616.                 // this a view definition; we just found the first db name
  617.                 // that follows DEFINER VIEW
  618.                 // so change it for the new db name
  619.                         $parsed_sql[$i]['data'] = $target_for_view;
  620.                 // then we have to find all references to the source db
  621.                 // and change them to the target db, ensuring we stay into
  622.                 // the $parsed_sql limits
  623.                 $last = $parsed_sql['len'] - 1;
  624.                 $backquoted_source_db = PMA_backquote($source_db);
  625.                 for (++$i; $i <= $last; $i++) {
  626.                             if ($parsed_sql[$i]['type'] == 'quote_backtick' && $parsed_sql[$i]['data'] == $backquoted_source_db) {
  627.                                 $parsed_sql[$i]['data'] = $target_for_view;
  628.                     }
  629.                 }
  630.                 unset($last,$backquoted_source_db);
  631.             } else {
  632.                 $parsed_sql[$i]['data'] = $target;
  633.             }
  634.  
  635.             /* Generate query back */
  636.             $sql_structure = PMA_SQP_formatHtml($parsed_sql, 'query_only');
  637.             // If table exists, and 'add drop table' is selected: Drop it!
  638.             $drop_query = '';
  639.             if (isset($GLOBALS['drop_if_exists'])
  640.               && $GLOBALS['drop_if_exists'] == 'true') {
  641.                 if (PMA_Table::_isView($target_db,$target_table)) {
  642.                     $drop_query = 'DROP VIEW';
  643.                 } else {
  644.                     $drop_query = 'DROP TABLE';
  645.                 }
  646.                 $drop_query .= ' IF EXISTS '
  647.                     . PMA_backquote($target_db) . '.'
  648.                     . PMA_backquote($target_table);
  649.                 PMA_DBI_query($drop_query);
  650.  
  651.                 $GLOBALS['sql_query'] .= "\n" . $drop_query . ';';
  652.  
  653.                 // garvin: If an existing table gets deleted, maintain any
  654.                 // entries for the PMA_* tables
  655.                 $maintain_relations = true;
  656.             }
  657.  
  658.             @PMA_DBI_query($sql_structure);
  659.             $GLOBALS['sql_query'] .= "\n" . $sql_structure . ';';
  660.  
  661.             if (($move || isset($GLOBALS['add_constraints']))
  662.               && !empty($GLOBALS['sql_constraints_query'])) {
  663.                 $parsed_sql =  PMA_SQP_parse($GLOBALS['sql_constraints_query']);
  664.                 $i = 0;
  665.  
  666.                 // find the first quote_backtick, it must be the source table name
  667.                 while ($parsed_sql[$i]['type'] != 'quote_backtick') {
  668.                     $i++;
  669.                     // maybe someday we should guard against going over limit
  670.                     //if ($i == $parsed_sql['len']) {
  671.                     //    break;
  672.                     //}
  673.                 }
  674.  
  675.                 // replace it by the target table name, no need to PMA_backquote()
  676.                 $parsed_sql[$i]['data'] = $target;
  677.  
  678.                 // now we must remove all quote_backtick that follow a CONSTRAINT
  679.                 // keyword, because a constraint name must be unique in a db
  680.  
  681.                 $cnt = $parsed_sql['len'] - 1;
  682.  
  683.                 for ($j = $i; $j < $cnt; $j++) {
  684.                     if ($parsed_sql[$j]['type'] == 'alpha_reservedWord'
  685.                       && strtoupper($parsed_sql[$j]['data']) == 'CONSTRAINT') {
  686.                         if ($parsed_sql[$j+1]['type'] == 'quote_backtick') {
  687.                             $parsed_sql[$j+1]['data'] = '';
  688.                         }
  689.                     }
  690.                 }
  691.  
  692.                 // Generate query back
  693.                 $GLOBALS['sql_constraints_query'] = PMA_SQP_formatHtml($parsed_sql,
  694.                     'query_only');
  695.                 if ($mode == 'one_table') {
  696.                     PMA_DBI_query($GLOBALS['sql_constraints_query']);
  697.                 }
  698.                 $GLOBALS['sql_query'] .= "\n" . $GLOBALS['sql_constraints_query'];
  699.                 if ($mode == 'one_table') {
  700.                     unset($GLOBALS['sql_constraints_query']);
  701.                 }
  702.             }
  703.         } else {
  704.             $GLOBALS['sql_query'] = '';
  705.         }
  706.  
  707.         // Copy the data unless this is a VIEW
  708.         if (($what == 'data' || $what == 'dataonly') && ! PMA_Table::_isView($target_db,$target_table)) {
  709.             $sql_insert_data =
  710.                 'INSERT INTO ' . $target . ' SELECT * FROM ' . $source;
  711.             PMA_DBI_query($sql_insert_data);
  712.             $GLOBALS['sql_query']      .= "\n\n" . $sql_insert_data . ';';
  713.         }
  714.  
  715.         require_once './libraries/relation.lib.php';
  716.         $GLOBALS['cfgRelation'] = PMA_getRelationsParam();
  717.  
  718.         // Drops old table if the user has requested to move it
  719.         if ($move) {
  720.  
  721.             // This could avoid some problems with replicated databases, when
  722.             // moving table from replicated one to not replicated one
  723.             PMA_DBI_select_db($source_db);
  724.  
  725.             if (PMA_Table::_isView($source_db,$source_table)) {
  726.                 $sql_drop_query = 'DROP VIEW';
  727.             } else {
  728.                 $sql_drop_query = 'DROP TABLE';
  729.             }
  730.             $sql_drop_query .= ' ' . $source;
  731.             PMA_DBI_query($sql_drop_query);
  732.  
  733.             // garvin: Move old entries from PMA-DBs to new table
  734.             if ($GLOBALS['cfgRelation']['commwork']) {
  735.                 $remove_query = 'UPDATE ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($GLOBALS['cfgRelation']['column_info'])
  736.                               . ' SET     table_name = \'' . PMA_sqlAddslashes($target_table) . '\', '
  737.                               . '        db_name    = \'' . PMA_sqlAddslashes($target_db) . '\''
  738.                               . ' WHERE db_name  = \'' . PMA_sqlAddslashes($source_db) . '\''
  739.                               . ' AND table_name = \'' . PMA_sqlAddslashes($source_table) . '\'';
  740.                 PMA_query_as_cu($remove_query);
  741.                 unset($remove_query);
  742.             }
  743.  
  744.             // garvin: updating bookmarks is not possible since only a single table is moved,
  745.             // and not the whole DB.
  746.  
  747.             if ($GLOBALS['cfgRelation']['displaywork']) {
  748.                 $table_query = 'UPDATE ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($GLOBALS['cfgRelation']['table_info'])
  749.                                 . ' SET     db_name = \'' . PMA_sqlAddslashes($target_db) . '\', '
  750.                                 . '         table_name = \'' . PMA_sqlAddslashes($target_table) . '\''
  751.                                 . ' WHERE db_name  = \'' . PMA_sqlAddslashes($source_db) . '\''
  752.                                 . ' AND table_name = \'' . PMA_sqlAddslashes($source_table) . '\'';
  753.                 PMA_query_as_cu($table_query);
  754.                 unset($table_query);
  755.             }
  756.  
  757.             if ($GLOBALS['cfgRelation']['relwork']) {
  758.                 $table_query = 'UPDATE ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($GLOBALS['cfgRelation']['relation'])
  759.                                 . ' SET     foreign_table = \'' . PMA_sqlAddslashes($target_table) . '\','
  760.                                 . '         foreign_db = \'' . PMA_sqlAddslashes($target_db) . '\''
  761.                                 . ' WHERE foreign_db  = \'' . PMA_sqlAddslashes($source_db) . '\''
  762.                                 . ' AND foreign_table = \'' . PMA_sqlAddslashes($source_table) . '\'';
  763.                 PMA_query_as_cu($table_query);
  764.                 unset($table_query);
  765.  
  766.                 $table_query = 'UPDATE ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($GLOBALS['cfgRelation']['relation'])
  767.                                 . ' SET     master_table = \'' . PMA_sqlAddslashes($target_table) . '\','
  768.                                 . '         master_db = \'' . PMA_sqlAddslashes($target_db) . '\''
  769.                                 . ' WHERE master_db  = \'' . PMA_sqlAddslashes($source_db) . '\''
  770.                                 . ' AND master_table = \'' . PMA_sqlAddslashes($source_table) . '\'';
  771.                 PMA_query_as_cu($table_query);
  772.                 unset($table_query);
  773.             }
  774.  
  775.             /**
  776.              * @todo garvin: Can't get moving PDFs the right way. The page numbers
  777.              * always get screwed up independently from duplication because the
  778.              * numbers do not seem to be stored on a per-database basis. Would
  779.              * the author of pdf support please have a look at it?
  780.              */
  781.  
  782.             if ($GLOBALS['cfgRelation']['pdfwork']) {
  783.                 $table_query = 'UPDATE ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($GLOBALS['cfgRelation']['table_coords'])
  784.                                 . ' SET     table_name = \'' . PMA_sqlAddslashes($target_table) . '\','
  785.                                 . '         db_name = \'' . PMA_sqlAddslashes($target_db) . '\''
  786.                                 . ' WHERE db_name  = \'' . PMA_sqlAddslashes($source_db) . '\''
  787.                                 . ' AND table_name = \'' . PMA_sqlAddslashes($source_table) . '\'';
  788.                 PMA_query_as_cu($table_query);
  789.                 unset($table_query);
  790.                 /*
  791.                 $pdf_query = 'SELECT pdf_page_number '
  792.                            . ' FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($GLOBALS['cfgRelation']['table_coords'])
  793.                            . ' WHERE db_name  = \'' . PMA_sqlAddslashes($target_db) . '\''
  794.                            . ' AND table_name = \'' . PMA_sqlAddslashes($target_table) . '\'';
  795.                 $pdf_rs = PMA_query_as_cu($pdf_query);
  796.  
  797.                 while ($pdf_copy_row = PMA_DBI_fetch_assoc($pdf_rs)) {
  798.                     $table_query = 'UPDATE ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($GLOBALS['cfgRelation']['pdf_pages'])
  799.                                     . ' SET     db_name = \'' . PMA_sqlAddslashes($target_db) . '\''
  800.                                     . ' WHERE db_name  = \'' . PMA_sqlAddslashes($source_db) . '\''
  801.                                     . ' AND page_nr = \'' . PMA_sqlAddslashes($pdf_copy_row['pdf_page_number']) . '\'';
  802.                     $tb_rs    = PMA_query_as_cu($table_query);
  803.                     unset($table_query);
  804.                     unset($tb_rs);
  805.                 }
  806.                 */
  807.             }
  808.  
  809.             if ($GLOBALS['cfgRelation']['designerwork']) {
  810.                 $table_query = 'UPDATE ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($GLOBALS['cfgRelation']['designer_coords'])
  811.                                 . ' SET     table_name = \'' . PMA_sqlAddslashes($target_table) . '\','
  812.                                 . '         db_name = \'' . PMA_sqlAddslashes($target_db) . '\''
  813.                                 . ' WHERE db_name  = \'' . PMA_sqlAddslashes($source_db) . '\''
  814.                                 . ' AND table_name = \'' . PMA_sqlAddslashes($source_table) . '\'';
  815.                 PMA_query_as_cu($table_query);
  816.                 unset($table_query);
  817.             }
  818.             $GLOBALS['sql_query']      .= "\n\n" . $sql_drop_query . ';';
  819.         // end if ($move)
  820.         } else {
  821.             // we are copying
  822.             // garvin: Create new entries as duplicates from old PMA DBs
  823.             if ($what != 'dataonly' && !isset($maintain_relations)) {
  824.                 if ($GLOBALS['cfgRelation']['commwork']) {
  825.                     // Get all comments and MIME-Types for current table
  826.                     $comments_copy_query = 'SELECT
  827.                                                 column_name, ' . PMA_backquote('comment') . ($GLOBALS['cfgRelation']['mimework'] ? ', mimetype, transformation, transformation_options' : '') . '
  828.                                             FROM ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($GLOBALS['cfgRelation']['column_info']) . '
  829.                                             WHERE
  830.                                                 db_name = \'' . PMA_sqlAddslashes($source_db) . '\' AND
  831.                                                 table_name = \'' . PMA_sqlAddslashes($source_table) . '\'';
  832.                     $comments_copy_rs    = PMA_query_as_cu($comments_copy_query);
  833.  
  834.                     // Write every comment as new copied entry. [MIME]
  835.                     while ($comments_copy_row = PMA_DBI_fetch_assoc($comments_copy_rs)) {
  836.                         $new_comment_query = 'REPLACE INTO ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.' . PMA_backquote($GLOBALS['cfgRelation']['column_info'])
  837.                                     . ' (db_name, table_name, column_name, ' . PMA_backquote('comment') . ($GLOBALS['cfgRelation']['mimework'] ? ', mimetype, transformation, transformation_options' : '') . ') '
  838.                                     . ' VALUES('
  839.                                     . '\'' . PMA_sqlAddslashes($target_db) . '\','
  840.                                     . '\'' . PMA_sqlAddslashes($target_table) . '\','
  841.                                     . '\'' . PMA_sqlAddslashes($comments_copy_row['column_name']) . '\''
  842.                                     . ($GLOBALS['cfgRelation']['mimework'] ? ',\'' . PMA_sqlAddslashes($comments_copy_row['comment']) . '\','
  843.                                             . '\'' . PMA_sqlAddslashes($comments_copy_row['mimetype']) . '\','
  844.                                             . '\'' . PMA_sqlAddslashes($comments_copy_row['transformation']) . '\','
  845.                                             . '\'' . PMA_sqlAddslashes($comments_copy_row['transformation_options']) . '\'' : '')
  846.                                     . ')';
  847.                         PMA_query_as_cu($new_comment_query);
  848.                     } // end while
  849.                     PMA_DBI_free_result($comments_copy_rs);
  850.                     unset($comments_copy_rs);
  851.                 }
  852.  
  853.                 // duplicating the bookmarks must not be done here, but
  854.                 // just once per db
  855.  
  856.                 $get_fields = array('display_field');
  857.                 $where_fields = array('db_name' => $source_db, 'table_name' => $source_table);
  858.                 $new_fields = array('db_name' => $target_db, 'table_name' => $target_table);
  859.                 PMA_Table::duplicateInfo('displaywork', 'table_info', $get_fields, $where_fields, $new_fields);
  860.                 
  861.  
  862.                 /**
  863.                  * @todo revise this code when we support cross-db relations
  864.                  */
  865.                 $get_fields = array('master_field', 'foreign_table', 'foreign_field');
  866.                 $where_fields = array('master_db' => $source_db, 'master_table' => $source_table);
  867.                 $new_fields = array('master_db' => $target_db, 'foreign_db' => $target_db, 'master_table' => $target_table);
  868.                 PMA_Table::duplicateInfo('relwork', 'relation', $get_fields, $where_fields, $new_fields);
  869.                 
  870.  
  871.                 $get_fields = array('foreign_field', 'master_table', 'master_field');
  872.                 $where_fields = array('foreign_db' => $source_db, 'foreign_table' => $source_table);
  873.                 $new_fields = array('master_db' => $target_db, 'foreign_db' => $target_db, 'foreign_table' => $target_table);
  874.                 PMA_Table::duplicateInfo('relwork', 'relation', $get_fields, $where_fields, $new_fields);
  875.                 
  876.  
  877.                 $get_fields = array('x', 'y', 'v', 'h');
  878.                 $where_fields = array('db_name' => $source_db, 'table_name' => $source_table);
  879.                 $new_fields = array('db_name' => $target_db, 'table_name' => $target_table);
  880.                 PMA_Table::duplicateInfo('designerwork', 'designer_coords', $get_fields, $where_fields, $new_fields);
  881.  
  882.                 /**
  883.                  * @todo garvin: Can't get duplicating PDFs the right way. The
  884.                  * page numbers always get screwed up independently from
  885.                  * duplication because the numbers do not seem to be stored on a
  886.                  * per-database basis. Would the author of pdf support please
  887.                  * have a look at it?
  888.                  *
  889.                 $get_fields = array('page_descr');
  890.                 $where_fields = array('db_name' => $source_db);
  891.                 $new_fields = array('db_name' => $target_db);
  892.                 $last_id = PMA_Table::duplicateInfo('pdfwork', 'pdf_pages', $get_fields, $where_fields, $new_fields);
  893.  
  894.                 if (isset($last_id) && $last_id >= 0) {
  895.                     $get_fields = array('x', 'y');
  896.                     $where_fields = array('db_name' => $source_db, 'table_name' => $source_table);
  897.                     $new_fields = array('db_name' => $target_db, 'table_name' => $target_table, 'pdf_page_number' => $last_id);
  898.                     PMA_Table::duplicateInfo('pdfwork', 'table_coords', $get_fields, $where_fields, $new_fields);
  899.                 }
  900.                  */
  901.             }
  902.         }
  903.  
  904.     }
  905.  
  906.     /**
  907.      * checks if given name is a valid table name,
  908.      * currently if not empty, trailing spaces, '.', '/' and '\'
  909.      *
  910.      * @todo    add check for valid chars in filename on current system/os
  911.      * @see     http://dev.mysql.com/doc/refman/5.0/en/legal-names.html
  912.      * @param   string  $table_name name to check
  913.      * @return  boolean whether the string is valid or not
  914.      */
  915.     function isValidName($table_name)
  916.     {
  917.         if ($table_name !== trim($table_name)) {
  918.             // trailing spaces
  919.             return false;
  920.         }
  921.  
  922.         if (! strlen($table_name)) {
  923.             // zero length
  924.             return false;
  925.         }
  926.  
  927.         if (preg_match('/[.\/\\\\]+/i', $table_name)) {
  928.             // illegal char . / \
  929.             return false;
  930.         }
  931.  
  932.         return true;
  933.     }
  934.  
  935.     /**
  936.      * renames table
  937.      *
  938.      * @param   string  new table name
  939.      * @param   string  new database name
  940.      * @return  boolean success
  941.      */
  942.     function rename($new_name, $new_db = null)
  943.     {
  944.         if (null !== $new_db && $new_db !== $this->getDbName()) {
  945.             // Ensure the target is valid
  946.             if (! $GLOBALS['PMA_List_Database']->exists($new_db)) {
  947.                 $this->errors[] = $GLOBALS['strInvalidDatabase'] . ': ' . $new_db;
  948.                 return false;
  949.             }
  950.         } else {
  951.             $new_db = $this->getDbName();
  952.         }
  953.  
  954.         $new_table = new PMA_Table($new_name, $new_db);
  955.  
  956.         if ($this->getFullName() === $new_table->getFullName()) {
  957.             return true;
  958.         }
  959.  
  960.         if (! PMA_Table::isValidName($new_name)) {
  961.             $this->errors[] = $GLOBALS['strInvalidTableName'] . ': ' . $new_table->getFullName();
  962.             return false;
  963.         }
  964.  
  965.         $GLOBALS['sql_query'] = '
  966.             RENAME TABLE ' . $this->getFullName(true) . '
  967.                       TO ' . $new_table->getFullName(true) . ';';
  968.         if (! PMA_DBI_query($GLOBALS['sql_query'])) {
  969.             $this->errors[] = sprintf($GLOBALS['strErrorRenamingTable'], $this->getFullName(), $new_table->getFullName());
  970.             return false;
  971.         }
  972.  
  973.         $old_name = $this->getName();
  974.         $old_db = $this->getDbName();
  975.         $this->setName($new_name);
  976.         $this->setDbName($new_db);
  977.  
  978.         /**
  979.          * @todo move into extra function PMA_Relation::renameTable($new_name, $old_name, $new_db, $old_db)
  980.          */
  981.         // garvin: Move old entries from comments to new table
  982.         require_once './libraries/relation.lib.php';
  983.         $GLOBALS['cfgRelation'] = PMA_getRelationsParam();
  984.         if ($GLOBALS['cfgRelation']['commwork']) {
  985.             $remove_query = '
  986.                 UPDATE ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.'
  987.                     . PMA_backquote($GLOBALS['cfgRelation']['column_info']) . '
  988.                    SET `db_name`    = \'' . PMA_sqlAddslashes($new_db) . '\',
  989.                        `table_name` = \'' . PMA_sqlAddslashes($new_name) . '\'
  990.                  WHERE `db_name`    = \'' . PMA_sqlAddslashes($old_db) . '\'
  991.                    AND `table_name` = \'' . PMA_sqlAddslashes($old_name) . '\'';
  992.             PMA_query_as_cu($remove_query);
  993.             unset($remove_query);
  994.         }
  995.  
  996.         if ($GLOBALS['cfgRelation']['displaywork']) {
  997.             $table_query = '
  998.                 UPDATE ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.'
  999.                     . PMA_backquote($GLOBALS['cfgRelation']['table_info']) . '
  1000.                    SET `db_name`    = \'' . PMA_sqlAddslashes($new_db) . '\',
  1001.                        `table_name` = \'' . PMA_sqlAddslashes($new_name) . '\'
  1002.                  WHERE `db_name`    = \'' . PMA_sqlAddslashes($old_db) . '\'
  1003.                    AND `table_name` = \'' . PMA_sqlAddslashes($old_name) . '\'';
  1004.             PMA_query_as_cu($table_query);
  1005.             unset($table_query);
  1006.         }
  1007.  
  1008.         if ($GLOBALS['cfgRelation']['relwork']) {
  1009.             $table_query = '
  1010.                 UPDATE ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.'
  1011.                     . PMA_backquote($GLOBALS['cfgRelation']['relation']) . '
  1012.                    SET `foreign_db`    = \'' . PMA_sqlAddslashes($new_db) . '\',
  1013.                        `foreign_table` = \'' . PMA_sqlAddslashes($new_name) . '\'
  1014.                  WHERE `foreign_db`    = \'' . PMA_sqlAddslashes($old_db) . '\'
  1015.                    AND `foreign_table` = \'' . PMA_sqlAddslashes($old_name) . '\'';
  1016.             PMA_query_as_cu($table_query);
  1017.  
  1018.             $table_query = '
  1019.                 UPDATE ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.'
  1020.                     . PMA_backquote($GLOBALS['cfgRelation']['relation']) . '
  1021.                    SET `master_db`    = \'' . PMA_sqlAddslashes($new_db) . '\',
  1022.                        `master_table` = \'' . PMA_sqlAddslashes($new_name) . '\'
  1023.                  WHERE `master_db`    = \'' . PMA_sqlAddslashes($old_db) . '\'
  1024.                    AND `master_table` = \'' . PMA_sqlAddslashes($old_name) . '\'';
  1025.             PMA_query_as_cu($table_query);
  1026.             unset($table_query);
  1027.         }
  1028.  
  1029.         if ($GLOBALS['cfgRelation']['pdfwork']) {
  1030.             $table_query = '
  1031.                 UPDATE ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.'
  1032.                     . PMA_backquote($GLOBALS['cfgRelation']['table_coords']) . '
  1033.                    SET `db_name`    = \'' . PMA_sqlAddslashes($new_db) . '\',
  1034.                        `table_name` = \'' . PMA_sqlAddslashes($new_name) . '\'
  1035.                  WHERE `db_name`    = \'' . PMA_sqlAddslashes($old_db) . '\'
  1036.                    AND `table_name` = \'' . PMA_sqlAddslashes($old_name) . '\'';
  1037.             PMA_query_as_cu($table_query);
  1038.             unset($table_query);
  1039.         }
  1040.  
  1041.         if ($GLOBALS['cfgRelation']['designerwork']) {
  1042.             $table_query = '
  1043.                 UPDATE ' . PMA_backquote($GLOBALS['cfgRelation']['db']) . '.'
  1044.                     . PMA_backquote($GLOBALS['cfgRelation']['designer_coords']) . '
  1045.                    SET `db_name`    = \'' . PMA_sqlAddslashes($new_db) . '\',
  1046.                        `table_name` = \'' . PMA_sqlAddslashes($new_name) . '\'
  1047.                  WHERE `db_name`    = \'' . PMA_sqlAddslashes($old_db) . '\'
  1048.                    AND `table_name` = \'' . PMA_sqlAddslashes($old_name) . '\'';
  1049.             PMA_query_as_cu($table_query);
  1050.             unset($table_query);
  1051.         }
  1052.  
  1053.         $this->messages[] = sprintf($GLOBALS['strRenameTableOK'],
  1054.             htmlspecialchars($old_name), htmlspecialchars($new_name));
  1055.         return true;
  1056.     }
  1057. }
  1058. ?>
  1059.