Warning: file_get_contents(https://raw.githubusercontent.com/Den1xxx/Filemanager/master/languages/ru.json): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found
in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 88
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 215
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 216
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 217
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 218
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 219
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 220
PK ! k k factories/UserFactory.phpnu [ define(User::class, function (Faker $faker) {
return [
'name' => $faker->name,
'email' => $faker->unique()->safeEmail,
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'remember_token' => Str::random(10),
];
});
PK ! v = migrations/2014_10_12_100000_create_password_resets_table.phpnu [ string('email')->index();
$table->string('token');
$table->timestamp('created_at')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('password_resets');
}
}
PK ! k- - 3 migrations/2014_10_12_000000_create_users_table.phpnu [ bigIncrements('id');
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
PK ! |l 9 migrations/2019_08_19_000000_create_failed_jobs_table.phpnu [ bigIncrements('id');
$table->text('connection');
$table->text('queue');
$table->longText('payload');
$table->longText('exception');
$table->timestamp('failed_at')->useCurrent();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('failed_jobs');
}
}
PK ! ) seeds/DatabaseSeeder.phpnu [ call(UsersTableSeeder::class);
}
}
PK ! xr
.gitignorenu [ *.sqlite
*.sqlite-journal
PK ! ψ]* ]* DB_utility.phpnu [ db =& $db;
log_message('info', 'Database Utility Class Initialized');
}
// --------------------------------------------------------------------
/**
* List databases
*
* @return array
*/
public function list_databases()
{
// Is there a cached result?
if (isset($this->db->data_cache['db_names']))
{
return $this->db->data_cache['db_names'];
}
elseif ($this->_list_databases === FALSE)
{
return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
}
$this->db->data_cache['db_names'] = array();
$query = $this->db->query($this->_list_databases);
if ($query === FALSE)
{
return $this->db->data_cache['db_names'];
}
for ($i = 0, $query = $query->result_array(), $c = count($query); $i < $c; $i++)
{
$this->db->data_cache['db_names'][] = current($query[$i]);
}
return $this->db->data_cache['db_names'];
}
// --------------------------------------------------------------------
/**
* Determine if a particular database exists
*
* @param string $database_name
* @return bool
*/
public function database_exists($database_name)
{
return in_array($database_name, $this->list_databases());
}
// --------------------------------------------------------------------
/**
* Optimize Table
*
* @param string $table_name
* @return mixed
*/
public function optimize_table($table_name)
{
if ($this->_optimize_table === FALSE)
{
return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
}
$query = $this->db->query(sprintf($this->_optimize_table, $this->db->escape_identifiers($table_name)));
if ($query !== FALSE)
{
$query = $query->result_array();
return current($query);
}
return FALSE;
}
// --------------------------------------------------------------------
/**
* Optimize Database
*
* @return mixed
*/
public function optimize_database()
{
if ($this->_optimize_table === FALSE)
{
return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
}
$result = array();
foreach ($this->db->list_tables() as $table_name)
{
$res = $this->db->query(sprintf($this->_optimize_table, $this->db->escape_identifiers($table_name)));
if (is_bool($res))
{
return $res;
}
// Build the result array...
$res = $res->result_array();
$res = current($res);
$key = str_replace($this->db->database.'.', '', current($res));
$keys = array_keys($res);
unset($res[$keys[0]]);
$result[$key] = $res;
}
return $result;
}
// --------------------------------------------------------------------
/**
* Repair Table
*
* @param string $table_name
* @return mixed
*/
public function repair_table($table_name)
{
if ($this->_repair_table === FALSE)
{
return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
}
$query = $this->db->query(sprintf($this->_repair_table, $this->db->escape_identifiers($table_name)));
if (is_bool($query))
{
return $query;
}
$query = $query->result_array();
return current($query);
}
// --------------------------------------------------------------------
/**
* Generate CSV from a query result object
*
* @param object $query Query result object
* @param string $delim Delimiter (default: ,)
* @param string $newline Newline character (default: \n)
* @param string $enclosure Enclosure (default: ")
* @return string
*/
public function csv_from_result($query, $delim = ',', $newline = "\n", $enclosure = '"')
{
if ( ! is_object($query) OR ! method_exists($query, 'list_fields'))
{
show_error('You must submit a valid result object');
}
$out = '';
// First generate the headings from the table column names
foreach ($query->list_fields() as $name)
{
$out .= $enclosure.str_replace($enclosure, $enclosure.$enclosure, $name).$enclosure.$delim;
}
$out = substr($out, 0, -strlen($delim)).$newline;
// Next blast through the result array and build out the rows
while ($row = $query->unbuffered_row('array'))
{
$line = array();
foreach ($row as $item)
{
$line[] = $enclosure.str_replace($enclosure, $enclosure.$enclosure, $item).$enclosure;
}
$out .= implode($delim, $line).$newline;
}
return $out;
}
// --------------------------------------------------------------------
/**
* Generate XML data from a query result object
*
* @param object $query Query result object
* @param array $params Any preferences
* @return string
*/
public function xml_from_result($query, $params = array())
{
if ( ! is_object($query) OR ! method_exists($query, 'list_fields'))
{
show_error('You must submit a valid result object');
}
// Set our default values
foreach (array('root' => 'root', 'element' => 'element', 'newline' => "\n", 'tab' => "\t") as $key => $val)
{
if ( ! isset($params[$key]))
{
$params[$key] = $val;
}
}
// Create variables for convenience
extract($params);
// Load the xml helper
get_instance()->load->helper('xml');
// Generate the result
$xml = '<'.$root.'>'.$newline;
while ($row = $query->unbuffered_row())
{
$xml .= $tab.'<'.$element.'>'.$newline;
foreach ($row as $key => $val)
{
$xml .= $tab.$tab.'<'.$key.'>'.xml_convert($val).''.$key.'>'.$newline;
}
$xml .= $tab.''.$element.'>'.$newline;
}
return $xml.''.$root.'>'.$newline;
}
// --------------------------------------------------------------------
/**
* Database Backup
*
* @param array $params
* @return string
*/
public function backup($params = array())
{
// If the parameters have not been submitted as an
// array then we know that it is simply the table
// name, which is a valid short cut.
if (is_string($params))
{
$params = array('tables' => $params);
}
// Set up our default preferences
$prefs = array(
'tables' => array(),
'ignore' => array(),
'filename' => '',
'format' => 'gzip', // gzip, zip, txt
'add_drop' => TRUE,
'add_insert' => TRUE,
'newline' => "\n",
'foreign_key_checks' => TRUE
);
// Did the user submit any preferences? If so set them....
if (count($params) > 0)
{
foreach ($prefs as $key => $val)
{
if (isset($params[$key]))
{
$prefs[$key] = $params[$key];
}
}
}
// Are we backing up a complete database or individual tables?
// If no table names were submitted we'll fetch the entire table list
if (count($prefs['tables']) === 0)
{
$prefs['tables'] = $this->db->list_tables();
}
// Validate the format
if ( ! in_array($prefs['format'], array('gzip', 'zip', 'txt'), TRUE))
{
$prefs['format'] = 'txt';
}
// Is the encoder supported? If not, we'll either issue an
// error or use plain text depending on the debug settings
if (($prefs['format'] === 'gzip' && ! function_exists('gzencode'))
OR ($prefs['format'] === 'zip' && ! function_exists('gzcompress')))
{
if ($this->db->db_debug)
{
return $this->db->display_error('db_unsupported_compression');
}
$prefs['format'] = 'txt';
}
// Was a Zip file requested?
if ($prefs['format'] === 'zip')
{
// Set the filename if not provided (only needed with Zip files)
if ($prefs['filename'] === '')
{
$prefs['filename'] = (count($prefs['tables']) === 1 ? $prefs['tables'] : $this->db->database)
.date('Y-m-d_H-i', time()).'.sql';
}
else
{
// If they included the .zip file extension we'll remove it
if (preg_match('|.+?\.zip$|', $prefs['filename']))
{
$prefs['filename'] = str_replace('.zip', '', $prefs['filename']);
}
// Tack on the ".sql" file extension if needed
if ( ! preg_match('|.+?\.sql$|', $prefs['filename']))
{
$prefs['filename'] .= '.sql';
}
}
// Load the Zip class and output it
$CI =& get_instance();
$CI->load->library('zip');
$CI->zip->add_data($prefs['filename'], $this->_backup($prefs));
return $CI->zip->get_zip();
}
elseif ($prefs['format'] === 'txt') // Was a text file requested?
{
return $this->_backup($prefs);
}
elseif ($prefs['format'] === 'gzip') // Was a Gzip file requested?
{
return gzencode($this->_backup($prefs));
}
return;
}
}
PK ! d DB.phpnu [ load->get_package_paths() as $path)
{
if ($path !== APPPATH)
{
if (file_exists($file_path = $path.'config/'.ENVIRONMENT.'/database.php'))
{
include($file_path);
}
elseif (file_exists($file_path = $path.'config/database.php'))
{
include($file_path);
}
}
}
}
if ( ! isset($db) OR count($db) === 0)
{
show_error('No database connection settings were found in the database config file.');
}
if ($params !== '')
{
$active_group = $params;
}
if ( ! isset($active_group))
{
show_error('You have not specified a database connection group via $active_group in your config/database.php file.');
}
elseif ( ! isset($db[$active_group]))
{
show_error('You have specified an invalid database connection group ('.$active_group.') in your config/database.php file.');
}
$params = $db[$active_group];
}
elseif (is_string($params))
{
/**
* Parse the URL from the DSN string
* Database settings can be passed as discreet
* parameters or as a data source name in the first
* parameter. DSNs must have this prototype:
* $dsn = 'driver://username:password@hostname/database';
*/
if (($dsn = @parse_url($params)) === FALSE)
{
show_error('Invalid DB Connection String');
}
$params = array(
'dbdriver' => $dsn['scheme'],
'hostname' => isset($dsn['host']) ? rawurldecode($dsn['host']) : '',
'port' => isset($dsn['port']) ? rawurldecode($dsn['port']) : '',
'username' => isset($dsn['user']) ? rawurldecode($dsn['user']) : '',
'password' => isset($dsn['pass']) ? rawurldecode($dsn['pass']) : '',
'database' => isset($dsn['path']) ? rawurldecode(substr($dsn['path'], 1)) : ''
);
// Were additional config items set?
if (isset($dsn['query']))
{
parse_str($dsn['query'], $extra);
foreach ($extra as $key => $val)
{
if (is_string($val) && in_array(strtoupper($val), array('TRUE', 'FALSE', 'NULL')))
{
$val = var_export($val, TRUE);
}
$params[$key] = $val;
}
}
}
// No DB specified yet? Beat them senseless...
if (empty($params['dbdriver']))
{
show_error('You have not selected a database type to connect to.');
}
// Load the DB classes. Note: Since the query builder class is optional
// we need to dynamically create a class that extends proper parent class
// based on whether we're using the query builder class or not.
if ($query_builder_override !== NULL)
{
$query_builder = $query_builder_override;
}
// Backwards compatibility work-around for keeping the
// $active_record config variable working. Should be
// removed in v3.1
elseif ( ! isset($query_builder) && isset($active_record))
{
$query_builder = $active_record;
}
require_once(BASEPATH.'database/DB_driver.php');
if ( ! isset($query_builder) OR $query_builder === TRUE)
{
require_once(BASEPATH.'database/DB_query_builder.php');
if ( ! class_exists('CI_DB', FALSE))
{
/**
* CI_DB
*
* Acts as an alias for both CI_DB_driver and CI_DB_query_builder.
*
* @see CI_DB_query_builder
* @see CI_DB_driver
*/
class CI_DB extends CI_DB_query_builder { }
}
}
elseif ( ! class_exists('CI_DB', FALSE))
{
/**
* @ignore
*/
class CI_DB extends CI_DB_driver { }
}
// Load the DB driver
$driver_file = BASEPATH.'database/drivers/'.$params['dbdriver'].'/'.$params['dbdriver'].'_driver.php';
file_exists($driver_file) OR show_error('Invalid DB driver');
require_once($driver_file);
// Instantiate the DB adapter
$driver = 'CI_DB_'.$params['dbdriver'].'_driver';
$DB = new $driver($params);
// Check for a subdriver
if ( ! empty($DB->subdriver))
{
$driver_file = BASEPATH.'database/drivers/'.$DB->dbdriver.'/subdrivers/'.$DB->dbdriver.'_'.$DB->subdriver.'_driver.php';
if (file_exists($driver_file))
{
require_once($driver_file);
$driver = 'CI_DB_'.$DB->dbdriver.'_'.$DB->subdriver.'_driver';
$DB = new $driver($params);
}
}
$DB->initialize();
return $DB;
}
PK ! ]] ] DB_forge.phpnu [ db =& $db;
log_message('info', 'Database Forge Class Initialized');
}
// --------------------------------------------------------------------
/**
* Create database
*
* @param string $db_name
* @return bool
*/
public function create_database($db_name)
{
if ($this->_create_database === FALSE)
{
return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
}
elseif ( ! $this->db->query(sprintf($this->_create_database, $this->db->escape_identifiers($db_name), $this->db->char_set, $this->db->dbcollat)))
{
return ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE;
}
if ( ! empty($this->db->data_cache['db_names']))
{
$this->db->data_cache['db_names'][] = $db_name;
}
return TRUE;
}
// --------------------------------------------------------------------
/**
* Drop database
*
* @param string $db_name
* @return bool
*/
public function drop_database($db_name)
{
if ($this->_drop_database === FALSE)
{
return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
}
elseif ( ! $this->db->query(sprintf($this->_drop_database, $this->db->escape_identifiers($db_name))))
{
return ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE;
}
if ( ! empty($this->db->data_cache['db_names']))
{
$key = array_search(strtolower($db_name), array_map('strtolower', $this->db->data_cache['db_names']), TRUE);
if ($key !== FALSE)
{
unset($this->db->data_cache['db_names'][$key]);
}
}
return TRUE;
}
// --------------------------------------------------------------------
/**
* Add Key
*
* @param string $key
* @param bool $primary
* @return CI_DB_forge
*/
public function add_key($key, $primary = FALSE)
{
// DO NOT change this! This condition is only applicable
// for PRIMARY keys because you can only have one such,
// and therefore all fields you add to it will be included
// in the same, composite PRIMARY KEY.
//
// It's not the same for regular indexes.
if ($primary === TRUE && is_array($key))
{
foreach ($key as $one)
{
$this->add_key($one, $primary);
}
return $this;
}
if ($primary === TRUE)
{
$this->primary_keys[] = $key;
}
else
{
$this->keys[] = $key;
}
return $this;
}
// --------------------------------------------------------------------
/**
* Add Field
*
* @param array $field
* @return CI_DB_forge
*/
public function add_field($field)
{
if (is_string($field))
{
if ($field === 'id')
{
$this->add_field(array(
'id' => array(
'type' => 'INT',
'constraint' => 9,
'auto_increment' => TRUE
)
));
$this->add_key('id', TRUE);
}
else
{
if (strpos($field, ' ') === FALSE)
{
show_error('Field information is required for that operation.');
}
$this->fields[] = $field;
}
}
if (is_array($field))
{
$this->fields = array_merge($this->fields, $field);
}
return $this;
}
// --------------------------------------------------------------------
/**
* Create Table
*
* @param string $table Table name
* @param bool $if_not_exists Whether to add IF NOT EXISTS condition
* @param array $attributes Associative array of table attributes
* @return bool
*/
public function create_table($table, $if_not_exists = FALSE, array $attributes = array())
{
if ($table === '')
{
show_error('A table name is required for that operation.');
}
else
{
$table = $this->db->dbprefix.$table;
}
if (count($this->fields) === 0)
{
show_error('Field information is required.');
}
$sql = $this->_create_table($table, $if_not_exists, $attributes);
if (is_bool($sql))
{
$this->_reset();
if ($sql === FALSE)
{
return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
}
}
if (($result = $this->db->query($sql)) !== FALSE)
{
empty($this->db->data_cache['table_names']) OR $this->db->data_cache['table_names'][] = $table;
// Most databases don't support creating indexes from within the CREATE TABLE statement
if ( ! empty($this->keys))
{
for ($i = 0, $sqls = $this->_process_indexes($table), $c = count($sqls); $i < $c; $i++)
{
$this->db->query($sqls[$i]);
}
}
}
$this->_reset();
return $result;
}
// --------------------------------------------------------------------
/**
* Create Table
*
* @param string $table Table name
* @param bool $if_not_exists Whether to add 'IF NOT EXISTS' condition
* @param array $attributes Associative array of table attributes
* @return mixed
*/
protected function _create_table($table, $if_not_exists, $attributes)
{
if ($if_not_exists === TRUE && $this->_create_table_if === FALSE)
{
if ($this->db->table_exists($table))
{
return TRUE;
}
else
{
$if_not_exists = FALSE;
}
}
$sql = ($if_not_exists)
? sprintf($this->_create_table_if, $this->db->escape_identifiers($table))
: 'CREATE TABLE';
$columns = $this->_process_fields(TRUE);
for ($i = 0, $c = count($columns); $i < $c; $i++)
{
$columns[$i] = ($columns[$i]['_literal'] !== FALSE)
? "\n\t".$columns[$i]['_literal']
: "\n\t".$this->_process_column($columns[$i]);
}
$columns = implode(',', $columns)
.$this->_process_primary_keys($table);
// Are indexes created from within the CREATE TABLE statement? (e.g. in MySQL)
if ($this->_create_table_keys === TRUE)
{
$columns .= $this->_process_indexes($table);
}
// _create_table will usually have the following format: "%s %s (%s\n)"
$sql = sprintf($this->_create_table.'%s',
$sql,
$this->db->escape_identifiers($table),
$columns,
$this->_create_table_attr($attributes)
);
return $sql;
}
// --------------------------------------------------------------------
/**
* CREATE TABLE attributes
*
* @param array $attributes Associative array of table attributes
* @return string
*/
protected function _create_table_attr($attributes)
{
$sql = '';
foreach (array_keys($attributes) as $key)
{
if (is_string($key))
{
$sql .= ' '.strtoupper($key).' '.$attributes[$key];
}
}
return $sql;
}
// --------------------------------------------------------------------
/**
* Drop Table
*
* @param string $table_name Table name
* @param bool $if_exists Whether to add an IF EXISTS condition
* @return bool
*/
public function drop_table($table_name, $if_exists = FALSE)
{
if ($table_name === '')
{
return ($this->db->db_debug) ? $this->db->display_error('db_table_name_required') : FALSE;
}
if (($query = $this->_drop_table($this->db->dbprefix.$table_name, $if_exists)) === TRUE)
{
return TRUE;
}
$query = $this->db->query($query);
// Update table list cache
if ($query && ! empty($this->db->data_cache['table_names']))
{
$key = array_search(strtolower($this->db->dbprefix.$table_name), array_map('strtolower', $this->db->data_cache['table_names']), TRUE);
if ($key !== FALSE)
{
unset($this->db->data_cache['table_names'][$key]);
}
}
return $query;
}
// --------------------------------------------------------------------
/**
* Drop Table
*
* Generates a platform-specific DROP TABLE string
*
* @param string $table Table name
* @param bool $if_exists Whether to add an IF EXISTS condition
* @return string
*/
protected function _drop_table($table, $if_exists)
{
$sql = 'DROP TABLE';
if ($if_exists)
{
if ($this->_drop_table_if === FALSE)
{
if ( ! $this->db->table_exists($table))
{
return TRUE;
}
}
else
{
$sql = sprintf($this->_drop_table_if, $this->db->escape_identifiers($table));
}
}
return $sql.' '.$this->db->escape_identifiers($table);
}
// --------------------------------------------------------------------
/**
* Rename Table
*
* @param string $table_name Old table name
* @param string $new_table_name New table name
* @return bool
*/
public function rename_table($table_name, $new_table_name)
{
if ($table_name === '' OR $new_table_name === '')
{
show_error('A table name is required for that operation.');
return FALSE;
}
elseif ($this->_rename_table === FALSE)
{
return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
}
$result = $this->db->query(sprintf($this->_rename_table,
$this->db->escape_identifiers($this->db->dbprefix.$table_name),
$this->db->escape_identifiers($this->db->dbprefix.$new_table_name))
);
if ($result && ! empty($this->db->data_cache['table_names']))
{
$key = array_search(strtolower($this->db->dbprefix.$table_name), array_map('strtolower', $this->db->data_cache['table_names']), TRUE);
if ($key !== FALSE)
{
$this->db->data_cache['table_names'][$key] = $this->db->dbprefix.$new_table_name;
}
}
return $result;
}
// --------------------------------------------------------------------
/**
* Column Add
*
* @todo Remove deprecated $_after option in 3.1+
* @param string $table Table name
* @param array $field Column definition
* @param string $_after Column for AFTER clause (deprecated)
* @return bool
*/
public function add_column($table, $field, $_after = NULL)
{
// Work-around for literal column definitions
is_array($field) OR $field = array($field);
foreach (array_keys($field) as $k)
{
// Backwards-compatibility work-around for MySQL/CUBRID AFTER clause (remove in 3.1+)
if ($_after !== NULL && is_array($field[$k]) && ! isset($field[$k]['after']))
{
$field[$k]['after'] = $_after;
}
$this->add_field(array($k => $field[$k]));
}
$sqls = $this->_alter_table('ADD', $this->db->dbprefix.$table, $this->_process_fields());
$this->_reset();
if ($sqls === FALSE)
{
return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
}
for ($i = 0, $c = count($sqls); $i < $c; $i++)
{
if ($this->db->query($sqls[$i]) === FALSE)
{
return FALSE;
}
}
return TRUE;
}
// --------------------------------------------------------------------
/**
* Column Drop
*
* @param string $table Table name
* @param string $column_name Column name
* @return bool
*/
public function drop_column($table, $column_name)
{
$sql = $this->_alter_table('DROP', $this->db->dbprefix.$table, $column_name);
if ($sql === FALSE)
{
return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
}
return $this->db->query($sql);
}
// --------------------------------------------------------------------
/**
* Column Modify
*
* @param string $table Table name
* @param string $field Column definition
* @return bool
*/
public function modify_column($table, $field)
{
// Work-around for literal column definitions
is_array($field) OR $field = array($field);
foreach (array_keys($field) as $k)
{
$this->add_field(array($k => $field[$k]));
}
if (count($this->fields) === 0)
{
show_error('Field information is required.');
}
$sqls = $this->_alter_table('CHANGE', $this->db->dbprefix.$table, $this->_process_fields());
$this->_reset();
if ($sqls === FALSE)
{
return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
}
for ($i = 0, $c = count($sqls); $i < $c; $i++)
{
if ($this->db->query($sqls[$i]) === FALSE)
{
return FALSE;
}
}
return TRUE;
}
// --------------------------------------------------------------------
/**
* ALTER TABLE
*
* @param string $alter_type ALTER type
* @param string $table Table name
* @param mixed $field Column definition
* @return string|string[]
*/
protected function _alter_table($alter_type, $table, $field)
{
$sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' ';
// DROP has everything it needs now.
if ($alter_type === 'DROP')
{
return $sql.'DROP COLUMN '.$this->db->escape_identifiers($field);
}
$sql .= ($alter_type === 'ADD')
? 'ADD '
: $alter_type.' COLUMN ';
$sqls = array();
for ($i = 0, $c = count($field); $i < $c; $i++)
{
$sqls[] = $sql
.($field[$i]['_literal'] !== FALSE ? $field[$i]['_literal'] : $this->_process_column($field[$i]));
}
return $sqls;
}
// --------------------------------------------------------------------
/**
* Process fields
*
* @param bool $create_table
* @return array
*/
protected function _process_fields($create_table = FALSE)
{
$fields = array();
foreach ($this->fields as $key => $attributes)
{
if (is_int($key) && ! is_array($attributes))
{
$fields[] = array('_literal' => $attributes);
continue;
}
$attributes = array_change_key_case($attributes, CASE_UPPER);
if ($create_table === TRUE && empty($attributes['TYPE']))
{
continue;
}
isset($attributes['TYPE']) && $this->_attr_type($attributes);
$field = array(
'name' => $key,
'new_name' => isset($attributes['NAME']) ? $attributes['NAME'] : NULL,
'type' => isset($attributes['TYPE']) ? $attributes['TYPE'] : NULL,
'length' => '',
'unsigned' => '',
'null' => '',
'unique' => '',
'default' => '',
'auto_increment' => '',
'_literal' => FALSE
);
isset($attributes['TYPE']) && $this->_attr_unsigned($attributes, $field);
if ($create_table === FALSE)
{
if (isset($attributes['AFTER']))
{
$field['after'] = $attributes['AFTER'];
}
elseif (isset($attributes['FIRST']))
{
$field['first'] = (bool) $attributes['FIRST'];
}
}
$this->_attr_default($attributes, $field);
if (isset($attributes['NULL']))
{
if ($attributes['NULL'] === TRUE)
{
$field['null'] = empty($this->_null) ? '' : ' '.$this->_null;
}
else
{
$field['null'] = ' NOT NULL';
}
}
elseif ($create_table === TRUE)
{
$field['null'] = ' NOT NULL';
}
$this->_attr_auto_increment($attributes, $field);
$this->_attr_unique($attributes, $field);
if (isset($attributes['COMMENT']))
{
$field['comment'] = $this->db->escape($attributes['COMMENT']);
}
if (isset($attributes['TYPE']) && ! empty($attributes['CONSTRAINT']))
{
switch (strtoupper($attributes['TYPE']))
{
case 'ENUM':
case 'SET':
$attributes['CONSTRAINT'] = $this->db->escape($attributes['CONSTRAINT']);
default:
$field['length'] = is_array($attributes['CONSTRAINT'])
? '('.implode(',', $attributes['CONSTRAINT']).')'
: '('.$attributes['CONSTRAINT'].')';
break;
}
}
$fields[] = $field;
}
return $fields;
}
// --------------------------------------------------------------------
/**
* Process column
*
* @param array $field
* @return string
*/
protected function _process_column($field)
{
return $this->db->escape_identifiers($field['name'])
.' '.$field['type'].$field['length']
.$field['unsigned']
.$field['default']
.$field['null']
.$field['auto_increment']
.$field['unique'];
}
// --------------------------------------------------------------------
/**
* Field attribute TYPE
*
* Performs a data type mapping between different databases.
*
* @param array &$attributes
* @return void
*/
protected function _attr_type(&$attributes)
{
// Usually overridden by drivers
}
// --------------------------------------------------------------------
/**
* Field attribute UNSIGNED
*
* Depending on the _unsigned property value:
*
* - TRUE will always set $field['unsigned'] to 'UNSIGNED'
* - FALSE will always set $field['unsigned'] to ''
* - array(TYPE) will set $field['unsigned'] to 'UNSIGNED',
* if $attributes['TYPE'] is found in the array
* - array(TYPE => UTYPE) will change $field['type'],
* from TYPE to UTYPE in case of a match
*
* @param array &$attributes
* @param array &$field
* @return void
*/
protected function _attr_unsigned(&$attributes, &$field)
{
if (empty($attributes['UNSIGNED']) OR $attributes['UNSIGNED'] !== TRUE)
{
return;
}
// Reset the attribute in order to avoid issues if we do type conversion
$attributes['UNSIGNED'] = FALSE;
if (is_array($this->_unsigned))
{
foreach (array_keys($this->_unsigned) as $key)
{
if (is_int($key) && strcasecmp($attributes['TYPE'], $this->_unsigned[$key]) === 0)
{
$field['unsigned'] = ' UNSIGNED';
return;
}
elseif (is_string($key) && strcasecmp($attributes['TYPE'], $key) === 0)
{
$field['type'] = $key;
return;
}
}
return;
}
$field['unsigned'] = ($this->_unsigned === TRUE) ? ' UNSIGNED' : '';
}
// --------------------------------------------------------------------
/**
* Field attribute DEFAULT
*
* @param array &$attributes
* @param array &$field
* @return void
*/
protected function _attr_default(&$attributes, &$field)
{
if ($this->_default === FALSE)
{
return;
}
if (array_key_exists('DEFAULT', $attributes))
{
if ($attributes['DEFAULT'] === NULL)
{
$field['default'] = empty($this->_null) ? '' : $this->_default.$this->_null;
// Override the NULL attribute if that's our default
$attributes['NULL'] = TRUE;
$field['null'] = empty($this->_null) ? '' : ' '.$this->_null;
}
else
{
$field['default'] = $this->_default.$this->db->escape($attributes['DEFAULT']);
}
}
}
// --------------------------------------------------------------------
/**
* Field attribute UNIQUE
*
* @param array &$attributes
* @param array &$field
* @return void
*/
protected function _attr_unique(&$attributes, &$field)
{
if ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE)
{
$field['unique'] = ' UNIQUE';
}
}
// --------------------------------------------------------------------
/**
* Field attribute AUTO_INCREMENT
*
* @param array &$attributes
* @param array &$field
* @return void
*/
protected function _attr_auto_increment(&$attributes, &$field)
{
if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
{
$field['auto_increment'] = ' AUTO_INCREMENT';
}
}
// --------------------------------------------------------------------
/**
* Process primary keys
*
* @param string $table Table name
* @return string
*/
protected function _process_primary_keys($table)
{
$sql = '';
for ($i = 0, $c = count($this->primary_keys); $i < $c; $i++)
{
if ( ! isset($this->fields[$this->primary_keys[$i]]))
{
unset($this->primary_keys[$i]);
}
}
if (count($this->primary_keys) > 0)
{
$sql .= ",\n\tCONSTRAINT ".$this->db->escape_identifiers('pk_'.$table)
.' PRIMARY KEY('.implode(', ', $this->db->escape_identifiers($this->primary_keys)).')';
}
return $sql;
}
// --------------------------------------------------------------------
/**
* Process indexes
*
* @param string $table
* @return string
*/
protected function _process_indexes($table)
{
$sqls = array();
for ($i = 0, $c = count($this->keys); $i < $c; $i++)
{
if (is_array($this->keys[$i]))
{
for ($i2 = 0, $c2 = count($this->keys[$i]); $i2 < $c2; $i2++)
{
if ( ! isset($this->fields[$this->keys[$i][$i2]]))
{
unset($this->keys[$i][$i2]);
continue;
}
}
}
elseif ( ! isset($this->fields[$this->keys[$i]]))
{
unset($this->keys[$i]);
continue;
}
is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);
$sqls[] = 'CREATE INDEX '.$this->db->escape_identifiers($table.'_'.implode('_', $this->keys[$i]))
.' ON '.$this->db->escape_identifiers($table)
.' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).');';
}
return $sqls;
}
// --------------------------------------------------------------------
/**
* Reset
*
* Resets table creation vars
*
* @return void
*/
protected function _reset()
{
$this->fields = $this->keys = $this->primary_keys = array();
}
}
PK ! IVi DB_cache.phpnu [ CI and load the file helper since we use it a lot
$this->CI =& get_instance();
$this->db =& $db;
$this->CI->load->helper('file');
$this->check_path();
}
// --------------------------------------------------------------------
/**
* Set Cache Directory Path
*
* @param string $path Path to the cache directory
* @return bool
*/
public function check_path($path = '')
{
if ($path === '')
{
if ($this->db->cachedir === '')
{
return $this->db->cache_off();
}
$path = $this->db->cachedir;
}
// Add a trailing slash to the path if needed
$path = realpath($path)
? rtrim(realpath($path), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR
: rtrim($path, '/').'/';
if ( ! is_dir($path))
{
log_message('debug', 'DB cache path error: '.$path);
// If the path is wrong we'll turn off caching
return $this->db->cache_off();
}
if ( ! is_really_writable($path))
{
log_message('debug', 'DB cache dir not writable: '.$path);
// If the path is not really writable we'll turn off caching
return $this->db->cache_off();
}
$this->db->cachedir = $path;
return TRUE;
}
// --------------------------------------------------------------------
/**
* Retrieve a cached query
*
* The URI being requested will become the name of the cache sub-folder.
* An MD5 hash of the SQL statement will become the cache file name.
*
* @param string $sql
* @return string
*/
public function read($sql)
{
$segment_one = ($this->CI->uri->segment(1) == FALSE) ? 'default' : $this->CI->uri->segment(1);
$segment_two = ($this->CI->uri->segment(2) == FALSE) ? 'index' : $this->CI->uri->segment(2);
$filepath = $this->db->cachedir.$segment_one.'+'.$segment_two.'/'.md5($sql);
if (FALSE === ($cachedata = @file_get_contents($filepath)))
{
return FALSE;
}
return unserialize($cachedata);
}
// --------------------------------------------------------------------
/**
* Write a query to a cache file
*
* @param string $sql
* @param object $object
* @return bool
*/
public function write($sql, $object)
{
$segment_one = ($this->CI->uri->segment(1) == FALSE) ? 'default' : $this->CI->uri->segment(1);
$segment_two = ($this->CI->uri->segment(2) == FALSE) ? 'index' : $this->CI->uri->segment(2);
$dir_path = $this->db->cachedir.$segment_one.'+'.$segment_two.'/';
$filename = md5($sql);
if ( ! is_dir($dir_path) && ! @mkdir($dir_path, 0750))
{
return FALSE;
}
if (write_file($dir_path.$filename, serialize($object)) === FALSE)
{
return FALSE;
}
chmod($dir_path.$filename, 0640);
return TRUE;
}
// --------------------------------------------------------------------
/**
* Delete cache files within a particular directory
*
* @param string $segment_one
* @param string $segment_two
* @return void
*/
public function delete($segment_one = '', $segment_two = '')
{
if ($segment_one === '')
{
$segment_one = ($this->CI->uri->segment(1) == FALSE) ? 'default' : $this->CI->uri->segment(1);
}
if ($segment_two === '')
{
$segment_two = ($this->CI->uri->segment(2) == FALSE) ? 'index' : $this->CI->uri->segment(2);
}
$dir_path = $this->db->cachedir.$segment_one.'+'.$segment_two.'/';
delete_files($dir_path, TRUE);
}
// --------------------------------------------------------------------
/**
* Delete all existing cache files
*
* @return void
*/
public function delete_all()
{
delete_files($this->db->cachedir, TRUE, TRUE);
}
}
PK ! jst! t! " drivers/sqlite3/sqlite3_driver.phpnu [ password)
? new SQLite3($this->database)
: new SQLite3($this->database, SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE, $this->password);
}
catch (Exception $e)
{
return FALSE;
}
}
// --------------------------------------------------------------------
/**
* Database version number
*
* @return string
*/
public function version()
{
if (isset($this->data_cache['version']))
{
return $this->data_cache['version'];
}
$version = SQLite3::version();
return $this->data_cache['version'] = $version['versionString'];
}
// --------------------------------------------------------------------
/**
* Execute the query
*
* @todo Implement use of SQLite3::querySingle(), if needed
* @param string $sql
* @return mixed SQLite3Result object or bool
*/
protected function _execute($sql)
{
return $this->is_write_type($sql)
? $this->conn_id->exec($sql)
: $this->conn_id->query($sql);
}
// --------------------------------------------------------------------
/**
* Begin Transaction
*
* @return bool
*/
protected function _trans_begin()
{
return $this->conn_id->exec('BEGIN TRANSACTION');
}
// --------------------------------------------------------------------
/**
* Commit Transaction
*
* @return bool
*/
protected function _trans_commit()
{
return $this->conn_id->exec('END TRANSACTION');
}
// --------------------------------------------------------------------
/**
* Rollback Transaction
*
* @return bool
*/
protected function _trans_rollback()
{
return $this->conn_id->exec('ROLLBACK');
}
// --------------------------------------------------------------------
/**
* Platform-dependant string escape
*
* @param string
* @return string
*/
protected function _escape_str($str)
{
return $this->conn_id->escapeString($str);
}
// --------------------------------------------------------------------
/**
* Affected Rows
*
* @return int
*/
public function affected_rows()
{
return $this->conn_id->changes();
}
// --------------------------------------------------------------------
/**
* Insert ID
*
* @return int
*/
public function insert_id()
{
return $this->conn_id->lastInsertRowID();
}
// --------------------------------------------------------------------
/**
* Show table query
*
* Generates a platform-specific query string so that the table names can be fetched
*
* @param bool $prefix_limit
* @return string
*/
protected function _list_tables($prefix_limit = FALSE)
{
return 'SELECT "NAME" FROM "SQLITE_MASTER" WHERE "TYPE" = \'table\''
.(($prefix_limit !== FALSE && $this->dbprefix != '')
? ' AND "NAME" LIKE \''.$this->escape_like_str($this->dbprefix).'%\' '.sprintf($this->_like_escape_str, $this->_like_escape_chr)
: '');
}
// --------------------------------------------------------------------
/**
* Fetch Field Names
*
* @param string $table Table name
* @return array
*/
public function list_fields($table)
{
// Is there a cached result?
if (isset($this->data_cache['field_names'][$table]))
{
return $this->data_cache['field_names'][$table];
}
if (($result = $this->query('PRAGMA TABLE_INFO('.$this->protect_identifiers($table, TRUE, NULL, FALSE).')')) === FALSE)
{
return FALSE;
}
$this->data_cache['field_names'][$table] = array();
foreach ($result->result_array() as $row)
{
$this->data_cache['field_names'][$table][] = $row['name'];
}
return $this->data_cache['field_names'][$table];
}
// --------------------------------------------------------------------
/**
* Returns an object with field data
*
* @param string $table
* @return array
*/
public function field_data($table)
{
if (($query = $this->query('PRAGMA TABLE_INFO('.$this->protect_identifiers($table, TRUE, NULL, FALSE).')')) === FALSE)
{
return FALSE;
}
$query = $query->result_array();
if (empty($query))
{
return FALSE;
}
$retval = array();
for ($i = 0, $c = count($query); $i < $c; $i++)
{
$retval[$i] = new stdClass();
$retval[$i]->name = $query[$i]['name'];
$retval[$i]->type = $query[$i]['type'];
$retval[$i]->max_length = NULL;
$retval[$i]->default = $query[$i]['dflt_value'];
$retval[$i]->primary_key = isset($query[$i]['pk']) ? (int) $query[$i]['pk'] : 0;
}
return $retval;
}
// --------------------------------------------------------------------
/**
* Error
*
* Returns an array containing code and message of the last
* database error that has occured.
*
* @return array
*/
public function error()
{
return array('code' => $this->conn_id->lastErrorCode(), 'message' => $this->conn_id->lastErrorMsg());
}
// --------------------------------------------------------------------
/**
* Replace statement
*
* Generates a platform-specific replace string from the supplied data
*
* @param string $table Table name
* @param array $keys INSERT keys
* @param array $values INSERT values
* @return string
*/
protected function _replace($table, $keys, $values)
{
return 'INSERT OR '.parent::_replace($table, $keys, $values);
}
// --------------------------------------------------------------------
/**
* Truncate statement
*
* Generates a platform-specific truncate string from the supplied data
*
* If the database does not support the TRUNCATE statement,
* then this method maps to 'DELETE FROM table'
*
* @param string $table
* @return string
*/
protected function _truncate($table)
{
return 'DELETE FROM '.$table;
}
// --------------------------------------------------------------------
/**
* Close DB Connection
*
* @return void
*/
protected function _close()
{
$this->conn_id->close();
}
}
PK ! sI+ + " drivers/sqlite3/sqlite3_result.phpnu [ result_id->numColumns();
}
// --------------------------------------------------------------------
/**
* Fetch Field Names
*
* Generates an array of column names
*
* @return array
*/
public function list_fields()
{
$field_names = array();
for ($i = 0, $c = $this->num_fields(); $i < $c; $i++)
{
$field_names[] = $this->result_id->columnName($i);
}
return $field_names;
}
// --------------------------------------------------------------------
/**
* Field data
*
* Generates an array of objects containing field meta-data
*
* @return array
*/
public function field_data()
{
static $data_types = array(
SQLITE3_INTEGER => 'integer',
SQLITE3_FLOAT => 'float',
SQLITE3_TEXT => 'text',
SQLITE3_BLOB => 'blob',
SQLITE3_NULL => 'null'
);
$retval = array();
for ($i = 0, $c = $this->num_fields(); $i < $c; $i++)
{
$retval[$i] = new stdClass();
$retval[$i]->name = $this->result_id->columnName($i);
$type = $this->result_id->columnType($i);
$retval[$i]->type = isset($data_types[$type]) ? $data_types[$type] : $type;
$retval[$i]->max_length = NULL;
}
return $retval;
}
// --------------------------------------------------------------------
/**
* Free the result
*
* @return void
*/
public function free_result()
{
if (is_object($this->result_id))
{
$this->result_id->finalize();
$this->result_id = NULL;
}
}
// --------------------------------------------------------------------
/**
* Result - associative array
*
* Returns the result set as an array
*
* @return array
*/
protected function _fetch_assoc()
{
return $this->result_id->fetchArray(SQLITE3_ASSOC);
}
// --------------------------------------------------------------------
/**
* Result - object
*
* Returns the result set as an object
*
* @param string $class_name
* @return object
*/
protected function _fetch_object($class_name = 'stdClass')
{
// No native support for fetching rows as objects
if (($row = $this->result_id->fetchArray(SQLITE3_ASSOC)) === FALSE)
{
return FALSE;
}
elseif ($class_name === 'stdClass')
{
return (object) $row;
}
$class_name = new $class_name();
foreach (array_keys($row) as $key)
{
$class_name->$key = $row[$key];
}
return $class_name;
}
// --------------------------------------------------------------------
/**
* Data Seek
*
* Moves the internal pointer to the desired offset. We call
* this internally before fetching results to make sure the
* result set starts at zero.
*
* @param int $n (ignored)
* @return array
*/
public function data_seek($n = 0)
{
// Only resetting to the start of the result set is supported
return ($n > 0) ? FALSE : $this->result_id->reset();
}
}
PK ! \[ [ # drivers/sqlite3/sqlite3_utility.phpnu [ db->display_error('db_unsupported_feature');
}
}
PK ! ( drivers/sqlite3/index.htmlnu [
403 Forbidden
Directory access is forbidden.
PK ! IK K ! drivers/sqlite3/sqlite3_forge.phpnu [ db->version(), '3.3', '<'))
{
$this->_create_table_if = FALSE;
$this->_drop_table_if = FALSE;
}
}
// --------------------------------------------------------------------
/**
* Create database
*
* @param string $db_name
* @return bool
*/
public function create_database($db_name)
{
// In SQLite, a database is created when you connect to the database.
// We'll return TRUE so that an error isn't generated
return TRUE;
}
// --------------------------------------------------------------------
/**
* Drop database
*
* @param string $db_name (ignored)
* @return bool
*/
public function drop_database($db_name)
{
// In SQLite, a database is dropped when we delete a file
if (file_exists($this->db->database))
{
// We need to close the pseudo-connection first
$this->db->close();
if ( ! @unlink($this->db->database))
{
return $this->db->db_debug ? $this->db->display_error('db_unable_to_drop') : FALSE;
}
elseif ( ! empty($this->db->data_cache['db_names']))
{
$key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE);
if ($key !== FALSE)
{
unset($this->db->data_cache['db_names'][$key]);
}
}
return TRUE;
}
return $this->db->db_debug ? $this->db->display_error('db_unable_to_drop') : FALSE;
}
// --------------------------------------------------------------------
/**
* ALTER TABLE
*
* @todo implement drop_column(), modify_column()
* @param string $alter_type ALTER type
* @param string $table Table name
* @param mixed $field Column definition
* @return string|string[]
*/
protected function _alter_table($alter_type, $table, $field)
{
if ($alter_type === 'DROP' OR $alter_type === 'CHANGE')
{
// drop_column():
// BEGIN TRANSACTION;
// CREATE TEMPORARY TABLE t1_backup(a,b);
// INSERT INTO t1_backup SELECT a,b FROM t1;
// DROP TABLE t1;
// CREATE TABLE t1(a,b);
// INSERT INTO t1 SELECT a,b FROM t1_backup;
// DROP TABLE t1_backup;
// COMMIT;
return FALSE;
}
return parent::_alter_table($alter_type, $table, $field);
}
// --------------------------------------------------------------------
/**
* Process column
*
* @param array $field
* @return string
*/
protected function _process_column($field)
{
return $this->db->escape_identifiers($field['name'])
.' '.$field['type']
.$field['auto_increment']
.$field['null']
.$field['unique']
.$field['default'];
}
// --------------------------------------------------------------------
/**
* Field attribute TYPE
*
* Performs a data type mapping between different databases.
*
* @param array &$attributes
* @return void
*/
protected function _attr_type(&$attributes)
{
switch (strtoupper($attributes['TYPE']))
{
case 'ENUM':
case 'SET':
$attributes['TYPE'] = 'TEXT';
return;
default: return;
}
}
// --------------------------------------------------------------------
/**
* Field attribute AUTO_INCREMENT
*
* @param array &$attributes
* @param array &$field
* @return void
*/
protected function _attr_auto_increment(&$attributes, &$field)
{
if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
{
$field['type'] = 'INTEGER PRIMARY KEY';
$field['default'] = '';
$field['null'] = '';
$field['unique'] = '';
$field['auto_increment'] = ' AUTOINCREMENT';
$this->primary_keys = array();
}
}
}
PK ! .