2014-04-04 19:59:39 +00:00
< ? php
###
2014-10-21 11:45:11 +00:00
# @name Database Module
2015-02-01 21:08:37 +00:00
# @copyright 2015 by Tobias Reich
2014-04-04 19:59:39 +00:00
###
if ( ! defined ( 'LYCHEE' )) exit ( 'Error: Direct access is not allowed!' );
class Database extends Module {
static function connect ( $host = 'localhost' , $user , $password , $name = 'lychee' ) {
2014-04-19 19:07:36 +00:00
# Check dependencies
Module :: dependencies ( isset ( $host , $user , $password , $name ));
2014-04-04 19:59:39 +00:00
$database = new mysqli ( $host , $user , $password );
# Check connection
if ( $database -> connect_errno ) exit ( 'Error: ' . $database -> connect_error );
2014-04-06 13:11:55 +00:00
# Avoid sql injection on older MySQL versions by using GBK
2015-01-22 20:24:20 +00:00
if ( $database -> server_version < 50500 ) @ $database -> set_charset ( 'GBK' );
else @ $database -> set_charset ( 'utf8' );
2014-09-19 21:32:35 +00:00
2014-09-16 12:20:35 +00:00
# Set unicode
$database -> query ( 'SET NAMES utf8;' );
2014-04-04 19:59:39 +00:00
# Check database
if ( ! $database -> select_db ( $name ))
if ( ! Database :: createDatabase ( $database , $name )) exit ( 'Error: Could not create database!' );
# Check tables
2014-08-30 05:05:26 +00:00
$query = Database :: prepare ( $database , 'SELECT * FROM ?, ?, ?, ? LIMIT 0' , array ( LYCHEE_TABLE_PHOTOS , LYCHEE_TABLE_ALBUMS , LYCHEE_TABLE_SETTINGS , LYCHEE_TABLE_LOG ));
2014-08-29 21:08:18 +00:00
if ( ! $database -> query ( $query ))
2014-04-04 19:59:39 +00:00
if ( ! Database :: createTables ( $database )) exit ( 'Error: Could not create tables!' );
return $database ;
}
2014-04-19 19:07:36 +00:00
static function update ( $database , $dbName , $version = 0 ) {
2014-04-04 19:59:39 +00:00
2014-04-19 19:07:36 +00:00
# Check dependencies
Module :: dependencies ( isset ( $database , $dbName ));
2014-09-19 21:32:35 +00:00
if ( ! isset ( $version )) return true ;
2014-04-05 16:30:24 +00:00
# List of updates
$updates = array (
'020100' , #2.1
'020101' , #2.1.1
2014-04-10 20:42:14 +00:00
'020200' , #2.2
2014-07-04 22:39:31 +00:00
'020500' , #2.5
2014-08-09 15:57:31 +00:00
'020505' , #2.5.5
2014-08-27 19:17:05 +00:00
'020601' , #2.6.1
2014-10-11 14:09:10 +00:00
'020602' , #2.6.2
2015-02-08 14:36:13 +00:00
'020700' , #2.7.0
2015-05-10 21:01:07 +00:00
'030000' , #3.0.0
2015-06-27 19:03:27 +00:00
'030001' , #3.0.1
'030003' #3.0.3
2014-04-05 16:30:24 +00:00
);
# For each update
foreach ( $updates as $update ) {
2014-09-19 21:32:35 +00:00
if ( $update <= $version ) continue ;
2014-04-05 16:30:24 +00:00
# Load update
2014-04-09 18:26:25 +00:00
include ( __DIR__ . '/../database/update_' . $update . '.php' );
2014-04-05 16:30:24 +00:00
}
return true ;
}
2014-08-29 17:55:21 +00:00
static function createConfig ( $host = 'localhost' , $user , $password , $name = 'lychee' , $prefix = '' ) {
2014-04-05 16:30:24 +00:00
2014-04-19 19:07:36 +00:00
# Check dependencies
Module :: dependencies ( isset ( $host , $user , $password , $name ));
2014-04-04 19:59:39 +00:00
$database = new mysqli ( $host , $user , $password );
if ( $database -> connect_errno ) return 'Warning: Connection failed!' ;
2014-08-08 14:28:34 +00:00
# Check if database exists
if ( ! $database -> select_db ( $name )) {
# Database doesn't exist
2015-01-23 19:50:21 +00:00
# Check if user can create the database
$result = Database :: createDatabase ( $database , $name );
if ( $result === false ) return 'Warning: Creation failed!' ;
2014-08-08 14:28:34 +00:00
}
2014-08-07 18:23:39 +00:00
2014-08-29 18:10:50 +00:00
# Escape data
$host = mysqli_real_escape_string ( $database , $host );
$user = mysqli_real_escape_string ( $database , $user );
$password = mysqli_real_escape_string ( $database , $password );
$name = mysqli_real_escape_string ( $database , $name );
$prefix = mysqli_real_escape_string ( $database , $prefix );
2014-08-07 18:23:39 +00:00
# Save config.php
2014-04-04 19:59:39 +00:00
$config = " <?php
###
2014-08-29 17:55:21 +00:00
# @name Configuration
2014-04-04 19:59:39 +00:00
# @author Tobias Reich
2015-03-29 16:56:08 +00:00
# @copyright 2015 Tobias Reich
2014-04-04 19:59:39 +00:00
###
if ( ! defined ( 'LYCHEE' )) exit ( 'Error: Direct access is not allowed!' );
# Database configuration
\ $dbHost = '$host' ; # Host of the database
\ $dbUser = '$user' ; # Username of the database
\ $dbPassword = '$password' ; # Password of the database
\ $dbName = '$name' ; # Database name
2014-08-29 17:55:21 +00:00
\ $dbTablePrefix = '$prefix' ; # Table prefix
2014-04-04 19:59:39 +00:00
?> ";
2014-08-07 18:23:39 +00:00
# Save file
if ( file_put_contents ( LYCHEE_CONFIG_FILE , $config ) === false ) return 'Warning: Could not create file!' ;
2014-04-04 19:59:39 +00:00
2014-08-07 18:23:39 +00:00
return true ;
2014-04-04 19:59:39 +00:00
}
static function createDatabase ( $database , $name = 'lychee' ) {
2014-04-19 19:07:36 +00:00
# Check dependencies
Module :: dependencies ( isset ( $database , $name ));
2014-04-04 19:59:39 +00:00
2014-04-05 16:30:24 +00:00
# Create database
2015-01-23 19:50:21 +00:00
$query = Database :: prepare ( $database , 'CREATE DATABASE IF NOT EXISTS ?' , array ( $name ));
$result = $database -> query ( $query );
2014-04-04 19:59:39 +00:00
if ( ! $database -> select_db ( $name ) ||! $result ) return false ;
return true ;
}
static function createTables ( $database ) {
2014-04-19 19:07:36 +00:00
# Check dependencies
Module :: dependencies ( isset ( $database ));
2014-04-04 19:59:39 +00:00
2014-05-06 19:22:56 +00:00
# Create log
2014-08-30 05:05:26 +00:00
$exist = Database :: prepare ( $database , 'SELECT * FROM ? LIMIT 0' , array ( LYCHEE_TABLE_LOG ));
2014-08-29 21:08:18 +00:00
if ( ! $database -> query ( $exist )) {
2014-05-06 19:22:56 +00:00
# Read file
$file = __DIR__ . '/../database/log_table.sql' ;
$query = @ file_get_contents ( $file );
if ( ! isset ( $query ) || $query === false ) return false ;
2014-08-29 21:08:18 +00:00
# Create table
2014-08-30 05:05:26 +00:00
$query = Database :: prepare ( $database , $query , array ( LYCHEE_TABLE_LOG ));
2014-05-06 19:22:56 +00:00
if ( ! $database -> query ( $query )) return false ;
}
2014-04-04 19:59:39 +00:00
# Create settings
2014-08-30 05:05:26 +00:00
$exist = Database :: prepare ( $database , 'SELECT * FROM ? LIMIT 0' , array ( LYCHEE_TABLE_SETTINGS ));
2014-08-29 21:08:18 +00:00
if ( ! $database -> query ( $exist )) {
2014-04-04 19:59:39 +00:00
2014-04-05 16:30:24 +00:00
# Read file
2014-04-09 18:26:25 +00:00
$file = __DIR__ . '/../database/settings_table.sql' ;
2014-04-19 14:57:36 +00:00
$query = @ file_get_contents ( $file );
2014-04-04 19:59:39 +00:00
2014-05-30 14:54:34 +00:00
if ( ! isset ( $query ) || $query === false ) {
Log :: error ( $database , __METHOD__ , __LINE__ , 'Could not load query for lychee_settings' );
return false ;
}
2014-08-29 21:08:18 +00:00
# Create table
2014-08-30 05:05:26 +00:00
$query = Database :: prepare ( $database , $query , array ( LYCHEE_TABLE_SETTINGS ));
2014-05-30 14:54:34 +00:00
if ( ! $database -> query ( $query )) {
Log :: error ( $database , __METHOD__ , __LINE__ , $database -> error );
return false ;
}
2014-04-04 19:59:39 +00:00
2014-04-05 16:30:24 +00:00
# Read file
2014-04-09 18:26:25 +00:00
$file = __DIR__ . '/../database/settings_content.sql' ;
2014-04-19 14:57:36 +00:00
$query = @ file_get_contents ( $file );
2014-04-04 19:59:39 +00:00
2014-05-30 14:54:34 +00:00
if ( ! isset ( $query ) || $query === false ) {
Log :: error ( $database , __METHOD__ , __LINE__ , 'Could not load content-query for lychee_settings' );
return false ;
}
2014-08-29 21:08:18 +00:00
# Add content
2014-08-30 05:05:26 +00:00
$query = Database :: prepare ( $database , $query , array ( LYCHEE_TABLE_SETTINGS ));
2014-05-30 14:54:34 +00:00
if ( ! $database -> query ( $query )) {
Log :: error ( $database , __METHOD__ , __LINE__ , $database -> error );
return false ;
}
2014-04-04 19:59:39 +00:00
2015-06-28 15:47:19 +00:00
# Generate identifier
$identifier = md5 ( microtime ( true ));
$query = Database :: prepare ( $database , " UPDATE `?` SET `value` = '?' WHERE `key` = 'identifier' LIMIT 1 " , array ( LYCHEE_TABLE_SETTINGS , $identifier ));
if ( ! $database -> query ( $query )) {
Log :: error ( $database , __METHOD__ , __LINE__ , $database -> error );
return false ;
}
2014-04-04 19:59:39 +00:00
}
# Create albums
2014-08-30 05:05:26 +00:00
$exist = Database :: prepare ( $database , 'SELECT * FROM ? LIMIT 0' , array ( LYCHEE_TABLE_ALBUMS ));
2014-08-29 21:08:18 +00:00
if ( ! $database -> query ( $exist )) {
2014-04-04 19:59:39 +00:00
2014-04-05 16:30:24 +00:00
# Read file
2014-04-09 18:26:25 +00:00
$file = __DIR__ . '/../database/albums_table.sql' ;
2014-04-19 14:57:36 +00:00
$query = @ file_get_contents ( $file );
2014-04-04 19:59:39 +00:00
2014-05-30 14:54:34 +00:00
if ( ! isset ( $query ) || $query === false ) {
Log :: error ( $database , __METHOD__ , __LINE__ , 'Could not load query for lychee_albums' );
return false ;
}
2014-08-29 21:08:18 +00:00
# Create table
2014-08-30 05:05:26 +00:00
$query = Database :: prepare ( $database , $query , array ( LYCHEE_TABLE_ALBUMS ));
2014-05-30 14:54:34 +00:00
if ( ! $database -> query ( $query )) {
Log :: error ( $database , __METHOD__ , __LINE__ , $database -> error );
return false ;
}
2014-04-04 19:59:39 +00:00
}
# Create photos
2014-08-30 05:05:26 +00:00
$exist = Database :: prepare ( $database , 'SELECT * FROM ? LIMIT 0' , array ( LYCHEE_TABLE_PHOTOS ));
2014-08-29 21:08:18 +00:00
if ( ! $database -> query ( $exist )) {
2014-04-04 19:59:39 +00:00
2014-04-05 16:30:24 +00:00
# Read file
2014-04-09 18:26:25 +00:00
$file = __DIR__ . '/../database/photos_table.sql' ;
2014-04-19 14:57:36 +00:00
$query = @ file_get_contents ( $file );
2014-04-04 19:59:39 +00:00
2014-05-30 14:54:34 +00:00
if ( ! isset ( $query ) || $query === false ) {
Log :: error ( $database , __METHOD__ , __LINE__ , 'Could not load query for lychee_photos' );
return false ;
}
2014-08-29 21:08:18 +00:00
# Create table
2014-08-30 05:05:26 +00:00
$query = Database :: prepare ( $database , $query , array ( LYCHEE_TABLE_PHOTOS ));
2014-05-30 14:54:34 +00:00
if ( ! $database -> query ( $query )) {
Log :: error ( $database , __METHOD__ , __LINE__ , $database -> error );
return false ;
}
2014-04-04 19:59:39 +00:00
}
return true ;
}
2014-08-30 17:25:01 +00:00
static function setVersion ( $database , $version ) {
$query = Database :: prepare ( $database , " UPDATE ? SET value = '?' WHERE `key` = 'version' " , array ( LYCHEE_TABLE_SETTINGS , $version ));
$result = $database -> query ( $query );
if ( ! $result ) {
Log :: error ( $database , __METHOD__ , __LINE__ , 'Could not update database (' . $database -> error . ')' );
return false ;
}
}
2014-08-29 17:12:35 +00:00
static function prepare ( $database , $query , $data ) {
# Check dependencies
Module :: dependencies ( isset ( $database , $query , $data ));
2014-08-31 21:49:25 +00:00
# Count the number of placeholders and compare it with the number of arguments
# If it doesn't match, calculate the difference and skip this number of placeholders before starting the replacement
# This avoids problems with placeholders in user-input
# $skip = Number of placeholders which need to be skipped
$skip = 0 ;
$num = array (
'placeholder' => substr_count ( $query , '?' ),
'data' => count ( $data )
);
if (( $num [ 'data' ] - $num [ 'placeholder' ]) < 0 ) Log :: notice ( $database , __METHOD__ , __LINE__ , 'Could not completely prepare query. Query has more placeholders than values.' );
2014-08-29 17:12:35 +00:00
foreach ( $data as $value ) {
# Escape
$value = mysqli_real_escape_string ( $database , $value );
2014-08-31 21:49:25 +00:00
# Recalculate number of placeholders
$num [ 'placeholder' ] = substr_count ( $query , '?' );
# Calculate number of skips
if ( $num [ 'placeholder' ] > $num [ 'data' ]) $skip = $num [ 'placeholder' ] - $num [ 'data' ];
if ( $skip > 0 ) {
# Need to skip $skip placeholders, because the user input contained placeholders
# Calculate a substring which does not contain the user placeholders
# 1 or -1 is the length of the placeholder (placeholder = ?)
$pos = - 1 ;
for ( $i = $skip ; $i > 0 ; $i -- ) $pos = strpos ( $query , '?' , $pos + 1 );
$pos ++ ;
$temp = substr ( $query , 0 , $pos ); # First part of $query
$query = substr ( $query , $pos ); # Last part of $query
}
2014-08-29 17:12:35 +00:00
# Replace
$query = preg_replace ( '/\?/' , $value , $query , 1 );
2014-08-31 21:49:25 +00:00
if ( $skip > 0 ) {
2014-08-29 17:12:35 +00:00
2014-08-31 21:49:25 +00:00
# Reassemble the parts of $query
$query = $temp . $query ;
}
# Reset skip
$skip = 0 ;
# Decrease number of data elements
$num [ 'data' ] -- ;
}
2014-08-29 17:12:35 +00:00
return $query ;
}
2014-04-04 19:59:39 +00:00
}
?>