First commit of smf_2-0-7_upgrade.tar.bz2
12
.gitignore
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# backup files
|
||||||
|
**~
|
||||||
|
**.bak
|
||||||
|
|
||||||
|
# settings files
|
||||||
|
Settings.php
|
||||||
|
Settings_bak.php
|
||||||
|
|
||||||
|
# things that change
|
||||||
|
attachments/
|
||||||
|
avatars/
|
||||||
|
cache/
|
5
Packages/.htaccess
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<Files *>
|
||||||
|
Order Deny,Allow
|
||||||
|
Deny from all
|
||||||
|
Allow from localhost
|
||||||
|
</Files>
|
5
Packages/backups/.htaccess
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<Files *>
|
||||||
|
Order Deny,Allow
|
||||||
|
Deny from all
|
||||||
|
Allow from localhost
|
||||||
|
</Files>
|
9
Packages/backups/index.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// Try to handle it with the upper level index.php. (it should know what to do.)
|
||||||
|
if (file_exists(dirname(dirname(__FILE__)) . '/index.php'))
|
||||||
|
include (dirname(dirname(__FILE__)) . '/index.php');
|
||||||
|
else
|
||||||
|
exit;
|
||||||
|
|
||||||
|
?>
|
16
Packages/index.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// This file is here solely to protect your Packages directory.
|
||||||
|
|
||||||
|
// Look for Settings.php....
|
||||||
|
if (file_exists(dirname(dirname(__FILE__)) . '/Settings.php'))
|
||||||
|
{
|
||||||
|
// Found it!
|
||||||
|
require(dirname(dirname(__FILE__)) . '/Settings.php');
|
||||||
|
header('Location: ' . $boardurl);
|
||||||
|
}
|
||||||
|
// Can't find it... just forget it.
|
||||||
|
else
|
||||||
|
exit;
|
||||||
|
|
||||||
|
?>
|
0
Packages/installed.list
Normal file
62
Settings.orig.php
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple Machines Forum (SMF)
|
||||||
|
*
|
||||||
|
* @package SMF
|
||||||
|
* @author Simple Machines http://www.simplemachines.org
|
||||||
|
* @copyright 2011 Simple Machines
|
||||||
|
* @license http://www.simplemachines.org/about/smf/license.php BSD
|
||||||
|
*
|
||||||
|
* @version 2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
########## Maintenance ##########
|
||||||
|
# Note: If $maintenance is set to 2, the forum will be unusable! Change it to 0 to fix it.
|
||||||
|
$maintenance = 0; # Set to 1 to enable Maintenance Mode, 2 to make the forum untouchable. (you'll have to make it 0 again manually!)
|
||||||
|
$mtitle = 'Maintenance Mode'; # Title for the Maintenance Mode message.
|
||||||
|
$mmessage = 'Okay faithful users...we\'re attempting to restore an older backup of the database...news will be posted once we\'re back!'; # Description of why the forum is in maintenance mode.
|
||||||
|
|
||||||
|
########## Forum Info ##########
|
||||||
|
$mbname = 'My Community'; # The name of your forum.
|
||||||
|
$language = 'english'; # The default language file set for the forum.
|
||||||
|
$boardurl = 'http://127.0.0.1/smf'; # URL to your forum's folder. (without the trailing /!)
|
||||||
|
$webmaster_email = 'noreply@myserver.com'; # Email address to send emails from. (like noreply@yourdomain.com.)
|
||||||
|
$cookiename = 'SMFCookie11'; # Name of the cookie to set for authentication.
|
||||||
|
|
||||||
|
########## Database Info ##########
|
||||||
|
$db_type = 'mysql';
|
||||||
|
$db_server = 'localhost';
|
||||||
|
$db_name = 'smf';
|
||||||
|
$db_user = 'root';
|
||||||
|
$db_passwd = '';
|
||||||
|
$ssi_db_user = '';
|
||||||
|
$ssi_db_passwd = '';
|
||||||
|
$db_prefix = 'smf_';
|
||||||
|
$db_persist = 0;
|
||||||
|
$db_error_send = 1;
|
||||||
|
|
||||||
|
########## Directories/Files ##########
|
||||||
|
# Note: These directories do not have to be changed unless you move things.
|
||||||
|
$boarddir = dirname(__FILE__); # The absolute path to the forum's folder. (not just '.'!)
|
||||||
|
$sourcedir = dirname(__FILE__) . '/Sources'; # Path to the Sources directory.
|
||||||
|
$cachedir = dirname(__FILE__) . '/cache'; # Path to the cache directory.
|
||||||
|
|
||||||
|
########## Error-Catching ##########
|
||||||
|
# Note: You shouldn't touch these settings.
|
||||||
|
$db_last_error = 0;
|
||||||
|
|
||||||
|
if (file_exists(dirname(__FILE__) . '/install.php'))
|
||||||
|
{
|
||||||
|
header('Location: http' . (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on' ? 's' : '') . '://' . (empty($_SERVER['HTTP_HOST']) ? $_SERVER['SERVER_NAME'] . (empty($_SERVER['SERVER_PORT']) || $_SERVER['SERVER_PORT'] == '80' ? '' : ':' . $_SERVER['SERVER_PORT']) : $_SERVER['HTTP_HOST']) . (strtr(dirname($_SERVER['PHP_SELF']), '\\', '/') == '/' ? '' : strtr(dirname($_SERVER['PHP_SELF']), '\\', '/')) . '/install.php'); exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Make sure the paths are correct... at least try to fix them.
|
||||||
|
if (!file_exists($boarddir) && file_exists(dirname(__FILE__) . '/agreement.txt'))
|
||||||
|
$boarddir = dirname(__FILE__);
|
||||||
|
if (!file_exists($sourcedir) && file_exists($boarddir . '/Sources'))
|
||||||
|
$sourcedir = $boarddir . '/Sources';
|
||||||
|
if (!file_exists($cachedir) && file_exists($boarddir . '/cache'))
|
||||||
|
$cachedir = $boarddir . '/cache';
|
||||||
|
|
||||||
|
?>
|
BIN
Smileys/aaron/afro.gif
Normal file
After Width: | Height: | Size: 691 B |
BIN
Smileys/aaron/angel.gif
Normal file
After Width: | Height: | Size: 425 B |
BIN
Smileys/aaron/angry.gif
Normal file
After Width: | Height: | Size: 612 B |
BIN
Smileys/aaron/azn.gif
Normal file
After Width: | Height: | Size: 621 B |
BIN
Smileys/aaron/blank.gif
Normal file
After Width: | Height: | Size: 615 B |
BIN
Smileys/aaron/cheesy.gif
Normal file
After Width: | Height: | Size: 608 B |
BIN
Smileys/aaron/cool.gif
Normal file
After Width: | Height: | Size: 608 B |
BIN
Smileys/aaron/cry.gif
Normal file
After Width: | Height: | Size: 648 B |
BIN
Smileys/aaron/embarrassed.gif
Normal file
After Width: | Height: | Size: 621 B |
BIN
Smileys/aaron/evil.gif
Normal file
After Width: | Height: | Size: 639 B |
BIN
Smileys/aaron/grin.gif
Normal file
After Width: | Height: | Size: 612 B |
BIN
Smileys/aaron/huh.gif
Normal file
After Width: | Height: | Size: 612 B |
9
Smileys/aaron/index.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// Try to handle it with the upper level index.php. (it should know what to do.)
|
||||||
|
if (file_exists(dirname(dirname(__FILE__)) . '/index.php'))
|
||||||
|
include (dirname(dirname(__FILE__)) . '/index.php');
|
||||||
|
else
|
||||||
|
exit;
|
||||||
|
|
||||||
|
?>
|
BIN
Smileys/aaron/kiss.gif
Normal file
After Width: | Height: | Size: 621 B |
BIN
Smileys/aaron/laugh.gif
Normal file
After Width: | Height: | Size: 610 B |
BIN
Smileys/aaron/lipsrsealed.gif
Normal file
After Width: | Height: | Size: 613 B |
BIN
Smileys/aaron/police.gif
Normal file
After Width: | Height: | Size: 689 B |
BIN
Smileys/aaron/rolleyes.gif
Normal file
After Width: | Height: | Size: 613 B |
BIN
Smileys/aaron/sad.gif
Normal file
After Width: | Height: | Size: 617 B |
BIN
Smileys/aaron/shocked.gif
Normal file
After Width: | Height: | Size: 608 B |
BIN
Smileys/aaron/smiley.gif
Normal file
After Width: | Height: | Size: 617 B |
BIN
Smileys/aaron/tongue.gif
Normal file
After Width: | Height: | Size: 622 B |
BIN
Smileys/aaron/undecided.gif
Normal file
After Width: | Height: | Size: 618 B |
BIN
Smileys/aaron/wink.gif
Normal file
After Width: | Height: | Size: 621 B |
BIN
Smileys/akyhne/afro.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Smileys/akyhne/angel.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Smileys/akyhne/angry.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Smileys/akyhne/azn.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Smileys/akyhne/blank.gif
Normal file
After Width: | Height: | Size: 670 B |
BIN
Smileys/akyhne/cheesy.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Smileys/akyhne/cool.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Smileys/akyhne/cry.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Smileys/akyhne/embarrassed.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Smileys/akyhne/evil.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Smileys/akyhne/grin.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Smileys/akyhne/huh.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
9
Smileys/akyhne/index.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// Try to handle it with the upper level index.php. (it should know what to do.)
|
||||||
|
if (file_exists(dirname(dirname(__FILE__)) . '/index.php'))
|
||||||
|
include (dirname(dirname(__FILE__)) . '/index.php');
|
||||||
|
else
|
||||||
|
exit;
|
||||||
|
|
||||||
|
?>
|
BIN
Smileys/akyhne/kiss.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Smileys/akyhne/laugh.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Smileys/akyhne/lipsrsealed.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Smileys/akyhne/police.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Smileys/akyhne/rolleyes.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Smileys/akyhne/sad.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Smileys/akyhne/shocked.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Smileys/akyhne/smiley.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Smileys/akyhne/tongue.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Smileys/akyhne/undecided.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Smileys/akyhne/wink.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Smileys/default/afro.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Smileys/default/angel.gif
Normal file
After Width: | Height: | Size: 622 B |
BIN
Smileys/default/angry.gif
Normal file
After Width: | Height: | Size: 1004 B |
BIN
Smileys/default/azn.gif
Normal file
After Width: | Height: | Size: 399 B |
BIN
Smileys/default/blank.gif
Normal file
After Width: | Height: | Size: 374 B |
BIN
Smileys/default/cheesy.gif
Normal file
After Width: | Height: | Size: 1012 B |
BIN
Smileys/default/cool.gif
Normal file
After Width: | Height: | Size: 999 B |
BIN
Smileys/default/cry.gif
Normal file
After Width: | Height: | Size: 1017 B |
BIN
Smileys/default/embarrassed.gif
Normal file
After Width: | Height: | Size: 1008 B |
BIN
Smileys/default/evil.gif
Normal file
After Width: | Height: | Size: 636 B |
BIN
Smileys/default/grin.gif
Normal file
After Width: | Height: | Size: 1001 B |
BIN
Smileys/default/huh.gif
Normal file
After Width: | Height: | Size: 1005 B |
9
Smileys/default/index.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// Try to handle it with the upper level index.php. (it should know what to do.)
|
||||||
|
if (file_exists(dirname(dirname(__FILE__)) . '/index.php'))
|
||||||
|
include (dirname(dirname(__FILE__)) . '/index.php');
|
||||||
|
else
|
||||||
|
exit;
|
||||||
|
|
||||||
|
?>
|
BIN
Smileys/default/kiss.gif
Normal file
After Width: | Height: | Size: 1008 B |
BIN
Smileys/default/laugh.gif
Normal file
After Width: | Height: | Size: 609 B |
BIN
Smileys/default/lipsrsealed.gif
Normal file
After Width: | Height: | Size: 1006 B |
BIN
Smileys/default/police.gif
Normal file
After Width: | Height: | Size: 686 B |
BIN
Smileys/default/rolleyes.gif
Normal file
After Width: | Height: | Size: 400 B |
BIN
Smileys/default/sad.gif
Normal file
After Width: | Height: | Size: 1009 B |
BIN
Smileys/default/shocked.gif
Normal file
After Width: | Height: | Size: 1012 B |
BIN
Smileys/default/smiley.gif
Normal file
After Width: | Height: | Size: 1009 B |
BIN
Smileys/default/tongue.gif
Normal file
After Width: | Height: | Size: 1005 B |
BIN
Smileys/default/undecided.gif
Normal file
After Width: | Height: | Size: 405 B |
BIN
Smileys/default/wink.gif
Normal file
After Width: | Height: | Size: 1004 B |
16
Smileys/index.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// This file is here solely to protect your Smileys directory.
|
||||||
|
|
||||||
|
// Look for Settings.php....
|
||||||
|
if (file_exists(dirname(dirname(__FILE__)) . '/Settings.php'))
|
||||||
|
{
|
||||||
|
// Found it!
|
||||||
|
require(dirname(dirname(__FILE__)) . '/Settings.php');
|
||||||
|
header('Location: ' . $boardurl);
|
||||||
|
}
|
||||||
|
// Can't find it... just forget it.
|
||||||
|
else
|
||||||
|
exit;
|
||||||
|
|
||||||
|
?>
|
999
Sources/Admin.php
Normal file
@ -0,0 +1,999 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple Machines Forum (SMF)
|
||||||
|
*
|
||||||
|
* @package SMF
|
||||||
|
* @author Simple Machines
|
||||||
|
*
|
||||||
|
* @copyright 2011 Simple Machines
|
||||||
|
* @license http://www.simplemachines.org/about/smf/license.php BSD
|
||||||
|
*
|
||||||
|
* @version 2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('SMF'))
|
||||||
|
die('Hacking attempt...');
|
||||||
|
|
||||||
|
/* This file, unpredictable as this might be, handles basic administration.
|
||||||
|
|
||||||
|
void AdminMain()
|
||||||
|
- initialises all the basic context required for the admin center.
|
||||||
|
- passes execution onto the relevant admin section.
|
||||||
|
- if the passed section is not found it shows the admin home page.
|
||||||
|
|
||||||
|
void AdminHome()
|
||||||
|
- prepares all the data necessary for the administration front page.
|
||||||
|
- uses the Admin template along with the admin sub template.
|
||||||
|
- requires the moderate_forum, manage_membergroups, manage_bans,
|
||||||
|
admin_forum, manage_permissions, manage_attachments, manage_smileys,
|
||||||
|
manage_boards, edit_news, or send_mail permission.
|
||||||
|
- uses the index administrative area.
|
||||||
|
- can be found by going to ?action=admin.
|
||||||
|
|
||||||
|
void AdminSearch()
|
||||||
|
- allocates out all the search stuff.
|
||||||
|
|
||||||
|
void AdminSearchInternal()
|
||||||
|
- a complicated but relatively quick internal search.
|
||||||
|
|
||||||
|
void AdminSearchMember()
|
||||||
|
- pass through to manage members.
|
||||||
|
|
||||||
|
void DisplayAdminFile()
|
||||||
|
- get one of the admin information files from Simple Machines.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// The main admin handling function.
|
||||||
|
function AdminMain()
|
||||||
|
{
|
||||||
|
global $txt, $context, $scripturl, $sc, $modSettings, $user_info, $settings, $sourcedir, $options, $smcFunc, $boarddir;
|
||||||
|
|
||||||
|
// Load the language and templates....
|
||||||
|
loadLanguage('Admin');
|
||||||
|
loadTemplate('Admin', 'admin');
|
||||||
|
|
||||||
|
// No indexing evil stuff.
|
||||||
|
$context['robot_no_index'] = true;
|
||||||
|
|
||||||
|
require_once($sourcedir . '/Subs-Menu.php');
|
||||||
|
|
||||||
|
// Some preferences.
|
||||||
|
$context['admin_preferences'] = !empty($options['admin_preferences']) ? unserialize($options['admin_preferences']) : array();
|
||||||
|
|
||||||
|
// Define all the menu structure - see Subs-Menu.php for details!
|
||||||
|
$admin_areas = array(
|
||||||
|
'forum' => array(
|
||||||
|
'title' => $txt['admin_main'],
|
||||||
|
'permission' => array('admin_forum', 'manage_permissions', 'moderate_forum', 'manage_membergroups', 'manage_bans', 'send_mail', 'edit_news', 'manage_boards', 'manage_smileys', 'manage_attachments'),
|
||||||
|
'areas' => array(
|
||||||
|
'index' => array(
|
||||||
|
'label' => $txt['admin_center'],
|
||||||
|
'function' => 'AdminHome',
|
||||||
|
'icon' => 'administration.gif',
|
||||||
|
),
|
||||||
|
'credits' => array(
|
||||||
|
'label' => $txt['support_credits_title'],
|
||||||
|
'function' => 'AdminHome',
|
||||||
|
'icon' => 'support.gif',
|
||||||
|
),
|
||||||
|
'news' => array(
|
||||||
|
'label' => $txt['news_title'],
|
||||||
|
'file' => 'ManageNews.php',
|
||||||
|
'function' => 'ManageNews',
|
||||||
|
'icon' => 'news.gif',
|
||||||
|
'permission' => array('edit_news', 'send_mail', 'admin_forum'),
|
||||||
|
'subsections' => array(
|
||||||
|
'editnews' => array($txt['admin_edit_news'], 'edit_news'),
|
||||||
|
'mailingmembers' => array($txt['admin_newsletters'], 'send_mail'),
|
||||||
|
'settings' => array($txt['settings'], 'admin_forum'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'packages' => array(
|
||||||
|
'label' => $txt['package'],
|
||||||
|
'file' => 'Packages.php',
|
||||||
|
'function' => 'Packages',
|
||||||
|
'permission' => array('admin_forum'),
|
||||||
|
'icon' => 'packages.gif',
|
||||||
|
'subsections' => array(
|
||||||
|
'browse' => array($txt['browse_packages']),
|
||||||
|
'packageget' => array($txt['download_packages'], 'url' => $scripturl . '?action=admin;area=packages;sa=packageget;get'),
|
||||||
|
'installed' => array($txt['installed_packages']),
|
||||||
|
'perms' => array($txt['package_file_perms']),
|
||||||
|
'options' => array($txt['package_settings']),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'search' => array(
|
||||||
|
'function' => 'AdminSearch',
|
||||||
|
'permission' => array('admin_forum'),
|
||||||
|
'select' => 'index'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'config' => array(
|
||||||
|
'title' => $txt['admin_config'],
|
||||||
|
'permission' => array('admin_forum'),
|
||||||
|
'areas' => array(
|
||||||
|
'corefeatures' => array(
|
||||||
|
'label' => $txt['core_settings_title'],
|
||||||
|
'file' => 'ManageSettings.php',
|
||||||
|
'function' => 'ModifyCoreFeatures',
|
||||||
|
'icon' => 'corefeatures.gif',
|
||||||
|
),
|
||||||
|
'featuresettings' => array(
|
||||||
|
'label' => $txt['modSettings_title'],
|
||||||
|
'file' => 'ManageSettings.php',
|
||||||
|
'function' => 'ModifyFeatureSettings',
|
||||||
|
'icon' => 'features.gif',
|
||||||
|
'subsections' => array(
|
||||||
|
'basic' => array($txt['mods_cat_features']),
|
||||||
|
'layout' => array($txt['mods_cat_layout']),
|
||||||
|
'karma' => array($txt['karma'], 'enabled' => in_array('k', $context['admin_features'])),
|
||||||
|
'sig' => array($txt['signature_settings_short']),
|
||||||
|
'profile' => array($txt['custom_profile_shorttitle'], 'enabled' => in_array('cp', $context['admin_features'])),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'securitysettings' => array(
|
||||||
|
'label' => $txt['admin_security_moderation'],
|
||||||
|
'file' => 'ManageSettings.php',
|
||||||
|
'function' => 'ModifySecuritySettings',
|
||||||
|
'icon' => 'security.gif',
|
||||||
|
'subsections' => array(
|
||||||
|
'general' => array($txt['mods_cat_security_general']),
|
||||||
|
'spam' => array($txt['antispam_title']),
|
||||||
|
'moderation' => array($txt['moderation_settings_short'], 'enabled' => substr($modSettings['warning_settings'], 0, 1) == 1),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'languages' => array(
|
||||||
|
'label' => $txt['language_configuration'],
|
||||||
|
'file' => 'ManageServer.php',
|
||||||
|
'function' => 'ManageLanguages',
|
||||||
|
'icon' => 'languages.gif',
|
||||||
|
'subsections' => array(
|
||||||
|
'edit' => array($txt['language_edit']),
|
||||||
|
'add' => array($txt['language_add']),
|
||||||
|
'settings' => array($txt['language_settings']),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'serversettings' => array(
|
||||||
|
'label' => $txt['admin_server_settings'],
|
||||||
|
'file' => 'ManageServer.php',
|
||||||
|
'function' => 'ModifySettings',
|
||||||
|
'icon' => 'server.gif',
|
||||||
|
'subsections' => array(
|
||||||
|
'general' => array($txt['general_settings']),
|
||||||
|
'database' => array($txt['database_paths_settings']),
|
||||||
|
'cookie' => array($txt['cookies_sessions_settings']),
|
||||||
|
'cache' => array($txt['caching_settings']),
|
||||||
|
'loads' => array($txt['load_balancing_settings']),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'current_theme' => array(
|
||||||
|
'label' => $txt['theme_current_settings'],
|
||||||
|
'file' => 'Themes.php',
|
||||||
|
'function' => 'ThemesMain',
|
||||||
|
'custom_url' => $scripturl . '?action=admin;area=theme;sa=settings;th=' . $settings['theme_id'],
|
||||||
|
'icon' => 'current_theme.gif',
|
||||||
|
),
|
||||||
|
'theme' => array(
|
||||||
|
'label' => $txt['theme_admin'],
|
||||||
|
'file' => 'Themes.php',
|
||||||
|
'function' => 'ThemesMain',
|
||||||
|
'custom_url' => $scripturl . '?action=admin;area=theme;sa=admin',
|
||||||
|
'icon' => 'themes.gif',
|
||||||
|
'subsections' => array(
|
||||||
|
'admin' => array($txt['themeadmin_admin_title']),
|
||||||
|
'list' => array($txt['themeadmin_list_title']),
|
||||||
|
'reset' => array($txt['themeadmin_reset_title']),
|
||||||
|
'edit' => array($txt['themeadmin_edit_title']),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'modsettings' => array(
|
||||||
|
'label' => $txt['admin_modifications'],
|
||||||
|
'file' => 'ManageSettings.php',
|
||||||
|
'function' => 'ModifyModSettings',
|
||||||
|
'icon' => 'modifications.gif',
|
||||||
|
'subsections' => array(
|
||||||
|
'general' => array($txt['mods_cat_modifications_misc']),
|
||||||
|
// Mod Authors for a "ADD AFTER" on this line. Ensure you end your change with a comma. For example:
|
||||||
|
// 'shout' => array($txt['shout']),
|
||||||
|
// Note the comma!! The setting with automatically appear with the first mod to be added.
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'layout' => array(
|
||||||
|
'title' => $txt['layout_controls'],
|
||||||
|
'permission' => array('manage_boards', 'admin_forum', 'manage_smileys', 'manage_attachments', 'moderate_forum'),
|
||||||
|
'areas' => array(
|
||||||
|
'manageboards' => array(
|
||||||
|
'label' => $txt['admin_boards'],
|
||||||
|
'file' => 'ManageBoards.php',
|
||||||
|
'function' => 'ManageBoards',
|
||||||
|
'icon' => 'boards.gif',
|
||||||
|
'permission' => array('manage_boards'),
|
||||||
|
'subsections' => array(
|
||||||
|
'main' => array($txt['boardsEdit']),
|
||||||
|
'newcat' => array($txt['mboards_new_cat']),
|
||||||
|
'settings' => array($txt['settings'], 'admin_forum'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'postsettings' => array(
|
||||||
|
'label' => $txt['manageposts'],
|
||||||
|
'file' => 'ManagePosts.php',
|
||||||
|
'function' => 'ManagePostSettings',
|
||||||
|
'permission' => array('admin_forum'),
|
||||||
|
'icon' => 'posts.gif',
|
||||||
|
'subsections' => array(
|
||||||
|
'posts' => array($txt['manageposts_settings']),
|
||||||
|
'bbc' => array($txt['manageposts_bbc_settings']),
|
||||||
|
'censor' => array($txt['admin_censored_words']),
|
||||||
|
'topics' => array($txt['manageposts_topic_settings']),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'managecalendar' => array(
|
||||||
|
'label' => $txt['manage_calendar'],
|
||||||
|
'file' => 'ManageCalendar.php',
|
||||||
|
'function' => 'ManageCalendar',
|
||||||
|
'icon' => 'calendar.gif',
|
||||||
|
'permission' => array('admin_forum'),
|
||||||
|
'enabled' => in_array('cd', $context['admin_features']),
|
||||||
|
'subsections' => array(
|
||||||
|
'holidays' => array($txt['manage_holidays'], 'admin_forum', 'enabled' => !empty($modSettings['cal_enabled'])),
|
||||||
|
'settings' => array($txt['calendar_settings'], 'admin_forum'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'managesearch' => array(
|
||||||
|
'label' => $txt['manage_search'],
|
||||||
|
'file' => 'ManageSearch.php',
|
||||||
|
'function' => 'ManageSearch',
|
||||||
|
'icon' => 'search.gif',
|
||||||
|
'permission' => array('admin_forum'),
|
||||||
|
'subsections' => array(
|
||||||
|
'weights' => array($txt['search_weights']),
|
||||||
|
'method' => array($txt['search_method']),
|
||||||
|
'settings' => array($txt['settings']),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'smileys' => array(
|
||||||
|
'label' => $txt['smileys_manage'],
|
||||||
|
'file' => 'ManageSmileys.php',
|
||||||
|
'function' => 'ManageSmileys',
|
||||||
|
'icon' => 'smiley.gif',
|
||||||
|
'permission' => array('manage_smileys'),
|
||||||
|
'subsections' => array(
|
||||||
|
'editsets' => array($txt['smiley_sets']),
|
||||||
|
'addsmiley' => array($txt['smileys_add'], 'enabled' => !empty($modSettings['smiley_enable'])),
|
||||||
|
'editsmileys' => array($txt['smileys_edit'], 'enabled' => !empty($modSettings['smiley_enable'])),
|
||||||
|
'setorder' => array($txt['smileys_set_order'], 'enabled' => !empty($modSettings['smiley_enable'])),
|
||||||
|
'editicons' => array($txt['icons_edit_message_icons'], 'enabled' => !empty($modSettings['messageIcons_enable'])),
|
||||||
|
'settings' => array($txt['settings']),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'manageattachments' => array(
|
||||||
|
'label' => $txt['attachments_avatars'],
|
||||||
|
'file' => 'ManageAttachments.php',
|
||||||
|
'function' => 'ManageAttachments',
|
||||||
|
'icon' => 'attachment.gif',
|
||||||
|
'permission' => array('manage_attachments'),
|
||||||
|
'subsections' => array(
|
||||||
|
'browse' => array($txt['attachment_manager_browse']),
|
||||||
|
'attachments' => array($txt['attachment_manager_settings']),
|
||||||
|
'avatars' => array($txt['attachment_manager_avatar_settings']),
|
||||||
|
'maintenance' => array($txt['attachment_manager_maintenance']),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'members' => array(
|
||||||
|
'title' => $txt['admin_manage_members'],
|
||||||
|
'permission' => array('moderate_forum', 'manage_membergroups', 'manage_bans', 'manage_permissions', 'admin_forum'),
|
||||||
|
'areas' => array(
|
||||||
|
'viewmembers' => array(
|
||||||
|
'label' => $txt['admin_users'],
|
||||||
|
'file' => 'ManageMembers.php',
|
||||||
|
'function' => 'ViewMembers',
|
||||||
|
'icon' => 'members.gif',
|
||||||
|
'permission' => array('moderate_forum'),
|
||||||
|
'subsections' => array(
|
||||||
|
'all' => array($txt['view_all_members']),
|
||||||
|
'search' => array($txt['mlist_search']),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'membergroups' => array(
|
||||||
|
'label' => $txt['admin_groups'],
|
||||||
|
'file' => 'ManageMembergroups.php',
|
||||||
|
'function' => 'ModifyMembergroups',
|
||||||
|
'icon' => 'membergroups.gif',
|
||||||
|
'permission' => array('manage_membergroups'),
|
||||||
|
'subsections' => array(
|
||||||
|
'index' => array($txt['membergroups_edit_groups'], 'manage_membergroups'),
|
||||||
|
'add' => array($txt['membergroups_new_group'], 'manage_membergroups'),
|
||||||
|
'settings' => array($txt['settings'], 'admin_forum'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'permissions' => array(
|
||||||
|
'label' => $txt['edit_permissions'],
|
||||||
|
'file' => 'ManagePermissions.php',
|
||||||
|
'function' => 'ModifyPermissions',
|
||||||
|
'icon' => 'permissions.gif',
|
||||||
|
'permission' => array('manage_permissions'),
|
||||||
|
'subsections' => array(
|
||||||
|
'index' => array($txt['permissions_groups'], 'manage_permissions'),
|
||||||
|
'board' => array($txt['permissions_boards'], 'manage_permissions'),
|
||||||
|
'profiles' => array($txt['permissions_profiles'], 'manage_permissions'),
|
||||||
|
'postmod' => array($txt['permissions_post_moderation'], 'manage_permissions', 'enabled' => $modSettings['postmod_active']),
|
||||||
|
'settings' => array($txt['settings'], 'admin_forum'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'regcenter' => array(
|
||||||
|
'label' => $txt['registration_center'],
|
||||||
|
'file' => 'ManageRegistration.php',
|
||||||
|
'function' => 'RegCenter',
|
||||||
|
'icon' => 'regcenter.gif',
|
||||||
|
'permission' => array('admin_forum', 'moderate_forum'),
|
||||||
|
'subsections' => array(
|
||||||
|
'register' => array($txt['admin_browse_register_new'], 'moderate_forum'),
|
||||||
|
'agreement' => array($txt['registration_agreement'], 'admin_forum'),
|
||||||
|
'reservednames' => array($txt['admin_reserved_set'], 'admin_forum'),
|
||||||
|
'settings' => array($txt['settings'], 'admin_forum'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'ban' => array(
|
||||||
|
'label' => $txt['ban_title'],
|
||||||
|
'file' => 'ManageBans.php',
|
||||||
|
'function' => 'Ban',
|
||||||
|
'icon' => 'ban.gif',
|
||||||
|
'permission' => 'manage_bans',
|
||||||
|
'subsections' => array(
|
||||||
|
'list' => array($txt['ban_edit_list']),
|
||||||
|
'add' => array($txt['ban_add_new']),
|
||||||
|
'browse' => array($txt['ban_trigger_browse']),
|
||||||
|
'log' => array($txt['ban_log']),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'paidsubscribe' => array(
|
||||||
|
'label' => $txt['paid_subscriptions'],
|
||||||
|
'enabled' => in_array('ps', $context['admin_features']),
|
||||||
|
'file' => 'ManagePaid.php',
|
||||||
|
'icon' => 'paid.gif',
|
||||||
|
'function' => 'ManagePaidSubscriptions',
|
||||||
|
'permission' => 'admin_forum',
|
||||||
|
'subsections' => array(
|
||||||
|
'view' => array($txt['paid_subs_view']),
|
||||||
|
'settings' => array($txt['settings']),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'sengines' => array(
|
||||||
|
'label' => $txt['search_engines'],
|
||||||
|
'enabled' => in_array('sp', $context['admin_features']),
|
||||||
|
'file' => 'ManageSearchEngines.php',
|
||||||
|
'icon' => 'engines.gif',
|
||||||
|
'function' => 'SearchEngines',
|
||||||
|
'permission' => 'admin_forum',
|
||||||
|
'subsections' => array(
|
||||||
|
'stats' => array($txt['spider_stats']),
|
||||||
|
'logs' => array($txt['spider_logs']),
|
||||||
|
'spiders' => array($txt['spiders']),
|
||||||
|
'settings' => array($txt['settings']),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'maintenance' => array(
|
||||||
|
'title' => $txt['admin_maintenance'],
|
||||||
|
'permission' => array('admin_forum'),
|
||||||
|
'areas' => array(
|
||||||
|
'maintain' => array(
|
||||||
|
'label' => $txt['maintain_title'],
|
||||||
|
'file' => 'ManageMaintenance.php',
|
||||||
|
'icon' => 'maintain.gif',
|
||||||
|
'function' => 'ManageMaintenance',
|
||||||
|
'subsections' => array(
|
||||||
|
'routine' => array($txt['maintain_sub_routine'], 'admin_forum'),
|
||||||
|
'database' => array($txt['maintain_sub_database'], 'admin_forum'),
|
||||||
|
'members' => array($txt['maintain_sub_members'], 'admin_forum'),
|
||||||
|
'topics' => array($txt['maintain_sub_topics'], 'admin_forum'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'scheduledtasks' => array(
|
||||||
|
'label' => $txt['maintain_tasks'],
|
||||||
|
'file' => 'ManageScheduledTasks.php',
|
||||||
|
'icon' => 'scheduled.gif',
|
||||||
|
'function' => 'ManageScheduledTasks',
|
||||||
|
'subsections' => array(
|
||||||
|
'tasks' => array($txt['maintain_tasks'], 'admin_forum'),
|
||||||
|
'tasklog' => array($txt['scheduled_log'], 'admin_forum'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'mailqueue' => array(
|
||||||
|
'label' => $txt['mailqueue_title'],
|
||||||
|
'file' => 'ManageMail.php',
|
||||||
|
'function' => 'ManageMail',
|
||||||
|
'icon' => 'mail.gif',
|
||||||
|
'subsections' => array(
|
||||||
|
'browse' => array($txt['mailqueue_browse'], 'admin_forum'),
|
||||||
|
'settings' => array($txt['mailqueue_settings'], 'admin_forum'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'reports' => array(
|
||||||
|
'enabled' => in_array('rg', $context['admin_features']),
|
||||||
|
'label' => $txt['generate_reports'],
|
||||||
|
'file' => 'Reports.php',
|
||||||
|
'function' => 'ReportsMain',
|
||||||
|
'icon' => 'reports.gif',
|
||||||
|
),
|
||||||
|
'logs' => array(
|
||||||
|
'label' => $txt['logs'],
|
||||||
|
'function' => 'AdminLogs',
|
||||||
|
'icon' => 'logs.gif',
|
||||||
|
'subsections' => array(
|
||||||
|
'errorlog' => array($txt['errlog'], 'admin_forum', 'enabled' => !empty($modSettings['enableErrorLogging']), 'url' => $scripturl . '?action=admin;area=logs;sa=errorlog;desc'),
|
||||||
|
'adminlog' => array($txt['admin_log'], 'admin_forum', 'enabled' => in_array('ml', $context['admin_features'])),
|
||||||
|
'modlog' => array($txt['moderation_log'], 'admin_forum', 'enabled' => in_array('ml', $context['admin_features'])),
|
||||||
|
'banlog' => array($txt['ban_log'], 'manage_bans'),
|
||||||
|
'spiderlog' => array($txt['spider_logs'], 'admin_forum', 'enabled' => in_array('sp', $context['admin_features'])),
|
||||||
|
'tasklog' => array($txt['scheduled_log'], 'admin_forum'),
|
||||||
|
'pruning' => array($txt['pruning_title'], 'admin_forum'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'repairboards' => array(
|
||||||
|
'label' => $txt['admin_repair'],
|
||||||
|
'file' => 'RepairBoards.php',
|
||||||
|
'function' => 'RepairBoards',
|
||||||
|
'select' => 'maintain',
|
||||||
|
'hidden' => true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Any files to include for administration?
|
||||||
|
if (!empty($modSettings['integrate_admin_include']))
|
||||||
|
{
|
||||||
|
$admin_includes = explode(',', $modSettings['integrate_admin_include']);
|
||||||
|
foreach ($admin_includes as $include)
|
||||||
|
{
|
||||||
|
$include = strtr(trim($include), array('$boarddir' => $boarddir, '$sourcedir' => $sourcedir, '$themedir' => $settings['theme_dir']));
|
||||||
|
if (file_exists($include))
|
||||||
|
require_once($include);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let them modify admin areas easily.
|
||||||
|
call_integration_hook('integrate_admin_areas', array(&$admin_areas));
|
||||||
|
|
||||||
|
// Make sure the administrator has a valid session...
|
||||||
|
validateSession();
|
||||||
|
|
||||||
|
// Actually create the menu!
|
||||||
|
$admin_include_data = createMenu($admin_areas);
|
||||||
|
unset($admin_areas);
|
||||||
|
|
||||||
|
// Nothing valid?
|
||||||
|
if ($admin_include_data == false)
|
||||||
|
fatal_lang_error('no_access', false);
|
||||||
|
|
||||||
|
// Build the link tree.
|
||||||
|
$context['linktree'][] = array(
|
||||||
|
'url' => $scripturl . '?action=admin',
|
||||||
|
'name' => $txt['admin_center'],
|
||||||
|
);
|
||||||
|
if (isset($admin_include_data['current_area']) && $admin_include_data['current_area'] != 'index')
|
||||||
|
$context['linktree'][] = array(
|
||||||
|
'url' => $scripturl . '?action=admin;area=' . $admin_include_data['current_area'] . ';' . $context['session_var'] . '=' . $context['session_id'],
|
||||||
|
'name' => $admin_include_data['label'],
|
||||||
|
);
|
||||||
|
if (!empty($admin_include_data['current_subsection']) && $admin_include_data['subsections'][$admin_include_data['current_subsection']][0] != $admin_include_data['label'])
|
||||||
|
$context['linktree'][] = array(
|
||||||
|
'url' => $scripturl . '?action=admin;area=' . $admin_include_data['current_area'] . ';sa=' . $admin_include_data['current_subsection'] . ';' . $context['session_var'] . '=' . $context['session_id'],
|
||||||
|
'name' => $admin_include_data['subsections'][$admin_include_data['current_subsection']][0],
|
||||||
|
);
|
||||||
|
|
||||||
|
// Make a note of the Unique ID for this menu.
|
||||||
|
$context['admin_menu_id'] = $context['max_menu_id'];
|
||||||
|
$context['admin_menu_name'] = 'menu_data_' . $context['admin_menu_id'];
|
||||||
|
|
||||||
|
// Why on the admin are we?
|
||||||
|
$context['admin_area'] = $admin_include_data['current_area'];
|
||||||
|
|
||||||
|
// Now - finally - call the right place!
|
||||||
|
if (isset($admin_include_data['file']))
|
||||||
|
require_once($sourcedir . '/' . $admin_include_data['file']);
|
||||||
|
|
||||||
|
$admin_include_data['function']();
|
||||||
|
}
|
||||||
|
|
||||||
|
// The main administration section.
|
||||||
|
function AdminHome()
|
||||||
|
{
|
||||||
|
global $sourcedir, $forum_version, $txt, $scripturl, $context, $user_info, $boardurl, $modSettings, $smcFunc;
|
||||||
|
|
||||||
|
// You have to be able to do at least one of the below to see this page.
|
||||||
|
isAllowedTo(array('admin_forum', 'manage_permissions', 'moderate_forum', 'manage_membergroups', 'manage_bans', 'send_mail', 'edit_news', 'manage_boards', 'manage_smileys', 'manage_attachments'));
|
||||||
|
|
||||||
|
// Find all of this forum's administrators...
|
||||||
|
require_once($sourcedir . '/Subs-Membergroups.php');
|
||||||
|
if (listMembergroupMembers_Href($context['administrators'], 1, 32) && allowedTo('manage_membergroups'))
|
||||||
|
{
|
||||||
|
// Add a 'more'-link if there are more than 32.
|
||||||
|
$context['more_admins_link'] = '<a href="' . $scripturl . '?action=moderate;area=viewgroups;sa=members;group=1">' . $txt['more'] . '</a>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the credits stuff.
|
||||||
|
require_once($sourcedir . '/Who.php');
|
||||||
|
Credits(true);
|
||||||
|
|
||||||
|
// This makes it easier to get the latest news with your time format.
|
||||||
|
$context['time_format'] = urlencode($user_info['time_format']);
|
||||||
|
|
||||||
|
$context['current_versions'] = array(
|
||||||
|
'php' => array('title' => $txt['support_versions_php'], 'version' => PHP_VERSION),
|
||||||
|
'db' => array('title' => sprintf($txt['support_versions_db'], $smcFunc['db_title']), 'version' => ''),
|
||||||
|
'server' => array('title' => $txt['support_versions_server'], 'version' => $_SERVER['SERVER_SOFTWARE']),
|
||||||
|
);
|
||||||
|
$context['forum_version'] = $forum_version;
|
||||||
|
|
||||||
|
// Get a list of current server versions.
|
||||||
|
require_once($sourcedir . '/Subs-Admin.php');
|
||||||
|
$checkFor = array(
|
||||||
|
'gd',
|
||||||
|
'db_server',
|
||||||
|
'mmcache',
|
||||||
|
'eaccelerator',
|
||||||
|
'phpa',
|
||||||
|
'apc',
|
||||||
|
'memcache',
|
||||||
|
'xcache',
|
||||||
|
'php',
|
||||||
|
'server',
|
||||||
|
);
|
||||||
|
$context['current_versions'] = getServerVersions($checkFor);
|
||||||
|
|
||||||
|
$context['can_admin'] = allowedTo('admin_forum');
|
||||||
|
|
||||||
|
$context['sub_template'] = $context['admin_area'] == 'credits' ? 'credits' : 'admin';
|
||||||
|
$context['page_title'] = $context['admin_area'] == 'credits' ? $txt['support_credits_title'] : $txt['admin_center'];
|
||||||
|
|
||||||
|
// The format of this array is: permission, action, title, description, icon.
|
||||||
|
$quick_admin_tasks = array(
|
||||||
|
array('', 'credits', 'support_credits_title', 'support_credits_info', 'support_and_credits.png'),
|
||||||
|
array('admin_forum', 'featuresettings', 'modSettings_title', 'modSettings_info', 'features_and_options.png'),
|
||||||
|
array('admin_forum', 'maintain', 'maintain_title', 'maintain_info', 'forum_maintenance.png'),
|
||||||
|
array('manage_permissions', 'permissions', 'edit_permissions', 'edit_permissions_info', 'permissions.png'),
|
||||||
|
array('admin_forum', 'theme;sa=admin;' . $context['session_var'] . '=' . $context['session_id'], 'theme_admin', 'theme_admin_info', 'themes_and_layout.png'),
|
||||||
|
array('admin_forum', 'packages', 'package', 'package_info', 'packages.png'),
|
||||||
|
array('manage_smileys', 'smileys', 'smileys_manage', 'smileys_manage_info', 'smilies_and_messageicons.png'),
|
||||||
|
array('moderate_forum', 'viewmembers', 'admin_users', 'member_center_info', 'members.png'),
|
||||||
|
);
|
||||||
|
|
||||||
|
$context['quick_admin_tasks'] = array();
|
||||||
|
foreach ($quick_admin_tasks as $task)
|
||||||
|
{
|
||||||
|
if (!empty($task[0]) && !allowedTo($task[0]))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$context['quick_admin_tasks'][] = array(
|
||||||
|
'href' => $scripturl . '?action=admin;area=' . $task[1],
|
||||||
|
'link' => '<a href="' . $scripturl . '?action=admin;area=' . $task[1] . '">' . $txt[$task[2]] . '</a>',
|
||||||
|
'title' => $txt[$task[2]],
|
||||||
|
'description' => $txt[$task[3]],
|
||||||
|
'icon' => $task[4],
|
||||||
|
'is_last' => false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($context['quick_admin_tasks']) % 2 == 1)
|
||||||
|
{
|
||||||
|
$context['quick_admin_tasks'][] = array(
|
||||||
|
'href' => '',
|
||||||
|
'link' => '',
|
||||||
|
'title' => '',
|
||||||
|
'description' => '',
|
||||||
|
'is_last' => true
|
||||||
|
);
|
||||||
|
$context['quick_admin_tasks'][count($context['quick_admin_tasks']) - 2]['is_last'] = true;
|
||||||
|
}
|
||||||
|
elseif (count($context['quick_admin_tasks']) != 0)
|
||||||
|
{
|
||||||
|
$context['quick_admin_tasks'][count($context['quick_admin_tasks']) - 1]['is_last'] = true;
|
||||||
|
$context['quick_admin_tasks'][count($context['quick_admin_tasks']) - 2]['is_last'] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lastly, fill in the blanks in the support resources paragraphs.
|
||||||
|
$txt['support_resources_p1'] = sprintf($txt['support_resources_p1'],
|
||||||
|
'http://wiki.simplemachines.org/',
|
||||||
|
'http://wiki.simplemachines.org/smf/features2',
|
||||||
|
'http://wiki.simplemachines.org/smf/options2',
|
||||||
|
'http://wiki.simplemachines.org/smf/themes2',
|
||||||
|
'http://wiki.simplemachines.org/smf/packages2'
|
||||||
|
);
|
||||||
|
$txt['support_resources_p2'] = sprintf($txt['support_resources_p2'],
|
||||||
|
'http://www.simplemachines.org/community/',
|
||||||
|
'http://www.simplemachines.org/redirect/english_support',
|
||||||
|
'http://www.simplemachines.org/redirect/international_support_boards',
|
||||||
|
'http://www.simplemachines.org/redirect/smf_support',
|
||||||
|
'http://www.simplemachines.org/redirect/customize_support'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get one of the admin information files from Simple Machines.
|
||||||
|
function DisplayAdminFile()
|
||||||
|
{
|
||||||
|
global $context, $modSettings, $smcFunc;
|
||||||
|
|
||||||
|
@ini_set('memory_limit', '32M');
|
||||||
|
|
||||||
|
if (empty($_REQUEST['filename']) || !is_string($_REQUEST['filename']))
|
||||||
|
fatal_lang_error('no_access', false);
|
||||||
|
|
||||||
|
$request = $smcFunc['db_query']('', '
|
||||||
|
SELECT data, filetype
|
||||||
|
FROM {db_prefix}admin_info_files
|
||||||
|
WHERE filename = {string:current_filename}
|
||||||
|
LIMIT 1',
|
||||||
|
array(
|
||||||
|
'current_filename' => $_REQUEST['filename'],
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($smcFunc['db_num_rows']($request) == 0)
|
||||||
|
fatal_lang_error('admin_file_not_found', true, array($_REQUEST['filename']));
|
||||||
|
|
||||||
|
list ($file_data, $filetype) = $smcFunc['db_fetch_row']($request);
|
||||||
|
$smcFunc['db_free_result']($request);
|
||||||
|
|
||||||
|
// !!! Temp.
|
||||||
|
// Figure out if sesc is still being used.
|
||||||
|
if (strpos($file_data, ';sesc=') !== false)
|
||||||
|
$file_data = '
|
||||||
|
if (!(\'smfForum_sessionvar\' in window))
|
||||||
|
window.smfForum_sessionvar = \'sesc\';
|
||||||
|
' . strtr($file_data, array(';sesc=' => ';\' + window.smfForum_sessionvar + \'='));
|
||||||
|
|
||||||
|
$context['template_layers'] = array();
|
||||||
|
// Lets make sure we aren't going to output anything nasty.
|
||||||
|
@ob_end_clean();
|
||||||
|
if (!empty($modSettings['enableCompressedOutput']))
|
||||||
|
@ob_start('ob_gzhandler');
|
||||||
|
else
|
||||||
|
@ob_start();
|
||||||
|
|
||||||
|
// Make sure they know what type of file we are.
|
||||||
|
header('Content-Type: ' . $filetype);
|
||||||
|
echo $file_data;
|
||||||
|
obExit(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This allocates out all the search stuff.
|
||||||
|
function AdminSearch()
|
||||||
|
{
|
||||||
|
global $txt, $context, $smcFunc, $sourcedir;
|
||||||
|
|
||||||
|
isAllowedTo('admin_forum');
|
||||||
|
|
||||||
|
// What can we search for?
|
||||||
|
$subactions = array(
|
||||||
|
'internal' => 'AdminSearchInternal',
|
||||||
|
'online' => 'AdminSearchOM',
|
||||||
|
'member' => 'AdminSearchMember',
|
||||||
|
);
|
||||||
|
|
||||||
|
$context['search_type'] = !isset($_REQUEST['search_type']) || !isset($subactions[$_REQUEST['search_type']]) ? 'internal' : $_REQUEST['search_type'];
|
||||||
|
$context['search_term'] = isset($_REQUEST['search_term']) ? $smcFunc['htmlspecialchars']($_REQUEST['search_term'], ENT_QUOTES) : '';
|
||||||
|
|
||||||
|
$context['sub_template'] = 'admin_search_results';
|
||||||
|
$context['page_title'] = $txt['admin_search_results'];
|
||||||
|
|
||||||
|
// Keep track of what the admin wants.
|
||||||
|
if (empty($context['admin_preferences']['sb']) || $context['admin_preferences']['sb'] != $context['search_type'])
|
||||||
|
{
|
||||||
|
$context['admin_preferences']['sb'] = $context['search_type'];
|
||||||
|
|
||||||
|
// Update the preferences.
|
||||||
|
require_once($sourcedir . '/Subs-Admin.php');
|
||||||
|
updateAdminPreferences();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trim($context['search_term']) == '')
|
||||||
|
$context['search_results'] = array();
|
||||||
|
else
|
||||||
|
$subactions[$context['search_type']]();
|
||||||
|
}
|
||||||
|
|
||||||
|
// A complicated but relatively quick internal search.
|
||||||
|
function AdminSearchInternal()
|
||||||
|
{
|
||||||
|
global $context, $txt, $helptxt, $scripturl, $sourcedir;
|
||||||
|
|
||||||
|
// Try to get some more memory.
|
||||||
|
@ini_set('memory_limit', '128M');
|
||||||
|
|
||||||
|
// Load a lot of language files.
|
||||||
|
$language_files = array(
|
||||||
|
'Help', 'ManageMail', 'ManageSettings', 'ManageCalendar', 'ManageBoards', 'ManagePaid', 'ManagePermissions', 'Search',
|
||||||
|
'Login', 'ManageSmileys',
|
||||||
|
);
|
||||||
|
loadLanguage(implode('+', $language_files));
|
||||||
|
|
||||||
|
// All the files we need to include.
|
||||||
|
$include_files = array(
|
||||||
|
'ManageSettings', 'ManageBoards', 'ManageNews', 'ManageAttachments', 'ManageCalendar', 'ManageMail', 'ManagePaid', 'ManagePermissions',
|
||||||
|
'ManagePosts', 'ManageRegistration', 'ManageSearch', 'ManageSearchEngines', 'ManageServer', 'ManageSmileys',
|
||||||
|
);
|
||||||
|
foreach ($include_files as $file)
|
||||||
|
require_once($sourcedir . '/' . $file . '.php');
|
||||||
|
|
||||||
|
/* This is the huge array that defines everything... it's a huge array of items formatted as follows:
|
||||||
|
0 = Language index (Can be array of indexes) to search through for this setting.
|
||||||
|
1 = URL for this indexes page.
|
||||||
|
2 = Help index for help associated with this item (If different from 0)
|
||||||
|
*/
|
||||||
|
|
||||||
|
$search_data = array(
|
||||||
|
// All the major sections of the forum.
|
||||||
|
'sections' => array(
|
||||||
|
),
|
||||||
|
'settings' => array(
|
||||||
|
array('COPPA', 'area=regcenter;sa=settings'),
|
||||||
|
array('CAPTCHA', 'area=securitysettings;sa=spam'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Go through the admin menu structure trying to find suitably named areas!
|
||||||
|
foreach ($context[$context['admin_menu_name']]['sections'] as $section)
|
||||||
|
{
|
||||||
|
foreach ($section['areas'] as $menu_key => $menu_item)
|
||||||
|
{
|
||||||
|
$search_data['sections'][] = array($menu_item['label'], 'area=' . $menu_key);
|
||||||
|
if (!empty($menu_item['subsections']))
|
||||||
|
foreach ($menu_item['subsections'] as $key => $sublabel)
|
||||||
|
{
|
||||||
|
if (isset($sublabel['label']))
|
||||||
|
$search_data['sections'][] = array($sublabel['label'], 'area=' . $menu_key . ';sa=' . $key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a special array of functions that contain setting data - we query all these to simply pull all setting bits!
|
||||||
|
$settings_search = array(
|
||||||
|
array('ModifyCoreFeatures', 'area=corefeatures'),
|
||||||
|
array('ModifyBasicSettings', 'area=featuresettings;sa=basic'),
|
||||||
|
array('ModifyLayoutSettings', 'area=featuresettings;sa=layout'),
|
||||||
|
array('ModifyKarmaSettings', 'area=featuresettings;sa=karma'),
|
||||||
|
array('ModifySignatureSettings', 'area=featuresettings;sa=sig'),
|
||||||
|
array('ModifyGeneralSecuritySettings', 'area=securitysettings;sa=general'),
|
||||||
|
array('ModifySpamSettings', 'area=securitysettings;sa=spam'),
|
||||||
|
array('ModifyModerationSettings', 'area=securitysettings;sa=moderation'),
|
||||||
|
array('ModifyGeneralModSettings', 'area=modsettings;sa=general'),
|
||||||
|
// Mod authors if you want to be "real freaking good" then add any setting pages for your mod BELOW this line!
|
||||||
|
array('ManageAttachmentSettings', 'area=manageattachments;sa=attachments'),
|
||||||
|
array('ManageAvatarSettings', 'area=manageattachments;sa=avatars'),
|
||||||
|
array('ModifyCalendarSettings', 'area=managecalendar;sa=settings'),
|
||||||
|
array('EditBoardSettings', 'area=manageboards;sa=settings'),
|
||||||
|
array('ModifyMailSettings', 'area=mailqueue;sa=settings'),
|
||||||
|
array('ModifyNewsSettings', 'area=news;sa=settings'),
|
||||||
|
array('GeneralPermissionSettings', 'area=permissions;sa=settings'),
|
||||||
|
array('ModifyPostSettings', 'area=postsettings;sa=posts'),
|
||||||
|
array('ModifyBBCSettings', 'area=postsettings;sa=bbc'),
|
||||||
|
array('ModifyTopicSettings', 'area=postsettings;sa=topics'),
|
||||||
|
array('EditSearchSettings', 'area=managesearch;sa=settings'),
|
||||||
|
array('EditSmileySettings', 'area=smileys;sa=settings'),
|
||||||
|
array('ModifyGeneralSettings', 'area=serversettings;sa=general'),
|
||||||
|
array('ModifyDatabaseSettings', 'area=serversettings;sa=database'),
|
||||||
|
array('ModifyCookieSettings', 'area=serversettings;sa=cookie'),
|
||||||
|
array('ModifyCacheSettings', 'area=serversettings;sa=cache'),
|
||||||
|
array('ModifyLanguageSettings', 'area=languages;sa=settings'),
|
||||||
|
array('ModifyRegistrationSettings', 'area=regcenter;sa=settings'),
|
||||||
|
array('ManageSearchEngineSettings', 'area=sengines;sa=settings'),
|
||||||
|
array('ModifySubscriptionSettings', 'area=paidsubscribe;sa=settings'),
|
||||||
|
array('ModifyPruningSettings', 'area=logs;sa=pruning'),
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($settings_search as $setting_area)
|
||||||
|
{
|
||||||
|
// Get a list of their variables.
|
||||||
|
$config_vars = $setting_area[0](true);
|
||||||
|
|
||||||
|
foreach ($config_vars as $var)
|
||||||
|
if (!empty($var[1]) && !in_array($var[0], array('permissions', 'switch')))
|
||||||
|
$search_data['settings'][] = array($var[(isset($var[2]) && in_array($var[2], array('file', 'db'))) ? 0 : 1], $setting_area[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$context['page_title'] = $txt['admin_search_results'];
|
||||||
|
$context['search_results'] = array();
|
||||||
|
|
||||||
|
$search_term = strtolower($context['search_term']);
|
||||||
|
// Go through all the search data trying to find this text!
|
||||||
|
foreach ($search_data as $section => $data)
|
||||||
|
{
|
||||||
|
foreach ($data as $item)
|
||||||
|
{
|
||||||
|
$found = false;
|
||||||
|
if (!is_array($item[0]))
|
||||||
|
$item[0] = array($item[0]);
|
||||||
|
foreach ($item[0] as $term)
|
||||||
|
{
|
||||||
|
$lc_term = strtolower($term);
|
||||||
|
if (strpos($lc_term, $search_term) !== false || (isset($txt[$term]) && strpos(strtolower($txt[$term]), $search_term) !== false) || (isset($txt['setting_' . $term]) && strpos(strtolower($txt['setting_' . $term]), $search_term) !== false))
|
||||||
|
{
|
||||||
|
$found = $term;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($found)
|
||||||
|
{
|
||||||
|
// Format the name - and remove any descriptions the entry may have.
|
||||||
|
$name = isset($txt[$found]) ? $txt[$found] : (isset($txt['setting_' . $found]) ? $txt['setting_' . $found] : $found);
|
||||||
|
$name = preg_replace('~<(?:div|span)\sclass="smalltext">.+?</(?:div|span)>~', '', $name);
|
||||||
|
|
||||||
|
$context['search_results'][] = array(
|
||||||
|
'url' => (substr($item[1], 0, 4) == 'area' ? $scripturl . '?action=admin;' . $item[1] : $item[1]) . ';' . $context['session_var'] . '=' . $context['session_id'] . ((substr($item[1], 0, 4) == 'area' && $section == 'settings' ? '#' . $item[0][0] : '')),
|
||||||
|
'name' => $name,
|
||||||
|
'type' => $section,
|
||||||
|
'help' => shorten_subject(isset($item[2]) ? strip_tags($helptxt[$item2]) : (isset($helptxt[$found]) ? strip_tags($helptxt[$found]) : ''), 255),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// All this does is pass through to manage members.
|
||||||
|
function AdminSearchMember()
|
||||||
|
{
|
||||||
|
global $context, $sourcedir;
|
||||||
|
|
||||||
|
require_once($sourcedir . '/ManageMembers.php');
|
||||||
|
$_REQUEST['sa'] = 'query';
|
||||||
|
|
||||||
|
$_POST['membername'] = $context['search_term'];
|
||||||
|
|
||||||
|
ViewMembers();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This file allows the user to search the SM online manual for a little of help.
|
||||||
|
function AdminSearchOM()
|
||||||
|
{
|
||||||
|
global $context, $sourcedir;
|
||||||
|
|
||||||
|
$docsURL = 'docs.simplemachines.org';
|
||||||
|
$context['doc_scripturl'] = 'http://docs.simplemachines.org/index.php';
|
||||||
|
|
||||||
|
// Set all the parameters search might expect.
|
||||||
|
$postVars = array(
|
||||||
|
'search' => $context['search_term'],
|
||||||
|
);
|
||||||
|
|
||||||
|
// Encode the search data.
|
||||||
|
foreach ($postVars as $k => $v)
|
||||||
|
$postVars[$k] = urlencode($k) . '=' . urlencode($v);
|
||||||
|
|
||||||
|
// This is what we will send.
|
||||||
|
$postVars = implode('&', $postVars);
|
||||||
|
|
||||||
|
// Get the results from the doc site.
|
||||||
|
require_once($sourcedir . '/Subs-Package.php');
|
||||||
|
$search_results = fetch_web_data($context['doc_scripturl'] . '?action=search2&xml', $postVars);
|
||||||
|
|
||||||
|
// If we didn't get any xml back we are in trouble - perhaps the doc site is overloaded?
|
||||||
|
if (!$search_results || preg_match('~<' . '\?xml\sversion="\d+\.\d+"\sencoding=".+?"\?' . '>\s*(<smf>.+?</smf>)~is', $search_results, $matches) != true)
|
||||||
|
fatal_lang_error('cannot_connect_doc_site');
|
||||||
|
|
||||||
|
$search_results = $matches[1];
|
||||||
|
|
||||||
|
// Otherwise we simply walk through the XML and stick it in context for display.
|
||||||
|
$context['search_results'] = array();
|
||||||
|
loadClassFile('Class-Package.php');
|
||||||
|
|
||||||
|
// Get the results loaded into an array for processing!
|
||||||
|
$results = new xmlArray($search_results, false);
|
||||||
|
|
||||||
|
// Move through the smf layer.
|
||||||
|
if (!$results->exists('smf'))
|
||||||
|
fatal_lang_error('cannot_connect_doc_site');
|
||||||
|
$results = $results->path('smf[0]');
|
||||||
|
|
||||||
|
// Are there actually some results?
|
||||||
|
if (!$results->exists('noresults') && !$results->exists('results'))
|
||||||
|
fatal_lang_error('cannot_connect_doc_site');
|
||||||
|
elseif ($results->exists('results'))
|
||||||
|
{
|
||||||
|
foreach ($results->set('results/result') as $result)
|
||||||
|
{
|
||||||
|
if (!$result->exists('messages'))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$context['search_results'][$result->fetch('id')] = array(
|
||||||
|
'topic_id' => $result->fetch('id'),
|
||||||
|
'relevance' => $result->fetch('relevance'),
|
||||||
|
'board' => array(
|
||||||
|
'id' => $result->fetch('board/id'),
|
||||||
|
'name' => $result->fetch('board/name'),
|
||||||
|
'href' => $result->fetch('board/href'),
|
||||||
|
),
|
||||||
|
'category' => array(
|
||||||
|
'id' => $result->fetch('category/id'),
|
||||||
|
'name' => $result->fetch('category/name'),
|
||||||
|
'href' => $result->fetch('category/href'),
|
||||||
|
),
|
||||||
|
'messages' => array(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add the messages.
|
||||||
|
foreach ($result->set('messages/message') as $message)
|
||||||
|
$context['search_results'][$result->fetch('id')]['messages'][] = array(
|
||||||
|
'id' => $message->fetch('id'),
|
||||||
|
'subject' => $message->fetch('subject'),
|
||||||
|
'body' => $message->fetch('body'),
|
||||||
|
'time' => $message->fetch('time'),
|
||||||
|
'timestamp' => $message->fetch('timestamp'),
|
||||||
|
'start' => $message->fetch('start'),
|
||||||
|
'author' => array(
|
||||||
|
'id' => $message->fetch('author/id'),
|
||||||
|
'name' => $message->fetch('author/name'),
|
||||||
|
'href' => $message->fetch('author/href'),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function decides which log to load.
|
||||||
|
function AdminLogs()
|
||||||
|
{
|
||||||
|
global $sourcedir, $context, $txt, $scripturl;
|
||||||
|
|
||||||
|
// These are the logs they can load.
|
||||||
|
$log_functions = array(
|
||||||
|
'errorlog' => array('ManageErrors.php', 'ViewErrorLog'),
|
||||||
|
'adminlog' => array('Modlog.php', 'ViewModlog'),
|
||||||
|
'modlog' => array('Modlog.php', 'ViewModlog'),
|
||||||
|
'banlog' => array('ManageBans.php', 'BanLog'),
|
||||||
|
'spiderlog' => array('ManageSearchEngines.php', 'SpiderLogs'),
|
||||||
|
'tasklog' => array('ManageScheduledTasks.php', 'TaskLog'),
|
||||||
|
'pruning' => array('ManageSettings.php', 'ModifyPruningSettings'),
|
||||||
|
);
|
||||||
|
|
||||||
|
$sub_action = isset($_REQUEST['sa']) && isset($log_functions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : 'errorlog';
|
||||||
|
// If it's not got a sa set it must have come here for first time, pretend error log should be reversed.
|
||||||
|
if (!isset($_REQUEST['sa']))
|
||||||
|
$_REQUEST['desc'] = true;
|
||||||
|
|
||||||
|
// Setup some tab stuff.
|
||||||
|
$context[$context['admin_menu_name']]['tab_data'] = array(
|
||||||
|
'title' => $txt['logs'],
|
||||||
|
'help' => '',
|
||||||
|
'description' => $txt['maintain_info'],
|
||||||
|
'tabs' => array(
|
||||||
|
'errorlog' => array(
|
||||||
|
'url' => $scripturl . '?action=admin;area=logs;sa=errorlog;desc',
|
||||||
|
'description' => sprintf($txt['errlog_desc'], $txt['remove']),
|
||||||
|
),
|
||||||
|
'adminlog' => array(
|
||||||
|
'description' => $txt['admin_log_desc'],
|
||||||
|
),
|
||||||
|
'modlog' => array(
|
||||||
|
'description' => $txt['moderation_log_desc'],
|
||||||
|
),
|
||||||
|
'banlog' => array(
|
||||||
|
'description' => $txt['ban_log_description'],
|
||||||
|
),
|
||||||
|
'spiderlog' => array(
|
||||||
|
'description' => $txt['spider_log_desc'],
|
||||||
|
),
|
||||||
|
'tasklog' => array(
|
||||||
|
'description' => $txt['scheduled_log_desc'],
|
||||||
|
),
|
||||||
|
'pruning' => array(
|
||||||
|
'description' => $txt['pruning_log_desc'],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
require_once($sourcedir . '/' . $log_functions[$sub_action][0]);
|
||||||
|
$log_functions[$sub_action][1]();
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
143
Sources/BoardIndex.php
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple Machines Forum (SMF)
|
||||||
|
*
|
||||||
|
* @package SMF
|
||||||
|
* @author Simple Machines http://www.simplemachines.org
|
||||||
|
* @copyright 2011 Simple Machines
|
||||||
|
* @license http://www.simplemachines.org/about/smf/license.php BSD
|
||||||
|
*
|
||||||
|
* @version 2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('SMF'))
|
||||||
|
die('Hacking attempt...');
|
||||||
|
|
||||||
|
/* The single function this file contains is used to display the main
|
||||||
|
board index. It uses just the following functions:
|
||||||
|
|
||||||
|
void BoardIndex()
|
||||||
|
- shows the board index.
|
||||||
|
- uses the BoardIndex template, and main sub template.
|
||||||
|
- may use the boardindex subtemplate for wireless support.
|
||||||
|
- updates the most online statistics.
|
||||||
|
- is accessed by ?action=boardindex.
|
||||||
|
|
||||||
|
void CollapseCategory()
|
||||||
|
- collapse or expand a category
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Show the board index!
|
||||||
|
function BoardIndex()
|
||||||
|
{
|
||||||
|
global $txt, $user_info, $sourcedir, $modSettings, $context, $settings, $scripturl;
|
||||||
|
|
||||||
|
// For wireless, we use the Wireless template...
|
||||||
|
if (WIRELESS)
|
||||||
|
$context['sub_template'] = WIRELESS_PROTOCOL . '_boardindex';
|
||||||
|
else
|
||||||
|
loadTemplate('BoardIndex');
|
||||||
|
|
||||||
|
// Set a canonical URL for this page.
|
||||||
|
$context['canonical_url'] = $scripturl;
|
||||||
|
|
||||||
|
// Do not let search engines index anything if there is a random thing in $_GET.
|
||||||
|
if (!empty($_GET))
|
||||||
|
$context['robot_no_index'] = true;
|
||||||
|
|
||||||
|
// Retrieve the categories and boards.
|
||||||
|
require_once($sourcedir . '/Subs-BoardIndex.php');
|
||||||
|
$boardIndexOptions = array(
|
||||||
|
'include_categories' => true,
|
||||||
|
'base_level' => 0,
|
||||||
|
'parent_id' => 0,
|
||||||
|
'set_latest_post' => true,
|
||||||
|
'countChildPosts' => !empty($modSettings['countChildPosts']),
|
||||||
|
);
|
||||||
|
$context['categories'] = getBoardIndex($boardIndexOptions);
|
||||||
|
|
||||||
|
// Get the user online list.
|
||||||
|
require_once($sourcedir . '/Subs-MembersOnline.php');
|
||||||
|
$membersOnlineOptions = array(
|
||||||
|
'show_hidden' => allowedTo('moderate_forum'),
|
||||||
|
'sort' => 'log_time',
|
||||||
|
'reverse_sort' => true,
|
||||||
|
);
|
||||||
|
$context += getMembersOnlineStats($membersOnlineOptions);
|
||||||
|
|
||||||
|
$context['show_buddies'] = !empty($user_info['buddies']);
|
||||||
|
|
||||||
|
// Are we showing all membergroups on the board index?
|
||||||
|
if (!empty($settings['show_group_key']))
|
||||||
|
$context['membergroups'] = cache_quick_get('membergroup_list', 'Subs-Membergroups.php', 'cache_getMembergroupList', array());
|
||||||
|
|
||||||
|
// Track most online statistics? (Subs-MembersOnline.php)
|
||||||
|
if (!empty($modSettings['trackStats']))
|
||||||
|
trackStatsUsersOnline($context['num_guests'] + $context['num_spiders'] + $context['num_users_online']);
|
||||||
|
|
||||||
|
// Retrieve the latest posts if the theme settings require it.
|
||||||
|
if (isset($settings['number_recent_posts']) && $settings['number_recent_posts'] > 1)
|
||||||
|
{
|
||||||
|
$latestPostOptions = array(
|
||||||
|
'number_posts' => $settings['number_recent_posts'],
|
||||||
|
);
|
||||||
|
$context['latest_posts'] = cache_quick_get('boardindex-latest_posts:' . md5($user_info['query_wanna_see_board'] . $user_info['language']), 'Subs-Recent.php', 'cache_getLastPosts', array($latestPostOptions));
|
||||||
|
}
|
||||||
|
|
||||||
|
$settings['display_recent_bar'] = !empty($settings['number_recent_posts']) ? $settings['number_recent_posts'] : 0;
|
||||||
|
$settings['show_member_bar'] &= allowedTo('view_mlist');
|
||||||
|
$context['show_stats'] = allowedTo('view_stats') && !empty($modSettings['trackStats']);
|
||||||
|
$context['show_member_list'] = allowedTo('view_mlist');
|
||||||
|
$context['show_who'] = allowedTo('who_view') && !empty($modSettings['who_enabled']);
|
||||||
|
|
||||||
|
// Load the calendar?
|
||||||
|
if (!empty($modSettings['cal_enabled']) && allowedTo('calendar_view'))
|
||||||
|
{
|
||||||
|
// Retrieve the calendar data (events, birthdays, holidays).
|
||||||
|
$eventOptions = array(
|
||||||
|
'include_holidays' => $modSettings['cal_showholidays'] > 1,
|
||||||
|
'include_birthdays' => $modSettings['cal_showbdays'] > 1,
|
||||||
|
'include_events' => $modSettings['cal_showevents'] > 1,
|
||||||
|
'num_days_shown' => empty($modSettings['cal_days_for_index']) || $modSettings['cal_days_for_index'] < 1 ? 1 : $modSettings['cal_days_for_index'],
|
||||||
|
);
|
||||||
|
$context += cache_quick_get('calendar_index_offset_' . ($user_info['time_offset'] + $modSettings['time_offset']), 'Subs-Calendar.php', 'cache_getRecentEvents', array($eventOptions));
|
||||||
|
|
||||||
|
// Whether one or multiple days are shown on the board index.
|
||||||
|
$context['calendar_only_today'] = $modSettings['cal_days_for_index'] == 1;
|
||||||
|
|
||||||
|
// This is used to show the "how-do-I-edit" help.
|
||||||
|
$context['calendar_can_edit'] = allowedTo('calendar_edit_any');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$context['show_calendar'] = false;
|
||||||
|
|
||||||
|
$context['page_title'] = sprintf($txt['forum_index'], $context['forum_name']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collapse or expand a category
|
||||||
|
function CollapseCategory()
|
||||||
|
{
|
||||||
|
global $user_info, $sourcedir, $context;
|
||||||
|
|
||||||
|
// Just in case, no need, no need.
|
||||||
|
$context['robot_no_index'] = true;
|
||||||
|
|
||||||
|
checkSession('request');
|
||||||
|
|
||||||
|
if (!isset($_GET['sa']))
|
||||||
|
fatal_lang_error('no_access', false);
|
||||||
|
|
||||||
|
// Check if the input values are correct.
|
||||||
|
if (in_array($_REQUEST['sa'], array('expand', 'collapse', 'toggle')) && isset($_REQUEST['c']))
|
||||||
|
{
|
||||||
|
// And collapse/expand/toggle the category.
|
||||||
|
require_once($sourcedir . '/Subs-Categories.php');
|
||||||
|
collapseCategories(array((int) $_REQUEST['c']), $_REQUEST['sa'], array($user_info['id']));
|
||||||
|
}
|
||||||
|
|
||||||
|
// And go back to the board index.
|
||||||
|
BoardIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
487
Sources/Calendar.php
Normal file
@ -0,0 +1,487 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple Machines Forum (SMF)
|
||||||
|
*
|
||||||
|
* @package SMF
|
||||||
|
* @author Simple Machines http://www.simplemachines.org
|
||||||
|
* @copyright 2011 Simple Machines
|
||||||
|
* @license http://www.simplemachines.org/about/smf/license.php BSD
|
||||||
|
*
|
||||||
|
* @version 2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Original module by Aaron O'Neil - aaron@mud-master.com
|
||||||
|
|
||||||
|
if (!defined('SMF'))
|
||||||
|
die('Hacking attempt...');
|
||||||
|
|
||||||
|
/* This file has only one real task... showing the calendar. Posting is done
|
||||||
|
in Post.php - this just has the following functions:
|
||||||
|
|
||||||
|
void CalendarMain()
|
||||||
|
- loads the specified month's events, holidays, and birthdays.
|
||||||
|
- requires the calendar_view permission.
|
||||||
|
- depends on the cal_enabled setting, and many of the other cal_
|
||||||
|
settings.
|
||||||
|
- uses the calendar_start_day theme option. (Monday/Sunday)
|
||||||
|
- uses the main sub template in the Calendar template.
|
||||||
|
- goes to the month and year passed in 'month' and 'year' by
|
||||||
|
get or post.
|
||||||
|
- accessed through ?action=calendar.
|
||||||
|
|
||||||
|
void CalendarPost()
|
||||||
|
- processes posting/editing/deleting a calendar event.
|
||||||
|
- calls Post() function if event is linked to a post.
|
||||||
|
- calls insertEvent() to insert the event if not linked to post.
|
||||||
|
- requires the calendar_post permission to use.
|
||||||
|
- uses the event_post sub template in the Calendar template.
|
||||||
|
- is accessed with ?action=calendar;sa=post.
|
||||||
|
|
||||||
|
void iCalDownload()
|
||||||
|
- offers up a download of an event in iCal 2.0 format.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Show the calendar.
|
||||||
|
function CalendarMain()
|
||||||
|
{
|
||||||
|
global $txt, $context, $modSettings, $scripturl, $options, $sourcedir;
|
||||||
|
|
||||||
|
// Permissions, permissions, permissions.
|
||||||
|
isAllowedTo('calendar_view');
|
||||||
|
|
||||||
|
// Doing something other than calendar viewing?
|
||||||
|
$subActions = array(
|
||||||
|
'ical' => 'iCalDownload',
|
||||||
|
'post' => 'CalendarPost',
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isset($_GET['sa']) && isset($subActions[$_GET['sa']]) && !WIRELESS)
|
||||||
|
return $subActions[$_GET['sa']]();
|
||||||
|
|
||||||
|
// This is gonna be needed...
|
||||||
|
loadTemplate('Calendar');
|
||||||
|
|
||||||
|
// You can't do anything if the calendar is off.
|
||||||
|
if (empty($modSettings['cal_enabled']))
|
||||||
|
fatal_lang_error('calendar_off', false);
|
||||||
|
|
||||||
|
// Set the page title to mention the calendar ;).
|
||||||
|
$context['page_title'] = $txt['calendar'];
|
||||||
|
|
||||||
|
// Is this a week view?
|
||||||
|
$context['view_week'] = isset($_GET['viewweek']);
|
||||||
|
|
||||||
|
// Don't let search engines index weekly calendar pages.
|
||||||
|
if ($context['view_week'])
|
||||||
|
$context['robot_no_index'] = true;
|
||||||
|
|
||||||
|
// Get the current day of month...
|
||||||
|
require_once($sourcedir . '/Subs-Calendar.php');
|
||||||
|
$today = getTodayInfo();
|
||||||
|
|
||||||
|
// If the month and year are not passed in, use today's date as a starting point.
|
||||||
|
$curPage = array(
|
||||||
|
'day' => isset($_REQUEST['day']) ? (int) $_REQUEST['day'] : $today['day'],
|
||||||
|
'month' => isset($_REQUEST['month']) ? (int) $_REQUEST['month'] : $today['month'],
|
||||||
|
'year' => isset($_REQUEST['year']) ? (int) $_REQUEST['year'] : $today['year']
|
||||||
|
);
|
||||||
|
|
||||||
|
// Make sure the year and month are in valid ranges.
|
||||||
|
if ($curPage['month'] < 1 || $curPage['month'] > 12)
|
||||||
|
fatal_lang_error('invalid_month', false);
|
||||||
|
if ($curPage['year'] < $modSettings['cal_minyear'] || $curPage['year'] > $modSettings['cal_maxyear'])
|
||||||
|
fatal_lang_error('invalid_year', false);
|
||||||
|
// If we have a day clean that too.
|
||||||
|
if ($context['view_week'])
|
||||||
|
{
|
||||||
|
// Note $isValid is -1 < PHP 5.1
|
||||||
|
$isValid = mktime(0, 0, 0, $curPage['month'], $curPage['day'], $curPage['year']);
|
||||||
|
if ($curPage['day'] > 31 || !$isValid || $isValid == -1)
|
||||||
|
fatal_lang_error('invalid_day', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load all the context information needed to show the calendar grid.
|
||||||
|
$calendarOptions = array(
|
||||||
|
'start_day' => !empty($options['calendar_start_day']) ? $options['calendar_start_day'] : 0,
|
||||||
|
'show_birthdays' => in_array($modSettings['cal_showbdays'], array(1, 2)),
|
||||||
|
'show_events' => in_array($modSettings['cal_showevents'], array(1, 2)),
|
||||||
|
'show_holidays' => in_array($modSettings['cal_showholidays'], array(1, 2)),
|
||||||
|
'show_week_num' => true,
|
||||||
|
'short_day_titles' => false,
|
||||||
|
'show_next_prev' => true,
|
||||||
|
'show_week_links' => true,
|
||||||
|
'size' => 'large',
|
||||||
|
);
|
||||||
|
|
||||||
|
// Load up the main view.
|
||||||
|
if ($context['view_week'])
|
||||||
|
$context['calendar_grid_main'] = getCalendarWeek($curPage['month'], $curPage['year'], $curPage['day'], $calendarOptions);
|
||||||
|
else
|
||||||
|
$context['calendar_grid_main'] = getCalendarGrid($curPage['month'], $curPage['year'], $calendarOptions);
|
||||||
|
|
||||||
|
// Load up the previous and next months.
|
||||||
|
$calendarOptions['show_birthdays'] = $calendarOptions['show_events'] = $calendarOptions['show_holidays'] = false;
|
||||||
|
$calendarOptions['short_day_titles'] = true;
|
||||||
|
$calendarOptions['show_next_prev'] = false;
|
||||||
|
$calendarOptions['show_week_links'] = false;
|
||||||
|
$calendarOptions['size'] = 'small';
|
||||||
|
$context['calendar_grid_current'] = getCalendarGrid($curPage['month'], $curPage['year'], $calendarOptions);
|
||||||
|
// Only show previous month if it isn't pre-January of the min-year
|
||||||
|
if ($context['calendar_grid_current']['previous_calendar']['year'] > $modSettings['cal_minyear'] || $curPage['month'] != 1)
|
||||||
|
$context['calendar_grid_prev'] = getCalendarGrid($context['calendar_grid_current']['previous_calendar']['month'], $context['calendar_grid_current']['previous_calendar']['year'], $calendarOptions);
|
||||||
|
// Only show next month if it isn't post-December of the max-year
|
||||||
|
if ($context['calendar_grid_current']['next_calendar']['year'] < $modSettings['cal_maxyear'] || $curPage['month'] != 12)
|
||||||
|
$context['calendar_grid_next'] = getCalendarGrid($context['calendar_grid_current']['next_calendar']['month'], $context['calendar_grid_current']['next_calendar']['year'], $calendarOptions);
|
||||||
|
|
||||||
|
// Basic template stuff.
|
||||||
|
$context['can_post'] = allowedTo('calendar_post');
|
||||||
|
$context['current_day'] = $curPage['day'];
|
||||||
|
$context['current_month'] = $curPage['month'];
|
||||||
|
$context['current_year'] = $curPage['year'];
|
||||||
|
$context['show_all_birthdays'] = isset($_GET['showbd']);
|
||||||
|
|
||||||
|
// Set the page title to mention the month or week, too
|
||||||
|
$context['page_title'] .= ' - ' . ($context['view_week'] ? sprintf($txt['calendar_week_title'], $context['calendar_grid_main']['week_number'], ($context['calendar_grid_main']['week_number'] == 53 ? $context['current_year'] - 1 : $context['current_year'])) : $txt['months'][$context['current_month']] . ' ' . $context['current_year']);
|
||||||
|
|
||||||
|
// Load up the linktree!
|
||||||
|
$context['linktree'][] = array(
|
||||||
|
'url' => $scripturl . '?action=calendar',
|
||||||
|
'name' => $txt['calendar']
|
||||||
|
);
|
||||||
|
// Add the current month to the linktree.
|
||||||
|
$context['linktree'][] = array(
|
||||||
|
'url' => $scripturl . '?action=calendar;year=' . $context['current_year'] . ';month=' . $context['current_month'],
|
||||||
|
'name' => $txt['months'][$context['current_month']] . ' ' . $context['current_year']
|
||||||
|
);
|
||||||
|
// If applicable, add the current week to the linktree.
|
||||||
|
if ($context['view_week'])
|
||||||
|
$context['linktree'][] = array(
|
||||||
|
'url' => $scripturl . '?action=calendar;viewweek;year=' . $context['current_year'] . ';month=' . $context['current_month'] . ';day=' . $context['current_day'],
|
||||||
|
'name' => $txt['calendar_week'] . ' ' . $context['calendar_grid_main']['week_number']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function CalendarPost()
|
||||||
|
{
|
||||||
|
global $context, $txt, $user_info, $sourcedir, $scripturl;
|
||||||
|
global $modSettings, $topic, $smcFunc;
|
||||||
|
|
||||||
|
// Well - can they?
|
||||||
|
isAllowedTo('calendar_post');
|
||||||
|
|
||||||
|
// We need this for all kinds of useful functions.
|
||||||
|
require_once($sourcedir . '/Subs-Calendar.php');
|
||||||
|
|
||||||
|
// Cast this for safety...
|
||||||
|
if (isset($_REQUEST['eventid']))
|
||||||
|
$_REQUEST['eventid'] = (int) $_REQUEST['eventid'];
|
||||||
|
|
||||||
|
// Submitting?
|
||||||
|
if (isset($_POST[$context['session_var']], $_REQUEST['eventid']))
|
||||||
|
{
|
||||||
|
checkSession();
|
||||||
|
|
||||||
|
// Validate the post...
|
||||||
|
if (!isset($_POST['link_to_board']))
|
||||||
|
validateEventPost();
|
||||||
|
|
||||||
|
// If you're not allowed to edit any events, you have to be the poster.
|
||||||
|
if ($_REQUEST['eventid'] > 0 && !allowedTo('calendar_edit_any'))
|
||||||
|
isAllowedTo('calendar_edit_' . (!empty($user_info['id']) && getEventPoster($_REQUEST['eventid']) == $user_info['id'] ? 'own' : 'any'));
|
||||||
|
|
||||||
|
// New - and directing?
|
||||||
|
if ($_REQUEST['eventid'] == -1 && isset($_POST['link_to_board']))
|
||||||
|
{
|
||||||
|
$_REQUEST['calendar'] = 1;
|
||||||
|
require_once($sourcedir . '/Post.php');
|
||||||
|
return Post();
|
||||||
|
}
|
||||||
|
// New...
|
||||||
|
elseif ($_REQUEST['eventid'] == -1)
|
||||||
|
{
|
||||||
|
$eventOptions = array(
|
||||||
|
'board' => 0,
|
||||||
|
'topic' => 0,
|
||||||
|
'title' => substr($_REQUEST['evtitle'], 0, 60),
|
||||||
|
'member' => $user_info['id'],
|
||||||
|
'start_date' => sprintf('%04d-%02d-%02d', $_POST['year'], $_POST['month'], $_POST['day']),
|
||||||
|
'span' => isset($_POST['span']) && $_POST['span'] > 0 ? min((int) $modSettings['cal_maxspan'], (int) $_POST['span'] - 1) : 0,
|
||||||
|
);
|
||||||
|
insertEvent($eventOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deleting...
|
||||||
|
elseif (isset($_REQUEST['deleteevent']))
|
||||||
|
removeEvent($_REQUEST['eventid']);
|
||||||
|
|
||||||
|
// ... or just update it?
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$eventOptions = array(
|
||||||
|
'title' => substr($_REQUEST['evtitle'], 0, 60),
|
||||||
|
'span' => empty($modSettings['cal_allowspan']) || empty($_POST['span']) || $_POST['span'] == 1 || empty($modSettings['cal_maxspan']) || $_POST['span'] > $modSettings['cal_maxspan'] ? 0 : min((int) $modSettings['cal_maxspan'], (int) $_POST['span'] - 1),
|
||||||
|
'start_date' => strftime('%Y-%m-%d', mktime(0, 0, 0, (int) $_REQUEST['month'], (int) $_REQUEST['day'], (int) $_REQUEST['year'])),
|
||||||
|
);
|
||||||
|
|
||||||
|
modifyEvent($_REQUEST['eventid'], $eventOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSettings(array(
|
||||||
|
'calendar_updated' => time(),
|
||||||
|
));
|
||||||
|
|
||||||
|
// No point hanging around here now...
|
||||||
|
redirectexit($scripturl . '?action=calendar;month=' . $_POST['month'] . ';year=' . $_POST['year']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we are not enabled... we are not enabled.
|
||||||
|
if (empty($modSettings['cal_allow_unlinked']) && empty($_REQUEST['eventid']))
|
||||||
|
{
|
||||||
|
$_REQUEST['calendar'] = 1;
|
||||||
|
require_once($sourcedir . '/Post.php');
|
||||||
|
return Post();
|
||||||
|
}
|
||||||
|
|
||||||
|
// New?
|
||||||
|
if (!isset($_REQUEST['eventid']))
|
||||||
|
{
|
||||||
|
$today = getdate();
|
||||||
|
|
||||||
|
$context['event'] = array(
|
||||||
|
'boards' => array(),
|
||||||
|
'board' => 0,
|
||||||
|
'new' => 1,
|
||||||
|
'eventid' => -1,
|
||||||
|
'year' => isset($_REQUEST['year']) ? $_REQUEST['year'] : $today['year'],
|
||||||
|
'month' => isset($_REQUEST['month']) ? $_REQUEST['month'] : $today['mon'],
|
||||||
|
'day' => isset($_REQUEST['day']) ? $_REQUEST['day'] : $today['mday'],
|
||||||
|
'title' => '',
|
||||||
|
'span' => 1,
|
||||||
|
);
|
||||||
|
$context['event']['last_day'] = (int) strftime('%d', mktime(0, 0, 0, $context['event']['month'] == 12 ? 1 : $context['event']['month'] + 1, 0, $context['event']['month'] == 12 ? $context['event']['year'] + 1 : $context['event']['year']));
|
||||||
|
|
||||||
|
// Get list of boards that can be posted in.
|
||||||
|
$boards = boardsAllowedTo('post_new');
|
||||||
|
if (empty($boards))
|
||||||
|
fatal_lang_error('cannot_post_new', 'permission');
|
||||||
|
|
||||||
|
// Load the list of boards and categories in the context.
|
||||||
|
require_once($sourcedir . '/Subs-MessageIndex.php');
|
||||||
|
$boardListOptions = array(
|
||||||
|
'included_boards' => in_array(0, $boards) ? null : $boards,
|
||||||
|
'not_redirection' => true,
|
||||||
|
'use_permissions' => true,
|
||||||
|
'selected_board' => $modSettings['cal_defaultboard'],
|
||||||
|
);
|
||||||
|
$context['event']['categories'] = getBoardList($boardListOptions);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$context['event'] = getEventProperties($_REQUEST['eventid']);
|
||||||
|
|
||||||
|
if ($context['event'] === false)
|
||||||
|
fatal_lang_error('no_access', false);
|
||||||
|
|
||||||
|
// If it has a board, then they should be editing it within the topic.
|
||||||
|
if (!empty($context['event']['topic']['id']) && !empty($context['event']['topic']['first_msg']))
|
||||||
|
{
|
||||||
|
// We load the board up, for a check on the board access rights...
|
||||||
|
$topic = $context['event']['topic']['id'];
|
||||||
|
loadBoard();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the user is allowed to edit this event.
|
||||||
|
if ($context['event']['member'] != $user_info['id'])
|
||||||
|
isAllowedTo('calendar_edit_any');
|
||||||
|
elseif (!allowedTo('calendar_edit_any'))
|
||||||
|
isAllowedTo('calendar_edit_own');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Template, sub template, etc.
|
||||||
|
loadTemplate('Calendar');
|
||||||
|
$context['sub_template'] = 'event_post';
|
||||||
|
|
||||||
|
$context['page_title'] = isset($_REQUEST['eventid']) ? $txt['calendar_edit'] : $txt['calendar_post_event'];
|
||||||
|
$context['linktree'][] = array(
|
||||||
|
'name' => $context['page_title'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function iCalDownload()
|
||||||
|
{
|
||||||
|
global $smcFunc, $sourcedir, $forum_version, $context, $modSettings;
|
||||||
|
|
||||||
|
// Goes without saying that this is required.
|
||||||
|
if (!isset($_REQUEST['eventid']))
|
||||||
|
fatal_lang_error('no_access', false);
|
||||||
|
|
||||||
|
// This is kinda wanted.
|
||||||
|
require_once($sourcedir . '/Subs-Calendar.php');
|
||||||
|
|
||||||
|
// Load up the event in question and check it exists.
|
||||||
|
$event = getEventProperties($_REQUEST['eventid']);
|
||||||
|
|
||||||
|
if ($event === false)
|
||||||
|
fatal_lang_error('no_access', false);
|
||||||
|
|
||||||
|
// Check the title isn't too long - iCal requires some formatting if so.
|
||||||
|
$title = str_split($event['title'], 30);
|
||||||
|
foreach ($title as $id => $line)
|
||||||
|
{
|
||||||
|
if ($id != 0)
|
||||||
|
$title[$id] = ' ' . $title[$id];
|
||||||
|
$title[$id] .= "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format the date.
|
||||||
|
$date = $event['year'] . '-' . ($event['month'] < 10 ? '0' . $event['month'] : $event['month']) . '-' . ($event['day'] < 10 ? '0' . $event['day'] : $event['day']) . 'T';
|
||||||
|
$date .= '1200:00:00Z';
|
||||||
|
|
||||||
|
// This is what we will be sending later.
|
||||||
|
$filecontents = '';
|
||||||
|
$filecontents .= 'BEGIN:VCALENDAR' . "\n";
|
||||||
|
$filecontents .= 'VERSION:2.0' . "\n";
|
||||||
|
$filecontents .= 'PRODID:-//SimpleMachines//SMF ' . (empty($forum_version) ? 1.0 : strtr($forum_version, array('SMF ' => ''))) . '//EN' . "\n";
|
||||||
|
$filecontents .= 'BEGIN:VEVENT' . "\n";
|
||||||
|
$filecontents .= 'DTSTART:' . $date . "\n";
|
||||||
|
$filecontents .= 'DTEND:' . $date . "\n";
|
||||||
|
$filecontents .= 'SUMMARY:' . implode('', $title);
|
||||||
|
$filecontents .= 'END:VEVENT' . "\n";
|
||||||
|
$filecontents .= 'END:VCALENDAR';
|
||||||
|
|
||||||
|
// Send some standard headers.
|
||||||
|
ob_end_clean();
|
||||||
|
if (!empty($modSettings['enableCompressedOutput']))
|
||||||
|
@ob_start('ob_gzhandler');
|
||||||
|
else
|
||||||
|
ob_start();
|
||||||
|
|
||||||
|
// Send the file headers
|
||||||
|
header('Pragma: ');
|
||||||
|
header('Cache-Control: no-cache');
|
||||||
|
if (!$context['browser']['is_gecko'])
|
||||||
|
header('Content-Transfer-Encoding: binary');
|
||||||
|
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 525600 * 60) . ' GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', time()) . 'GMT');
|
||||||
|
header('Accept-Ranges: bytes');
|
||||||
|
header('Connection: close');
|
||||||
|
header('Content-Disposition: attachment; filename=' . $event['title'] . '.ics');
|
||||||
|
|
||||||
|
// How big is it?
|
||||||
|
if (empty($modSettings['enableCompressedOutput']))
|
||||||
|
header('Content-Length: ' . $smcFunc['strlen']($filecontents));
|
||||||
|
|
||||||
|
// This is a calendar item!
|
||||||
|
header('Content-Type: text/calendar');
|
||||||
|
|
||||||
|
// Chuck out the card.
|
||||||
|
echo $filecontents;
|
||||||
|
|
||||||
|
// Off we pop - lovely!
|
||||||
|
obExit(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is not the code you are looking for.
|
||||||
|
function clock()
|
||||||
|
{
|
||||||
|
global $settings, $context;
|
||||||
|
$context['onimg'] = $settings['images_url'] . '/bbc/bbc_bg.gif';
|
||||||
|
$context['offimg'] = $settings['images_url'] . '/bbc/bbc_hoverbg.gif';
|
||||||
|
|
||||||
|
$context['page_title'] = 'Anyone know what time it is?';
|
||||||
|
$context['robot_no_index'] = true;
|
||||||
|
|
||||||
|
$omfg = isset($_REQUEST['omfg']);
|
||||||
|
$bcd = !isset($_REQUEST['rb']) && !isset($_REQUEST['omfg']) && !isset($_REQUEST['time']);
|
||||||
|
|
||||||
|
loadTemplate('Calendar');
|
||||||
|
|
||||||
|
if ($bcd && !$omfg)
|
||||||
|
{
|
||||||
|
$context['sub_template'] = 'bcd';
|
||||||
|
$context['clockicons'] = unserialize(base64_decode('YTo2OntzOjI6ImgxIjthOjI6e2k6MDtpOjI7aToxO2k6MTt9czoyOiJoMiI7YTo0OntpOjA7aTo4O2k6MTtpOjQ7aToyO2k6MjtpOjM7aToxO31zOjI6Im0xIjthOjM6e2k6MDtpOjQ7aToxO2k6MjtpOjI7aToxO31zOjI6Im0yIjthOjQ6e2k6MDtpOjg7aToxO2k6NDtpOjI7aToyO2k6MztpOjE7fXM6MjoiczEiO2E6Mzp7aTowO2k6NDtpOjE7aToyO2k6MjtpOjE7fXM6MjoiczIiO2E6NDp7aTowO2k6ODtpOjE7aTo0O2k6MjtpOjI7aTozO2k6MTt9fQ=='));
|
||||||
|
}
|
||||||
|
elseif (!$omfg && !isset($_REQUEST['time']))
|
||||||
|
{
|
||||||
|
$context['sub_template'] = 'hms';
|
||||||
|
$context['clockicons'] = unserialize(base64_decode('YTozOntzOjE6ImgiO2E6NTp7aTowO2k6MTY7aToxO2k6ODtpOjI7aTo0O2k6MztpOjI7aTo0O2k6MTt9czoxOiJtIjthOjY6e2k6MDtpOjMyO2k6MTtpOjE2O2k6MjtpOjg7aTozO2k6NDtpOjQ7aToyO2k6NTtpOjE7fXM6MToicyI7YTo2OntpOjA7aTozMjtpOjE7aToxNjtpOjI7aTo4O2k6MztpOjQ7aTo0O2k6MjtpOjU7aToxO319'));
|
||||||
|
}
|
||||||
|
elseif ($omfg)
|
||||||
|
{
|
||||||
|
$context['sub_template'] = 'omfg';
|
||||||
|
$context['clockicons'] = unserialize(base64_decode('YTo2OntzOjQ6InllYXIiO2E6Nzp7aTowO2k6NjQ7aToxO2k6MzI7aToyO2k6MTY7aTozO2k6ODtpOjQ7aTo0O2k6NTtpOjI7aTo2O2k6MTt9czo1OiJtb250aCI7YTo0OntpOjA7aTo4O2k6MTtpOjQ7aToyO2k6MjtpOjM7aToxO31zOjM6ImRheSI7YTo1OntpOjA7aToxNjtpOjE7aTo4O2k6MjtpOjQ7aTozO2k6MjtpOjQ7aToxO31zOjQ6ImhvdXIiO2E6NTp7aTowO2k6MTY7aToxO2k6ODtpOjI7aTo0O2k6MztpOjI7aTo0O2k6MTt9czozOiJtaW4iO2E6Njp7aTowO2k6MzI7aToxO2k6MTY7aToyO2k6ODtpOjM7aTo0O2k6NDtpOjI7aTo1O2k6MTt9czozOiJzZWMiO2E6Njp7aTowO2k6MzI7aToxO2k6MTY7aToyO2k6ODtpOjM7aTo0O2k6NDtpOjI7aTo1O2k6MTt9fQ=='));
|
||||||
|
}
|
||||||
|
elseif (isset($_REQUEST['time']))
|
||||||
|
{
|
||||||
|
$context['sub_template'] = 'thetime';
|
||||||
|
$time = getdate($_REQUEST['time'] == 'now' ? time() : (int) $_REQUEST['time']);
|
||||||
|
|
||||||
|
$context['clockicons'] = array(
|
||||||
|
'year' => array(
|
||||||
|
64 => false,
|
||||||
|
32 => false,
|
||||||
|
16 => false,
|
||||||
|
8 => false,
|
||||||
|
4 => false,
|
||||||
|
2 => false,
|
||||||
|
1 => false
|
||||||
|
),
|
||||||
|
'month' => array(
|
||||||
|
8 => false,
|
||||||
|
4 => false,
|
||||||
|
2 => false,
|
||||||
|
1 => false
|
||||||
|
),
|
||||||
|
'day' => array(
|
||||||
|
16 => false,
|
||||||
|
4 => false,
|
||||||
|
8 => false,
|
||||||
|
2 => false,
|
||||||
|
1 => false
|
||||||
|
),
|
||||||
|
'hour' => array(
|
||||||
|
32 => false,
|
||||||
|
16 => false,
|
||||||
|
8 => false,
|
||||||
|
4 => false,
|
||||||
|
2 => false,
|
||||||
|
1 => false
|
||||||
|
),
|
||||||
|
'min' => array(
|
||||||
|
32 => false,
|
||||||
|
16 => false,
|
||||||
|
8 => false,
|
||||||
|
4 => false,
|
||||||
|
2 => false,
|
||||||
|
1 => false
|
||||||
|
),
|
||||||
|
'sec' => array(
|
||||||
|
32 => false,
|
||||||
|
16 => false,
|
||||||
|
8 => false,
|
||||||
|
4 => false,
|
||||||
|
2 => false,
|
||||||
|
1 => false
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$year = $time['year'] % 100;
|
||||||
|
$month = $time['mon'];
|
||||||
|
$day = $time['mday'];
|
||||||
|
$hour = $time['hours'];
|
||||||
|
$min = $time['minutes'];
|
||||||
|
$sec = $time['seconds'];
|
||||||
|
|
||||||
|
foreach ($context['clockicons'] as $t => $vs)
|
||||||
|
foreach ($vs as $v => $dumb)
|
||||||
|
{
|
||||||
|
if ($$t >= $v)
|
||||||
|
{
|
||||||
|
$$t -= $v;
|
||||||
|
$context['clockicons'][$t][$v] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
715
Sources/Class-Graphics.php
Normal file
@ -0,0 +1,715 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple Machines Forum (SMF)
|
||||||
|
*
|
||||||
|
* @package SMF
|
||||||
|
* @author Simple Machines http://www.simplemachines.org
|
||||||
|
* @copyright 2011 Simple Machines
|
||||||
|
* @license http://www.simplemachines.org/about/smf/license.php BSD
|
||||||
|
*
|
||||||
|
* @version 2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Gif Util copyright 2003 by Yamasoft (S/C). All rights reserved.
|
||||||
|
Do not remove this portion of the header, or use these functions except
|
||||||
|
from the original author. To get it, please navigate to:
|
||||||
|
http://www.yamasoft.com/php-gif.zip
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('SMF'))
|
||||||
|
die('Hacking attempt...');
|
||||||
|
|
||||||
|
/* Classes used for reading gif files (in case PHP's GD doesn't provide the
|
||||||
|
proper gif-functions).
|
||||||
|
*/
|
||||||
|
|
||||||
|
class gif_lzw_compression
|
||||||
|
{
|
||||||
|
public $MAX_LZW_BITS;
|
||||||
|
public $Fresh, $CodeSize, $SetCodeSize, $MaxCode, $MaxCodeSize, $FirstCode, $OldCode;
|
||||||
|
public $ClearCode, $EndCode, $Next, $Vals, $Stack, $sp, $Buf, $CurBit, $LastBit, $Done, $LastByte;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->MAX_LZW_BITS = 12;
|
||||||
|
unset($this->Next, $this->Vals, $this->Stack, $this->Buf);
|
||||||
|
|
||||||
|
$this->Next = range(0, (1 << $this->MAX_LZW_BITS) - 1);
|
||||||
|
$this->Vals = range(0, (1 << $this->MAX_LZW_BITS) - 1);
|
||||||
|
$this->Stack = range(0, (1 << ($this->MAX_LZW_BITS + 1)) - 1);
|
||||||
|
$this->Buf = range(0, 279);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function decompress($data, &$datLen)
|
||||||
|
{
|
||||||
|
$stLen = strlen($data);
|
||||||
|
$datLen = 0;
|
||||||
|
$ret = '';
|
||||||
|
|
||||||
|
$this->LZWCommand($data, true);
|
||||||
|
|
||||||
|
while (($iIndex = $this->LZWCommand($data, false)) >= 0)
|
||||||
|
$ret .= chr($iIndex);
|
||||||
|
|
||||||
|
$datLen = $stLen - strlen($data);
|
||||||
|
|
||||||
|
if ($iIndex != -2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function LZWCommand(&$data, $bInit)
|
||||||
|
{
|
||||||
|
if ($bInit)
|
||||||
|
{
|
||||||
|
$this->SetCodeSize = ord($data[0]);
|
||||||
|
$data = substr($data, 1);
|
||||||
|
|
||||||
|
$this->CodeSize = $this->SetCodeSize + 1;
|
||||||
|
$this->ClearCode = 1 << $this->SetCodeSize;
|
||||||
|
$this->EndCode = $this->ClearCode + 1;
|
||||||
|
$this->MaxCode = $this->ClearCode + 2;
|
||||||
|
$this->MaxCodeSize = $this->ClearCode << 1;
|
||||||
|
|
||||||
|
$this->GetCode($data, $bInit);
|
||||||
|
|
||||||
|
$this->Fresh = 1;
|
||||||
|
for ($i = 0; $i < $this->ClearCode; $i++)
|
||||||
|
{
|
||||||
|
$this->Next[$i] = 0;
|
||||||
|
$this->Vals[$i] = $i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; $i < (1 << $this->MAX_LZW_BITS); $i++)
|
||||||
|
{
|
||||||
|
$this->Next[$i] = 0;
|
||||||
|
$this->Vals[$i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->sp = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->Fresh)
|
||||||
|
{
|
||||||
|
$this->Fresh = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
$this->FirstCode = $this->GetCode($data, $bInit);
|
||||||
|
$this->OldCode = $this->FirstCode;
|
||||||
|
}
|
||||||
|
while ($this->FirstCode == $this->ClearCode);
|
||||||
|
|
||||||
|
return $this->FirstCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->sp > 0)
|
||||||
|
{
|
||||||
|
$this->sp--;
|
||||||
|
return $this->Stack[$this->sp];
|
||||||
|
}
|
||||||
|
|
||||||
|
while (($Code = $this->GetCode($data, $bInit)) >= 0)
|
||||||
|
{
|
||||||
|
if ($Code == $this->ClearCode)
|
||||||
|
{
|
||||||
|
for ($i = 0; $i < $this->ClearCode; $i++)
|
||||||
|
{
|
||||||
|
$this->Next[$i] = 0;
|
||||||
|
$this->Vals[$i] = $i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; $i < (1 << $this->MAX_LZW_BITS); $i++)
|
||||||
|
{
|
||||||
|
$this->Next[$i] = 0;
|
||||||
|
$this->Vals[$i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->CodeSize = $this->SetCodeSize + 1;
|
||||||
|
$this->MaxCodeSize = $this->ClearCode << 1;
|
||||||
|
$this->MaxCode = $this->ClearCode + 2;
|
||||||
|
$this->sp = 0;
|
||||||
|
$this->FirstCode = $this->GetCode($data, $bInit);
|
||||||
|
$this->OldCode = $this->FirstCode;
|
||||||
|
|
||||||
|
return $this->FirstCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Code == $this->EndCode)
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
$InCode = $Code;
|
||||||
|
if ($Code >= $this->MaxCode)
|
||||||
|
{
|
||||||
|
$this->Stack[$this->sp] = $this->FirstCode;
|
||||||
|
$this->sp++;
|
||||||
|
$Code = $this->OldCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ($Code >= $this->ClearCode)
|
||||||
|
{
|
||||||
|
$this->Stack[$this->sp] = $this->Vals[$Code];
|
||||||
|
$this->sp++;
|
||||||
|
|
||||||
|
if ($Code == $this->Next[$Code]) // Circular table entry, big GIF Error!
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
$Code = $this->Next[$Code];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->FirstCode = $this->Vals[$Code];
|
||||||
|
$this->Stack[$this->sp] = $this->FirstCode;
|
||||||
|
$this->sp++;
|
||||||
|
|
||||||
|
if (($Code = $this->MaxCode) < (1 << $this->MAX_LZW_BITS))
|
||||||
|
{
|
||||||
|
$this->Next[$Code] = $this->OldCode;
|
||||||
|
$this->Vals[$Code] = $this->FirstCode;
|
||||||
|
$this->MaxCode++;
|
||||||
|
|
||||||
|
if (($this->MaxCode >= $this->MaxCodeSize) && ($this->MaxCodeSize < (1 << $this->MAX_LZW_BITS)))
|
||||||
|
{
|
||||||
|
$this->MaxCodeSize *= 2;
|
||||||
|
$this->CodeSize++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->OldCode = $InCode;
|
||||||
|
if ($this->sp > 0)
|
||||||
|
{
|
||||||
|
$this->sp--;
|
||||||
|
return $this->Stack[$this->sp];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $Code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function GetCode(&$data, $bInit)
|
||||||
|
{
|
||||||
|
if ($bInit)
|
||||||
|
{
|
||||||
|
$this->CurBit = 0;
|
||||||
|
$this->LastBit = 0;
|
||||||
|
$this->Done = 0;
|
||||||
|
$this->LastByte = 2;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($this->CurBit + $this->CodeSize) >= $this->LastBit)
|
||||||
|
{
|
||||||
|
if ($this->Done)
|
||||||
|
{
|
||||||
|
// Ran off the end of my bits...
|
||||||
|
if ($this->CurBit >= $this->LastBit)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->Buf[0] = $this->Buf[$this->LastByte - 2];
|
||||||
|
$this->Buf[1] = $this->Buf[$this->LastByte - 1];
|
||||||
|
|
||||||
|
$count = ord($data[0]);
|
||||||
|
$data = substr($data, 1);
|
||||||
|
|
||||||
|
if ($count)
|
||||||
|
{
|
||||||
|
for ($i = 0; $i < $count; $i++)
|
||||||
|
$this->Buf[2 + $i] = ord($data{$i});
|
||||||
|
|
||||||
|
$data = substr($data, $count);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$this->Done = 1;
|
||||||
|
|
||||||
|
$this->LastByte = 2 + $count;
|
||||||
|
$this->CurBit = ($this->CurBit - $this->LastBit) + 16;
|
||||||
|
$this->LastBit = (2 + $count) << 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
$iRet = 0;
|
||||||
|
for ($i = $this->CurBit, $j = 0; $j < $this->CodeSize; $i++, $j++)
|
||||||
|
$iRet |= (($this->Buf[intval($i / 8)] & (1 << ($i % 8))) != 0) << $j;
|
||||||
|
|
||||||
|
$this->CurBit += $this->CodeSize;
|
||||||
|
return $iRet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class gif_color_table
|
||||||
|
{
|
||||||
|
public $m_nColors;
|
||||||
|
public $m_arColors;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
unset($this->m_nColors, $this->m_arColors);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function load($lpData, $num)
|
||||||
|
{
|
||||||
|
$this->m_nColors = 0;
|
||||||
|
$this->m_arColors = array();
|
||||||
|
|
||||||
|
for ($i = 0; $i < $num; $i++)
|
||||||
|
{
|
||||||
|
$rgb = substr($lpData, $i * 3, 3);
|
||||||
|
if (strlen($rgb) < 3)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
$this->m_arColors[] = (ord($rgb[2]) << 16) + (ord($rgb[1]) << 8) + ord($rgb[0]);
|
||||||
|
$this->m_nColors++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toString()
|
||||||
|
{
|
||||||
|
$ret = '';
|
||||||
|
|
||||||
|
for ($i = 0; $i < $this->m_nColors; $i++)
|
||||||
|
{
|
||||||
|
$ret .=
|
||||||
|
chr(($this->m_arColors[$i] & 0x000000FF)) . // R
|
||||||
|
chr(($this->m_arColors[$i] & 0x0000FF00) >> 8) . // G
|
||||||
|
chr(($this->m_arColors[$i] & 0x00FF0000) >> 16); // B
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function colorIndex($rgb)
|
||||||
|
{
|
||||||
|
$rgb = intval($rgb) & 0xFFFFFF;
|
||||||
|
$r1 = ($rgb & 0x0000FF);
|
||||||
|
$g1 = ($rgb & 0x00FF00) >> 8;
|
||||||
|
$b1 = ($rgb & 0xFF0000) >> 16;
|
||||||
|
$idx = -1;
|
||||||
|
|
||||||
|
for ($i = 0; $i < $this->m_nColors; $i++)
|
||||||
|
{
|
||||||
|
$r2 = ($this->m_arColors[$i] & 0x000000FF);
|
||||||
|
$g2 = ($this->m_arColors[$i] & 0x0000FF00) >> 8;
|
||||||
|
$b2 = ($this->m_arColors[$i] & 0x00FF0000) >> 16;
|
||||||
|
$d = abs($r2 - $r1) + abs($g2 - $g1) + abs($b2 - $b1);
|
||||||
|
|
||||||
|
if (($idx == -1) || ($d < $dif))
|
||||||
|
{
|
||||||
|
$idx = $i;
|
||||||
|
$dif = $d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class gif_file_header
|
||||||
|
{
|
||||||
|
public $m_lpVer, $m_nWidth, $m_nHeight, $m_bGlobalClr, $m_nColorRes;
|
||||||
|
public $m_bSorted, $m_nTableSize, $m_nBgColor, $m_nPixelRatio;
|
||||||
|
public $m_colorTable;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
unset($this->m_lpVer, $this->m_nWidth, $this->m_nHeight, $this->m_bGlobalClr, $this->m_nColorRes);
|
||||||
|
unset($this->m_bSorted, $this->m_nTableSize, $this->m_nBgColor, $this->m_nPixelRatio, $this->m_colorTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function load($lpData, &$hdrLen)
|
||||||
|
{
|
||||||
|
$hdrLen = 0;
|
||||||
|
|
||||||
|
$this->m_lpVer = substr($lpData, 0, 6);
|
||||||
|
if (($this->m_lpVer != 'GIF87a') && ($this->m_lpVer != 'GIF89a'))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
list ($this->m_nWidth, $this->m_nHeight) = array_values(unpack('v2', substr($lpData, 6, 4)));
|
||||||
|
|
||||||
|
if (!$this->m_nWidth || !$this->m_nHeight)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
$b = ord(substr($lpData, 10, 1));
|
||||||
|
$this->m_bGlobalClr = ($b & 0x80) ? true : false;
|
||||||
|
$this->m_nColorRes = ($b & 0x70) >> 4;
|
||||||
|
$this->m_bSorted = ($b & 0x08) ? true : false;
|
||||||
|
$this->m_nTableSize = 2 << ($b & 0x07);
|
||||||
|
$this->m_nBgColor = ord(substr($lpData, 11, 1));
|
||||||
|
$this->m_nPixelRatio = ord(substr($lpData, 12, 1));
|
||||||
|
$hdrLen = 13;
|
||||||
|
|
||||||
|
if ($this->m_bGlobalClr)
|
||||||
|
{
|
||||||
|
$this->m_colorTable = new gif_color_table();
|
||||||
|
if (!$this->m_colorTable->load(substr($lpData, $hdrLen), $this->m_nTableSize))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
$hdrLen += 3 * $this->m_nTableSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class gif_image_header
|
||||||
|
{
|
||||||
|
public $m_nLeft, $m_nTop, $m_nWidth, $m_nHeight, $m_bLocalClr;
|
||||||
|
public $m_bInterlace, $m_bSorted, $m_nTableSize, $m_colorTable;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
unset($this->m_nLeft, $this->m_nTop, $this->m_nWidth, $this->m_nHeight, $this->m_bLocalClr);
|
||||||
|
unset($this->m_bInterlace, $this->m_bSorted, $this->m_nTableSize, $this->m_colorTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function load($lpData, &$hdrLen)
|
||||||
|
{
|
||||||
|
$hdrLen = 0;
|
||||||
|
|
||||||
|
// Get the width/height/etc. from the header.
|
||||||
|
list ($this->m_nLeft, $this->m_nTop, $this->m_nWidth, $this->m_nHeight) = array_values(unpack('v4', substr($lpData, 0, 8)));
|
||||||
|
|
||||||
|
if (!$this->m_nWidth || !$this->m_nHeight)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
$b = ord($lpData[8]);
|
||||||
|
$this->m_bLocalClr = ($b & 0x80) ? true : false;
|
||||||
|
$this->m_bInterlace = ($b & 0x40) ? true : false;
|
||||||
|
$this->m_bSorted = ($b & 0x20) ? true : false;
|
||||||
|
$this->m_nTableSize = 2 << ($b & 0x07);
|
||||||
|
$hdrLen = 9;
|
||||||
|
|
||||||
|
if ($this->m_bLocalClr)
|
||||||
|
{
|
||||||
|
$this->m_colorTable = new gif_color_table();
|
||||||
|
if (!$this->m_colorTable->load(substr($lpData, $hdrLen), $this->m_nTableSize))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
$hdrLen += 3 * $this->m_nTableSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class gif_image
|
||||||
|
{
|
||||||
|
public $m_disp, $m_bUser, $m_bTrans, $m_nDelay, $m_nTrans, $m_lpComm;
|
||||||
|
public $m_gih, $m_data, $m_lzw;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
unset($this->m_disp, $this->m_bUser, $this->m_nDelay, $this->m_nTrans, $this->m_lpComm, $this->m_data);
|
||||||
|
$this->m_gih = new gif_image_header();
|
||||||
|
$this->m_lzw = new gif_lzw_compression();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function load($data, &$datLen)
|
||||||
|
{
|
||||||
|
$datLen = 0;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
$b = ord($data[0]);
|
||||||
|
$data = substr($data, 1);
|
||||||
|
$datLen++;
|
||||||
|
|
||||||
|
switch ($b)
|
||||||
|
{
|
||||||
|
// Extension...
|
||||||
|
case 0x21:
|
||||||
|
$len = 0;
|
||||||
|
if (!$this->skipExt($data, $len))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
$datLen += $len;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Image...
|
||||||
|
case 0x2C:
|
||||||
|
// Load the header and color table.
|
||||||
|
$len = 0;
|
||||||
|
if (!$this->m_gih->load($data, $len))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
$data = substr($data, $len);
|
||||||
|
$datLen += $len;
|
||||||
|
|
||||||
|
// Decompress the data, and ride on home ;).
|
||||||
|
$len = 0;
|
||||||
|
if (!($this->m_data = $this->m_lzw->decompress($data, $len)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
$data = substr($data, $len);
|
||||||
|
$datLen += $len;
|
||||||
|
|
||||||
|
if ($this->m_gih->m_bInterlace)
|
||||||
|
$this->deInterlace();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case 0x3B: // EOF
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function skipExt(&$data, &$extLen)
|
||||||
|
{
|
||||||
|
$extLen = 0;
|
||||||
|
|
||||||
|
$b = ord($data[0]);
|
||||||
|
$data = substr($data, 1);
|
||||||
|
$extLen++;
|
||||||
|
|
||||||
|
switch ($b)
|
||||||
|
{
|
||||||
|
// Graphic Control...
|
||||||
|
case 0xF9:
|
||||||
|
$b = ord($data[1]);
|
||||||
|
$this->m_disp = ($b & 0x1C) >> 2;
|
||||||
|
$this->m_bUser = ($b & 0x02) ? true : false;
|
||||||
|
$this->m_bTrans = ($b & 0x01) ? true : false;
|
||||||
|
list ($this->m_nDelay) = array_values(unpack('v', substr($data, 2, 2)));
|
||||||
|
$this->m_nTrans = ord($data[4]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Comment...
|
||||||
|
case 0xFE:
|
||||||
|
$this->m_lpComm = substr($data, 1, ord($data[0]));
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Plain text...
|
||||||
|
case 0x01:
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Application...
|
||||||
|
case 0xFF:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip default as defs may change.
|
||||||
|
$b = ord($data[0]);
|
||||||
|
$data = substr($data, 1);
|
||||||
|
$extLen++;
|
||||||
|
while ($b > 0)
|
||||||
|
{
|
||||||
|
$data = substr($data, $b);
|
||||||
|
$extLen += $b;
|
||||||
|
$b = ord($data[0]);
|
||||||
|
$data = substr($data, 1);
|
||||||
|
$extLen++;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function deInterlace()
|
||||||
|
{
|
||||||
|
$data = $this->m_data;
|
||||||
|
|
||||||
|
for ($i = 0; $i < 4; $i++)
|
||||||
|
{
|
||||||
|
switch ($i)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
$s = 8;
|
||||||
|
$y = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
$s = 8;
|
||||||
|
$y = 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
$s = 4;
|
||||||
|
$y = 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
$s = 2;
|
||||||
|
$y = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; $y < $this->m_gih->m_nHeight; $y += $s)
|
||||||
|
{
|
||||||
|
$lne = substr($this->m_data, 0, $this->m_gih->m_nWidth);
|
||||||
|
$this->m_data = substr($this->m_data, $this->m_gih->m_nWidth);
|
||||||
|
|
||||||
|
$data =
|
||||||
|
substr($data, 0, $y * $this->m_gih->m_nWidth) .
|
||||||
|
$lne .
|
||||||
|
substr($data, ($y + 1) * $this->m_gih->m_nWidth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->m_data = $data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class gif_file
|
||||||
|
{
|
||||||
|
public $header, $image, $data, $loaded;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->data = '';
|
||||||
|
$this->loaded = false;
|
||||||
|
$this->header = new gif_file_header();
|
||||||
|
$this->image = new gif_image();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadFile($filename, $iIndex)
|
||||||
|
{
|
||||||
|
if ($iIndex < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
$this->data = @file_get_contents($filename);
|
||||||
|
if ($this->data === false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Tell the header to load up....
|
||||||
|
$len = 0;
|
||||||
|
if (!$this->header->load($this->data, $len))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
$this->data = substr($this->data, $len);
|
||||||
|
|
||||||
|
// Keep reading (at least once) so we get to the actual image we're looking for.
|
||||||
|
for ($j = 0; $j <= $iIndex; $j++)
|
||||||
|
{
|
||||||
|
$imgLen = 0;
|
||||||
|
if (!$this->image->load($this->data, $imgLen))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
$this->data = substr($this->data, $imgLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->loaded = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_png_data($background_color)
|
||||||
|
{
|
||||||
|
if (!$this->loaded)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Prepare the color table.
|
||||||
|
if ($this->image->m_gih->m_bLocalClr)
|
||||||
|
{
|
||||||
|
$colors = $this->image->m_gih->m_nTableSize;
|
||||||
|
$pal = $this->image->m_gih->m_colorTable->toString();
|
||||||
|
|
||||||
|
if ($background_color != -1)
|
||||||
|
$background_color = $this->image->m_gih->m_colorTable->colorIndex($background_color);
|
||||||
|
}
|
||||||
|
elseif ($this->header->m_bGlobalClr)
|
||||||
|
{
|
||||||
|
$colors = $this->header->m_nTableSize;
|
||||||
|
$pal = $this->header->m_colorTable->toString();
|
||||||
|
|
||||||
|
if ($background_color != -1)
|
||||||
|
$background_color = $this->header->m_colorTable->colorIndex($background_color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$colors = 0;
|
||||||
|
$background_color = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($background_color == -1)
|
||||||
|
$background_color = $this->header->m_nBgColor;
|
||||||
|
|
||||||
|
$data = &$this->image->m_data;
|
||||||
|
$header = &$this->image->m_gih;
|
||||||
|
|
||||||
|
$i = 0;
|
||||||
|
$bmp = '';
|
||||||
|
|
||||||
|
// Prepare the bitmap itself.
|
||||||
|
for ($y = 0; $y < $this->header->m_nHeight; $y++)
|
||||||
|
{
|
||||||
|
$bmp .= "\x00";
|
||||||
|
|
||||||
|
for ($x = 0; $x < $this->header->m_nWidth; $x++, $i++)
|
||||||
|
{
|
||||||
|
// Is this in the proper range? If so, get the specific pixel data...
|
||||||
|
if ($x >= $header->m_nLeft && $y >= $header->m_nTop && $x < ($header->m_nLeft + $header->m_nWidth) && $y < ($header->m_nTop + $header->m_nHeight))
|
||||||
|
$bmp .= $data{$i};
|
||||||
|
// Otherwise, this is background...
|
||||||
|
else
|
||||||
|
$bmp .= chr($background_color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$bmp = gzcompress($bmp, 9);
|
||||||
|
|
||||||
|
// Output the basic signature first of all.
|
||||||
|
$out = "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A";
|
||||||
|
|
||||||
|
// Now, we want the header...
|
||||||
|
$out .= "\x00\x00\x00\x0D";
|
||||||
|
$tmp = 'IHDR' . pack('N', (int) $this->header->m_nWidth) . pack('N', (int) $this->header->m_nHeight) . "\x08\x03\x00\x00\x00";
|
||||||
|
$out .= $tmp . pack('N', smf_crc32($tmp));
|
||||||
|
|
||||||
|
// The palette, assuming we have one to speak of...
|
||||||
|
if ($colors > 0)
|
||||||
|
{
|
||||||
|
$out .= pack('N', (int) $colors * 3);
|
||||||
|
$tmp = 'PLTE' . $pal;
|
||||||
|
$out .= $tmp . pack('N', smf_crc32($tmp));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do we have any transparency we want to make available?
|
||||||
|
if ($this->image->m_bTrans && $colors > 0)
|
||||||
|
{
|
||||||
|
$out .= pack('N', (int) $colors);
|
||||||
|
$tmp = 'tRNS';
|
||||||
|
|
||||||
|
// Stick each color on - full transparency or none.
|
||||||
|
for ($i = 0; $i < $colors; $i++)
|
||||||
|
$tmp .= $i == $this->image->m_nTrans ? "\x00" : "\xFF";
|
||||||
|
|
||||||
|
$out .= $tmp . pack('N', smf_crc32($tmp));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Here's the data itself!
|
||||||
|
$out .= pack('N', strlen($bmp));
|
||||||
|
$tmp = 'IDAT' . $bmp;
|
||||||
|
$out .= $tmp . pack('N', smf_crc32($tmp));
|
||||||
|
|
||||||
|
// EOF marker...
|
||||||
|
$out .= "\x00\x00\x00\x00" . 'IEND' . "\xAE\x42\x60\x82";
|
||||||
|
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// crc32 doesn't work as expected on 64-bit functions - make our own.
|
||||||
|
// http://www.php.net/crc32#79567
|
||||||
|
if (!function_exists('smf_crc32'))
|
||||||
|
{
|
||||||
|
function smf_crc32($number)
|
||||||
|
{
|
||||||
|
$crc = crc32($number);
|
||||||
|
|
||||||
|
if ($crc & 0x80000000)
|
||||||
|
{
|
||||||
|
$crc ^= 0xffffffff;
|
||||||
|
$crc += 1;
|
||||||
|
$crc = -$crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $crc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
1019
Sources/Class-Package.php
Normal file
454
Sources/DbExtra-mysql.php
Normal file
@ -0,0 +1,454 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple Machines Forum (SMF)
|
||||||
|
*
|
||||||
|
* @package SMF
|
||||||
|
* @author Simple Machines http://www.simplemachines.org
|
||||||
|
* @copyright 2011 Simple Machines
|
||||||
|
* @license http://www.simplemachines.org/about/smf/license.php BSD
|
||||||
|
*
|
||||||
|
* @version 2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('SMF'))
|
||||||
|
die('Hacking attempt...');
|
||||||
|
|
||||||
|
/* This file contains rarely used extended database functionality.
|
||||||
|
|
||||||
|
void db_extra_init()
|
||||||
|
- add this file's functions to the $smcFunc array.
|
||||||
|
|
||||||
|
resource smf_db_backup_table($table, $backup_table)
|
||||||
|
- backup $table to $backup_table.
|
||||||
|
- returns the request handle to the table creation query
|
||||||
|
|
||||||
|
string function smf_db_get_version()
|
||||||
|
- get the version number.
|
||||||
|
|
||||||
|
string db_insert_sql(string table_name)
|
||||||
|
- gets all the necessary INSERTs for the table named table_name.
|
||||||
|
- goes in 250 row segments.
|
||||||
|
- returns the query to insert the data back in.
|
||||||
|
- returns an empty string if the table was empty.
|
||||||
|
|
||||||
|
array smf_db_list_tables($db = false, $filter = false)
|
||||||
|
- lists all tables in the database
|
||||||
|
- could be filtered according to $filter
|
||||||
|
- returns an array of table names. (strings)
|
||||||
|
|
||||||
|
float smf_db_optimize_table($table)
|
||||||
|
- optimize a table
|
||||||
|
- $table - the table to be optimized
|
||||||
|
- returns how much it was gained
|
||||||
|
|
||||||
|
string db_table_sql(string table_name)
|
||||||
|
- dumps the CREATE for the specified table. (by table_name.)
|
||||||
|
- returns the CREATE statement.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Add the file functions to the $smcFunc array.
|
||||||
|
function db_extra_init()
|
||||||
|
{
|
||||||
|
global $smcFunc;
|
||||||
|
|
||||||
|
if (!isset($smcFunc['db_backup_table']) || $smcFunc['db_backup_table'] != 'smf_db_backup_table')
|
||||||
|
$smcFunc += array(
|
||||||
|
'db_backup_table' => 'smf_db_backup_table',
|
||||||
|
'db_optimize_table' => 'smf_db_optimize_table',
|
||||||
|
'db_insert_sql' => 'smf_db_insert_sql',
|
||||||
|
'db_table_sql' => 'smf_db_table_sql',
|
||||||
|
'db_list_tables' => 'smf_db_list_tables',
|
||||||
|
'db_get_version' => 'smf_db_get_version',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Backup $table to $backup_table.
|
||||||
|
function smf_db_backup_table($table, $backup_table)
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$table = str_replace('{db_prefix}', $db_prefix, $table);
|
||||||
|
|
||||||
|
// First, get rid of the old table.
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
DROP TABLE IF EXISTS {raw:backup_table}',
|
||||||
|
array(
|
||||||
|
'backup_table' => $backup_table,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Can we do this the quick way?
|
||||||
|
$result = $smcFunc['db_query']('', '
|
||||||
|
CREATE TABLE {raw:backup_table} LIKE {raw:table}',
|
||||||
|
array(
|
||||||
|
'backup_table' => $backup_table,
|
||||||
|
'table' => $table
|
||||||
|
));
|
||||||
|
// If this failed, we go old school.
|
||||||
|
if ($result)
|
||||||
|
{
|
||||||
|
$request = $smcFunc['db_query']('', '
|
||||||
|
INSERT INTO {raw:backup_table}
|
||||||
|
SELECT *
|
||||||
|
FROM {raw:table}',
|
||||||
|
array(
|
||||||
|
'backup_table' => $backup_table,
|
||||||
|
'table' => $table
|
||||||
|
));
|
||||||
|
|
||||||
|
// Old school or no school?
|
||||||
|
if ($request)
|
||||||
|
return $request;
|
||||||
|
}
|
||||||
|
|
||||||
|
// At this point, the quick method failed.
|
||||||
|
$result = $smcFunc['db_query']('', '
|
||||||
|
SHOW CREATE TABLE {raw:table}',
|
||||||
|
array(
|
||||||
|
'table' => $table,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
list (, $create) = $smcFunc['db_fetch_row']($result);
|
||||||
|
$smcFunc['db_free_result']($result);
|
||||||
|
|
||||||
|
$create = preg_split('/[\n\r]/', $create);
|
||||||
|
|
||||||
|
$auto_inc = '';
|
||||||
|
// Default engine type.
|
||||||
|
$engine = 'MyISAM';
|
||||||
|
$charset = '';
|
||||||
|
$collate = '';
|
||||||
|
|
||||||
|
foreach ($create as $k => $l)
|
||||||
|
{
|
||||||
|
// Get the name of the auto_increment column.
|
||||||
|
if (strpos($l, 'auto_increment'))
|
||||||
|
$auto_inc = trim($l);
|
||||||
|
|
||||||
|
// For the engine type, see if we can work out what it is.
|
||||||
|
if (strpos($l, 'ENGINE') !== false || strpos($l, 'TYPE') !== false)
|
||||||
|
{
|
||||||
|
// Extract the engine type.
|
||||||
|
preg_match('~(ENGINE|TYPE)=(\w+)(\sDEFAULT)?(\sCHARSET=(\w+))?(\sCOLLATE=(\w+))?~', $l, $match);
|
||||||
|
|
||||||
|
if (!empty($match[1]))
|
||||||
|
$engine = $match[1];
|
||||||
|
|
||||||
|
if (!empty($match[2]))
|
||||||
|
$engine = $match[2];
|
||||||
|
|
||||||
|
if (!empty($match[5]))
|
||||||
|
$charset = $match[5];
|
||||||
|
|
||||||
|
if (!empty($match[7]))
|
||||||
|
$collate = $match[7];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip everything but keys...
|
||||||
|
if (strpos($l, 'KEY') === false)
|
||||||
|
unset($create[$k]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($create))
|
||||||
|
$create = '(
|
||||||
|
' . implode('
|
||||||
|
', $create) . ')';
|
||||||
|
else
|
||||||
|
$create = '';
|
||||||
|
|
||||||
|
$request = $smcFunc['db_query']('', '
|
||||||
|
CREATE TABLE {raw:backup_table} {raw:create}
|
||||||
|
ENGINE={raw:engine}' . (empty($charset) ? '' : ' CHARACTER SET {raw:charset}' . (empty($collate) ? '' : ' COLLATE {raw:collate}')) . '
|
||||||
|
SELECT *
|
||||||
|
FROM {raw:table}',
|
||||||
|
array(
|
||||||
|
'backup_table' => $backup_table,
|
||||||
|
'table' => $table,
|
||||||
|
'create' => $create,
|
||||||
|
'engine' => $engine,
|
||||||
|
'charset' => empty($charset) ? '' : $charset,
|
||||||
|
'collate' => empty($collate) ? '' : $collate,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($auto_inc != '')
|
||||||
|
{
|
||||||
|
if (preg_match('~\`(.+?)\`\s~', $auto_inc, $match) != 0 && substr($auto_inc, -1, 1) == ',')
|
||||||
|
$auto_inc = substr($auto_inc, 0, -1);
|
||||||
|
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
ALTER TABLE {raw:backup_table}
|
||||||
|
CHANGE COLUMN {raw:column_detail} {raw:auto_inc}',
|
||||||
|
array(
|
||||||
|
'backup_table' => $backup_table,
|
||||||
|
'column_detail' => $match[1],
|
||||||
|
'auto_inc' => $auto_inc,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $request;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optimize a table - return data freed!
|
||||||
|
function smf_db_optimize_table($table)
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_name, $db_prefix;
|
||||||
|
|
||||||
|
$table = str_replace('{db_prefix}', $db_prefix, $table);
|
||||||
|
|
||||||
|
// Get how much overhead there is.
|
||||||
|
$request = $smcFunc['db_query']('', '
|
||||||
|
SHOW TABLE STATUS LIKE {string:table_name}',
|
||||||
|
array(
|
||||||
|
'table_name' => str_replace('_', '\_', $table),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$row = $smcFunc['db_fetch_assoc']($request);
|
||||||
|
$smcFunc['db_free_result']($request);
|
||||||
|
|
||||||
|
$data_before = isset($row['Data_free']) ? $row['Data_free'] : 0;
|
||||||
|
$request = $smcFunc['db_query']('', '
|
||||||
|
OPTIMIZE TABLE `{raw:table}`',
|
||||||
|
array(
|
||||||
|
'table' => $table,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if (!$request)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// How much left?
|
||||||
|
$request = $smcFunc['db_query']('', '
|
||||||
|
SHOW TABLE STATUS LIKE {string:table}',
|
||||||
|
array(
|
||||||
|
'table' => str_replace('_', '\_', $table),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$row = $smcFunc['db_fetch_assoc']($request);
|
||||||
|
$smcFunc['db_free_result']($request);
|
||||||
|
|
||||||
|
$total_change = isset($row['Data_free']) && $data_before > $row['Data_free'] ? $data_before / 1024 : 0;
|
||||||
|
|
||||||
|
return $total_change;
|
||||||
|
}
|
||||||
|
|
||||||
|
// List all the tables in the database.
|
||||||
|
function smf_db_list_tables($db = false, $filter = false)
|
||||||
|
{
|
||||||
|
global $db_name, $smcFunc;
|
||||||
|
|
||||||
|
$db = $db == false ? $db_name : $db;
|
||||||
|
$db = trim($db);
|
||||||
|
$filter = $filter == false ? '' : ' LIKE \'' . $filter . '\'';
|
||||||
|
|
||||||
|
$request = $smcFunc['db_query']('', '
|
||||||
|
SHOW TABLES
|
||||||
|
FROM `{raw:db}`
|
||||||
|
{raw:filter}',
|
||||||
|
array(
|
||||||
|
'db' => $db[0] == '`' ? strtr($db, array('`' => '')) : $db,
|
||||||
|
'filter' => $filter,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$tables = array();
|
||||||
|
while ($row = $smcFunc['db_fetch_row']($request))
|
||||||
|
$tables[] = $row[0];
|
||||||
|
$smcFunc['db_free_result']($request);
|
||||||
|
|
||||||
|
return $tables;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the content (INSERTs) for a table.
|
||||||
|
function smf_db_insert_sql($tableName)
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$tableName = str_replace('{db_prefix}', $db_prefix, $tableName);
|
||||||
|
|
||||||
|
// This will be handy...
|
||||||
|
$crlf = "\r\n";
|
||||||
|
|
||||||
|
// Get everything from the table.
|
||||||
|
$result = $smcFunc['db_query']('', '
|
||||||
|
SELECT /*!40001 SQL_NO_CACHE */ *
|
||||||
|
FROM `{raw:table}`',
|
||||||
|
array(
|
||||||
|
'table' => $tableName,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// The number of rows, just for record keeping and breaking INSERTs up.
|
||||||
|
$num_rows = $smcFunc['db_num_rows']($result);
|
||||||
|
$current_row = 0;
|
||||||
|
|
||||||
|
if ($num_rows == 0)
|
||||||
|
return '';
|
||||||
|
|
||||||
|
$fields = array_keys($smcFunc['db_fetch_assoc']($result));
|
||||||
|
$smcFunc['db_data_seek']($result, 0);
|
||||||
|
|
||||||
|
// Start it off with the basic INSERT INTO.
|
||||||
|
$data = 'INSERT INTO `' . $tableName . '`' . $crlf . "\t" . '(`' . implode('`, `', $fields) . '`)' . $crlf . 'VALUES ';
|
||||||
|
|
||||||
|
// Loop through each row.
|
||||||
|
while ($row = $smcFunc['db_fetch_row']($result))
|
||||||
|
{
|
||||||
|
$current_row++;
|
||||||
|
|
||||||
|
// Get the fields in this row...
|
||||||
|
$field_list = array();
|
||||||
|
for ($j = 0; $j < $smcFunc['db_num_fields']($result); $j++)
|
||||||
|
{
|
||||||
|
// Try to figure out the type of each field. (NULL, number, or 'string'.)
|
||||||
|
if (!isset($row[$j]))
|
||||||
|
$field_list[] = 'NULL';
|
||||||
|
elseif (is_numeric($row[$j]) && (int) $row[$j] == $row[$j])
|
||||||
|
$field_list[] = $row[$j];
|
||||||
|
else
|
||||||
|
$field_list[] = '\'' . $smcFunc['db_escape_string']($row[$j]) . '\'';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 'Insert' the data.
|
||||||
|
$data .= '(' . implode(', ', $field_list) . ')';
|
||||||
|
|
||||||
|
// All done!
|
||||||
|
if ($current_row == $num_rows)
|
||||||
|
$data .= ';' . $crlf;
|
||||||
|
// Start a new INSERT statement after every 250....
|
||||||
|
elseif ($current_row > 249 && $current_row % 250 == 0)
|
||||||
|
$data .= ';' . $crlf . 'INSERT INTO `' . $tableName . '`' . $crlf . "\t" . '(`' . implode('`, `', $fields) . '`)' . $crlf . 'VALUES ';
|
||||||
|
// Otherwise, go to the next line.
|
||||||
|
else
|
||||||
|
$data .= ',' . $crlf . "\t";
|
||||||
|
}
|
||||||
|
$smcFunc['db_free_result']($result);
|
||||||
|
|
||||||
|
// Return an empty string if there were no rows.
|
||||||
|
return $num_rows == 0 ? '' : $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the schema (CREATE) for a table.
|
||||||
|
function smf_db_table_sql($tableName)
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$tableName = str_replace('{db_prefix}', $db_prefix, $tableName);
|
||||||
|
|
||||||
|
// This will be needed...
|
||||||
|
$crlf = "\r\n";
|
||||||
|
|
||||||
|
// Drop it if it exists.
|
||||||
|
$schema_create = 'DROP TABLE IF EXISTS `' . $tableName . '`;' . $crlf . $crlf;
|
||||||
|
|
||||||
|
// Start the create table...
|
||||||
|
$schema_create .= 'CREATE TABLE `' . $tableName . '` (' . $crlf;
|
||||||
|
|
||||||
|
// Find all the fields.
|
||||||
|
$result = $smcFunc['db_query']('', '
|
||||||
|
SHOW FIELDS
|
||||||
|
FROM `{raw:table}`',
|
||||||
|
array(
|
||||||
|
'table' => $tableName,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
while ($row = $smcFunc['db_fetch_assoc']($result))
|
||||||
|
{
|
||||||
|
// Make the CREATE for this column.
|
||||||
|
$schema_create .= ' `' . $row['Field'] . '` ' . $row['Type'] . ($row['Null'] != 'YES' ? ' NOT NULL' : '');
|
||||||
|
|
||||||
|
// Add a default...?
|
||||||
|
if (!empty($row['Default']) || $row['Null'] !== 'YES')
|
||||||
|
{
|
||||||
|
// Make a special case of auto-timestamp.
|
||||||
|
if ($row['Default'] == 'CURRENT_TIMESTAMP')
|
||||||
|
$schema_create .= ' /*!40102 NOT NULL default CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP */';
|
||||||
|
// Text shouldn't have a default.
|
||||||
|
elseif ($row['Default'] !== null)
|
||||||
|
{
|
||||||
|
// If this field is numeric the default needs no escaping.
|
||||||
|
$type = strtolower($row['Type']);
|
||||||
|
$isNumericColumn = strpos($type, 'int') !== false || strpos($type, 'bool') !== false || strpos($type, 'bit') !== false || strpos($type, 'float') !== false || strpos($type, 'double') !== false || strpos($type, 'decimal') !== false;
|
||||||
|
|
||||||
|
$schema_create .= ' default ' . ($isNumericColumn ? $row['Default'] : '\'' . $smcFunc['db_escape_string']($row['Default']) . '\'');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// And now any extra information. (such as auto_increment.)
|
||||||
|
$schema_create .= ($row['Extra'] != '' ? ' ' . $row['Extra'] : '') . ',' . $crlf;
|
||||||
|
}
|
||||||
|
$smcFunc['db_free_result']($result);
|
||||||
|
|
||||||
|
// Take off the last comma.
|
||||||
|
$schema_create = substr($schema_create, 0, -strlen($crlf) - 1);
|
||||||
|
|
||||||
|
// Find the keys.
|
||||||
|
$result = $smcFunc['db_query']('', '
|
||||||
|
SHOW KEYS
|
||||||
|
FROM `{raw:table}`',
|
||||||
|
array(
|
||||||
|
'table' => $tableName,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$indexes = array();
|
||||||
|
while ($row = $smcFunc['db_fetch_assoc']($result))
|
||||||
|
{
|
||||||
|
// IS this a primary key, unique index, or regular index?
|
||||||
|
$row['Key_name'] = $row['Key_name'] == 'PRIMARY' ? 'PRIMARY KEY' : (empty($row['Non_unique']) ? 'UNIQUE ' : ($row['Comment'] == 'FULLTEXT' || (isset($row['Index_type']) && $row['Index_type'] == 'FULLTEXT') ? 'FULLTEXT ' : 'KEY ')) . '`' . $row['Key_name'] . '`';
|
||||||
|
|
||||||
|
// Is this the first column in the index?
|
||||||
|
if (empty($indexes[$row['Key_name']]))
|
||||||
|
$indexes[$row['Key_name']] = array();
|
||||||
|
|
||||||
|
// A sub part, like only indexing 15 characters of a varchar.
|
||||||
|
if (!empty($row['Sub_part']))
|
||||||
|
$indexes[$row['Key_name']][$row['Seq_in_index']] = '`' . $row['Column_name'] . '`(' . $row['Sub_part'] . ')';
|
||||||
|
else
|
||||||
|
$indexes[$row['Key_name']][$row['Seq_in_index']] = '`' . $row['Column_name'] . '`';
|
||||||
|
}
|
||||||
|
$smcFunc['db_free_result']($result);
|
||||||
|
|
||||||
|
// Build the CREATEs for the keys.
|
||||||
|
foreach ($indexes as $keyname => $columns)
|
||||||
|
{
|
||||||
|
// Ensure the columns are in proper order.
|
||||||
|
ksort($columns);
|
||||||
|
|
||||||
|
$schema_create .= ',' . $crlf . ' ' . $keyname . ' (' . implode($columns, ', ') . ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now just get the comment and type... (MyISAM, etc.)
|
||||||
|
$result = $smcFunc['db_query']('', '
|
||||||
|
SHOW TABLE STATUS
|
||||||
|
LIKE {string:table}',
|
||||||
|
array(
|
||||||
|
'table' => strtr($tableName, array('_' => '\\_', '%' => '\\%')),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$row = $smcFunc['db_fetch_assoc']($result);
|
||||||
|
$smcFunc['db_free_result']($result);
|
||||||
|
|
||||||
|
// Probably MyISAM.... and it might have a comment.
|
||||||
|
$schema_create .= $crlf . ') ENGINE=' . (isset($row['Type']) ? $row['Type'] : $row['Engine']) . ($row['Comment'] != '' ? ' COMMENT="' . $row['Comment'] . '"' : '');
|
||||||
|
|
||||||
|
return $schema_create;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the version number.
|
||||||
|
function smf_db_get_version()
|
||||||
|
{
|
||||||
|
global $smcFunc;
|
||||||
|
|
||||||
|
$request = $smcFunc['db_query']('', '
|
||||||
|
SELECT VERSION()',
|
||||||
|
array(
|
||||||
|
)
|
||||||
|
);
|
||||||
|
list ($ver) = $smcFunc['db_fetch_row']($request);
|
||||||
|
$smcFunc['db_free_result']($request);
|
||||||
|
|
||||||
|
return $ver;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
328
Sources/DbExtra-postgresql.php
Normal file
@ -0,0 +1,328 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple Machines Forum (SMF)
|
||||||
|
*
|
||||||
|
* @package SMF
|
||||||
|
* @author Simple Machines http://www.simplemachines.org
|
||||||
|
* @copyright 2011 Simple Machines
|
||||||
|
* @license http://www.simplemachines.org/about/smf/license.php BSD
|
||||||
|
*
|
||||||
|
* @version 2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('SMF'))
|
||||||
|
die('Hacking attempt...');
|
||||||
|
|
||||||
|
/* This file contains rarely used extended database functionality.
|
||||||
|
|
||||||
|
void db_extra_init()
|
||||||
|
- add this file's functions to the $smcFunc array.
|
||||||
|
|
||||||
|
resource smf_db_backup_table($table, $backup_table)
|
||||||
|
- backup $table to $backup_table.
|
||||||
|
- returns the request handle to the table creation query
|
||||||
|
|
||||||
|
string function smf_db_get_version()
|
||||||
|
- get the version number.
|
||||||
|
|
||||||
|
string db_insert_sql(string table_name)
|
||||||
|
- gets all the necessary INSERTs for the table named table_name.
|
||||||
|
- goes in 250 row segments.
|
||||||
|
- returns the query to insert the data back in.
|
||||||
|
- returns an empty string if the table was empty.
|
||||||
|
|
||||||
|
array smf_db_list_tables($db = false, $filter = false)
|
||||||
|
- lists all tables in the database
|
||||||
|
- could be filtered according to $filter
|
||||||
|
- returns an array of table names. (strings)
|
||||||
|
|
||||||
|
float smf_db_optimize_table($table)
|
||||||
|
- optimize a table
|
||||||
|
- $table - the table to be optimized
|
||||||
|
- returns how much it was gained
|
||||||
|
|
||||||
|
string db_table_sql(string table_name)
|
||||||
|
- dumps the CREATE for the specified table. (by table_name.)
|
||||||
|
- returns the CREATE statement.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Add the file functions to the $smcFunc array.
|
||||||
|
function db_extra_init()
|
||||||
|
{
|
||||||
|
global $smcFunc;
|
||||||
|
|
||||||
|
if (!isset($smcFunc['db_backup_table']) || $smcFunc['db_backup_table'] != 'smf_db_backup_table')
|
||||||
|
$smcFunc += array(
|
||||||
|
'db_backup_table' => 'smf_db_backup_table',
|
||||||
|
'db_optimize_table' => 'smf_db_optimize_table',
|
||||||
|
'db_insert_sql' => 'smf_db_insert_sql',
|
||||||
|
'db_table_sql' => 'smf_db_table_sql',
|
||||||
|
'db_list_tables' => 'smf_db_list_tables',
|
||||||
|
'db_get_version' => 'smf_db_get_version',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Backup $table to $backup_table.
|
||||||
|
function smf_db_backup_table($table, $backup_table)
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$table = str_replace('{db_prefix}', $db_prefix, $table);
|
||||||
|
|
||||||
|
// Do we need to drop it first?
|
||||||
|
$tables = smf_db_list_tables(false, $backup_table);
|
||||||
|
if (!empty($tables))
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
DROP TABLE {raw:backup_table}',
|
||||||
|
array(
|
||||||
|
'backup_table' => $backup_table,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
//!!! Should we create backups of sequences as well?
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
CREATE TABLE {raw:backup_table}
|
||||||
|
(
|
||||||
|
LIKE {raw:table}
|
||||||
|
INCLUDING DEFAULTS
|
||||||
|
)',
|
||||||
|
array(
|
||||||
|
'backup_table' => $backup_table,
|
||||||
|
'table' => $table,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
INSERT INTO {raw:backup_table}
|
||||||
|
SELECT * FROM {raw:table}',
|
||||||
|
array(
|
||||||
|
'backup_table' => $backup_table,
|
||||||
|
'table' => $table,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optimize a table - return data freed!
|
||||||
|
function smf_db_optimize_table($table)
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$table = str_replace('{db_prefix}', $db_prefix, $table);
|
||||||
|
|
||||||
|
$request = $smcFunc['db_query']('', '
|
||||||
|
VACUUM ANALYZE {raw:table}',
|
||||||
|
array(
|
||||||
|
'table' => $table,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if (!$request)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
$row = $smcFunc['db_fetch_assoc']($request);
|
||||||
|
$smcFunc['db_free_result']($request);
|
||||||
|
|
||||||
|
if (isset($row['Data_free']))
|
||||||
|
return $row['Data_free'] / 1024;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// List all the tables in the database.
|
||||||
|
function smf_db_list_tables($db = false, $filter = false)
|
||||||
|
{
|
||||||
|
global $smcFunc;
|
||||||
|
|
||||||
|
$request = $smcFunc['db_query']('', '
|
||||||
|
SELECT tablename
|
||||||
|
FROM pg_tables
|
||||||
|
WHERE schemaname = {string:schema_public}' . ($filter == false ? '' : '
|
||||||
|
AND tablename LIKE {string:filter}') . '
|
||||||
|
ORDER BY tablename',
|
||||||
|
array(
|
||||||
|
'schema_public' => 'public',
|
||||||
|
'filter' => $filter,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$tables = array();
|
||||||
|
while ($row = $smcFunc['db_fetch_row']($request))
|
||||||
|
$tables[] = $row[0];
|
||||||
|
$smcFunc['db_free_result']($request);
|
||||||
|
|
||||||
|
return $tables;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the content (INSERTs) for a table.
|
||||||
|
function smf_db_insert_sql($tableName)
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$tableName = str_replace('{db_prefix}', $db_prefix, $tableName);
|
||||||
|
|
||||||
|
// This will be handy...
|
||||||
|
$crlf = "\r\n";
|
||||||
|
|
||||||
|
// Get everything from the table.
|
||||||
|
$result = $smcFunc['db_query']('', '
|
||||||
|
SELECT *
|
||||||
|
FROM {raw:table}',
|
||||||
|
array(
|
||||||
|
'table' => $tableName,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// The number of rows, just for record keeping and breaking INSERTs up.
|
||||||
|
$num_rows = $smcFunc['db_num_rows']($result);
|
||||||
|
|
||||||
|
if ($num_rows == 0)
|
||||||
|
return '';
|
||||||
|
|
||||||
|
$fields = array_keys($smcFunc['db_fetch_assoc']($result));
|
||||||
|
$smcFunc['db_data_seek']($result, 0);
|
||||||
|
|
||||||
|
// Start it off with the basic INSERT INTO.
|
||||||
|
$data = '';
|
||||||
|
$insert_msg = $crlf . 'INSERT INTO ' . $tableName . $crlf . "\t" . '(' . implode(', ', $fields) . ')' . $crlf . 'VALUES ' . $crlf . "\t";
|
||||||
|
|
||||||
|
// Loop through each row.
|
||||||
|
while ($row = $smcFunc['db_fetch_row']($result))
|
||||||
|
{
|
||||||
|
// Get the fields in this row...
|
||||||
|
$field_list = array();
|
||||||
|
for ($j = 0; $j < $smcFunc['db_num_fields']($result); $j++)
|
||||||
|
{
|
||||||
|
// Try to figure out the type of each field. (NULL, number, or 'string'.)
|
||||||
|
if (!isset($row[$j]))
|
||||||
|
$field_list[] = 'NULL';
|
||||||
|
elseif (is_numeric($row[$j]) && (int) $row[$j] == $row[$j])
|
||||||
|
$field_list[] = $row[$j];
|
||||||
|
else
|
||||||
|
$field_list[] = '\'' . $smcFunc['db_escape_string']($row[$j]) . '\'';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 'Insert' the data.
|
||||||
|
$data .= $insert_msg . '(' . implode(', ', $field_list) . ');';
|
||||||
|
}
|
||||||
|
$smcFunc['db_free_result']($result);
|
||||||
|
|
||||||
|
// Return an empty string if there were no rows.
|
||||||
|
return $num_rows == 0 ? '' : $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the schema (CREATE) for a table.
|
||||||
|
function smf_db_table_sql($tableName)
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$tableName = str_replace('{db_prefix}', $db_prefix, $tableName);
|
||||||
|
|
||||||
|
// This will be needed...
|
||||||
|
$crlf = "\r\n";
|
||||||
|
|
||||||
|
// Start the create table...
|
||||||
|
$schema_create = 'CREATE TABLE ' . $tableName . ' (' . $crlf;
|
||||||
|
$index_create = '';
|
||||||
|
$seq_create = '';
|
||||||
|
|
||||||
|
// Find all the fields.
|
||||||
|
$result = $smcFunc['db_query']('', '
|
||||||
|
SELECT column_name, column_default, is_nullable, data_type, character_maximum_length
|
||||||
|
FROM information_schema.columns
|
||||||
|
WHERE table_name = {string:table}
|
||||||
|
ORDER BY ordinal_position',
|
||||||
|
array(
|
||||||
|
'table' => $tableName,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
while ($row = $smcFunc['db_fetch_assoc']($result))
|
||||||
|
{
|
||||||
|
if ($row['data_type'] == 'character varying')
|
||||||
|
$row['data_type'] = 'varchar';
|
||||||
|
elseif ($row['data_type'] == 'character')
|
||||||
|
$row['data_type'] = 'char';
|
||||||
|
if ($row['character_maximum_length'])
|
||||||
|
$row['data_type'] .= '(' . $row['character_maximum_length'] . ')';
|
||||||
|
|
||||||
|
// Make the CREATE for this column.
|
||||||
|
$schema_create .= ' "' . $row['column_name'] . '" ' . $row['data_type'] . ($row['is_nullable'] != 'YES' ? ' NOT NULL' : '');
|
||||||
|
|
||||||
|
// Add a default...?
|
||||||
|
if (trim($row['column_default']) != '')
|
||||||
|
{
|
||||||
|
$schema_create .= ' default ' . $row['column_default'] . '';
|
||||||
|
|
||||||
|
// Auto increment?
|
||||||
|
if (preg_match('~nextval\(\'(.+?)\'(.+?)*\)~i', $row['column_default'], $matches) != 0)
|
||||||
|
{
|
||||||
|
// Get to find the next variable first!
|
||||||
|
$count_req = $smcFunc['db_query']('', '
|
||||||
|
SELECT MAX("{raw:column}")
|
||||||
|
FROM {raw:table}',
|
||||||
|
array(
|
||||||
|
'column' => $row['column_name'],
|
||||||
|
'table' => $tableName,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
list ($max_ind) = $smcFunc['db_fetch_row']($count_req);
|
||||||
|
$smcFunc['db_free_result']($count_req);
|
||||||
|
// Get the right bloody start!
|
||||||
|
$seq_create .= 'CREATE SEQUENCE ' . $matches[1] . ' START WITH ' . ($max_ind + 1) . ';' . $crlf . $crlf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$schema_create .= ',' . $crlf;
|
||||||
|
}
|
||||||
|
$smcFunc['db_free_result']($result);
|
||||||
|
|
||||||
|
// Take off the last comma.
|
||||||
|
$schema_create = substr($schema_create, 0, -strlen($crlf) - 1);
|
||||||
|
|
||||||
|
$result = $smcFunc['db_query']('', '
|
||||||
|
SELECT CASE WHEN i.indisprimary THEN 1 ELSE 0 END AS is_primary, pg_get_indexdef(i.indexrelid) AS inddef
|
||||||
|
FROM pg_class AS c
|
||||||
|
INNER JOIN pg_index AS i ON (i.indrelid = c.oid)
|
||||||
|
INNER JOIN pg_class AS c2 ON (c2.oid = i.indexrelid)
|
||||||
|
WHERE c.relname = {string:table}',
|
||||||
|
array(
|
||||||
|
'table' => $tableName,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$indexes = array();
|
||||||
|
while ($row = $smcFunc['db_fetch_assoc']($result))
|
||||||
|
{
|
||||||
|
if ($row['is_primary'])
|
||||||
|
{
|
||||||
|
if (preg_match('~\(([^\)]+?)\)~i', $row['inddef'], $matches) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$index_create .= $crlf . 'ALTER TABLE ' . $tableName . ' ADD PRIMARY KEY ("' . $matches[1] . '");';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$index_create .= $crlf . $row['inddef'] . ';';
|
||||||
|
}
|
||||||
|
$smcFunc['db_free_result']($result);
|
||||||
|
|
||||||
|
// Finish it off!
|
||||||
|
$schema_create .= $crlf . ');';
|
||||||
|
|
||||||
|
return $seq_create . $schema_create . $index_create;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the version number.
|
||||||
|
function smf_db_get_version()
|
||||||
|
{
|
||||||
|
global $smcFunc;
|
||||||
|
|
||||||
|
$request = $smcFunc['db_query']('', '
|
||||||
|
SHOW server_version',
|
||||||
|
array(
|
||||||
|
)
|
||||||
|
);
|
||||||
|
list ($ver) = $smcFunc['db_fetch_row']($request);
|
||||||
|
$smcFunc['db_free_result']($request);
|
||||||
|
|
||||||
|
return $ver;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
346
Sources/DbExtra-sqlite.php
Normal file
@ -0,0 +1,346 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple Machines Forum (SMF)
|
||||||
|
*
|
||||||
|
* @package SMF
|
||||||
|
* @author Simple Machines http://www.simplemachines.org
|
||||||
|
* @copyright 2011 Simple Machines
|
||||||
|
* @license http://www.simplemachines.org/about/smf/license.php BSD
|
||||||
|
*
|
||||||
|
* @version 2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('SMF'))
|
||||||
|
die('Hacking attempt...');
|
||||||
|
|
||||||
|
/* This file contains rarely used extended database functionality.
|
||||||
|
|
||||||
|
void db_extra_init()
|
||||||
|
- add this file's functions to the $smcFunc array.
|
||||||
|
|
||||||
|
resource smf_db_backup_table($table, $backup_table)
|
||||||
|
- backup $table to $backup_table.
|
||||||
|
- returns the request handle to the table creation query
|
||||||
|
|
||||||
|
string function smf_db_get_version()
|
||||||
|
- get the version number.
|
||||||
|
|
||||||
|
string db_insert_sql(string table_name)
|
||||||
|
- gets all the necessary INSERTs for the table named table_name.
|
||||||
|
- goes in 250 row segments.
|
||||||
|
- returns the query to insert the data back in.
|
||||||
|
- returns an empty string if the table was empty.
|
||||||
|
|
||||||
|
array smf_db_list_tables($db = false, $filter = false)
|
||||||
|
- lists all tables in the database
|
||||||
|
- could be filtered according to $filter
|
||||||
|
- returns an array of table names. (strings)
|
||||||
|
|
||||||
|
float smf_db_optimize_table($table)
|
||||||
|
- optimize a table
|
||||||
|
- $table - the table to be optimized
|
||||||
|
- returns how much it was gained
|
||||||
|
|
||||||
|
string db_table_sql(string table_name)
|
||||||
|
- dumps the CREATE for the specified table. (by table_name.)
|
||||||
|
- returns the CREATE statement.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Add the file functions to the $smcFunc array.
|
||||||
|
function db_extra_init()
|
||||||
|
{
|
||||||
|
global $smcFunc;
|
||||||
|
|
||||||
|
if (!isset($smcFunc['db_backup_table']) || $smcFunc['db_backup_table'] != 'smf_db_backup_table')
|
||||||
|
$smcFunc += array(
|
||||||
|
'db_backup_table' => 'smf_db_backup_table',
|
||||||
|
'db_optimize_table' => 'smf_db_optimize_table',
|
||||||
|
'db_insert_sql' => 'smf_db_insert_sql',
|
||||||
|
'db_table_sql' => 'smf_db_table_sql',
|
||||||
|
'db_list_tables' => 'smf_db_list_tables',
|
||||||
|
'db_get_backup' => 'smf_db_get_backup',
|
||||||
|
'db_get_version' => 'smf_db_get_version',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Backup $table to $backup_table.
|
||||||
|
function smf_db_backup_table($table, $backup_table)
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$table = str_replace('{db_prefix}', $db_prefix, $table);
|
||||||
|
|
||||||
|
$result = $smcFunc['db_query']('', '
|
||||||
|
SELECT sql
|
||||||
|
FROM sqlite_master
|
||||||
|
WHERE type = {string:txttable}
|
||||||
|
AND name = {string:table}',
|
||||||
|
array(
|
||||||
|
'table' => $table,
|
||||||
|
'txttable' => 'table'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
list ($create) = $smcFunc['db_fetch_row']($result);
|
||||||
|
$smcFunc['db_free_result']($result);
|
||||||
|
|
||||||
|
$create = preg_split('/[\n\r]/', $create);
|
||||||
|
$auto_inc = '';
|
||||||
|
|
||||||
|
// Remove the first line and check to see if the second one contain useless info.
|
||||||
|
unset($create[0]);
|
||||||
|
if (trim($create[1]) == '(')
|
||||||
|
unset($create[1]);
|
||||||
|
if (trim($create[count($create)]) == ')')
|
||||||
|
unset($create[count($create)]);
|
||||||
|
|
||||||
|
foreach ($create as $k => $l)
|
||||||
|
{
|
||||||
|
// Get the name of the auto_increment column.
|
||||||
|
if (strpos($l, 'primary') || strpos($l, 'PRIMARY'))
|
||||||
|
$auto_inc = trim($l);
|
||||||
|
|
||||||
|
// Skip everything but keys...
|
||||||
|
if ((strpos($l, 'KEY') !== false && strpos($l, 'PRIMARY KEY') === false) || strpos($l, $table) !== false || strpos(trim($l), 'PRIMARY KEY') === 0)
|
||||||
|
unset($create[$k]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($create))
|
||||||
|
$create = '(
|
||||||
|
' . implode('
|
||||||
|
', $create) . ')';
|
||||||
|
else
|
||||||
|
$create = '';
|
||||||
|
|
||||||
|
// Is there an extra junk at the end?
|
||||||
|
if (substr($create, -2, 1) == ',')
|
||||||
|
$create = substr($create, 0, -2) . ')';
|
||||||
|
if (substr($create, -2) == '))')
|
||||||
|
$create = substr($create, 0, -1);
|
||||||
|
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
DROP TABLE {raw:backup_table}',
|
||||||
|
array(
|
||||||
|
'backup_table' => $backup_table,
|
||||||
|
'db_error_skip' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$request = $smcFunc['db_quote']('
|
||||||
|
CREATE TABLE {raw:backup_table} {raw:create}',
|
||||||
|
array(
|
||||||
|
'backup_table' => $backup_table,
|
||||||
|
'create' => $create,
|
||||||
|
));
|
||||||
|
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
CREATE TABLE {raw:backup_table} {raw:create}',
|
||||||
|
array(
|
||||||
|
'backup_table' => $backup_table,
|
||||||
|
'create' => $create,
|
||||||
|
));
|
||||||
|
|
||||||
|
$request = $smcFunc['db_query']('', '
|
||||||
|
INSERT INTO {raw:backup_table}
|
||||||
|
SELECT *
|
||||||
|
FROM {raw:table}',
|
||||||
|
array(
|
||||||
|
'backup_table' => $backup_table,
|
||||||
|
'table' => $table,
|
||||||
|
));
|
||||||
|
|
||||||
|
return $request;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optimize a table - return data freed!
|
||||||
|
function smf_db_optimize_table($table)
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$table = str_replace('{db_prefix}', $db_prefix, $table);
|
||||||
|
|
||||||
|
$request = $smcFunc['db_query']('', '
|
||||||
|
VACUUM {raw:table}',
|
||||||
|
array(
|
||||||
|
'table' => $table,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if (!$request)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
$row = $smcFunc['db_fetch_assoc']($request);
|
||||||
|
$smcFunc['db_free_result']($request);
|
||||||
|
|
||||||
|
// The function returns nothing.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// List all the tables in the database.
|
||||||
|
function smf_db_list_tables($db = false, $filter = false)
|
||||||
|
{
|
||||||
|
global $smcFunc;
|
||||||
|
|
||||||
|
$filter = $filter == false ? '' : ' AND name LIKE \'' . str_replace("\_", "_", $filter) . '\'';
|
||||||
|
|
||||||
|
$request = $smcFunc['db_query']('', '
|
||||||
|
SELECT name
|
||||||
|
FROM sqlite_master
|
||||||
|
WHERE type = {string:type}
|
||||||
|
{raw:filter}
|
||||||
|
ORDER BY name',
|
||||||
|
array(
|
||||||
|
'type' => 'table',
|
||||||
|
'filter' => $filter,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$tables = array();
|
||||||
|
while ($row = $smcFunc['db_fetch_row']($request))
|
||||||
|
$tables[] = $row[0];
|
||||||
|
$smcFunc['db_free_result']($request);
|
||||||
|
|
||||||
|
return $tables;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the content (INSERTs) for a table.
|
||||||
|
function smf_db_insert_sql($tableName)
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$tableName = str_replace('{db_prefix}', $db_prefix, $tableName);
|
||||||
|
|
||||||
|
// This will be handy...
|
||||||
|
$crlf = "\r\n";
|
||||||
|
|
||||||
|
// Get everything from the table.
|
||||||
|
$result = $smcFunc['db_query']('', '
|
||||||
|
SELECT *
|
||||||
|
FROM {raw:table}',
|
||||||
|
array(
|
||||||
|
'table' => $tableName,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// The number of rows, just for record keeping and breaking INSERTs up.
|
||||||
|
$num_rows = $smcFunc['db_num_rows']($result);
|
||||||
|
|
||||||
|
if ($num_rows == 0)
|
||||||
|
return '';
|
||||||
|
|
||||||
|
$fields = array_keys($smcFunc['db_fetch_assoc']($result));
|
||||||
|
|
||||||
|
// SQLite fetches an array so we need to filter out the numberic index for the columns.
|
||||||
|
foreach ($fields as $key => $name)
|
||||||
|
if (is_numeric($name))
|
||||||
|
unset($fields[$key]);
|
||||||
|
|
||||||
|
$smcFunc['db_data_seek']($result, 0);
|
||||||
|
|
||||||
|
// Start it off with the basic INSERT INTO.
|
||||||
|
$data = 'BEGIN TRANSACTION;' . $crlf;
|
||||||
|
|
||||||
|
// Loop through each row.
|
||||||
|
while ($row = $smcFunc['db_fetch_row']($result))
|
||||||
|
{
|
||||||
|
// Get the fields in this row...
|
||||||
|
$field_list = array();
|
||||||
|
for ($j = 0; $j < $smcFunc['db_num_fields']($result); $j++)
|
||||||
|
{
|
||||||
|
// Try to figure out the type of each field. (NULL, number, or 'string'.)
|
||||||
|
if (!isset($row[$j]))
|
||||||
|
$field_list[] = 'NULL';
|
||||||
|
elseif (is_numeric($row[$j]) && (int) $row[$j] == $row[$j])
|
||||||
|
$field_list[] = $row[$j];
|
||||||
|
else
|
||||||
|
$field_list[] = '\'' . $smcFunc['db_escape_string']($row[$j]) . '\'';
|
||||||
|
}
|
||||||
|
$data .= 'INSERT INTO ' . $tableName . ' (' . implode(', ', $fields) . ') VALUES (' . implode(', ', $field_list) . ');' . $crlf;
|
||||||
|
}
|
||||||
|
$smcFunc['db_free_result']($result);
|
||||||
|
|
||||||
|
// Return an empty string if there were no rows.
|
||||||
|
return $num_rows == 0 ? '' : $data . 'COMMIT;' . $crlf;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the schema (CREATE) for a table.
|
||||||
|
function smf_db_table_sql($tableName)
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$tableName = str_replace('{db_prefix}', $db_prefix, $tableName);
|
||||||
|
|
||||||
|
// This will be needed...
|
||||||
|
$crlf = "\r\n";
|
||||||
|
|
||||||
|
// Start the create table...
|
||||||
|
$schema_create = '';
|
||||||
|
$index_create = '';
|
||||||
|
|
||||||
|
// Let's get the create statement directly from SQLite.
|
||||||
|
$result = $smcFunc['db_query']('', '
|
||||||
|
SELECT sql
|
||||||
|
FROM sqlite_master
|
||||||
|
WHERE type = {string:type}
|
||||||
|
AND name = {string:table_name}',
|
||||||
|
array(
|
||||||
|
'type' => 'table',
|
||||||
|
'table_name' => $tableName,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
list ($schema_create) = $smcFunc['db_fetch_row']($result);
|
||||||
|
$smcFunc['db_free_result']($result);
|
||||||
|
|
||||||
|
// Now the indexes.
|
||||||
|
$result = $smcFunc['db_query']('', '
|
||||||
|
SELECT sql
|
||||||
|
FROM sqlite_master
|
||||||
|
WHERE type = {string:type}
|
||||||
|
AND tbl_name = {string:table_name}',
|
||||||
|
array(
|
||||||
|
'type' => 'index',
|
||||||
|
'table_name' => $tableName,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$indexes = array();
|
||||||
|
while ($row = $smcFunc['db_fetch_assoc']($result))
|
||||||
|
if (trim($row['sql']) != '')
|
||||||
|
$indexes[] = $row['sql'];
|
||||||
|
$smcFunc['db_free_result']($result);
|
||||||
|
|
||||||
|
$index_create .= implode(';' . $crlf, $indexes);
|
||||||
|
$schema_create = empty($indexes) ? rtrim($schema_create) : $schema_create . ';' . $crlf . $crlf;
|
||||||
|
|
||||||
|
return $schema_create . $index_create;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the version number.
|
||||||
|
function smf_db_get_version()
|
||||||
|
{
|
||||||
|
return sqlite_libversion();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple return the database - and die!
|
||||||
|
function smf_db_get_backup()
|
||||||
|
{
|
||||||
|
global $db_name;
|
||||||
|
|
||||||
|
$db_file = substr($db_name, -3) === '.db' ? $db_name : $db_name . '.db';
|
||||||
|
|
||||||
|
// Add more info if zipped...
|
||||||
|
$ext = '';
|
||||||
|
if (isset($_REQUEST['compress']) && function_exists('gzencode'))
|
||||||
|
$ext = '.gz';
|
||||||
|
|
||||||
|
// Do the remaining headers.
|
||||||
|
header('Content-Disposition: attachment; filename="' . $db_file . $ext . '"');
|
||||||
|
header('Cache-Control: private');
|
||||||
|
header('Connection: close');
|
||||||
|
|
||||||
|
// Literally dump the contents. Try reading the file first.
|
||||||
|
if (@readfile($db_file) == null)
|
||||||
|
echo file_get_contents($db_file);
|
||||||
|
|
||||||
|
obExit(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
582
Sources/DbPackages-mysql.php
Normal file
@ -0,0 +1,582 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple Machines Forum (SMF)
|
||||||
|
*
|
||||||
|
* @package SMF
|
||||||
|
* @author Simple Machines http://www.simplemachines.org
|
||||||
|
* @copyright 2011 Simple Machines
|
||||||
|
* @license http://www.simplemachines.org/about/smf/license.php BSD
|
||||||
|
*
|
||||||
|
* @version 2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('SMF'))
|
||||||
|
die('Hacking attempt...');
|
||||||
|
|
||||||
|
/* This file contains database functionality specifically designed for packages to utilize.
|
||||||
|
|
||||||
|
bool smf_db_create_table(string table_name, array columns, array indexes = array(),
|
||||||
|
array parameters = array(), string if_exists = 'ignore')
|
||||||
|
- Can be used to create a table without worrying about schema compatabilities.
|
||||||
|
- If the table exists will, by default, do nothing.
|
||||||
|
- Builds table with columns as passed to it - at least one column must be sent.
|
||||||
|
The columns array should have one sub-array for each column - these sub arrays contain:
|
||||||
|
+ 'name' = Column name
|
||||||
|
+ 'type' = Type of column - values from (smallint,mediumint,int,text,varchar,char,tinytext,mediumtext,largetext)
|
||||||
|
+ 'size' => Size of column (If applicable) - for example 255 for a large varchar, 10 for an int etc. If not
|
||||||
|
set SMF will pick a size.
|
||||||
|
+ 'default' = Default value - do not set if no default required.
|
||||||
|
+ 'null' => Can it be null (true or false) - if not set default will be false.
|
||||||
|
+ 'auto' => Set to true to make it an auto incrementing column. Set to a numerical value to set
|
||||||
|
from what it should begin counting.
|
||||||
|
- Adds indexes as specified within indexes parameter. Each index should be a member of $indexes. Values are:
|
||||||
|
+ 'name' => Index name (If left empty SMF will generate).
|
||||||
|
+ 'type' => Type of index. Choose from 'primary', 'unique' or 'index'. If not set will default to 'index'.
|
||||||
|
+ 'columns' => Array containing columns that form part of key - in the order the index is to be created.
|
||||||
|
- parameters: (None yet)
|
||||||
|
- if_exists values:
|
||||||
|
+ 'ignore' will do nothing if the table exists. (And will return true)
|
||||||
|
+ 'overwrite' will drop any existing table of the same name.
|
||||||
|
+ 'error' will return false if the table already exists.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Add the file functions to the $smcFunc array.
|
||||||
|
function db_packages_init()
|
||||||
|
{
|
||||||
|
global $smcFunc, $reservedTables, $db_package_log, $db_prefix;
|
||||||
|
|
||||||
|
if (!isset($smcFunc['db_create_table']) || $smcFunc['db_create_table'] != 'smf_db_create_table')
|
||||||
|
{
|
||||||
|
$smcFunc += array(
|
||||||
|
'db_add_column' => 'smf_db_add_column',
|
||||||
|
'db_add_index' => 'smf_db_add_index',
|
||||||
|
'db_calculate_type' => 'smf_db_calculate_type',
|
||||||
|
'db_change_column' => 'smf_db_change_column',
|
||||||
|
'db_create_table' => 'smf_db_create_table',
|
||||||
|
'db_drop_table' => 'smf_db_drop_table',
|
||||||
|
'db_table_structure' => 'smf_db_table_structure',
|
||||||
|
'db_list_columns' => 'smf_db_list_columns',
|
||||||
|
'db_list_indexes' => 'smf_db_list_indexes',
|
||||||
|
'db_remove_column' => 'smf_db_remove_column',
|
||||||
|
'db_remove_index' => 'smf_db_remove_index',
|
||||||
|
);
|
||||||
|
$db_package_log = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
// We setup an array of SMF tables we can't do auto-remove on - in case a mod writer cocks it up!
|
||||||
|
$reservedTables = array('admin_info_files', 'approval_queue', 'attachments', 'ban_groups', 'ban_items',
|
||||||
|
'board_permissions', 'boards', 'calendar', 'calendar_holidays', 'categories', 'collapsed_categories',
|
||||||
|
'custom_fields', 'group_moderators', 'log_actions', 'log_activity', 'log_banned', 'log_boards',
|
||||||
|
'log_digest', 'log_errors', 'log_floodcontrol', 'log_group_requests', 'log_karma', 'log_mark_read',
|
||||||
|
'log_notify', 'log_online', 'log_packages', 'log_polls', 'log_reported', 'log_reported_comments',
|
||||||
|
'log_scheduled_tasks', 'log_search_messages', 'log_search_results', 'log_search_subjects',
|
||||||
|
'log_search_topics', 'log_topics', 'mail_queue', 'membergroups', 'members', 'message_icons',
|
||||||
|
'messages', 'moderators', 'package_servers', 'permission_profiles', 'permissions', 'personal_messages',
|
||||||
|
'pm_recipients', 'poll_choices', 'polls', 'scheduled_tasks', 'sessions', 'settings', 'smileys',
|
||||||
|
'themes', 'topics');
|
||||||
|
foreach ($reservedTables as $k => $table_name)
|
||||||
|
$reservedTables[$k] = strtolower($db_prefix . $table_name);
|
||||||
|
|
||||||
|
// We in turn may need the extra stuff.
|
||||||
|
db_extend('extra');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a table.
|
||||||
|
function smf_db_create_table($table_name, $columns, $indexes = array(), $parameters = array(), $if_exists = 'ignore', $error = 'fatal')
|
||||||
|
{
|
||||||
|
global $reservedTables, $smcFunc, $db_package_log, $db_prefix, $db_character_set;
|
||||||
|
|
||||||
|
// Strip out the table name, we might not need it in some cases
|
||||||
|
$real_prefix = preg_match('~^(`?)(.+?)\\1\\.(.*?)$~', $db_prefix, $match) === 1 ? $match[3] : $db_prefix;
|
||||||
|
|
||||||
|
// With or without the database name, the fullname looks like this.
|
||||||
|
$full_table_name = str_replace('{db_prefix}', $real_prefix, $table_name);
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
// First - no way do we touch SMF tables.
|
||||||
|
if (in_array(strtolower($table_name), $reservedTables))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Log that we'll want to remove this on uninstall.
|
||||||
|
$db_package_log[] = array('remove_table', $table_name);
|
||||||
|
|
||||||
|
// Slightly easier on MySQL than the others...
|
||||||
|
$tables = $smcFunc['db_list_tables']();
|
||||||
|
if (in_array($full_table_name, $tables))
|
||||||
|
{
|
||||||
|
// This is a sad day... drop the table? If not, return false (error) by default.
|
||||||
|
if ($if_exists == 'overwrite')
|
||||||
|
$smcFunc['db_drop_table']($table_name);
|
||||||
|
else
|
||||||
|
return $if_exists == 'ignore';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Righty - let's do the damn thing!
|
||||||
|
$table_query = 'CREATE TABLE ' . $table_name . "\n" . '(';
|
||||||
|
foreach ($columns as $column)
|
||||||
|
{
|
||||||
|
// Auto increment is easy here!
|
||||||
|
if (!empty($column['auto']))
|
||||||
|
{
|
||||||
|
$default = 'auto_increment';
|
||||||
|
}
|
||||||
|
elseif (isset($column['default']) && $column['default'] !== null)
|
||||||
|
$default = 'default \'' . $smcFunc['db_escape_string']($column['default']) . '\'';
|
||||||
|
else
|
||||||
|
$default = '';
|
||||||
|
|
||||||
|
// Sort out the size... and stuff...
|
||||||
|
$column['size'] = isset($column['size']) && is_numeric($column['size']) ? $column['size'] : null;
|
||||||
|
list ($type, $size) = $smcFunc['db_calculate_type']($column['type'], $column['size']);
|
||||||
|
|
||||||
|
// Allow unsigned integers (mysql only)
|
||||||
|
$unsigned = in_array($type, array('int', 'tinyint', 'smallint', 'mediumint', 'bigint')) && !empty($column['unsigned']) ? 'unsigned ' : '';
|
||||||
|
|
||||||
|
if ($size !== null)
|
||||||
|
$type = $type . '(' . $size . ')';
|
||||||
|
|
||||||
|
// Now just put it together!
|
||||||
|
$table_query .= "\n\t`" .$column['name'] . '` ' . $type . ' ' . (!empty($unsigned) ? $unsigned : '') . (!empty($column['null']) ? '' : 'NOT NULL') . ' ' . $default . ',';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop through the indexes next...
|
||||||
|
foreach ($indexes as $index)
|
||||||
|
{
|
||||||
|
$columns = implode(',', $index['columns']);
|
||||||
|
|
||||||
|
// Is it the primary?
|
||||||
|
if (isset($index['type']) && $index['type'] == 'primary')
|
||||||
|
$table_query .= "\n\t" . 'PRIMARY KEY (' . implode(',', $index['columns']) . '),';
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (empty($index['name']))
|
||||||
|
$index['name'] = implode('_', $index['columns']);
|
||||||
|
$table_query .= "\n\t" . (isset($index['type']) && $index['type'] == 'unique' ? 'UNIQUE' : 'KEY') . ' ' . $index['name'] . ' (' . $columns . '),';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No trailing commas!
|
||||||
|
if (substr($table_query, -1) == ',')
|
||||||
|
$table_query = substr($table_query, 0, -1);
|
||||||
|
|
||||||
|
$table_query .= ') ENGINE=MyISAM';
|
||||||
|
if (!empty($db_character_set) && $db_character_set == 'utf8')
|
||||||
|
$table_query .= ' DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci';
|
||||||
|
|
||||||
|
// Create the table!
|
||||||
|
$smcFunc['db_query']('', $table_query,
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drop a table.
|
||||||
|
function smf_db_drop_table($table_name, $parameters = array(), $error = 'fatal')
|
||||||
|
{
|
||||||
|
global $reservedTables, $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
// After stripping away the database name, this is what's left.
|
||||||
|
$real_prefix = preg_match('~^(`?)(.+?)\\1\\.(.*?)$~', $db_prefix, $match) === 1 ? $match[3] : $db_prefix;
|
||||||
|
|
||||||
|
// Get some aliases.
|
||||||
|
$full_table_name = str_replace('{db_prefix}', $real_prefix, $table_name);
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
// God no - dropping one of these = bad.
|
||||||
|
if (in_array(strtolower($table_name), $reservedTables))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Does it exist?
|
||||||
|
if (in_array($full_table_name, $smcFunc['db_list_tables']()))
|
||||||
|
{
|
||||||
|
$query = 'DROP TABLE ' . $table_name;
|
||||||
|
$smcFunc['db_query']('',
|
||||||
|
$query,
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise do 'nout.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a column.
|
||||||
|
function smf_db_add_column($table_name, $column_info, $parameters = array(), $if_exists = 'update', $error = 'fatal')
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_package_log, $txt, $db_prefix;
|
||||||
|
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
// Log that we will want to uninstall this!
|
||||||
|
$db_package_log[] = array('remove_column', $table_name, $column_info['name']);
|
||||||
|
|
||||||
|
// Does it exist - if so don't add it again!
|
||||||
|
$columns = $smcFunc['db_list_columns']($table_name, false);
|
||||||
|
foreach ($columns as $column)
|
||||||
|
if ($column == $column_info['name'])
|
||||||
|
{
|
||||||
|
// If we're going to overwrite then use change column.
|
||||||
|
if ($if_exists == 'update')
|
||||||
|
return $smcFunc['db_change_column']($table_name, $column_info['name'], $column_info);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the specifics...
|
||||||
|
$column_info['size'] = isset($column_info['size']) && is_numeric($column_info['size']) ? $column_info['size'] : null;
|
||||||
|
list ($type, $size) = $smcFunc['db_calculate_type']($column_info['type'], $column_info['size']);
|
||||||
|
|
||||||
|
// Allow unsigned integers (mysql only)
|
||||||
|
$unsigned = in_array($type, array('int', 'tinyint', 'smallint', 'mediumint', 'bigint')) && !empty($column_info['unsigned']) ? 'unsigned ' : '';
|
||||||
|
|
||||||
|
if ($size !== null)
|
||||||
|
$type = $type . '(' . $size . ')';
|
||||||
|
|
||||||
|
// Now add the thing!
|
||||||
|
$query = '
|
||||||
|
ALTER TABLE ' . $table_name . '
|
||||||
|
ADD `' . $column_info['name'] . '` ' . $type . ' ' . (!empty($unsigned) ? $unsigned : '') . (empty($column_info['null']) ? 'NOT NULL' : '') . ' ' .
|
||||||
|
(!isset($column_info['default']) ? '' : 'default \'' . $smcFunc['db_escape_string']($column_info['default']) . '\'') . ' ' .
|
||||||
|
(empty($column_info['auto']) ? '' : 'auto_increment primary key') . ' ';
|
||||||
|
$smcFunc['db_query']('', $query,
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove a column.
|
||||||
|
function smf_db_remove_column($table_name, $column_name, $parameters = array(), $error = 'fatal')
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
// Does it exist?
|
||||||
|
$columns = $smcFunc['db_list_columns']($table_name, true);
|
||||||
|
foreach ($columns as $column)
|
||||||
|
if ($column['name'] == $column_name)
|
||||||
|
{
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
ALTER TABLE ' . $table_name . '
|
||||||
|
DROP COLUMN ' . $column_name,
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If here we didn't have to work - joy!
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change a column.
|
||||||
|
function smf_db_change_column($table_name, $old_column, $column_info, $parameters = array(), $error = 'fatal')
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
// Check it does exist!
|
||||||
|
$columns = $smcFunc['db_list_columns']($table_name, true);
|
||||||
|
$old_info = null;
|
||||||
|
foreach ($columns as $column)
|
||||||
|
if ($column['name'] == $old_column)
|
||||||
|
$old_info = $column;
|
||||||
|
|
||||||
|
// Nothing?
|
||||||
|
if ($old_info == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Get the right bits.
|
||||||
|
if (!isset($column_info['name']))
|
||||||
|
$column_info['name'] = $old_column;
|
||||||
|
if (!isset($column_info['default']))
|
||||||
|
$column_info['default'] = $old_info['default'];
|
||||||
|
if (!isset($column_info['null']))
|
||||||
|
$column_info['null'] = $old_info['null'];
|
||||||
|
if (!isset($column_info['auto']))
|
||||||
|
$column_info['auto'] = $old_info['auto'];
|
||||||
|
if (!isset($column_info['type']))
|
||||||
|
$column_info['type'] = $old_info['type'];
|
||||||
|
if (!isset($column_info['size']) || !is_numeric($column_info['size']))
|
||||||
|
$column_info['size'] = $old_info['size'];
|
||||||
|
if (!isset($column_info['unsigned']) || !in_array($column_info['type'], array('int', 'tinyint', 'smallint', 'mediumint', 'bigint')))
|
||||||
|
$column_info['unsigned'] = '';
|
||||||
|
|
||||||
|
list ($type, $size) = $smcFunc['db_calculate_type']($column_info['type'], $column_info['size']);
|
||||||
|
|
||||||
|
// Allow for unsigned integers (mysql only)
|
||||||
|
$unsigned = in_array($type, array('int', 'tinyint', 'smallint', 'mediumint', 'bigint')) && !empty($column_info['unsigned']) ? 'unsigned ' : '';
|
||||||
|
|
||||||
|
if ($size !== null)
|
||||||
|
$type = $type . '(' . $size . ')';
|
||||||
|
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
ALTER TABLE ' . $table_name . '
|
||||||
|
CHANGE COLUMN `' . $old_column . '` `' . $column_info['name'] . '` ' . $type . ' ' . (!empty($unsigned) ? $unsigned : '') . (empty($column_info['null']) ? 'NOT NULL' : '') . ' ' .
|
||||||
|
(!isset($column_info['default']) ? '' : 'default \'' . $smcFunc['db_escape_string']($column_info['default']) . '\'') . ' ' .
|
||||||
|
(empty($column_info['auto']) ? '' : 'auto_increment') . ' ',
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add an index.
|
||||||
|
function smf_db_add_index($table_name, $index_info, $parameters = array(), $if_exists = 'update', $error = 'fatal')
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_package_log, $db_prefix;
|
||||||
|
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
// No columns = no index.
|
||||||
|
if (empty($index_info['columns']))
|
||||||
|
return false;
|
||||||
|
$columns = implode(',', $index_info['columns']);
|
||||||
|
|
||||||
|
// No name - make it up!
|
||||||
|
if (empty($index_info['name']))
|
||||||
|
{
|
||||||
|
// No need for primary.
|
||||||
|
if (isset($index_info['type']) && $index_info['type'] == 'primary')
|
||||||
|
$index_info['name'] = '';
|
||||||
|
else
|
||||||
|
$index_info['name'] = implode('_', $index_info['columns']);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$index_info['name'] = $index_info['name'];
|
||||||
|
|
||||||
|
// Log that we are going to want to remove this!
|
||||||
|
$db_package_log[] = array('remove_index', $table_name, $index_info['name']);
|
||||||
|
|
||||||
|
// Let's get all our indexes.
|
||||||
|
$indexes = $smcFunc['db_list_indexes']($table_name, true);
|
||||||
|
// Do we already have it?
|
||||||
|
foreach ($indexes as $index)
|
||||||
|
{
|
||||||
|
if ($index['name'] == $index_info['name'] || ($index['type'] == 'primary' && isset($index_info['type']) && $index_info['type'] == 'primary'))
|
||||||
|
{
|
||||||
|
// If we want to overwrite simply remove the current one then continue.
|
||||||
|
if ($if_exists != 'update' || $index['type'] == 'primary')
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
$smcFunc['db_remove_index']($table_name, $index_info['name']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're here we know we don't have the index - so just add it.
|
||||||
|
if (!empty($index_info['type']) && $index_info['type'] == 'primary')
|
||||||
|
{
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
ALTER TABLE ' . $table_name . '
|
||||||
|
ADD PRIMARY KEY (' . $columns . ')',
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
ALTER TABLE ' . $table_name . '
|
||||||
|
ADD ' . (isset($index_info['type']) && $index_info['type'] == 'unique' ? 'UNIQUE' : 'INDEX') . ' ' . $index_info['name'] . ' (' . $columns . ')',
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove an index.
|
||||||
|
function smf_db_remove_index($table_name, $index_name, $parameters = array(), $error = 'fatal')
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
// Better exist!
|
||||||
|
$indexes = $smcFunc['db_list_indexes']($table_name, true);
|
||||||
|
|
||||||
|
foreach ($indexes as $index)
|
||||||
|
{
|
||||||
|
// If the name is primary we want the primary key!
|
||||||
|
if ($index['type'] == 'primary' && $index_name == 'primary')
|
||||||
|
{
|
||||||
|
// Dropping primary key?
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
ALTER TABLE ' . $table_name . '
|
||||||
|
DROP PRIMARY KEY',
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ($index['name'] == $index_name)
|
||||||
|
{
|
||||||
|
// Drop the bugger...
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
ALTER TABLE ' . $table_name . '
|
||||||
|
DROP INDEX ' . $index_name,
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not to be found ;(
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the schema formatted name for a type.
|
||||||
|
function smf_db_calculate_type($type_name, $type_size = null, $reverse = false)
|
||||||
|
{
|
||||||
|
// MySQL is actually the generic baseline.
|
||||||
|
return array($type_name, $type_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get table structure.
|
||||||
|
function smf_db_table_structure($table_name, $parameters = array())
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'name' => $table_name,
|
||||||
|
'columns' => $smcFunc['db_list_columns']($table_name, true),
|
||||||
|
'indexes' => $smcFunc['db_list_indexes']($table_name, true),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return column information for a table.
|
||||||
|
function smf_db_list_columns($table_name, $detail = false, $parameters = array())
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
$result = $smcFunc['db_query']('', '
|
||||||
|
SHOW FIELDS
|
||||||
|
FROM {raw:table_name}',
|
||||||
|
array(
|
||||||
|
'table_name' => substr($table_name, 0, 1) == '`' ? $table_name : '`' . $table_name . '`',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$columns = array();
|
||||||
|
while ($row = $smcFunc['db_fetch_assoc']($result))
|
||||||
|
{
|
||||||
|
if (!$detail)
|
||||||
|
{
|
||||||
|
$columns[] = $row['Field'];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Is there an auto_increment?
|
||||||
|
$auto = strpos($row['Extra'], 'auto_increment') !== false ? true : false;
|
||||||
|
|
||||||
|
// Can we split out the size?
|
||||||
|
if (preg_match('~(.+?)\s*\((\d+)\)(?:(?:\s*)?(unsigned))?~i', $row['Type'], $matches) === 1)
|
||||||
|
{
|
||||||
|
$type = $matches[1];
|
||||||
|
$size = $matches[2];
|
||||||
|
if (!empty($matches[3]) && $matches[3] == 'unsigned')
|
||||||
|
$unsigned = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$type = $row['Type'];
|
||||||
|
$size = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$columns[$row['Field']] = array(
|
||||||
|
'name' => $row['Field'],
|
||||||
|
'null' => $row['Null'] != 'YES' ? false : true,
|
||||||
|
'default' => isset($row['Default']) ? $row['Default'] : null,
|
||||||
|
'type' => $type,
|
||||||
|
'size' => $size,
|
||||||
|
'auto' => $auto,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isset($unsigned))
|
||||||
|
{
|
||||||
|
$columns[$row['Field']]['unsigned'] = $unsigned;
|
||||||
|
unset($unsigned);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$smcFunc['db_free_result']($result);
|
||||||
|
|
||||||
|
return $columns;
|
||||||
|
}
|
||||||
|
|
||||||
|
// What about some index information?
|
||||||
|
function smf_db_list_indexes($table_name, $detail = false, $parameters = array())
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
$result = $smcFunc['db_query']('', '
|
||||||
|
SHOW KEYS
|
||||||
|
FROM {raw:table_name}',
|
||||||
|
array(
|
||||||
|
'table_name' => substr($table_name, 0, 1) == '`' ? $table_name : '`' . $table_name . '`',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$indexes = array();
|
||||||
|
while ($row = $smcFunc['db_fetch_assoc']($result))
|
||||||
|
{
|
||||||
|
if (!$detail)
|
||||||
|
$indexes[] = $row['Key_name'];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// What is the type?
|
||||||
|
if ($row['Key_name'] == 'PRIMARY')
|
||||||
|
$type = 'primary';
|
||||||
|
elseif (empty($row['Non_unique']))
|
||||||
|
$type = 'unique';
|
||||||
|
elseif (isset($row['Index_type']) && $row['Index_type'] == 'FULLTEXT')
|
||||||
|
$type = 'fulltext';
|
||||||
|
else
|
||||||
|
$type = 'index';
|
||||||
|
|
||||||
|
// This is the first column we've seen?
|
||||||
|
if (empty($indexes[$row['Key_name']]))
|
||||||
|
{
|
||||||
|
$indexes[$row['Key_name']] = array(
|
||||||
|
'name' => $row['Key_name'],
|
||||||
|
'type' => $type,
|
||||||
|
'columns' => array(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is it a partial index?
|
||||||
|
if (!empty($row['Sub_part']))
|
||||||
|
$indexes[$row['Key_name']]['columns'][] = $row['Column_name'] . '(' . $row['Sub_part'] . ')';
|
||||||
|
else
|
||||||
|
$indexes[$row['Key_name']]['columns'][] = $row['Column_name'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$smcFunc['db_free_result']($result);
|
||||||
|
|
||||||
|
return $indexes;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
746
Sources/DbPackages-postgresql.php
Normal file
@ -0,0 +1,746 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple Machines Forum (SMF)
|
||||||
|
*
|
||||||
|
* @package SMF
|
||||||
|
* @author Simple Machines http://www.simplemachines.org
|
||||||
|
* @copyright 2011 Simple Machines
|
||||||
|
* @license http://www.simplemachines.org/about/smf/license.php BSD
|
||||||
|
*
|
||||||
|
* @version 2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('SMF'))
|
||||||
|
die('Hacking attempt...');
|
||||||
|
|
||||||
|
/* This file contains database functionality specifically designed for packages to utilize.
|
||||||
|
|
||||||
|
bool smf_db_create_table(string table_name, array columns, array indexes = array(),
|
||||||
|
array parameters = array(), string if_exists = 'ignore')
|
||||||
|
- Can be used to create a table without worrying about schema compatabilities.
|
||||||
|
- If the table exists will, by default, do nothing.
|
||||||
|
- Builds table with columns as passed to it - at least one column must be sent.
|
||||||
|
The columns array should have one sub-array for each column - these sub arrays contain:
|
||||||
|
+ 'name' = Column name
|
||||||
|
+ 'type' = Type of column - values from (smallint,mediumint,int,text,varchar,char,tinytext,mediumtext,largetext)
|
||||||
|
+ 'size' => Size of column (If applicable) - for example 255 for a large varchar, 10 for an int etc. If not
|
||||||
|
set SMF will pick a size.
|
||||||
|
+ 'default' = Default value - do not set if no default required.
|
||||||
|
+ 'null' => Can it be null (true or false) - if not set default will be false.
|
||||||
|
+ 'auto' => Set to true to make it an auto incrementing column. Set to a numerical value to set
|
||||||
|
from what it should begin counting.
|
||||||
|
- Adds indexes as specified within indexes parameter. Each index should be a member of $indexes. Values are:
|
||||||
|
+ 'name' => Index name (If left empty SMF will generate).
|
||||||
|
+ 'type' => Type of index. Choose from 'primary', 'unique' or 'index'. If not set will default to 'index'.
|
||||||
|
+ 'columns' => Array containing columns that form part of key - in the order the index is to be created.
|
||||||
|
- parameters: (None yet)
|
||||||
|
- if_exists values:
|
||||||
|
+ 'ignore' will do nothing if the table exists. (And will return true)
|
||||||
|
+ 'overwrite' will drop any existing table of the same name.
|
||||||
|
+ 'error' will return false if the table already exists.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Add the file functions to the $smcFunc array.
|
||||||
|
function db_packages_init()
|
||||||
|
{
|
||||||
|
global $smcFunc, $reservedTables, $db_package_log, $db_prefix;
|
||||||
|
|
||||||
|
if (!isset($smcFunc['db_create_table']) || $smcFunc['db_create_table'] != 'smf_db_create_table')
|
||||||
|
{
|
||||||
|
$smcFunc += array(
|
||||||
|
'db_add_column' => 'smf_db_add_column',
|
||||||
|
'db_add_index' => 'smf_db_add_index',
|
||||||
|
'db_calculate_type' => 'smf_db_calculate_type',
|
||||||
|
'db_change_column' => 'smf_db_change_column',
|
||||||
|
'db_create_table' => 'smf_db_create_table',
|
||||||
|
'db_drop_table' => 'smf_db_drop_table',
|
||||||
|
'db_table_structure' => 'smf_db_table_structure',
|
||||||
|
'db_list_columns' => 'smf_db_list_columns',
|
||||||
|
'db_list_indexes' => 'smf_db_list_indexes',
|
||||||
|
'db_remove_column' => 'smf_db_remove_column',
|
||||||
|
'db_remove_index' => 'smf_db_remove_index',
|
||||||
|
);
|
||||||
|
$db_package_log = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
// We setup an array of SMF tables we can't do auto-remove on - in case a mod writer cocks it up!
|
||||||
|
$reservedTables = array('admin_info_files', 'approval_queue', 'attachments', 'ban_groups', 'ban_items',
|
||||||
|
'board_permissions', 'boards', 'calendar', 'calendar_holidays', 'categories', 'collapsed_categories',
|
||||||
|
'custom_fields', 'group_moderators', 'log_actions', 'log_activity', 'log_banned', 'log_boards',
|
||||||
|
'log_digest', 'log_errors', 'log_floodcontrol', 'log_group_requests', 'log_karma', 'log_mark_read',
|
||||||
|
'log_notify', 'log_online', 'log_packages', 'log_polls', 'log_reported', 'log_reported_comments',
|
||||||
|
'log_scheduled_tasks', 'log_search_messages', 'log_search_results', 'log_search_subjects',
|
||||||
|
'log_search_topics', 'log_topics', 'mail_queue', 'membergroups', 'members', 'message_icons',
|
||||||
|
'messages', 'moderators', 'package_servers', 'permission_profiles', 'permissions', 'personal_messages',
|
||||||
|
'pm_recipients', 'poll_choices', 'polls', 'scheduled_tasks', 'sessions', 'settings', 'smileys',
|
||||||
|
'themes', 'topics');
|
||||||
|
foreach ($reservedTables as $k => $table_name)
|
||||||
|
$reservedTables[$k] = strtolower($db_prefix . $table_name);
|
||||||
|
|
||||||
|
// We in turn may need the extra stuff.
|
||||||
|
db_extend('extra');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a table.
|
||||||
|
function smf_db_create_table($table_name, $columns, $indexes = array(), $parameters = array(), $if_exists = 'ignore', $error = 'fatal')
|
||||||
|
{
|
||||||
|
global $reservedTables, $smcFunc, $db_package_log, $db_prefix;
|
||||||
|
|
||||||
|
// Strip out the table name, we might not need it in some cases
|
||||||
|
$real_prefix = preg_match('~^("?)(.+?)\\1\\.(.*?)$~', $db_prefix, $match) === 1 ? $match[3] : $db_prefix;
|
||||||
|
|
||||||
|
// With or without the database name, the fullname looks like this.
|
||||||
|
$full_table_name = str_replace('{db_prefix}', $real_prefix, $table_name);
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
// First - no way do we touch SMF tables.
|
||||||
|
if (in_array(strtolower($table_name), $reservedTables))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Log that we'll want to remove this on uninstall.
|
||||||
|
$db_package_log[] = array('remove_table', $table_name);
|
||||||
|
|
||||||
|
// This... my friends... is a function in a half - let's start by checking if the table exists!
|
||||||
|
$tables = $smcFunc['db_list_tables']();
|
||||||
|
if (in_array($full_table_name, $tables))
|
||||||
|
{
|
||||||
|
// This is a sad day... drop the table? If not, return false (error) by default.
|
||||||
|
if ($if_exists == 'overwrite')
|
||||||
|
$smcFunc['db_drop_table']($table_name);
|
||||||
|
else
|
||||||
|
return $if_exists == 'ignore';
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we've got this far - good news - no table exists. We can build our own!
|
||||||
|
$smcFunc['db_transaction']('begin');
|
||||||
|
$table_query = 'CREATE TABLE ' . $table_name . "\n" . '(';
|
||||||
|
foreach ($columns as $column)
|
||||||
|
{
|
||||||
|
// If we have an auto increment do it!
|
||||||
|
if (!empty($column['auto']))
|
||||||
|
{
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
CREATE SEQUENCE ' . $table_name . '_seq',
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$default = 'default nextval(\'' . $table_name . '_seq\')';
|
||||||
|
}
|
||||||
|
elseif (isset($column['default']) && $column['default'] !== null)
|
||||||
|
$default = 'default \'' . $smcFunc['db_escape_string']($column['default']) . '\'';
|
||||||
|
else
|
||||||
|
$default = '';
|
||||||
|
|
||||||
|
// Sort out the size...
|
||||||
|
$column['size'] = isset($column['size']) && is_numeric($column['size']) ? $column['size'] : null;
|
||||||
|
list ($type, $size) = $smcFunc['db_calculate_type']($column['type'], $column['size']);
|
||||||
|
if ($size !== null)
|
||||||
|
$type = $type . '(' . $size . ')';
|
||||||
|
|
||||||
|
// Now just put it together!
|
||||||
|
$table_query .= "\n\t\"" . $column['name'] . '" ' . $type . ' ' . (!empty($column['null']) ? '' : 'NOT NULL') . ' ' . $default . ',';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop through the indexes a sec...
|
||||||
|
$index_queries = array();
|
||||||
|
foreach ($indexes as $index)
|
||||||
|
{
|
||||||
|
$columns = implode(',', $index['columns']);
|
||||||
|
|
||||||
|
// Primary goes in the table...
|
||||||
|
if (isset($index['type']) && $index['type'] == 'primary')
|
||||||
|
$table_query .= "\n\t" . 'PRIMARY KEY (' . implode(',', $index['columns']) . '),';
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (empty($index['name']))
|
||||||
|
$index['name'] = implode('_', $index['columns']);
|
||||||
|
$index_queries[] = 'CREATE ' . (isset($index['type']) && $index['type'] == 'unique' ? 'UNIQUE' : '') . ' INDEX ' . $table_name . '_' . $index['name'] . ' ON ' . $table_name . ' (' . $columns . ')';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No trailing commas!
|
||||||
|
if (substr($table_query, -1) == ',')
|
||||||
|
$table_query = substr($table_query, 0, -1);
|
||||||
|
|
||||||
|
$table_query .= ')';
|
||||||
|
|
||||||
|
// Create the table!
|
||||||
|
$smcFunc['db_query']('', $table_query,
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
// And the indexes...
|
||||||
|
foreach ($index_queries as $query)
|
||||||
|
$smcFunc['db_query']('', $query,
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Go, go power rangers!
|
||||||
|
$smcFunc['db_transaction']('commit');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drop a table.
|
||||||
|
function smf_db_drop_table($table_name, $parameters = array(), $error = 'fatal')
|
||||||
|
{
|
||||||
|
global $reservedTables, $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
// After stripping away the database name, this is what's left.
|
||||||
|
$real_prefix = preg_match('~^("?)(.+?)\\1\\.(.*?)$~', $db_prefix, $match) === 1 ? $match[3] : $db_prefix;
|
||||||
|
|
||||||
|
// Get some aliases.
|
||||||
|
$full_table_name = str_replace('{db_prefix}', $real_prefix, $table_name);
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
// God no - dropping one of these = bad.
|
||||||
|
if (in_array(strtolower($table_name), $reservedTables))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Does it exist?
|
||||||
|
if (in_array($full_table_name, $smcFunc['db_list_tables']()))
|
||||||
|
{
|
||||||
|
// We can then drop the table.
|
||||||
|
$smcFunc['db_transaction']('begin');
|
||||||
|
|
||||||
|
// the table
|
||||||
|
$table_query = 'DROP TABLE ' . $table_name;
|
||||||
|
|
||||||
|
// and the assosciated sequence, if any
|
||||||
|
$sequence_query = 'DROP SEQUENCE IF EXISTS ' . $table_name . '_seq';
|
||||||
|
|
||||||
|
// drop them
|
||||||
|
$smcFunc['db_query']('',
|
||||||
|
$table_query,
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$smcFunc['db_query']('',
|
||||||
|
$sequence_query,
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$smcFunc['db_transaction']('commit');
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise do 'nout.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a column.
|
||||||
|
function smf_db_add_column($table_name, $column_info, $parameters = array(), $if_exists = 'update', $error = 'fatal')
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_package_log, $txt, $db_prefix;
|
||||||
|
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
// Log that we will want to uninstall this!
|
||||||
|
$db_package_log[] = array('remove_column', $table_name, $column_info['name']);
|
||||||
|
|
||||||
|
// Does it exist - if so don't add it again!
|
||||||
|
$columns = $smcFunc['db_list_columns']($table_name, false);
|
||||||
|
foreach ($columns as $column)
|
||||||
|
if ($column == $column_info['name'])
|
||||||
|
{
|
||||||
|
// If we're going to overwrite then use change column.
|
||||||
|
if ($if_exists == 'update')
|
||||||
|
return $smcFunc['db_change_column']($table_name, $column_info['name'], $column_info);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the specifics...
|
||||||
|
$column_info['size'] = isset($column_info['size']) && is_numeric($column_info['size']) ? $column_info['size'] : null;
|
||||||
|
list ($type, $size) = $smcFunc['db_calculate_type']($column_info['type'], $column_info['size']);
|
||||||
|
if ($size !== null)
|
||||||
|
$type = $type . '(' . $size . ')';
|
||||||
|
|
||||||
|
// Now add the thing!
|
||||||
|
$query = '
|
||||||
|
ALTER TABLE ' . $table_name . '
|
||||||
|
ADD COLUMN ' . $column_info['name'] . ' ' . $type;
|
||||||
|
$smcFunc['db_query']('', $query,
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// If there's more attributes they need to be done via a change on PostgreSQL.
|
||||||
|
unset($column_info['type'], $column_info['size']);
|
||||||
|
|
||||||
|
if (count($column_info) != 1)
|
||||||
|
return $smcFunc['db_change_column']($table_name, $column_info['name'], $column_info);
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove a column.
|
||||||
|
function smf_db_remove_column($table_name, $column_name, $parameters = array(), $error = 'fatal')
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
// Does it exist?
|
||||||
|
$columns = $smcFunc['db_list_columns']($table_name, true);
|
||||||
|
foreach ($columns as $column)
|
||||||
|
if ($column['name'] == $column_name)
|
||||||
|
{
|
||||||
|
// If there is an auto we need remove it!
|
||||||
|
if ($column['auto'])
|
||||||
|
$smcFunc['db_query']('',
|
||||||
|
'DROP SEQUENCE ' . $table_name . '_seq',
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
ALTER TABLE ' . $table_name . '
|
||||||
|
DROP COLUMN ' . $column_name,
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If here we didn't have to work - joy!
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change a column.
|
||||||
|
function smf_db_change_column($table_name, $old_column, $column_info, $parameters = array(), $error = 'fatal')
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
// Check it does exist!
|
||||||
|
$columns = $smcFunc['db_list_columns']($table_name, true);
|
||||||
|
$old_info = null;
|
||||||
|
foreach ($columns as $column)
|
||||||
|
if ($column['name'] == $old_column)
|
||||||
|
$old_info = $column;
|
||||||
|
|
||||||
|
// Nothing?
|
||||||
|
if ($old_info == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Now we check each bit individually and ALTER as required.
|
||||||
|
if (isset($column_info['name']) && $column_info['name'] != $old_column)
|
||||||
|
{
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
ALTER TABLE ' . $table_name . '
|
||||||
|
RENAME COLUMN ' . $old_column . ' TO ' . $column_info['name'],
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Different default?
|
||||||
|
if (isset($column_info['default']) && $column_info['default'] != $old_info['default'])
|
||||||
|
{
|
||||||
|
$action = $column_info['default'] !== null ? 'SET DEFAULT \'' . $smcFunc['db_escape_string']($column_info['default']) . '\'' : 'DROP DEFAULT';
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
ALTER TABLE ' . $table_name . '
|
||||||
|
ALTER COLUMN ' . $column_info['name'] . ' ' . $action,
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Is it null - or otherwise?
|
||||||
|
if (isset($column_info['null']) && $column_info['null'] != $old_info['null'])
|
||||||
|
{
|
||||||
|
$action = $column_info['null'] ? 'DROP' : 'SET';
|
||||||
|
$smcFunc['db_transaction']('begin');
|
||||||
|
if (!$column_info['null'])
|
||||||
|
{
|
||||||
|
// We have to set it to something if we are making it NOT NULL.
|
||||||
|
$setTo = isset($column_info['default']) ? $column_info['default'] : '';
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
UPDATE ' . $table_name . '
|
||||||
|
SET ' . $column_info['name'] . ' = \'' . $setTo . '\'
|
||||||
|
WHERE ' . $column_info['name'] . ' = NULL',
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
ALTER TABLE ' . $table_name . '
|
||||||
|
ALTER COLUMN ' . $column_info['name'] . ' ' . $action . ' NOT NULL',
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$smcFunc['db_transaction']('commit');
|
||||||
|
}
|
||||||
|
// What about a change in type?
|
||||||
|
if (isset($column_info['type']) && ($column_info['type'] != $old_info['type'] || (isset($column_info['size']) && $column_info['size'] != $old_info['size'])))
|
||||||
|
{
|
||||||
|
$column_info['size'] = isset($column_info['size']) && is_numeric($column_info['size']) ? $column_info['size'] : null;
|
||||||
|
list ($type, $size) = $smcFunc['db_calculate_type']($column_info['type'], $column_info['size']);
|
||||||
|
if ($size !== null)
|
||||||
|
$type = $type . '(' . $size . ')';
|
||||||
|
|
||||||
|
// The alter is a pain.
|
||||||
|
$smcFunc['db_transaction']('begin');
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
ALTER TABLE ' . $table_name . '
|
||||||
|
ADD COLUMN ' . $column_info['name'] . '_tempxx ' . $type,
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
UPDATE ' . $table_name . '
|
||||||
|
SET ' . $column_info['name'] . '_tempxx = CAST(' . $column_info['name'] . ' AS ' . $type . ')',
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
ALTER TABLE ' . $table_name . '
|
||||||
|
DROP COLUMN ' . $column_info['name'],
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
ALTER TABLE ' . $table_name . '
|
||||||
|
RENAME COLUMN ' . $column_info['name'] . '_tempxx TO ' . $column_info['name'],
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$smcFunc['db_transaction']('commit');
|
||||||
|
}
|
||||||
|
// Finally - auto increment?!
|
||||||
|
if (isset($column_info['auto']) && $column_info['auto'] != $old_info['auto'])
|
||||||
|
{
|
||||||
|
// Are we removing an old one?
|
||||||
|
if ($old_info['auto'])
|
||||||
|
{
|
||||||
|
// Alter the table first - then drop the sequence.
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
ALTER TABLE ' . $table_name . '
|
||||||
|
ALTER COLUMN ' . $column_info['name'] . ' SET DEFAULT \'0\'',
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
DROP SEQUENCE ' . $table_name . '_seq',
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Otherwise add it!
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
CREATE SEQUENCE ' . $table_name . '_seq',
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
ALTER TABLE ' . $table_name . '
|
||||||
|
ALTER COLUMN ' . $column_info['name'] . ' SET DEFAULT nextval(\'' . $table_name . '_seq\')',
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add an index.
|
||||||
|
function smf_db_add_index($table_name, $index_info, $parameters = array(), $if_exists = 'update', $error = 'fatal')
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_package_log, $db_prefix;
|
||||||
|
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
// No columns = no index.
|
||||||
|
if (empty($index_info['columns']))
|
||||||
|
return false;
|
||||||
|
$columns = implode(',', $index_info['columns']);
|
||||||
|
|
||||||
|
// No name - make it up!
|
||||||
|
if (empty($index_info['name']))
|
||||||
|
{
|
||||||
|
// No need for primary.
|
||||||
|
if (isset($index_info['type']) && $index_info['type'] == 'primary')
|
||||||
|
$index_info['name'] = '';
|
||||||
|
else
|
||||||
|
$index_info['name'] = $table_name . implode('_', $index_info['columns']);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$index_info['name'] = $table_name . $index_info['name'];
|
||||||
|
|
||||||
|
// Log that we are going to want to remove this!
|
||||||
|
$db_package_log[] = array('remove_index', $table_name, $index_info['name']);
|
||||||
|
|
||||||
|
// Let's get all our indexes.
|
||||||
|
$indexes = $smcFunc['db_list_indexes']($table_name, true);
|
||||||
|
// Do we already have it?
|
||||||
|
foreach ($indexes as $index)
|
||||||
|
{
|
||||||
|
if ($index['name'] == $index_info['name'] || ($index['type'] == 'primary' && isset($index_info['type']) && $index_info['type'] == 'primary'))
|
||||||
|
{
|
||||||
|
// If we want to overwrite simply remove the current one then continue.
|
||||||
|
if ($if_exists != 'update' || $index['type'] == 'primary')
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
$smcFunc['db_remove_index']($table_name, $index_info['name']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're here we know we don't have the index - so just add it.
|
||||||
|
if (!empty($index_info['type']) && $index_info['type'] == 'primary')
|
||||||
|
{
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
ALTER TABLE ' . $table_name . '
|
||||||
|
ADD PRIMARY KEY (' . $columns . ')',
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
CREATE ' . (isset($index_info['type']) && $index_info['type'] == 'unique' ? 'UNIQUE' : '') . ' INDEX ' . $index_info['name'] . ' ON ' . $table_name . ' (' . $columns . ')',
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove an index.
|
||||||
|
function smf_db_remove_index($table_name, $index_name, $parameters = array(), $error = 'fatal')
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
// Better exist!
|
||||||
|
$indexes = $smcFunc['db_list_indexes']($table_name, true);
|
||||||
|
if ($index_name != 'primary')
|
||||||
|
$index_name = $table_name . '_' . $index_name;
|
||||||
|
|
||||||
|
foreach ($indexes as $index)
|
||||||
|
{
|
||||||
|
// If the name is primary we want the primary key!
|
||||||
|
if ($index['type'] == 'primary' && $index_name == 'primary')
|
||||||
|
{
|
||||||
|
// Dropping primary key is odd...
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
ALTER TABLE ' . $table_name . '
|
||||||
|
DROP CONSTRAINT ' . $index['name'],
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ($index['name'] == $index_name)
|
||||||
|
{
|
||||||
|
// Drop the bugger...
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
DROP INDEX ' . $index_name,
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not to be found ;(
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the schema formatted name for a type.
|
||||||
|
function smf_db_calculate_type($type_name, $type_size = null, $reverse = false)
|
||||||
|
{
|
||||||
|
// Generic => Specific.
|
||||||
|
if (!$reverse)
|
||||||
|
{
|
||||||
|
$types = array(
|
||||||
|
'varchar' => 'character varying',
|
||||||
|
'char' => 'character',
|
||||||
|
'mediumint' => 'int',
|
||||||
|
'tinyint' => 'smallint',
|
||||||
|
'tinytext' => 'character varying',
|
||||||
|
'mediumtext' => 'text',
|
||||||
|
'largetext' => 'text',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$types = array(
|
||||||
|
'character varying' => 'varchar',
|
||||||
|
'character' => 'char',
|
||||||
|
'integer' => 'int',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Got it? Change it!
|
||||||
|
if (isset($types[$type_name]))
|
||||||
|
{
|
||||||
|
if ($type_name == 'tinytext')
|
||||||
|
$type_size = 255;
|
||||||
|
$type_name = $types[$type_name];
|
||||||
|
}
|
||||||
|
// Numbers don't have a size.
|
||||||
|
if (strpos($type_name, 'int') !== false)
|
||||||
|
$type_size = null;
|
||||||
|
|
||||||
|
return array($type_name, $type_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get table structure.
|
||||||
|
function smf_db_table_structure($table_name, $parameters = array())
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'name' => $table_name,
|
||||||
|
'columns' => $smcFunc['db_list_columns']($table_name, true),
|
||||||
|
'indexes' => $smcFunc['db_list_indexes']($table_name, true),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return column information for a table.
|
||||||
|
function smf_db_list_columns($table_name, $detail = false, $parameters = array())
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
$result = $smcFunc['db_query']('', '
|
||||||
|
SELECT column_name, column_default, is_nullable, data_type, character_maximum_length
|
||||||
|
FROM information_schema.columns
|
||||||
|
WHERE table_name = \'' . $table_name . '\'
|
||||||
|
ORDER BY ordinal_position',
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$columns = array();
|
||||||
|
while ($row = $smcFunc['db_fetch_assoc']($result))
|
||||||
|
{
|
||||||
|
if (!$detail)
|
||||||
|
{
|
||||||
|
$columns[] = $row['column_name'];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$auto = false;
|
||||||
|
// What is the default?
|
||||||
|
if (preg_match('~nextval\(\'(.+?)\'(.+?)*\)~i', $row['column_default'], $matches) != 0)
|
||||||
|
{
|
||||||
|
$default = null;
|
||||||
|
$auto = true;
|
||||||
|
}
|
||||||
|
elseif (trim($row['column_default']) != '')
|
||||||
|
$default = strpos($row['column_default'], '::') === false ? $row['column_default'] : substr($row['column_default'], 0, strpos($row['column_default'], '::'));
|
||||||
|
else
|
||||||
|
$default = null;
|
||||||
|
|
||||||
|
// Make the type generic.
|
||||||
|
list ($type, $size) = $smcFunc['db_calculate_type']($row['data_type'], $row['character_maximum_length'], true);
|
||||||
|
|
||||||
|
$columns[$row['column_name']] = array(
|
||||||
|
'name' => $row['column_name'],
|
||||||
|
'null' => $row['is_nullable'] ? true : false,
|
||||||
|
'default' => $default,
|
||||||
|
'type' => $type,
|
||||||
|
'size' => $size,
|
||||||
|
'auto' => $auto,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$smcFunc['db_free_result']($result);
|
||||||
|
|
||||||
|
return $columns;
|
||||||
|
}
|
||||||
|
|
||||||
|
// What about some index information?
|
||||||
|
function smf_db_list_indexes($table_name, $detail = false, $parameters = array())
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
$result = $smcFunc['db_query']('', '
|
||||||
|
SELECT CASE WHEN i.indisprimary THEN 1 ELSE 0 END AS is_primary,
|
||||||
|
CASE WHEN i.indisunique THEN 1 ELSE 0 END AS is_unique,
|
||||||
|
c2.relname AS name,
|
||||||
|
pg_get_indexdef(i.indexrelid) AS inddef
|
||||||
|
FROM pg_class AS c, pg_class AS c2, pg_index AS i
|
||||||
|
WHERE c.relname = \'' . $table_name . '\'
|
||||||
|
AND c.oid = i.indrelid
|
||||||
|
AND i.indexrelid = c2.oid',
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$indexes = array();
|
||||||
|
while ($row = $smcFunc['db_fetch_assoc']($result))
|
||||||
|
{
|
||||||
|
// Try get the columns that make it up.
|
||||||
|
if (preg_match('~\(([^\)]+?)\)~i', $row['inddef'], $matches) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$columns = explode(',', $matches[1]);
|
||||||
|
|
||||||
|
if (empty($columns))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
foreach ($columns as $k => $v)
|
||||||
|
$columns[$k] = trim($v);
|
||||||
|
|
||||||
|
// Fix up the name to be consistent cross databases
|
||||||
|
if (substr($row['name'], -5) == '_pkey' && $row['is_primary'] == 1)
|
||||||
|
$row['name'] = 'PRIMARY';
|
||||||
|
else
|
||||||
|
$row['name'] = str_replace($table_name . '_', '', $row['name']);
|
||||||
|
|
||||||
|
if (!$detail)
|
||||||
|
$indexes[] = $row['name'];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$indexes[$row['name']] = array(
|
||||||
|
'name' => $row['name'],
|
||||||
|
'type' => $row['is_primary'] ? 'primary' : ($row['is_unique'] ? 'unique' : 'index'),
|
||||||
|
'columns' => $columns,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$smcFunc['db_free_result']($result);
|
||||||
|
|
||||||
|
return $indexes;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
736
Sources/DbPackages-sqlite.php
Normal file
@ -0,0 +1,736 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple Machines Forum (SMF)
|
||||||
|
*
|
||||||
|
* @package SMF
|
||||||
|
* @author Simple Machines http://www.simplemachines.org
|
||||||
|
* @copyright 2011 Simple Machines
|
||||||
|
* @license http://www.simplemachines.org/about/smf/license.php BSD
|
||||||
|
*
|
||||||
|
* @version 2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('SMF'))
|
||||||
|
die('Hacking attempt...');
|
||||||
|
|
||||||
|
/* This file contains database functionality specifically designed for packages to utilize.
|
||||||
|
|
||||||
|
bool smf_db_create_table(string table_name, array columns, array indexes = array(),
|
||||||
|
array parameters = array(), string if_exists = 'ignore')
|
||||||
|
- Can be used to create a table without worrying about schema compatabilities.
|
||||||
|
- If the table exists will, by default, do nothing.
|
||||||
|
- Builds table with columns as passed to it - at least one column must be sent.
|
||||||
|
The columns array should have one sub-array for each column - these sub arrays contain:
|
||||||
|
+ 'name' = Column name
|
||||||
|
+ 'type' = Type of column - values from (smallint,mediumint,int,text,varchar,char,tinytext,mediumtext,largetext)
|
||||||
|
+ 'size' => Size of column (If applicable) - for example 255 for a large varchar, 10 for an int etc. If not
|
||||||
|
set SMF will pick a size.
|
||||||
|
+ 'default' = Default value - do not set if no default required.
|
||||||
|
+ 'null' => Can it be null (true or false) - if not set default will be false.
|
||||||
|
+ 'auto' => Set to true to make it an auto incrementing column. Set to a numerical value to set
|
||||||
|
from what it should begin counting.
|
||||||
|
- Adds indexes as specified within indexes parameter. Each index should be a member of $indexes. Values are:
|
||||||
|
+ 'name' => Index name (If left empty SMF will generate).
|
||||||
|
+ 'type' => Type of index. Choose from 'primary', 'unique' or 'index'. If not set will default to 'index'.
|
||||||
|
+ 'columns' => Array containing columns that form part of key - in the order the index is to be created.
|
||||||
|
- parameters: (None yet)
|
||||||
|
- if_exists values:
|
||||||
|
+ 'ignore' will do nothing if the table exists. (And will return true)
|
||||||
|
+ 'overwrite' will drop any existing table of the same name.
|
||||||
|
+ 'error' will return false if the table already exists.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Add the file functions to the $smcFunc array.
|
||||||
|
function db_packages_init()
|
||||||
|
{
|
||||||
|
global $smcFunc, $reservedTables, $db_package_log, $db_prefix;
|
||||||
|
|
||||||
|
if (!isset($smcFunc['db_create_table']) || $smcFunc['db_create_table'] != 'smf_db_create_table')
|
||||||
|
{
|
||||||
|
$smcFunc += array(
|
||||||
|
'db_add_column' => 'smf_db_add_column',
|
||||||
|
'db_add_index' => 'smf_db_add_index',
|
||||||
|
'db_alter_table' => 'smf_db_alter_table',
|
||||||
|
'db_calculate_type' => 'smf_db_calculate_type',
|
||||||
|
'db_change_column' => 'smf_db_change_column',
|
||||||
|
'db_create_table' => 'smf_db_create_table',
|
||||||
|
'db_drop_table' => 'smf_db_drop_table',
|
||||||
|
'db_table_structure' => 'smf_db_table_structure',
|
||||||
|
'db_list_columns' => 'smf_db_list_columns',
|
||||||
|
'db_list_indexes' => 'smf_db_list_indexes',
|
||||||
|
'db_remove_column' => 'smf_db_remove_column',
|
||||||
|
'db_remove_index' => 'smf_db_remove_index',
|
||||||
|
);
|
||||||
|
$db_package_log = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
// We setup an array of SMF tables we can't do auto-remove on - in case a mod writer cocks it up!
|
||||||
|
$reservedTables = array('admin_info_files', 'approval_queue', 'attachments', 'ban_groups', 'ban_items',
|
||||||
|
'board_permissions', 'boards', 'calendar', 'calendar_holidays', 'categories', 'collapsed_categories',
|
||||||
|
'custom_fields', 'group_moderators', 'log_actions', 'log_activity', 'log_banned', 'log_boards',
|
||||||
|
'log_digest', 'log_errors', 'log_floodcontrol', 'log_group_requests', 'log_karma', 'log_mark_read',
|
||||||
|
'log_notify', 'log_online', 'log_packages', 'log_polls', 'log_reported', 'log_reported_comments',
|
||||||
|
'log_scheduled_tasks', 'log_search_messages', 'log_search_results', 'log_search_subjects',
|
||||||
|
'log_search_topics', 'log_topics', 'mail_queue', 'membergroups', 'members', 'message_icons',
|
||||||
|
'messages', 'moderators', 'package_servers', 'permission_profiles', 'permissions', 'personal_messages',
|
||||||
|
'pm_recipients', 'poll_choices', 'polls', 'scheduled_tasks', 'sessions', 'settings', 'smileys',
|
||||||
|
'themes', 'topics');
|
||||||
|
foreach ($reservedTables as $k => $table_name)
|
||||||
|
$reservedTables[$k] = strtolower($db_prefix . $table_name);
|
||||||
|
|
||||||
|
// We in turn may need the extra stuff.
|
||||||
|
db_extend('extra');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a table.
|
||||||
|
function smf_db_create_table($table_name, $columns, $indexes = array(), $parameters = array(), $if_exists = 'ignore', $error = 'fatal')
|
||||||
|
{
|
||||||
|
global $reservedTables, $smcFunc, $db_package_log, $db_prefix;
|
||||||
|
|
||||||
|
// With or without the database name, the full name looks like this.
|
||||||
|
$real_prefix = preg_match('~^(`?)(.+?)\\1\\.(.*?)$~', $db_prefix, $match) === 1 ? $match[3] : $db_prefix;
|
||||||
|
$full_table_name = str_replace('{db_prefix}', $real_prefix, $table_name);
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
// First - no way do we touch SMF tables.
|
||||||
|
// Commented out for now. We need to alter SMF tables in order to use this in the upgrade.
|
||||||
|
/*
|
||||||
|
if (in_array(strtolower($table_name), $reservedTables))
|
||||||
|
return false;
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Log that we'll want to remove this on uninstall.
|
||||||
|
$db_package_log[] = array('remove_table', $table_name);
|
||||||
|
|
||||||
|
// Does this table exist or not?
|
||||||
|
$tables = $smcFunc['db_list_tables']();
|
||||||
|
if (in_array($full_table_name, $tables))
|
||||||
|
{
|
||||||
|
// This is a sad day... drop the table? If not, return false (error) by default.
|
||||||
|
if ($if_exists == 'overwrite')
|
||||||
|
$smcFunc['db_drop_table']($table_name);
|
||||||
|
else
|
||||||
|
return $if_exists == 'ignore';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Righty - let's do the damn thing!
|
||||||
|
$table_query = 'CREATE TABLE ' . $table_name . "\n" . '(';
|
||||||
|
$done_primary = false;
|
||||||
|
foreach ($columns as $column)
|
||||||
|
{
|
||||||
|
// Auto increment is special
|
||||||
|
if (!empty($column['auto']))
|
||||||
|
{
|
||||||
|
$table_query .= "\n" . $column['name'] . ' integer PRIMARY KEY,';
|
||||||
|
$done_primary = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
elseif (isset($column['default']) && $column['default'] !== null)
|
||||||
|
$default = 'default \'' . $smcFunc['db_escape_string']($column['default']) . '\'';
|
||||||
|
else
|
||||||
|
$default = '';
|
||||||
|
|
||||||
|
// Sort out the size... and stuff...
|
||||||
|
$column['size'] = isset($column['size']) && is_numeric($column['size']) ? $column['size'] : null;
|
||||||
|
list ($type, $size) = $smcFunc['db_calculate_type']($column['type'], $column['size']);
|
||||||
|
if ($size !== null)
|
||||||
|
$type = $type . '(' . $size . ')';
|
||||||
|
|
||||||
|
// Now just put it together!
|
||||||
|
$table_query .= "\n\t" . $column['name'] . ' ' . $type . ' ' . (!empty($column['null']) ? '' : 'NOT NULL') . ' ' . $default . ',';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop through the indexes next...
|
||||||
|
$index_queries = array();
|
||||||
|
foreach ($indexes as $index)
|
||||||
|
{
|
||||||
|
$columns = implode(',', $index['columns']);
|
||||||
|
|
||||||
|
// Is it the primary?
|
||||||
|
if (isset($index['type']) && $index['type'] == 'primary')
|
||||||
|
{
|
||||||
|
// If we've done the primary via auto_inc, don't do it again!
|
||||||
|
if (!$done_primary)
|
||||||
|
$table_query .= "\n\t" . 'PRIMARY KEY (' . implode(',', $index['columns']) . '),';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (empty($index['name']))
|
||||||
|
$index['name'] = implode('_', $index['columns']);
|
||||||
|
$index_queries[] = 'CREATE ' . (isset($index['type']) && $index['type'] == 'unique' ? 'UNIQUE' : '') . ' INDEX ' . $table_name . '_' . $index['name'] . ' ON ' . $table_name . ' (' . $columns . ')';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No trailing commas!
|
||||||
|
if (substr($table_query, -1) == ',')
|
||||||
|
$table_query = substr($table_query, 0, -1);
|
||||||
|
|
||||||
|
$table_query .= ')';
|
||||||
|
|
||||||
|
if (empty($parameters['skip_transaction']))
|
||||||
|
$smcFunc['db_transaction']('begin');
|
||||||
|
|
||||||
|
// Do the table and indexes...
|
||||||
|
$smcFunc['db_query']('', $table_query,
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
foreach ($index_queries as $query)
|
||||||
|
$smcFunc['db_query']('', $query,
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (empty($parameters['skip_transaction']))
|
||||||
|
$smcFunc['db_transaction']('commit');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drop a table.
|
||||||
|
function smf_db_drop_table($table_name, $parameters = array(), $error = 'fatal')
|
||||||
|
{
|
||||||
|
global $reservedTables, $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
// Strip out the table name, we might not need it in some cases
|
||||||
|
$real_prefix = preg_match('~^(`?)(.+?)\\1\\.(.*?)$~', $db_prefix, $match) === 1 ? $match[3] : $db_prefix;
|
||||||
|
$full_table_name = str_replace('{db_prefix}', $real_prefix, $table_name);
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
// God no - dropping one of these = bad.
|
||||||
|
if (in_array(strtolower($table_name), $reservedTables))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Does it exist?
|
||||||
|
if (in_array($full_table_name, $smcFunc['db_list_tables']()))
|
||||||
|
{
|
||||||
|
$query = 'DROP TABLE ' . $table_name;
|
||||||
|
$smcFunc['db_query']('', $query,
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise do 'nout.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a column.
|
||||||
|
function smf_db_add_column($table_name, $column_info, $parameters = array(), $if_exists = 'update', $error = 'fatal')
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_package_log, $txt, $db_prefix;
|
||||||
|
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
// Log that we will want to uninstall this!
|
||||||
|
$db_package_log[] = array('remove_column', $table_name, $column_info['name']);
|
||||||
|
|
||||||
|
// Does it exist - if so don't add it again!
|
||||||
|
$columns = $smcFunc['db_list_columns']($table_name, false);
|
||||||
|
foreach ($columns as $column)
|
||||||
|
if ($column == $column_info['name'])
|
||||||
|
{
|
||||||
|
// If we're going to overwrite then use change column.
|
||||||
|
if ($if_exists == 'update')
|
||||||
|
return $smcFunc['db_change_column']($table_name, $column_info['name'], $column_info);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alter the table to add the column.
|
||||||
|
if ($smcFunc['db_alter_table']($table_name, array('add' => array($column_info))) === false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We can't reliably do this on SQLite - damn!
|
||||||
|
function smf_db_remove_column($table_name, $column_name, $parameters = array(), $error = 'fatal')
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
if ($smcFunc['db_alter_table']($table_name, array('remove' => array(array('name' => $column_name)))))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change a column.
|
||||||
|
function smf_db_change_column($table_name, $old_column, $column_info, $parameters = array(), $error = 'fatal')
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
if ($smcFunc['db_alter_table']($table_name, array('change' => array(array('name' => $old_column) + $column_info))))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add an index.
|
||||||
|
function smf_db_add_index($table_name, $index_info, $parameters = array(), $if_exists = 'update', $error = 'fatal')
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_package_log, $db_prefix;
|
||||||
|
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
// No columns = no index.
|
||||||
|
if (empty($index_info['columns']))
|
||||||
|
return false;
|
||||||
|
$columns = implode(',', $index_info['columns']);
|
||||||
|
|
||||||
|
// No name - make it up!
|
||||||
|
if (empty($index_info['name']))
|
||||||
|
{
|
||||||
|
// No need for primary.
|
||||||
|
if (isset($index_info['type']) && $index_info['type'] == 'primary')
|
||||||
|
$index_info['name'] = '';
|
||||||
|
else
|
||||||
|
$index_info['name'] = implode('_', $index_info['columns']);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$index_info['name'] = $index_info['name'];
|
||||||
|
|
||||||
|
// Log that we are going to want to remove this!
|
||||||
|
$db_package_log[] = array('remove_index', $table_name, $index_info['name']);
|
||||||
|
|
||||||
|
// Let's get all our indexes.
|
||||||
|
$indexes = $smcFunc['db_list_indexes']($table_name, true);
|
||||||
|
// Do we already have it?
|
||||||
|
foreach ($indexes as $index)
|
||||||
|
{
|
||||||
|
if ($index['name'] == $index_info['name'] || ($index['type'] == 'primary' && isset($index_info['type']) && $index_info['type'] == 'primary'))
|
||||||
|
{
|
||||||
|
// If we want to overwrite simply remove the current one then continue.
|
||||||
|
if ($if_exists != 'update' || $index['type'] == 'primary')
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
$smcFunc['db_remove_index']($table_name, $index_info['name']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're here we know we don't have the index - so just add it.
|
||||||
|
if (!empty($index_info['type']) && $index_info['type'] == 'primary')
|
||||||
|
{
|
||||||
|
//!!! Doesn't work with PRIMARY KEY yet.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
CREATE ' . (isset($index_info['type']) && $index_info['type'] == 'unique' ? 'UNIQUE' : '') . ' INDEX ' . $index_info['name'] . ' ON ' . $table_name . ' (' . $columns . ')',
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove an index.
|
||||||
|
function smf_db_remove_index($table_name, $index_name, $parameters = array(), $error = 'fatal')
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
// Better exist!
|
||||||
|
$indexes = $smcFunc['db_list_indexes']($table_name, true);
|
||||||
|
|
||||||
|
foreach ($indexes as $index)
|
||||||
|
{
|
||||||
|
//!!! Doesn't do primary key at the moment!
|
||||||
|
if ($index['type'] != 'primary' && $index['name'] == $index_name)
|
||||||
|
{
|
||||||
|
// Drop the bugger...
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
DROP INDEX ' . $index_name,
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not to be found ;(
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the schema formatted name for a type.
|
||||||
|
function smf_db_calculate_type($type_name, $type_size = null, $reverse = false)
|
||||||
|
{
|
||||||
|
// Generic => Specific.
|
||||||
|
if (!$reverse)
|
||||||
|
{
|
||||||
|
$types = array(
|
||||||
|
'mediumint' => 'int',
|
||||||
|
'tinyint' => 'smallint',
|
||||||
|
'mediumtext' => 'text',
|
||||||
|
'largetext' => 'text',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$types = array(
|
||||||
|
'integer' => 'int',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Got it? Change it!
|
||||||
|
if (isset($types[$type_name]))
|
||||||
|
{
|
||||||
|
if ($type_name == 'tinytext')
|
||||||
|
$type_size = 255;
|
||||||
|
$type_name = $types[$type_name];
|
||||||
|
}
|
||||||
|
// Numbers don't have a size.
|
||||||
|
if (strpos($type_name, 'int') !== false)
|
||||||
|
$type_size = null;
|
||||||
|
|
||||||
|
return array($type_name, $type_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get table structure.
|
||||||
|
function smf_db_table_structure($table_name, $parameters = array())
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'name' => $table_name,
|
||||||
|
'columns' => $smcFunc['db_list_columns']($table_name, true),
|
||||||
|
'indexes' => $smcFunc['db_list_indexes']($table_name, true),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Harder than it should be on sqlite!
|
||||||
|
function smf_db_list_columns($table_name, $detail = false, $parameters = array())
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
$result = $smcFunc['db_query']('', '
|
||||||
|
PRAGMA table_info(' . $table_name . ')',
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$columns = array();
|
||||||
|
|
||||||
|
$primaries = array();
|
||||||
|
while ($row = $smcFunc['db_fetch_assoc']($result))
|
||||||
|
{
|
||||||
|
if (!$detail)
|
||||||
|
{
|
||||||
|
$columns[] = $row['name'];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Auto increment is hard to tell really... if there's only one primary it probably is.
|
||||||
|
if ($row['pk'])
|
||||||
|
$primaries[] = $row['name'];
|
||||||
|
|
||||||
|
// Can we split out the size?
|
||||||
|
if (preg_match('~(.+?)\s*\((\d+)\)~i', $row['type'], $matches))
|
||||||
|
{
|
||||||
|
$type = $matches[1];
|
||||||
|
$size = $matches[2];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$type = $row['type'];
|
||||||
|
$size = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$columns[$row['name']] = array(
|
||||||
|
'name' => $row['name'],
|
||||||
|
'null' => $row['notnull'] ? false : true,
|
||||||
|
'default' => $row['dflt_value'],
|
||||||
|
'type' => $type,
|
||||||
|
'size' => $size,
|
||||||
|
'auto' => false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$smcFunc['db_free_result']($result);
|
||||||
|
|
||||||
|
// Put in our guess at auto_inc.
|
||||||
|
if (count($primaries) == 1)
|
||||||
|
$columns[$primaries[0]]['auto'] = true;
|
||||||
|
|
||||||
|
return $columns;
|
||||||
|
}
|
||||||
|
|
||||||
|
// What about some index information?
|
||||||
|
function smf_db_list_indexes($table_name, $detail = false, $parameters = array())
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
$result = $smcFunc['db_query']('', '
|
||||||
|
PRAGMA index_list(' . $table_name . ')',
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$indexes = array();
|
||||||
|
while ($row = $smcFunc['db_fetch_assoc']($result))
|
||||||
|
{
|
||||||
|
if (!$detail)
|
||||||
|
$indexes[] = $row['name'];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$result2 = $smcFunc['db_query']('', '
|
||||||
|
PRAGMA index_info(' . $row['name'] . ')',
|
||||||
|
array(
|
||||||
|
'security_override' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
while ($row2 = $smcFunc['db_fetch_assoc']($result2))
|
||||||
|
{
|
||||||
|
// What is the type?
|
||||||
|
if ($row['unique'])
|
||||||
|
$type = 'unique';
|
||||||
|
else
|
||||||
|
$type = 'index';
|
||||||
|
|
||||||
|
// This is the first column we've seen?
|
||||||
|
if (empty($indexes[$row['name']]))
|
||||||
|
{
|
||||||
|
$indexes[$row['name']] = array(
|
||||||
|
'name' => $row['name'],
|
||||||
|
'type' => $type,
|
||||||
|
'columns' => array(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the column...
|
||||||
|
$indexes[$row['name']]['columns'][] = $row2['name'];
|
||||||
|
}
|
||||||
|
$smcFunc['db_free_result']($result2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$smcFunc['db_free_result']($result);
|
||||||
|
|
||||||
|
return $indexes;
|
||||||
|
}
|
||||||
|
|
||||||
|
function smf_db_alter_table($table_name, $columns)
|
||||||
|
{
|
||||||
|
global $smcFunc, $db_prefix, $db_name, $boarddir;
|
||||||
|
|
||||||
|
$db_file = substr($db_name, -3) === '.db' ? $db_name : $db_name . '.db';
|
||||||
|
|
||||||
|
$table_name = str_replace('{db_prefix}', $db_prefix, $table_name);
|
||||||
|
|
||||||
|
// Let's get the current columns for the table.
|
||||||
|
$current_columns = $smcFunc['db_list_columns']($table_name, true);
|
||||||
|
|
||||||
|
// Let's get a list of columns for the temp table.
|
||||||
|
$temp_table_columns = array();
|
||||||
|
|
||||||
|
// Let's see if we have columns to remove or columns that are being added that already exist.
|
||||||
|
foreach ($current_columns as $key => $column)
|
||||||
|
{
|
||||||
|
$exists = false;
|
||||||
|
if (isset($columns['remove']))
|
||||||
|
foreach ($columns['remove'] as $drop)
|
||||||
|
if ($drop['name'] == $column['name'])
|
||||||
|
{
|
||||||
|
$exists = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($columns['add']))
|
||||||
|
foreach ($columns['add'] as $key2 => $add)
|
||||||
|
if ($add['name'] == $column['name'])
|
||||||
|
{
|
||||||
|
unset($columns['add'][$key2]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Doesn't exist then we 'remove'.
|
||||||
|
if (!$exists)
|
||||||
|
$temp_table_columns[] = $column['name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// If they are equal then that means that the column that we are adding exists or it doesn't exist and we are not looking to change any one of them.
|
||||||
|
if (count($temp_table_columns) == count($current_columns) && empty($columns['change']) && empty($columns['add']))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Drop the temp table.
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
DROP TABLE {raw:temp_table_name}',
|
||||||
|
array(
|
||||||
|
'temp_table_name' => $table_name . '_tmp',
|
||||||
|
'db_error_skip' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Let's make a backup of the current database.
|
||||||
|
// We only want the first backup of a table modification. So if there is a backup file and older than an hour just delete and back up again
|
||||||
|
$db_backup_file = $boarddir . '/Packages/backups/backup_' . $table_name . '_' . basename($db_file) . md5($table_name . $db_file);
|
||||||
|
if (file_exists($db_backup_file) && time() - filemtime($db_backup_file) > 3600)
|
||||||
|
{
|
||||||
|
@unlink($db_backup_file);
|
||||||
|
@copy($db_file, $db_backup_file);
|
||||||
|
}
|
||||||
|
elseif (!file_exists($db_backup_file))
|
||||||
|
@copy($db_file, $db_backup_file);
|
||||||
|
|
||||||
|
// If we don't have temp tables then everything crapped out. Just exit.
|
||||||
|
if (empty($temp_table_columns))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Start
|
||||||
|
$smcFunc['db_transaction']('begin');
|
||||||
|
|
||||||
|
// Let's create the temporary table.
|
||||||
|
$createTempTable = $smcFunc['db_query']('', '
|
||||||
|
CREATE TEMPORARY TABLE {raw:temp_table_name}
|
||||||
|
(
|
||||||
|
{raw:columns}
|
||||||
|
);',
|
||||||
|
array(
|
||||||
|
'temp_table_name' => $table_name . '_tmp',
|
||||||
|
'columns' => implode(', ', $temp_table_columns),
|
||||||
|
'db_error_skip' => true,
|
||||||
|
)
|
||||||
|
) !== false;
|
||||||
|
|
||||||
|
if (!$createTempTable)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Insert into temp table.
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
INSERT INTO {raw:temp_table_name}
|
||||||
|
({raw:columns})
|
||||||
|
SELECT {raw:columns}
|
||||||
|
FROM {raw:table_name}',
|
||||||
|
array(
|
||||||
|
'table_name' => $table_name,
|
||||||
|
'columns' => implode(', ', $temp_table_columns),
|
||||||
|
'temp_table_name' => $table_name . '_tmp',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Drop the current table.
|
||||||
|
$dropTable = $smcFunc['db_query']('', '
|
||||||
|
DROP TABLE {raw:table_name}',
|
||||||
|
array(
|
||||||
|
'table_name' => $table_name,
|
||||||
|
'db_error_skip' => true,
|
||||||
|
)
|
||||||
|
) !== false;
|
||||||
|
|
||||||
|
// If you can't drop the main table then there is no where to go from here. Just return.
|
||||||
|
if (!$dropTable)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// We need to keep track of the structure for the current columns and the new columns.
|
||||||
|
$new_columns = array();
|
||||||
|
$column_names = array();
|
||||||
|
|
||||||
|
// Let's get the ones that we already have first.
|
||||||
|
foreach ($current_columns as $name => $column)
|
||||||
|
{
|
||||||
|
if (in_array($name, $temp_table_columns))
|
||||||
|
{
|
||||||
|
$new_columns[$name] = array(
|
||||||
|
'name' => $name,
|
||||||
|
'type' => $column['type'],
|
||||||
|
'size' => isset($column['size']) ? (int) $column['size'] : null,
|
||||||
|
'null' => !empty($column['null']),
|
||||||
|
'auto' => isset($column['auto']) ? $column['auto'] : false,
|
||||||
|
'default' => isset($column['default']) ? $column['default'] : '',
|
||||||
|
);
|
||||||
|
|
||||||
|
// Lets keep track of the name for the column.
|
||||||
|
$column_names[$name] = $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now the new.
|
||||||
|
if (!empty($columns['add']))
|
||||||
|
foreach ($columns['add'] as $add)
|
||||||
|
{
|
||||||
|
$new_columns[$add['name']] = array(
|
||||||
|
'name' => $add['name'],
|
||||||
|
'type' => $add['type'],
|
||||||
|
'size' => isset($add['size']) ? (int) $add['size'] : null,
|
||||||
|
'null' => !empty($add['null']),
|
||||||
|
'auto' => isset($add['auto']) ? $add['auto'] : false,
|
||||||
|
'default' => isset($add['default']) ? $add['default'] : '',
|
||||||
|
);
|
||||||
|
|
||||||
|
// Let's keep track of the name for the column.
|
||||||
|
$column_names[$add['name']] = strstr('int', $add['type']) ? ' 0 AS ' . $add['name'] : ' {string:empty_string} AS ' . $add['name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now to change a column. Not drop but change it.
|
||||||
|
if (isset($columns['change']))
|
||||||
|
foreach ($columns['change'] as $change)
|
||||||
|
if (isset($new_columns[$change['name']]))
|
||||||
|
$new_columns[$change['name']] = array(
|
||||||
|
'name' => $change['name'],
|
||||||
|
'type' => $change['type'],
|
||||||
|
'size' => isset($change['size']) ? (int) $change['size'] : null,
|
||||||
|
'null' => !empty($change['null']),
|
||||||
|
'auto' => isset($change['auto']) ? $change['auto'] : false,
|
||||||
|
'default' => isset($change['default']) ? $change['default'] : '',
|
||||||
|
);
|
||||||
|
|
||||||
|
// Now let's create the table.
|
||||||
|
$createTable = $smcFunc['db_create_table']($table_name, $new_columns, array(), array('skip_transaction' => true));
|
||||||
|
|
||||||
|
// Did it create correctly?
|
||||||
|
if ($createTable === false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Back to it's original table.
|
||||||
|
$insertData = $smcFunc['db_query']('', '
|
||||||
|
INSERT INTO {raw:table_name}
|
||||||
|
({raw:columns})
|
||||||
|
SELECT ' . implode(', ', $column_names) . '
|
||||||
|
FROM {raw:temp_table_name}',
|
||||||
|
array(
|
||||||
|
'table_name' => $table_name,
|
||||||
|
'columns' => implode(', ', array_keys($new_columns)),
|
||||||
|
'columns_select' => implode(', ', $column_names),
|
||||||
|
'temp_table_name' => $table_name . '_tmp',
|
||||||
|
'empty_string' => '',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Did everything insert correctly?
|
||||||
|
if (!$insertData)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Drop the temp table.
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
DROP TABLE {raw:temp_table_name}',
|
||||||
|
array(
|
||||||
|
'temp_table_name' => $table_name . '_tmp',
|
||||||
|
'db_error_skip' => true,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Commit or else there is no point in doing the previous steps.
|
||||||
|
$smcFunc['db_transaction']('commit');
|
||||||
|
|
||||||
|
// We got here so we're good. The temp table should be deleted, if not it will be gone later on >:D.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
77
Sources/DbSearch-mysql.php
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple Machines Forum (SMF)
|
||||||
|
*
|
||||||
|
* @package SMF
|
||||||
|
* @author Simple Machines http://www.simplemachines.org
|
||||||
|
* @copyright 2011 Simple Machines
|
||||||
|
* @license http://www.simplemachines.org/about/smf/license.php BSD
|
||||||
|
*
|
||||||
|
* @version 2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('SMF'))
|
||||||
|
die('Hacking attempt...');
|
||||||
|
|
||||||
|
/* This file contains database functions specific to search related activity.
|
||||||
|
|
||||||
|
void db_search_init()
|
||||||
|
- adds the functions in this file to the $smcFunc array
|
||||||
|
|
||||||
|
boolean smf_db_search_support($search_type)
|
||||||
|
- whether this database type support the search type $search_type
|
||||||
|
|
||||||
|
void smf_db_create_word_search($size)
|
||||||
|
- create the custom word index table
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Add the file functions to the $smcFunc array.
|
||||||
|
function db_search_init()
|
||||||
|
{
|
||||||
|
global $smcFunc;
|
||||||
|
|
||||||
|
if (!isset($smcFunc['db_search_query']) || $smcFunc['db_search_query'] != 'smf_db_query')
|
||||||
|
$smcFunc += array(
|
||||||
|
'db_search_query' => 'smf_db_query',
|
||||||
|
'db_search_support' => 'smf_db_search_support',
|
||||||
|
'db_create_word_search' => 'smf_db_create_word_search',
|
||||||
|
'db_support_ignore' => true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Does this database type support this search type?
|
||||||
|
function smf_db_search_support($search_type)
|
||||||
|
{
|
||||||
|
$supported_types = array('fulltext');
|
||||||
|
|
||||||
|
return in_array($search_type, $supported_types);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Highly specific - create the custom word index table!
|
||||||
|
function smf_db_create_word_search($size)
|
||||||
|
{
|
||||||
|
global $smcFunc;
|
||||||
|
|
||||||
|
if ($size == 'small')
|
||||||
|
$size = 'smallint(5)';
|
||||||
|
elseif ($size == 'medium')
|
||||||
|
$size = 'mediumint(8)';
|
||||||
|
else
|
||||||
|
$size = 'int(10)';
|
||||||
|
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
CREATE TABLE {db_prefix}log_search_words (
|
||||||
|
id_word {raw:size} unsigned NOT NULL default {string:string_zero},
|
||||||
|
id_msg int(10) unsigned NOT NULL default {string:string_zero},
|
||||||
|
PRIMARY KEY (id_word, id_msg)
|
||||||
|
) ENGINE=InnoDB',
|
||||||
|
array(
|
||||||
|
'string_zero' => '0',
|
||||||
|
'size' => $size,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
122
Sources/DbSearch-postgresql.php
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple Machines Forum (SMF)
|
||||||
|
*
|
||||||
|
* @package SMF
|
||||||
|
* @author Simple Machines http://www.simplemachines.org
|
||||||
|
* @copyright 2011 Simple Machines
|
||||||
|
* @license http://www.simplemachines.org/about/smf/license.php BSD
|
||||||
|
*
|
||||||
|
* @version 2.0.7
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('SMF'))
|
||||||
|
die('Hacking attempt...');
|
||||||
|
|
||||||
|
/* This file contains database functions specific to search related activity.
|
||||||
|
|
||||||
|
void db_search_init()
|
||||||
|
- adds the functions in this file to the $smcFunc array
|
||||||
|
|
||||||
|
boolean smf_db_search_support($search_type)
|
||||||
|
- whether this database type support the search type $search_type
|
||||||
|
|
||||||
|
void smf_db_create_word_search($size)
|
||||||
|
- create the custom word index table
|
||||||
|
|
||||||
|
resource smf_db_search_query($identifier, $db_string, $db_values = array(), $connection = null)
|
||||||
|
- returns the correct query for this search type.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Add the file functions to the $smcFunc array.
|
||||||
|
function db_search_init()
|
||||||
|
{
|
||||||
|
global $smcFunc;
|
||||||
|
|
||||||
|
if (!isset($smcFunc['db_search_query']) || $smcFunc['db_search_query'] != 'smf_db_search_query')
|
||||||
|
$smcFunc += array(
|
||||||
|
'db_search_query' => 'smf_db_search_query',
|
||||||
|
'db_search_support' => 'smf_db_search_support',
|
||||||
|
'db_create_word_search' => 'smf_db_create_word_search',
|
||||||
|
'db_support_ignore' => false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Does this database type support this search type?
|
||||||
|
function smf_db_search_support($search_type)
|
||||||
|
{
|
||||||
|
$supported_types = array('custom');
|
||||||
|
|
||||||
|
return in_array($search_type, $supported_types);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the correct query for this search type.
|
||||||
|
function smf_db_search_query($identifier, $db_string, $db_values = array(), $connection = null)
|
||||||
|
{
|
||||||
|
global $smcFunc;
|
||||||
|
|
||||||
|
$replacements = array(
|
||||||
|
'create_tmp_log_search_topics' => array(
|
||||||
|
'~mediumint\(\d\)~i' => 'int',
|
||||||
|
'~unsigned~i' => '',
|
||||||
|
'~ENGINE=MEMORY~i' => '',
|
||||||
|
),
|
||||||
|
'create_tmp_log_search_messages' => array(
|
||||||
|
'~mediumint\(\d\)' => 'int',
|
||||||
|
'~unsigned~i' => '',
|
||||||
|
'~TYPE=HEAP~i' => '',
|
||||||
|
),
|
||||||
|
'drop_tmp_log_search_topics' => array(
|
||||||
|
'~IF\sEXISTS~i' => '',
|
||||||
|
),
|
||||||
|
'drop_tmp_log_search_messages' => array(
|
||||||
|
'~IF\sEXISTS~i' => '',
|
||||||
|
),
|
||||||
|
'insert_into_log_messages_fulltext' => array(
|
||||||
|
'~NOT\sRLIKE~i' => '!~*',
|
||||||
|
'~RLIKE~i' => '~*',
|
||||||
|
),
|
||||||
|
'insert_log_search_results_subject' => array(
|
||||||
|
'~NOT\sRLIKE~i' => '!~*',
|
||||||
|
'~RLIKE~i' => '~*',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isset($replacements[$identifier]))
|
||||||
|
$db_string = preg_replace(array_keys($replacements[$identifier]), array_values($replacements[$identifier]), $db_string);
|
||||||
|
elseif (preg_match('~^\s*INSERT\sIGNORE~i', $db_string) != 0)
|
||||||
|
{
|
||||||
|
$db_string = preg_replace('~^\s*INSERT\sIGNORE~i', 'INSERT', $db_string);
|
||||||
|
// Don't error on multi-insert.
|
||||||
|
$db_values['db_error_skip'] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$return = $smcFunc['db_query']('', $db_string,
|
||||||
|
$db_values, $connection
|
||||||
|
);
|
||||||
|
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Highly specific - create the custom word index table!
|
||||||
|
function smf_db_create_word_search($size)
|
||||||
|
{
|
||||||
|
global $smcFunc;
|
||||||
|
|
||||||
|
$size = 'int';
|
||||||
|
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
CREATE TABLE {db_prefix}log_search_words (
|
||||||
|
id_word {raw:size} NOT NULL default {string:string_zero},
|
||||||
|
id_msg int NOT NULL default {string:string_zero},
|
||||||
|
PRIMARY KEY (id_word, id_msg)
|
||||||
|
)',
|
||||||
|
array(
|
||||||
|
'size' => $size,
|
||||||
|
'string_zero' => '0',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
106
Sources/DbSearch-sqlite.php
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple Machines Forum (SMF)
|
||||||
|
*
|
||||||
|
* @package SMF
|
||||||
|
* @author Simple Machines http://www.simplemachines.org
|
||||||
|
* @copyright 2011 Simple Machines
|
||||||
|
* @license http://www.simplemachines.org/about/smf/license.php BSD
|
||||||
|
*
|
||||||
|
* @version 2.0.7
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('SMF'))
|
||||||
|
die('Hacking attempt...');
|
||||||
|
|
||||||
|
/* This file contains database functions specific to search related activity.
|
||||||
|
|
||||||
|
void db_search_init()
|
||||||
|
- adds the functions in this file to the $smcFunc array
|
||||||
|
|
||||||
|
boolean smf_db_search_support($search_type)
|
||||||
|
- whether this database type support the search type $search_type
|
||||||
|
|
||||||
|
void smf_db_create_word_search($size)
|
||||||
|
- create the custom word index table
|
||||||
|
|
||||||
|
resource smf_db_search_query($identifier, $db_string, $db_values = array(), $connection = null)
|
||||||
|
- returns the correct query for this search type.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Add the file functions to the $smcFunc array.
|
||||||
|
function db_search_init()
|
||||||
|
{
|
||||||
|
global $smcFunc;
|
||||||
|
|
||||||
|
if (!isset($smcFunc['db_search_query']) || $smcFunc['db_search_query'] != 'smf_db_search_query')
|
||||||
|
$smcFunc += array(
|
||||||
|
'db_search_query' => 'smf_db_search_query',
|
||||||
|
'db_search_support' => 'smf_db_search_support',
|
||||||
|
'db_create_word_search' => 'smf_db_create_word_search',
|
||||||
|
'db_support_ignore' => false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Does this database type support this search type?
|
||||||
|
function smf_db_search_support($search_type)
|
||||||
|
{
|
||||||
|
$supported_types = array('custom');
|
||||||
|
|
||||||
|
return in_array($search_type, $supported_types);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the correct query for this search type.
|
||||||
|
function smf_db_search_query($identifier, $db_string, $db_values = array(), $connection = null)
|
||||||
|
{
|
||||||
|
global $smcFunc;
|
||||||
|
|
||||||
|
$replacements = array(
|
||||||
|
'create_tmp_log_search_topics' => array(
|
||||||
|
'~mediumint\(\d\)~i' => 'int',
|
||||||
|
'~ENGINE=MEMORY~i' => '',
|
||||||
|
),
|
||||||
|
'create_tmp_log_search_messages' => array(
|
||||||
|
'~mediumint\(\d\)~i' => 'int',
|
||||||
|
'~TYPE=HEAP~i' => '',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isset($replacements[$identifier]))
|
||||||
|
$db_string = preg_replace(array_keys($replacements[$identifier]), array_values($replacements[$identifier]), $db_string);
|
||||||
|
elseif (preg_match('~^\s*INSERT\sIGNORE~i', $db_string) != 0)
|
||||||
|
{
|
||||||
|
$db_string = preg_replace('~^\s*INSERT\sIGNORE~i', 'INSERT', $db_string);
|
||||||
|
// Don't error on multi-insert.
|
||||||
|
$db_values['db_error_skip'] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$return = $smcFunc['db_query']('', $db_string,
|
||||||
|
$db_values, $connection
|
||||||
|
);
|
||||||
|
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Highly specific - create the custom word index table!
|
||||||
|
function smf_db_create_word_search($size)
|
||||||
|
{
|
||||||
|
global $smcFunc;
|
||||||
|
|
||||||
|
$size = 'int';
|
||||||
|
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
CREATE TABLE {db_prefix}log_search_words (
|
||||||
|
id_word {raw:size} NOT NULL default {string:string_zero},
|
||||||
|
id_msg int(10) NOT NULL default {string:string_zero},
|
||||||
|
PRIMARY KEY (id_word, id_msg)
|
||||||
|
)',
|
||||||
|
array(
|
||||||
|
'size' => $size,
|
||||||
|
'string_zero' => '0',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
1727
Sources/Display.php
Normal file
182
Sources/DumpDatabase.php
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple Machines Forum (SMF)
|
||||||
|
*
|
||||||
|
* @package SMF
|
||||||
|
* @author Simple Machines http://www.simplemachines.org
|
||||||
|
* @copyright 2011 Simple Machines
|
||||||
|
* @license http://www.simplemachines.org/about/smf/license.php BSD
|
||||||
|
*
|
||||||
|
* @version 2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('SMF'))
|
||||||
|
die('Hacking attempt...');
|
||||||
|
|
||||||
|
/*
|
||||||
|
This file has a single job - database backup.
|
||||||
|
|
||||||
|
void DumpDatabase2()
|
||||||
|
- writes all of the database to standard output.
|
||||||
|
- uses gzip compression if compress is set in the URL/post data.
|
||||||
|
- may possibly time out in some cases.
|
||||||
|
- the data dumped depends on whether "struct" and "data" are passed.
|
||||||
|
- requires an administrator and the session hash by post.
|
||||||
|
- is called from ManageMaintenance.php.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Dumps the database to a file.
|
||||||
|
function DumpDatabase2()
|
||||||
|
{
|
||||||
|
global $db_name, $scripturl, $context, $modSettings, $crlf, $smcFunc, $db_prefix;
|
||||||
|
|
||||||
|
// Administrators only!
|
||||||
|
if (!allowedTo('admin_forum'))
|
||||||
|
fatal_lang_error('no_dump_database', 'critical');
|
||||||
|
|
||||||
|
// You can't dump nothing!
|
||||||
|
if (!isset($_REQUEST['struct']) && !isset($_REQUEST['data']))
|
||||||
|
$_REQUEST['data'] = true;
|
||||||
|
|
||||||
|
checkSession('post');
|
||||||
|
|
||||||
|
// We will need this, badly!
|
||||||
|
db_extend();
|
||||||
|
|
||||||
|
// Attempt to stop from dying...
|
||||||
|
@set_time_limit(600);
|
||||||
|
if (@ini_get('memory_limit') < 256)
|
||||||
|
@ini_set('memory_limit', '256M');
|
||||||
|
|
||||||
|
// Start saving the output... (don't do it otherwise for memory reasons.)
|
||||||
|
if (isset($_REQUEST['compress']) && function_exists('gzencode'))
|
||||||
|
{
|
||||||
|
// Make sure we're gzipping output, but then say we're not in the header ^_^.
|
||||||
|
if (empty($modSettings['enableCompressedOutput']))
|
||||||
|
@ob_start('ob_gzhandler');
|
||||||
|
// Try to clean any data already outputted.
|
||||||
|
elseif (ob_get_length() != 0)
|
||||||
|
{
|
||||||
|
ob_end_clean();
|
||||||
|
@ob_start('ob_gzhandler');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send faked headers so it will just save the compressed output as a gzip.
|
||||||
|
header('Content-Type: application/x-gzip');
|
||||||
|
header('Accept-Ranges: bytes');
|
||||||
|
header('Content-Encoding: none');
|
||||||
|
|
||||||
|
// Gecko browsers... don't like this. (Mozilla, Firefox, etc.)
|
||||||
|
if (!$context['browser']['is_gecko'])
|
||||||
|
header('Content-Transfer-Encoding: binary');
|
||||||
|
|
||||||
|
// The file extension will include .gz...
|
||||||
|
$extension = '.sql.gz';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Get rid of the gzipping alreading being done.
|
||||||
|
if (!empty($modSettings['enableCompressedOutput']))
|
||||||
|
@ob_end_clean();
|
||||||
|
// If we can, clean anything already sent from the output buffer...
|
||||||
|
elseif (function_exists('ob_clean') && ob_get_length() != 0)
|
||||||
|
ob_clean();
|
||||||
|
|
||||||
|
// Tell the client to save this file, even though it's text.
|
||||||
|
header('Content-Type: ' . ($context['browser']['is_ie'] || $context['browser']['is_opera'] ? 'application/octetstream' : 'application/octet-stream'));
|
||||||
|
header('Content-Encoding: none');
|
||||||
|
|
||||||
|
// This time the extension should just be .sql.
|
||||||
|
$extension = '.sql';
|
||||||
|
}
|
||||||
|
|
||||||
|
// This should turn off the session URL parser.
|
||||||
|
$scripturl = '';
|
||||||
|
|
||||||
|
// If this database is flat file and has a handler function pass it to that.
|
||||||
|
if (!empty($smcFunc['db_get_backup']))
|
||||||
|
{
|
||||||
|
$smcFunc['db_get_backup']();
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the proper headers to let them download this file.
|
||||||
|
header('Content-Disposition: filename="' . $db_name . '-' . (empty($_REQUEST['struct']) ? 'data' : (empty($_REQUEST['data']) ? 'structure' : 'complete')) . '_' . strftime('%Y-%m-%d') . $extension . '"');
|
||||||
|
header('Cache-Control: private');
|
||||||
|
header('Connection: close');
|
||||||
|
|
||||||
|
// This makes things simpler when using it so very very often.
|
||||||
|
$crlf = "\r\n";
|
||||||
|
|
||||||
|
// SQL Dump Header.
|
||||||
|
echo
|
||||||
|
'-- ==========================================================', $crlf,
|
||||||
|
'--', $crlf,
|
||||||
|
'-- Database dump of tables in `', $db_name, '`', $crlf,
|
||||||
|
'-- ', timeformat(time(), false), $crlf,
|
||||||
|
'--', $crlf,
|
||||||
|
'-- ==========================================================', $crlf,
|
||||||
|
$crlf;
|
||||||
|
|
||||||
|
// Get all tables in the database....
|
||||||
|
if (preg_match('~^`(.+?)`\.(.+?)$~', $db_prefix, $match) != 0)
|
||||||
|
{
|
||||||
|
$db = strtr($match[1], array('`' => ''));
|
||||||
|
$dbp = str_replace('_', '\_', $match[2]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$db = false;
|
||||||
|
$dbp = $db_prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dump each table.
|
||||||
|
$tables = $smcFunc['db_list_tables'](false, $db_prefix . '%');
|
||||||
|
foreach ($tables as $tableName)
|
||||||
|
{
|
||||||
|
if (function_exists('apache_reset_timeout'))
|
||||||
|
@apache_reset_timeout();
|
||||||
|
|
||||||
|
// Are we dumping the structures?
|
||||||
|
if (isset($_REQUEST['struct']))
|
||||||
|
{
|
||||||
|
echo
|
||||||
|
$crlf,
|
||||||
|
'--', $crlf,
|
||||||
|
'-- Table structure for table `', $tableName, '`', $crlf,
|
||||||
|
'--', $crlf,
|
||||||
|
$crlf,
|
||||||
|
$smcFunc['db_table_sql']($tableName), ';', $crlf;
|
||||||
|
}
|
||||||
|
|
||||||
|
// How about the data?
|
||||||
|
if (!isset($_REQUEST['data']) || substr($tableName, -10) == 'log_errors')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Are there any rows in this table?
|
||||||
|
$get_rows = $smcFunc['db_insert_sql']($tableName);
|
||||||
|
|
||||||
|
// No rows to get - skip it.
|
||||||
|
if (empty($get_rows))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
echo
|
||||||
|
$crlf,
|
||||||
|
'--', $crlf,
|
||||||
|
'-- Dumping data in `', $tableName, '`', $crlf,
|
||||||
|
'--', $crlf,
|
||||||
|
$crlf,
|
||||||
|
$get_rows,
|
||||||
|
'-- --------------------------------------------------------', $crlf;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo
|
||||||
|
$crlf,
|
||||||
|
'-- Done', $crlf;
|
||||||
|
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
420
Sources/Errors.php
Normal file
@ -0,0 +1,420 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple Machines Forum (SMF)
|
||||||
|
*
|
||||||
|
* @package SMF
|
||||||
|
* @author Simple Machines http://www.simplemachines.org
|
||||||
|
* @copyright 2011 Simple Machines
|
||||||
|
* @license http://www.simplemachines.org/about/smf/license.php BSD
|
||||||
|
*
|
||||||
|
* @version 2.0.4
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('SMF'))
|
||||||
|
die('Hacking attempt...');
|
||||||
|
|
||||||
|
/* The purpose of this file is... errors. (hard to guess, huh?) It takes
|
||||||
|
care of logging, error messages, error handling, database errors, and
|
||||||
|
error log administration. It does this with:
|
||||||
|
|
||||||
|
bool db_fatal_error(bool loadavg = false)
|
||||||
|
- calls show_db_error().
|
||||||
|
- this is used for database connection error handling.
|
||||||
|
- loadavg means this is a load average problem, not a database error.
|
||||||
|
|
||||||
|
string log_error(string error_message, string error_type = general,
|
||||||
|
string filename = none, int line = none)
|
||||||
|
- logs an error, if error logging is enabled.
|
||||||
|
- depends on the enableErrorLogging setting.
|
||||||
|
- filename and line should be __FILE__ and __LINE__, respectively.
|
||||||
|
- returns the error message. (ie. die(log_error($msg));)
|
||||||
|
|
||||||
|
void fatal_error(string error_message, mixed (bool or string) log = general)
|
||||||
|
- stops execution and displays an error message.
|
||||||
|
- logs the error message if log is missing or true.
|
||||||
|
|
||||||
|
void fatal_lang_error(string error_message_key, mixed (bool or string) log = general,
|
||||||
|
array sprintf = array())
|
||||||
|
- stops execution and displays an error message by key.
|
||||||
|
- uses the string with the error_message_key key.
|
||||||
|
- loads the Errors language file.
|
||||||
|
- applies the sprintf information if specified.
|
||||||
|
- the information is logged if log is true or missing.
|
||||||
|
- logs the error in the forum's default language while displaying the error
|
||||||
|
message in the user's language
|
||||||
|
|
||||||
|
void error_handler(int error_level, string error_string, string filename,
|
||||||
|
int line)
|
||||||
|
- this is a standard PHP error handler replacement.
|
||||||
|
- dies with fatal_error() if the error_level matches with
|
||||||
|
error_reporting.
|
||||||
|
|
||||||
|
void setup_fatal_error_context(string error_message)
|
||||||
|
- uses the fatal_error sub template of the Errors template - or the
|
||||||
|
error sub template in the Wireless template.
|
||||||
|
- used by fatal_error() and fatal_lang_error()
|
||||||
|
|
||||||
|
void show_db_error(bool loadavg = false)
|
||||||
|
- called by db_fatal_error() function
|
||||||
|
- shows a complete page independent of language files or themes.
|
||||||
|
- used only if there's no way to connect to the database or the
|
||||||
|
load averages are too high to do so.
|
||||||
|
- loadavg means this is a load average problem, not a database error.
|
||||||
|
- stops further execution of the script.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Handle fatal errors - like connection errors or load average problems
|
||||||
|
function db_fatal_error($loadavg = false)
|
||||||
|
{
|
||||||
|
global $sourcedir;
|
||||||
|
|
||||||
|
show_db_error($loadavg);
|
||||||
|
|
||||||
|
// Since we use "or db_fatal_error();" this is needed...
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log an error, if the option is on.
|
||||||
|
function log_error($error_message, $error_type = 'general', $file = null, $line = null)
|
||||||
|
{
|
||||||
|
global $txt, $modSettings, $sc, $user_info, $smcFunc, $scripturl, $last_error;
|
||||||
|
|
||||||
|
// Check if error logging is actually on.
|
||||||
|
if (empty($modSettings['enableErrorLogging']))
|
||||||
|
return $error_message;
|
||||||
|
|
||||||
|
// Basically, htmlspecialchars it minus &. (for entities!)
|
||||||
|
$error_message = strtr($error_message, array('<' => '<', '>' => '>', '"' => '"'));
|
||||||
|
$error_message = strtr($error_message, array('<br />' => '<br />', '<b>' => '<strong>', '</b>' => '</strong>', "\n" => '<br />'));
|
||||||
|
|
||||||
|
// Add a file and line to the error message?
|
||||||
|
// Don't use the actual txt entries for file and line but instead use %1$s for file and %2$s for line
|
||||||
|
if ($file == null)
|
||||||
|
$file = '';
|
||||||
|
else
|
||||||
|
// Window style slashes don't play well, lets convert them to the unix style.
|
||||||
|
$file = str_replace('\\', '/', $file);
|
||||||
|
|
||||||
|
if ($line == null)
|
||||||
|
$line = 0;
|
||||||
|
else
|
||||||
|
$line = (int) $line;
|
||||||
|
|
||||||
|
// Just in case there's no id_member or IP set yet.
|
||||||
|
if (empty($user_info['id']))
|
||||||
|
$user_info['id'] = 0;
|
||||||
|
if (empty($user_info['ip']))
|
||||||
|
$user_info['ip'] = '';
|
||||||
|
|
||||||
|
// Find the best query string we can...
|
||||||
|
$query_string = empty($_SERVER['QUERY_STRING']) ? (empty($_SERVER['REQUEST_URL']) ? '' : str_replace($scripturl, '', $_SERVER['REQUEST_URL'])) : $_SERVER['QUERY_STRING'];
|
||||||
|
|
||||||
|
// Don't log the session hash in the url twice, it's a waste.
|
||||||
|
$query_string = htmlspecialchars((SMF == 'SSI' ? '' : '?') . preg_replace(array('~;sesc=[^&;]+~', '~' . session_name() . '=' . session_id() . '[&;]~'), array(';sesc', ''), $query_string));
|
||||||
|
|
||||||
|
// Just so we know what board error messages are from.
|
||||||
|
if (isset($_POST['board']) && !isset($_GET['board']))
|
||||||
|
$query_string .= ($query_string == '' ? 'board=' : ';board=') . $_POST['board'];
|
||||||
|
|
||||||
|
// What types of categories do we have?
|
||||||
|
$known_error_types = array(
|
||||||
|
'general',
|
||||||
|
'critical',
|
||||||
|
'database',
|
||||||
|
'undefined_vars',
|
||||||
|
'user',
|
||||||
|
'template',
|
||||||
|
'debug',
|
||||||
|
);
|
||||||
|
|
||||||
|
// Make sure the category that was specified is a valid one
|
||||||
|
$error_type = in_array($error_type, $known_error_types) && $error_type !== true ? $error_type : 'general';
|
||||||
|
|
||||||
|
// Don't log the same error countless times, as we can get in a cycle of depression...
|
||||||
|
$error_info = array($user_info['id'], time(), $user_info['ip'], $query_string, $error_message, (string) $sc, $error_type, $file, $line);
|
||||||
|
if (empty($last_error) || $last_error != $error_info)
|
||||||
|
{
|
||||||
|
// Insert the error into the database.
|
||||||
|
$smcFunc['db_insert']('',
|
||||||
|
'{db_prefix}log_errors',
|
||||||
|
array('id_member' => 'int', 'log_time' => 'int', 'ip' => 'string-16', 'url' => 'string-65534', 'message' => 'string-65534', 'session' => 'string', 'error_type' => 'string', 'file' => 'string-255', 'line' => 'int'),
|
||||||
|
$error_info,
|
||||||
|
array('id_error')
|
||||||
|
);
|
||||||
|
$last_error = $error_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the message to make things simpler.
|
||||||
|
return $error_message;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An irrecoverable error.
|
||||||
|
function fatal_error($error, $log = 'general')
|
||||||
|
{
|
||||||
|
global $txt, $context, $modSettings;
|
||||||
|
|
||||||
|
// We don't have $txt yet, but that's okay...
|
||||||
|
if (empty($txt))
|
||||||
|
die($error);
|
||||||
|
|
||||||
|
setup_fatal_error_context($log || (!empty($modSettings['enableErrorLogging']) && $modSettings['enableErrorLogging'] == 2) ? log_error($error, $log) : $error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// A fatal error with a message stored in the language file.
|
||||||
|
function fatal_lang_error($error, $log = 'general', $sprintf = array())
|
||||||
|
{
|
||||||
|
global $txt, $language, $modSettings, $user_info, $context;
|
||||||
|
static $fatal_error_called = false;
|
||||||
|
|
||||||
|
// Try to load a theme if we don't have one.
|
||||||
|
if (empty($context['theme_loaded']) && empty($fatal_error_called))
|
||||||
|
{
|
||||||
|
$fatal_error_called = true;
|
||||||
|
loadTheme();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have no theme stuff we can't have the language file...
|
||||||
|
if (empty($context['theme_loaded']))
|
||||||
|
die($error);
|
||||||
|
|
||||||
|
$reload_lang_file = true;
|
||||||
|
// Log the error in the forum's language, but don't waste the time if we aren't logging
|
||||||
|
if ($log || (!empty($modSettings['enableErrorLogging']) && $modSettings['enableErrorLogging'] == 2))
|
||||||
|
{
|
||||||
|
loadLanguage('Errors', $language);
|
||||||
|
$reload_lang_file = $language != $user_info['language'];
|
||||||
|
$error_message = empty($sprintf) ? $txt[$error] : vsprintf($txt[$error], $sprintf);
|
||||||
|
log_error($error_message, $log);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the language file, only if it needs to be reloaded
|
||||||
|
if ($reload_lang_file)
|
||||||
|
{
|
||||||
|
loadLanguage('Errors');
|
||||||
|
$error_message = empty($sprintf) ? $txt[$error] : vsprintf($txt[$error], $sprintf);
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_fatal_error_context($error_message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handler for standard error messages.
|
||||||
|
function error_handler($error_level, $error_string, $file, $line)
|
||||||
|
{
|
||||||
|
global $settings, $modSettings, $db_show_debug;
|
||||||
|
|
||||||
|
// Ignore errors if we're ignoring them or they are strict notices from PHP 5 (which cannot be solved without breaking PHP 4.)
|
||||||
|
if (error_reporting() == 0 || (defined('E_STRICT') && $error_level == E_STRICT && (empty($modSettings['enableErrorLogging']) || $modSettings['enableErrorLogging'] != 2)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (strpos($file, 'eval()') !== false && !empty($settings['current_include_filename']))
|
||||||
|
{
|
||||||
|
if (function_exists('debug_backtrace'))
|
||||||
|
{
|
||||||
|
$array = debug_backtrace();
|
||||||
|
for ($i = 0; $i < count($array); $i++)
|
||||||
|
{
|
||||||
|
if ($array[$i]['function'] != 'loadSubTemplate')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// This is a bug in PHP, with eval, it seems!
|
||||||
|
if (empty($array[$i]['args']))
|
||||||
|
$i++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($array[$i]) && !empty($array[$i]['args']))
|
||||||
|
$file = realpath($settings['current_include_filename']) . ' (' . $array[$i]['args'][0] . ' sub template - eval?)';
|
||||||
|
else
|
||||||
|
$file = realpath($settings['current_include_filename']) . ' (eval?)';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$file = realpath($settings['current_include_filename']) . ' (eval?)';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($db_show_debug) && $db_show_debug === true)
|
||||||
|
{
|
||||||
|
// Commonly, undefined indexes will occur inside attributes; try to show them anyway!
|
||||||
|
if ($error_level % 255 != E_ERROR)
|
||||||
|
{
|
||||||
|
$temporary = ob_get_contents();
|
||||||
|
if (substr($temporary, -2) == '="')
|
||||||
|
echo '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debugging! This should look like a PHP error message.
|
||||||
|
echo '<br />
|
||||||
|
<strong>', $error_level % 255 == E_ERROR ? 'Error' : ($error_level % 255 == E_WARNING ? 'Warning' : 'Notice'), '</strong>: ', $error_string, ' in <strong>', $file, '</strong> on line <strong>', $line, '</strong><br />';
|
||||||
|
}
|
||||||
|
|
||||||
|
$error_type = strpos(strtolower($error_string), 'undefined') !== false ? 'undefined_vars' : 'general';
|
||||||
|
|
||||||
|
$message = log_error($error_level . ': ' . $error_string, $error_type, $file, $line);
|
||||||
|
|
||||||
|
// Let's give integrations a chance to ouput a bit differently
|
||||||
|
call_integration_hook('integrate_output_error', array($message, $error_type, $error_level, $file, $line));
|
||||||
|
|
||||||
|
// Dying on these errors only causes MORE problems (blank pages!)
|
||||||
|
if ($file == 'Unknown')
|
||||||
|
return;
|
||||||
|
|
||||||
|
// If this is an E_ERROR or E_USER_ERROR.... die. Violently so.
|
||||||
|
if ($error_level % 255 == E_ERROR)
|
||||||
|
obExit(false);
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
// If this is an E_ERROR, E_USER_ERROR, E_WARNING, or E_USER_WARNING.... die. Violently so.
|
||||||
|
if ($error_level % 255 == E_ERROR || $error_level % 255 == E_WARNING)
|
||||||
|
fatal_error(allowedTo('admin_forum') ? $message : $error_string, false);
|
||||||
|
|
||||||
|
// We should NEVER get to this point. Any fatal error MUST quit, or very bad things can happen.
|
||||||
|
if ($error_level % 255 == E_ERROR)
|
||||||
|
die('Hacking attempt...');
|
||||||
|
}
|
||||||
|
|
||||||
|
function setup_fatal_error_context($error_message)
|
||||||
|
{
|
||||||
|
global $context, $txt, $ssi_on_error_method;
|
||||||
|
static $level = 0;
|
||||||
|
|
||||||
|
// Attempt to prevent a recursive loop.
|
||||||
|
++$level;
|
||||||
|
if ($level > 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Maybe they came from dlattach or similar?
|
||||||
|
if (SMF != 'SSI' && empty($context['theme_loaded']))
|
||||||
|
loadTheme();
|
||||||
|
|
||||||
|
// Don't bother indexing errors mate...
|
||||||
|
$context['robot_no_index'] = true;
|
||||||
|
|
||||||
|
if (!isset($context['error_title']))
|
||||||
|
$context['error_title'] = $txt['error_occured'];
|
||||||
|
$context['error_message'] = isset($context['error_message']) ? $context['error_message'] : $error_message;
|
||||||
|
|
||||||
|
if (empty($context['page_title']))
|
||||||
|
$context['page_title'] = $context['error_title'];
|
||||||
|
|
||||||
|
// Display the error message - wireless?
|
||||||
|
if (defined('WIRELESS') && WIRELESS)
|
||||||
|
$context['sub_template'] = WIRELESS_PROTOCOL . '_error';
|
||||||
|
// Load the template and set the sub template.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
loadTemplate('Errors');
|
||||||
|
$context['sub_template'] = 'fatal_error';
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is SSI, what do they want us to do?
|
||||||
|
if (SMF == 'SSI')
|
||||||
|
{
|
||||||
|
if (!empty($ssi_on_error_method) && $ssi_on_error_method !== true && is_callable($ssi_on_error_method))
|
||||||
|
$ssi_on_error_method();
|
||||||
|
elseif (empty($ssi_on_error_method) || $ssi_on_error_method !== true)
|
||||||
|
loadSubTemplate('fatal_error');
|
||||||
|
|
||||||
|
// No layers?
|
||||||
|
if (empty($ssi_on_error_method) || $ssi_on_error_method !== true)
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We want whatever for the header, and a footer. (footer includes sub template!)
|
||||||
|
obExit(null, true, false, true);
|
||||||
|
|
||||||
|
/* DO NOT IGNORE:
|
||||||
|
If you are creating a bridge to SMF or modifying this function, you MUST
|
||||||
|
make ABSOLUTELY SURE that this function quits and DOES NOT RETURN TO NORMAL
|
||||||
|
PROGRAM FLOW. Otherwise, security error messages will not be shown, and
|
||||||
|
your forum will be in a very easily hackable state.
|
||||||
|
*/
|
||||||
|
trigger_error('Hacking attempt...', E_USER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show an error message for the connection problems.
|
||||||
|
function show_db_error($loadavg = false)
|
||||||
|
{
|
||||||
|
global $sourcedir, $mbname, $maintenance, $mtitle, $mmessage, $modSettings;
|
||||||
|
global $db_connection, $webmaster_email, $db_last_error, $db_error_send, $smcFunc;
|
||||||
|
|
||||||
|
// Just check we're not in any buffers, just in case.
|
||||||
|
for ($i = ob_get_level(); $i > 0; $i--)
|
||||||
|
@ob_end_clean();
|
||||||
|
|
||||||
|
// Don't cache this page!
|
||||||
|
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||||
|
header('Cache-Control: no-cache');
|
||||||
|
|
||||||
|
// Send the right error codes.
|
||||||
|
header('HTTP/1.1 503 Service Temporarily Unavailable');
|
||||||
|
header('Status: 503 Service Temporarily Unavailable');
|
||||||
|
header('Retry-After: 3600');
|
||||||
|
|
||||||
|
if ($loadavg == false)
|
||||||
|
{
|
||||||
|
// For our purposes, we're gonna want this on if at all possible.
|
||||||
|
$modSettings['cache_enable'] = '1';
|
||||||
|
|
||||||
|
if (($temp = cache_get_data('db_last_error', 600)) !== null)
|
||||||
|
$db_last_error = max($db_last_error, $temp);
|
||||||
|
|
||||||
|
if ($db_last_error < time() - 3600 * 24 * 3 && empty($maintenance) && !empty($db_error_send))
|
||||||
|
{
|
||||||
|
require_once($sourcedir . '/Subs-Admin.php');
|
||||||
|
|
||||||
|
// Avoid writing to the Settings.php file if at all possible; use shared memory instead.
|
||||||
|
cache_put_data('db_last_error', time(), 600);
|
||||||
|
if (($temp = cache_get_data('db_last_error', 600)) == null)
|
||||||
|
updateLastDatabaseError();
|
||||||
|
|
||||||
|
// Language files aren't loaded yet :(.
|
||||||
|
$db_error = @$smcFunc['db_error']($db_connection);
|
||||||
|
@mail($webmaster_email, $mbname . ': SMF Database Error!', 'There has been a problem with the database!' . ($db_error == '' ? '' : "\n" . $smcFunc['db_title'] . ' reported:' . "\n" . $db_error) . "\n\n" . 'This is a notice email to let you know that SMF could not connect to the database, contact your host if this continues.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($maintenance))
|
||||||
|
echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta name="robots" content="noindex" />
|
||||||
|
<title>', $mtitle, '</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h3>', $mtitle, '</h3>
|
||||||
|
', $mmessage, '
|
||||||
|
</body>
|
||||||
|
</html>';
|
||||||
|
// If this is a load average problem, display an appropriate message (but we still don't have language files!)
|
||||||
|
elseif ($loadavg)
|
||||||
|
echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta name="robots" content="noindex" />
|
||||||
|
<title>Temporarily Unavailable</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h3>Temporarily Unavailable</h3>
|
||||||
|
Due to high stress on the server the forum is temporarily unavailable. Please try again later.
|
||||||
|
</body>
|
||||||
|
</html>';
|
||||||
|
// What to do? Language files haven't and can't be loaded yet...
|
||||||
|
else
|
||||||
|
echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta name="robots" content="noindex" />
|
||||||
|
<title>Connection Problems</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h3>Connection Problems</h3>
|
||||||
|
Sorry, SMF was unable to connect to the database. This may be caused by the server being busy. Please try again later.
|
||||||
|
</body>
|
||||||
|
</html>';
|
||||||
|
|
||||||
|
die;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
967
Sources/Groups.php
Normal file
@ -0,0 +1,967 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple Machines Forum (SMF)
|
||||||
|
*
|
||||||
|
* @package SMF
|
||||||
|
* @author Simple Machines http://www.simplemachines.org
|
||||||
|
* @copyright 2011 Simple Machines
|
||||||
|
* @license http://www.simplemachines.org/about/smf/license.php BSD
|
||||||
|
*
|
||||||
|
* @version 2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('SMF'))
|
||||||
|
die('Hacking attempt...');
|
||||||
|
|
||||||
|
/* This file currently just shows group info, and allows certain privaledged members to add/remove members.
|
||||||
|
|
||||||
|
void Groups()
|
||||||
|
- allows moderators and users to access the group showing functions.
|
||||||
|
- handles permission checks, and puts the moderation bar on as required.
|
||||||
|
|
||||||
|
void MembergroupMembers()
|
||||||
|
- can be called from ManageMembergroups if it needs templating within the admin environment.
|
||||||
|
- show a list of members that are part of a given membergroup.
|
||||||
|
- called by ?action=moderate;area=viewgroups;sa=members;group=x
|
||||||
|
- requires the manage_membergroups permission.
|
||||||
|
- uses the group_members sub template of ManageMembergroups.
|
||||||
|
- allows to add and remove members from the selected membergroup.
|
||||||
|
- allows sorting on several columns.
|
||||||
|
- redirects to itself.
|
||||||
|
|
||||||
|
int list_getGroupRequestCount(string where)
|
||||||
|
- callback function for createList()
|
||||||
|
- returns the count of group requests
|
||||||
|
|
||||||
|
array list_getGroupRequests(int start, int items_per_page, string sort, string where)
|
||||||
|
- callback function for createList()
|
||||||
|
- returns an array of group requests
|
||||||
|
- each group request has:
|
||||||
|
'id'
|
||||||
|
'member_link'
|
||||||
|
'group_link'
|
||||||
|
'reason'
|
||||||
|
'time_submitted'
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Entry point, permission checks, admin bars, etc.
|
||||||
|
function Groups()
|
||||||
|
{
|
||||||
|
global $context, $txt, $scripturl, $sourcedir, $user_info;
|
||||||
|
|
||||||
|
// The sub-actions that we can do. Format "Function Name, Mod Bar Index if appropriate".
|
||||||
|
$subActions = array(
|
||||||
|
'index' => array('GroupList', 'view_groups'),
|
||||||
|
'members' => array('MembergroupMembers', 'view_groups'),
|
||||||
|
'requests' => array('GroupRequests', 'group_requests'),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Default to sub action 'index' or 'settings' depending on permissions.
|
||||||
|
$_REQUEST['sa'] = isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : 'index';
|
||||||
|
|
||||||
|
// Get the template stuff up and running.
|
||||||
|
loadLanguage('ManageMembers');
|
||||||
|
loadLanguage('ModerationCenter');
|
||||||
|
loadTemplate('ManageMembergroups');
|
||||||
|
|
||||||
|
// If we can see the moderation center, and this has a mod bar entry, add the mod center bar.
|
||||||
|
if (allowedTo('access_mod_center') || $user_info['mod_cache']['bq'] != '0=1' || $user_info['mod_cache']['gq'] != '0=1' || allowedTo('manage_membergroups'))
|
||||||
|
{
|
||||||
|
require_once($sourcedir . '/ModerationCenter.php');
|
||||||
|
$_GET['area'] = $_REQUEST['sa'] == 'requests' ? 'groups' : 'viewgroups';
|
||||||
|
ModerationMain(true);
|
||||||
|
}
|
||||||
|
// Otherwise add something to the link tree, for normal people.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isAllowedTo('view_mlist');
|
||||||
|
|
||||||
|
$context['linktree'][] = array(
|
||||||
|
'url' => $scripturl . '?action=groups',
|
||||||
|
'name' => $txt['groups'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the actual function.
|
||||||
|
$subActions[$_REQUEST['sa']][0]();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This very simply lists the groups, nothing snazy.
|
||||||
|
function GroupList()
|
||||||
|
{
|
||||||
|
global $txt, $scripturl, $user_profile, $user_info, $context, $settings, $modSettings, $smcFunc, $sourcedir;
|
||||||
|
|
||||||
|
// Yep, find the groups...
|
||||||
|
$request = $smcFunc['db_query']('', '
|
||||||
|
SELECT mg.id_group, mg.group_name, mg.description, mg.group_type, mg.online_color, mg.hidden,
|
||||||
|
mg.stars, IFNULL(gm.id_member, 0) AS can_moderate
|
||||||
|
FROM {db_prefix}membergroups AS mg
|
||||||
|
LEFT JOIN {db_prefix}group_moderators AS gm ON (gm.id_group = mg.id_group AND gm.id_member = {int:current_member})
|
||||||
|
WHERE mg.min_posts = {int:min_posts}
|
||||||
|
AND mg.id_group != {int:mod_group}' . (allowedTo('admin_forum') ? '' : '
|
||||||
|
AND mg.group_type != {int:is_protected}') . '
|
||||||
|
ORDER BY group_name',
|
||||||
|
array(
|
||||||
|
'current_member' => $user_info['id'],
|
||||||
|
'min_posts' => -1,
|
||||||
|
'mod_group' => 3,
|
||||||
|
'is_protected' => 1,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
// This is where we store our groups.
|
||||||
|
$context['groups'] = array();
|
||||||
|
$group_ids = array();
|
||||||
|
$context['can_moderate'] = allowedTo('manage_membergroups');
|
||||||
|
while ($row = $smcFunc['db_fetch_assoc']($request))
|
||||||
|
{
|
||||||
|
// We only list the groups they can see.
|
||||||
|
if ($row['hidden'] && !$row['can_moderate'] && !allowedTo('manage_membergroups'))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$row['stars'] = explode('#', $row['stars']);
|
||||||
|
|
||||||
|
$context['groups'][$row['id_group']] = array(
|
||||||
|
'id' => $row['id_group'],
|
||||||
|
'name' => $row['group_name'],
|
||||||
|
'desc' => $row['description'],
|
||||||
|
'color' => $row['online_color'],
|
||||||
|
'type' => $row['group_type'],
|
||||||
|
'num_members' => 0,
|
||||||
|
'stars' => !empty($row['stars'][0]) && !empty($row['stars'][1]) ? str_repeat('<img src="' . $settings['images_url'] . '/' . $row['stars'][1] . '" alt="*" />', $row['stars'][0]) : '',
|
||||||
|
);
|
||||||
|
|
||||||
|
$context['can_moderate'] |= $row['can_moderate'];
|
||||||
|
$group_ids[] = $row['id_group'];
|
||||||
|
}
|
||||||
|
$smcFunc['db_free_result']($request);
|
||||||
|
|
||||||
|
// Count up the members separately...
|
||||||
|
if (!empty($group_ids))
|
||||||
|
{
|
||||||
|
$query = $smcFunc['db_query']('', '
|
||||||
|
SELECT id_group, COUNT(*) AS num_members
|
||||||
|
FROM {db_prefix}members
|
||||||
|
WHERE id_group IN ({array_int:group_list})
|
||||||
|
GROUP BY id_group',
|
||||||
|
array(
|
||||||
|
'group_list' => $group_ids,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
while ($row = $smcFunc['db_fetch_assoc']($query))
|
||||||
|
$context['groups'][$row['id_group']]['num_members'] += $row['num_members'];
|
||||||
|
$smcFunc['db_free_result']($query);
|
||||||
|
|
||||||
|
// Only do additional groups if we can moderate...
|
||||||
|
if ($context['can_moderate'])
|
||||||
|
{
|
||||||
|
$query = $smcFunc['db_query']('', '
|
||||||
|
SELECT mg.id_group, COUNT(*) AS num_members
|
||||||
|
FROM {db_prefix}membergroups AS mg
|
||||||
|
INNER JOIN {db_prefix}members AS mem ON (mem.additional_groups != {string:blank_screen}
|
||||||
|
AND mem.id_group != mg.id_group
|
||||||
|
AND FIND_IN_SET(mg.id_group, mem.additional_groups) != 0)
|
||||||
|
WHERE mg.id_group IN ({array_int:group_list})
|
||||||
|
GROUP BY mg.id_group',
|
||||||
|
array(
|
||||||
|
'group_list' => $group_ids,
|
||||||
|
'blank_screen' => '',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
while ($row = $smcFunc['db_fetch_assoc']($query))
|
||||||
|
$context['groups'][$row['id_group']]['num_members'] += $row['num_members'];
|
||||||
|
$smcFunc['db_free_result']($query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$context['sub_template'] = 'group_index';
|
||||||
|
$context['page_title'] = $txt['viewing_groups'];
|
||||||
|
|
||||||
|
// Making a list is not hard with this beauty.
|
||||||
|
require_once($sourcedir . '/Subs-List.php');
|
||||||
|
|
||||||
|
// Use the standard templates for showing this.
|
||||||
|
$listOptions = array(
|
||||||
|
'id' => 'group_lists',
|
||||||
|
'title' => $context['page_title'],
|
||||||
|
'get_items' => array(
|
||||||
|
'function' => 'list_getGroups',
|
||||||
|
),
|
||||||
|
'columns' => array(
|
||||||
|
'group' => array(
|
||||||
|
'header' => array(
|
||||||
|
'value' => $txt['name'],
|
||||||
|
),
|
||||||
|
'data' => array(
|
||||||
|
'function' => create_function('$group', '
|
||||||
|
global $scripturl, $context;
|
||||||
|
|
||||||
|
$output = \'<a href="\' . $scripturl . \'?action=\' . $context[\'current_action\'] . (isset($context[\'admin_area\']) ? \';area=\' . $context[\'admin_area\'] : \'\') . \';sa=members;group=\' . $group[\'id\'] . \'" \' . ($group[\'color\'] ? \'style="color: \' . $group[\'color\'] . \';"\' : \'\') . \'>\' . $group[\'name\'] . \'</a>\';
|
||||||
|
|
||||||
|
if ($group[\'desc\'])
|
||||||
|
$output .= \'<div class="smalltext">\' . $group[\'desc\'] . \'</div>\';
|
||||||
|
|
||||||
|
return $output;
|
||||||
|
'),
|
||||||
|
'style' => 'width: 50%;',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'stars' => array(
|
||||||
|
'header' => array(
|
||||||
|
'value' => $txt['membergroups_stars'],
|
||||||
|
),
|
||||||
|
'data' => array(
|
||||||
|
'db' => 'stars',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'moderators' => array(
|
||||||
|
'header' => array(
|
||||||
|
'value' => $txt['moderators'],
|
||||||
|
),
|
||||||
|
'data' => array(
|
||||||
|
'function' => create_function('$group', '
|
||||||
|
global $txt;
|
||||||
|
|
||||||
|
return empty($group[\'moderators\']) ? \'<em>\' . $txt[\'membergroups_new_copy_none\'] . \'</em>\' : implode(\', \', $group[\'moderators\']);
|
||||||
|
'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'members' => array(
|
||||||
|
'header' => array(
|
||||||
|
'value' => $txt['membergroups_members_top'],
|
||||||
|
),
|
||||||
|
'data' => array(
|
||||||
|
'comma_format' => true,
|
||||||
|
'db' => 'num_members',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create the request list.
|
||||||
|
createList($listOptions);
|
||||||
|
|
||||||
|
$context['sub_template'] = 'show_list';
|
||||||
|
$context['default_list'] = 'group_lists';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the group information for the list.
|
||||||
|
function list_getGroups($start, $items_per_page, $sort)
|
||||||
|
{
|
||||||
|
global $smcFunc, $txt, $scripturl, $user_info, $settings;
|
||||||
|
|
||||||
|
// Yep, find the groups...
|
||||||
|
$request = $smcFunc['db_query']('', '
|
||||||
|
SELECT mg.id_group, mg.group_name, mg.description, mg.group_type, mg.online_color, mg.hidden,
|
||||||
|
mg.stars, IFNULL(gm.id_member, 0) AS can_moderate
|
||||||
|
FROM {db_prefix}membergroups AS mg
|
||||||
|
LEFT JOIN {db_prefix}group_moderators AS gm ON (gm.id_group = mg.id_group AND gm.id_member = {int:current_member})
|
||||||
|
WHERE mg.min_posts = {int:min_posts}
|
||||||
|
AND mg.id_group != {int:mod_group}' . (allowedTo('admin_forum') ? '' : '
|
||||||
|
AND mg.group_type != {int:is_protected}') . '
|
||||||
|
ORDER BY group_name',
|
||||||
|
array(
|
||||||
|
'current_member' => $user_info['id'],
|
||||||
|
'min_posts' => -1,
|
||||||
|
'mod_group' => 3,
|
||||||
|
'is_protected' => 1,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
// Start collecting the data.
|
||||||
|
$groups = array();
|
||||||
|
$group_ids = array();
|
||||||
|
$context['can_moderate'] = allowedTo('manage_membergroups');
|
||||||
|
while ($row = $smcFunc['db_fetch_assoc']($request))
|
||||||
|
{
|
||||||
|
// We only list the groups they can see.
|
||||||
|
if ($row['hidden'] && !$row['can_moderate'] && !allowedTo('manage_membergroups'))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$row['stars'] = explode('#', $row['stars']);
|
||||||
|
|
||||||
|
$groups[$row['id_group']] = array(
|
||||||
|
'id' => $row['id_group'],
|
||||||
|
'name' => $row['group_name'],
|
||||||
|
'desc' => $row['description'],
|
||||||
|
'color' => $row['online_color'],
|
||||||
|
'type' => $row['group_type'],
|
||||||
|
'num_members' => 0,
|
||||||
|
'moderators' => array(),
|
||||||
|
'stars' => !empty($row['stars'][0]) && !empty($row['stars'][1]) ? str_repeat('<img src="' . $settings['images_url'] . '/' . $row['stars'][1] . '" alt="*" />', $row['stars'][0]) : '',
|
||||||
|
);
|
||||||
|
|
||||||
|
$context['can_moderate'] |= $row['can_moderate'];
|
||||||
|
$group_ids[] = $row['id_group'];
|
||||||
|
}
|
||||||
|
$smcFunc['db_free_result']($request);
|
||||||
|
|
||||||
|
// Count up the members separately...
|
||||||
|
if (!empty($group_ids))
|
||||||
|
{
|
||||||
|
$query = $smcFunc['db_query']('', '
|
||||||
|
SELECT id_group, COUNT(*) AS num_members
|
||||||
|
FROM {db_prefix}members
|
||||||
|
WHERE id_group IN ({array_int:group_list})
|
||||||
|
GROUP BY id_group',
|
||||||
|
array(
|
||||||
|
'group_list' => $group_ids,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
while ($row = $smcFunc['db_fetch_assoc']($query))
|
||||||
|
$groups[$row['id_group']]['num_members'] += $row['num_members'];
|
||||||
|
$smcFunc['db_free_result']($query);
|
||||||
|
|
||||||
|
// Only do additional groups if we can moderate...
|
||||||
|
if ($context['can_moderate'])
|
||||||
|
{
|
||||||
|
$query = $smcFunc['db_query']('', '
|
||||||
|
SELECT mg.id_group, COUNT(*) AS num_members
|
||||||
|
FROM {db_prefix}membergroups AS mg
|
||||||
|
INNER JOIN {db_prefix}members AS mem ON (mem.additional_groups != {string:blank_screen}
|
||||||
|
AND mem.id_group != mg.id_group
|
||||||
|
AND FIND_IN_SET(mg.id_group, mem.additional_groups) != 0)
|
||||||
|
WHERE mg.id_group IN ({array_int:group_list})
|
||||||
|
GROUP BY mg.id_group',
|
||||||
|
array(
|
||||||
|
'group_list' => $group_ids,
|
||||||
|
'blank_screen' => '',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
while ($row = $smcFunc['db_fetch_assoc']($query))
|
||||||
|
$groups[$row['id_group']]['num_members'] += $row['num_members'];
|
||||||
|
$smcFunc['db_free_result']($query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get any group moderators.
|
||||||
|
// Count up the members separately...
|
||||||
|
if (!empty($group_ids))
|
||||||
|
{
|
||||||
|
$query = $smcFunc['db_query']('', '
|
||||||
|
SELECT mods.id_group, mods.id_member, mem.member_name, mem.real_name
|
||||||
|
FROM {db_prefix}group_moderators AS mods
|
||||||
|
INNER JOIN {db_prefix}members AS mem ON (mem.id_member = mods.id_member)
|
||||||
|
WHERE mods.id_group IN ({array_int:group_list})',
|
||||||
|
array(
|
||||||
|
'group_list' => $group_ids,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
while ($row = $smcFunc['db_fetch_assoc']($query))
|
||||||
|
$groups[$row['id_group']]['moderators'][] = '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['real_name'] . '</a>';
|
||||||
|
$smcFunc['db_free_result']($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
// How many groups are there that are visible?
|
||||||
|
function list_getGroupCount()
|
||||||
|
{
|
||||||
|
global $smcFunc;
|
||||||
|
|
||||||
|
$request = $smcFunc['db_query']('', '
|
||||||
|
SELECT COUNT(id_group) AS group_count
|
||||||
|
FROM {db_prefix}membergroups
|
||||||
|
WHERE mg.min_posts = {int:min_posts}
|
||||||
|
AND mg.id_group != {int:mod_group}' . (allowedTo('admin_forum') ? '' : '
|
||||||
|
AND mg.group_type != {int:is_protected}'),
|
||||||
|
array(
|
||||||
|
'min_posts' => -1,
|
||||||
|
'mod_group' => 3,
|
||||||
|
'is_protected' => 1,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
list ($group_count) = $smcFunc['db_fetch_row']($request);
|
||||||
|
$smcFunc['db_free_result']($request);
|
||||||
|
|
||||||
|
return $group_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display members of a group, and allow adding of members to a group. Silly function name though ;)
|
||||||
|
function MembergroupMembers()
|
||||||
|
{
|
||||||
|
global $txt, $scripturl, $context, $modSettings, $sourcedir, $user_info, $settings, $smcFunc;
|
||||||
|
|
||||||
|
$_REQUEST['group'] = isset($_REQUEST['group']) ? (int) $_REQUEST['group'] : 0;
|
||||||
|
|
||||||
|
// No browsing of guests, membergroup 0 or moderators.
|
||||||
|
if (in_array($_REQUEST['group'], array(-1, 0, 3)))
|
||||||
|
fatal_lang_error('membergroup_does_not_exist', false);
|
||||||
|
|
||||||
|
// Load up the group details.
|
||||||
|
$request = $smcFunc['db_query']('', '
|
||||||
|
SELECT id_group AS id, group_name AS name, CASE WHEN min_posts = {int:min_posts} THEN 1 ELSE 0 END AS assignable, hidden, online_color,
|
||||||
|
stars, description, CASE WHEN min_posts != {int:min_posts} THEN 1 ELSE 0 END AS is_post_group, group_type
|
||||||
|
FROM {db_prefix}membergroups
|
||||||
|
WHERE id_group = {int:id_group}
|
||||||
|
LIMIT 1',
|
||||||
|
array(
|
||||||
|
'min_posts' => -1,
|
||||||
|
'id_group' => $_REQUEST['group'],
|
||||||
|
)
|
||||||
|
);
|
||||||
|
// Doesn't exist?
|
||||||
|
if ($smcFunc['db_num_rows']($request) == 0)
|
||||||
|
fatal_lang_error('membergroup_does_not_exist', false);
|
||||||
|
$context['group'] = $smcFunc['db_fetch_assoc']($request);
|
||||||
|
$smcFunc['db_free_result']($request);
|
||||||
|
|
||||||
|
// Fix the stars.
|
||||||
|
$context['group']['stars'] = explode('#', $context['group']['stars']);
|
||||||
|
$context['group']['stars'] = !empty($context['group']['stars'][0]) && !empty($context['group']['stars'][1]) ? str_repeat('<img src="' . $settings['images_url'] . '/' . $context['group']['stars'][1] . '" alt="*" />', $context['group']['stars'][0]) : '';
|
||||||
|
$context['group']['can_moderate'] = allowedTo('manage_membergroups') && (allowedTo('admin_forum') || $context['group']['group_type'] != 1);
|
||||||
|
|
||||||
|
$context['linktree'][] = array(
|
||||||
|
'url' => $scripturl . '?action=groups;sa=members;group=' . $context['group']['id'],
|
||||||
|
'name' => $context['group']['name'],
|
||||||
|
);
|
||||||
|
|
||||||
|
// Load all the group moderators, for fun.
|
||||||
|
$request = $smcFunc['db_query']('', '
|
||||||
|
SELECT mem.id_member, mem.real_name
|
||||||
|
FROM {db_prefix}group_moderators AS mods
|
||||||
|
INNER JOIN {db_prefix}members AS mem ON (mem.id_member = mods.id_member)
|
||||||
|
WHERE mods.id_group = {int:id_group}',
|
||||||
|
array(
|
||||||
|
'id_group' => $_REQUEST['group'],
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$context['group']['moderators'] = array();
|
||||||
|
while ($row = $smcFunc['db_fetch_assoc']($request))
|
||||||
|
{
|
||||||
|
$context['group']['moderators'][] = array(
|
||||||
|
'id' => $row['id_member'],
|
||||||
|
'name' => $row['real_name']
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($user_info['id'] == $row['id_member'] && $context['group']['group_type'] != 1)
|
||||||
|
$context['group']['can_moderate'] = true;
|
||||||
|
}
|
||||||
|
$smcFunc['db_free_result']($request);
|
||||||
|
|
||||||
|
// If this group is hidden then it can only "exists" if the user can moderate it!
|
||||||
|
if ($context['group']['hidden'] && !$context['group']['can_moderate'])
|
||||||
|
fatal_lang_error('membergroup_does_not_exist', false);
|
||||||
|
|
||||||
|
// You can only assign membership if you are the moderator and/or can manage groups!
|
||||||
|
if (!$context['group']['can_moderate'])
|
||||||
|
$context['group']['assignable'] = 0;
|
||||||
|
// Non-admins cannot assign admins.
|
||||||
|
elseif ($context['group']['id'] == 1 && !allowedTo('admin_forum'))
|
||||||
|
$context['group']['assignable'] = 0;
|
||||||
|
|
||||||
|
// Removing member from group?
|
||||||
|
if (isset($_POST['remove']) && !empty($_REQUEST['rem']) && is_array($_REQUEST['rem']) && $context['group']['assignable'])
|
||||||
|
{
|
||||||
|
checkSession();
|
||||||
|
|
||||||
|
// Make sure we're dealing with integers only.
|
||||||
|
foreach ($_REQUEST['rem'] as $key => $group)
|
||||||
|
$_REQUEST['rem'][$key] = (int) $group;
|
||||||
|
|
||||||
|
require_once($sourcedir . '/Subs-Membergroups.php');
|
||||||
|
removeMembersFromGroups($_REQUEST['rem'], $_REQUEST['group'], true);
|
||||||
|
}
|
||||||
|
// Must be adding new members to the group...
|
||||||
|
elseif (isset($_REQUEST['add']) && (!empty($_REQUEST['toAdd']) || !empty($_REQUEST['member_add'])) && $context['group']['assignable'])
|
||||||
|
{
|
||||||
|
checkSession();
|
||||||
|
|
||||||
|
$member_query = array();
|
||||||
|
$member_parameters = array();
|
||||||
|
|
||||||
|
// Get all the members to be added... taking into account names can be quoted ;)
|
||||||
|
$_REQUEST['toAdd'] = strtr($smcFunc['htmlspecialchars']($_REQUEST['toAdd'], ENT_QUOTES), array('"' => '"'));
|
||||||
|
preg_match_all('~"([^"]+)"~', $_REQUEST['toAdd'], $matches);
|
||||||
|
$member_names = array_unique(array_merge($matches[1], explode(',', preg_replace('~"[^"]+"~', '', $_REQUEST['toAdd']))));
|
||||||
|
|
||||||
|
foreach ($member_names as $index => $member_name)
|
||||||
|
{
|
||||||
|
$member_names[$index] = trim($smcFunc['strtolower']($member_names[$index]));
|
||||||
|
|
||||||
|
if (strlen($member_names[$index]) == 0)
|
||||||
|
unset($member_names[$index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any passed by ID?
|
||||||
|
$member_ids = array();
|
||||||
|
if (!empty($_REQUEST['member_add']))
|
||||||
|
foreach ($_REQUEST['member_add'] as $id)
|
||||||
|
if ($id > 0)
|
||||||
|
$member_ids[] = (int) $id;
|
||||||
|
|
||||||
|
// Construct the query pelements.
|
||||||
|
if (!empty($member_ids))
|
||||||
|
{
|
||||||
|
$member_query[] = 'id_member IN ({array_int:member_ids})';
|
||||||
|
$member_parameters['member_ids'] = $member_ids;
|
||||||
|
}
|
||||||
|
if (!empty($member_names))
|
||||||
|
{
|
||||||
|
$member_query[] = 'LOWER(member_name) IN ({array_string:member_names})';
|
||||||
|
$member_query[] = 'LOWER(real_name) IN ({array_string:member_names})';
|
||||||
|
$member_parameters['member_names'] = $member_names;
|
||||||
|
}
|
||||||
|
|
||||||
|
$members = array();
|
||||||
|
if (!empty($member_query))
|
||||||
|
{
|
||||||
|
$request = $smcFunc['db_query']('', '
|
||||||
|
SELECT id_member
|
||||||
|
FROM {db_prefix}members
|
||||||
|
WHERE (' . implode(' OR ', $member_query) . ')
|
||||||
|
AND id_group != {int:id_group}
|
||||||
|
AND FIND_IN_SET({int:id_group}, additional_groups) = 0',
|
||||||
|
array_merge($member_parameters, array(
|
||||||
|
'id_group' => $_REQUEST['group'],
|
||||||
|
))
|
||||||
|
);
|
||||||
|
while ($row = $smcFunc['db_fetch_assoc']($request))
|
||||||
|
$members[] = $row['id_member'];
|
||||||
|
$smcFunc['db_free_result']($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
// !!! Add $_POST['additional'] to templates!
|
||||||
|
|
||||||
|
// Do the updates...
|
||||||
|
if (!empty($members))
|
||||||
|
{
|
||||||
|
require_once($sourcedir . '/Subs-Membergroups.php');
|
||||||
|
addMembersToGroup($members, $_REQUEST['group'], isset($_POST['additional']) || $context['group']['hidden'] ? 'only_additional' : 'auto', true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort out the sorting!
|
||||||
|
$sort_methods = array(
|
||||||
|
'name' => 'real_name',
|
||||||
|
'email' => allowedTo('moderate_forum') ? 'email_address' : 'hide_email ' . (isset($_REQUEST['desc']) ? 'DESC' : 'ASC') . ', email_address',
|
||||||
|
'active' => 'last_login',
|
||||||
|
'registered' => 'date_registered',
|
||||||
|
'posts' => 'posts',
|
||||||
|
);
|
||||||
|
|
||||||
|
// They didn't pick one, default to by name..
|
||||||
|
if (!isset($_REQUEST['sort']) || !isset($sort_methods[$_REQUEST['sort']]))
|
||||||
|
{
|
||||||
|
$context['sort_by'] = 'name';
|
||||||
|
$querySort = 'real_name';
|
||||||
|
}
|
||||||
|
// Otherwise default to ascending.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$context['sort_by'] = $_REQUEST['sort'];
|
||||||
|
$querySort = $sort_methods[$_REQUEST['sort']];
|
||||||
|
}
|
||||||
|
|
||||||
|
$context['sort_direction'] = isset($_REQUEST['desc']) ? 'down' : 'up';
|
||||||
|
|
||||||
|
// The where on the query is interesting. Non-moderators should only see people who are in this group as primary.
|
||||||
|
if ($context['group']['can_moderate'])
|
||||||
|
$where = $context['group']['is_post_group'] ? 'id_post_group = {int:group}' : 'id_group = {int:group} OR FIND_IN_SET({int:group}, additional_groups) != 0';
|
||||||
|
else
|
||||||
|
$where = $context['group']['is_post_group'] ? 'id_post_group = {int:group}' : 'id_group = {int:group}';
|
||||||
|
|
||||||
|
// Count members of the group.
|
||||||
|
$request = $smcFunc['db_query']('', '
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM {db_prefix}members
|
||||||
|
WHERE ' . $where,
|
||||||
|
array(
|
||||||
|
'group' => $_REQUEST['group'],
|
||||||
|
)
|
||||||
|
);
|
||||||
|
list ($context['total_members']) = $smcFunc['db_fetch_row']($request);
|
||||||
|
$smcFunc['db_free_result']($request);
|
||||||
|
$context['total_members'] = comma_format($context['total_members']);
|
||||||
|
|
||||||
|
// Create the page index.
|
||||||
|
$context['page_index'] = constructPageIndex($scripturl . '?action=' . ($context['group']['can_moderate'] ? 'moderate;area=viewgroups' : 'groups') . ';sa=members;group=' . $_REQUEST['group'] . ';sort=' . $context['sort_by'] . (isset($_REQUEST['desc']) ? ';desc' : ''), $_REQUEST['start'], $context['total_members'], $modSettings['defaultMaxMembers']);
|
||||||
|
$context['start'] = $_REQUEST['start'];
|
||||||
|
$context['can_moderate_forum'] = allowedTo('moderate_forum');
|
||||||
|
|
||||||
|
// Load up all members of this group.
|
||||||
|
$request = $smcFunc['db_query']('', '
|
||||||
|
SELECT id_member, member_name, real_name, email_address, member_ip, date_registered, last_login,
|
||||||
|
hide_email, posts, is_activated, real_name
|
||||||
|
FROM {db_prefix}members
|
||||||
|
WHERE ' . $where . '
|
||||||
|
ORDER BY ' . $querySort . ' ' . ($context['sort_direction'] == 'down' ? 'DESC' : 'ASC') . '
|
||||||
|
LIMIT ' . $context['start'] . ', ' . $modSettings['defaultMaxMembers'],
|
||||||
|
array(
|
||||||
|
'group' => $_REQUEST['group'],
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$context['members'] = array();
|
||||||
|
while ($row = $smcFunc['db_fetch_assoc']($request))
|
||||||
|
{
|
||||||
|
$last_online = empty($row['last_login']) ? $txt['never'] : timeformat($row['last_login']);
|
||||||
|
|
||||||
|
// Italicize the online note if they aren't activated.
|
||||||
|
if ($row['is_activated'] % 10 != 1)
|
||||||
|
$last_online = '<em title="' . $txt['not_activated'] . '">' . $last_online . '</em>';
|
||||||
|
|
||||||
|
$context['members'][] = array(
|
||||||
|
'id' => $row['id_member'],
|
||||||
|
'name' => '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['real_name'] . '</a>',
|
||||||
|
'email' => $row['email_address'],
|
||||||
|
'show_email' => showEmailAddress(!empty($row['hide_email']), $row['id_member']),
|
||||||
|
'ip' => '<a href="' . $scripturl . '?action=trackip;searchip=' . $row['member_ip'] . '">' . $row['member_ip'] . '</a>',
|
||||||
|
'registered' => timeformat($row['date_registered']),
|
||||||
|
'last_online' => $last_online,
|
||||||
|
'posts' => comma_format($row['posts']),
|
||||||
|
'is_activated' => $row['is_activated'] % 10 == 1,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$smcFunc['db_free_result']($request);
|
||||||
|
|
||||||
|
// Select the template.
|
||||||
|
$context['sub_template'] = 'group_members';
|
||||||
|
$context['page_title'] = $txt['membergroups_members_title'] . ': ' . $context['group']['name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show and manage all group requests.
|
||||||
|
function GroupRequests()
|
||||||
|
{
|
||||||
|
global $txt, $context, $scripturl, $user_info, $sourcedir, $smcFunc, $modSettings, $language;
|
||||||
|
|
||||||
|
// Set up the template stuff...
|
||||||
|
$context['page_title'] = $txt['mc_group_requests'];
|
||||||
|
$context['sub_template'] = 'show_list';
|
||||||
|
|
||||||
|
// Verify we can be here.
|
||||||
|
if ($user_info['mod_cache']['gq'] == '0=1')
|
||||||
|
isAllowedTo('manage_membergroups');
|
||||||
|
|
||||||
|
// Normally, we act normally...
|
||||||
|
$where = $user_info['mod_cache']['gq'] == '1=1' || $user_info['mod_cache']['gq'] == '0=1' ? $user_info['mod_cache']['gq'] : 'lgr.' . $user_info['mod_cache']['gq'];
|
||||||
|
$where_parameters = array();
|
||||||
|
|
||||||
|
// We've submitted?
|
||||||
|
if (isset($_POST[$context['session_var']]) && !empty($_POST['groupr']) && !empty($_POST['req_action']))
|
||||||
|
{
|
||||||
|
checkSession('post');
|
||||||
|
|
||||||
|
// Clean the values.
|
||||||
|
foreach ($_POST['groupr'] as $k => $request)
|
||||||
|
$_POST['groupr'][$k] = (int) $request;
|
||||||
|
|
||||||
|
// If we are giving a reason (And why shouldn't we?), then we don't actually do much.
|
||||||
|
if ($_POST['req_action'] == 'reason')
|
||||||
|
{
|
||||||
|
// Different sub template...
|
||||||
|
$context['sub_template'] = 'group_request_reason';
|
||||||
|
// And a limitation. We don't care that the page number bit makes no sense, as we don't need it!
|
||||||
|
$where .= ' AND lgr.id_request IN ({array_int:request_ids})';
|
||||||
|
$where_parameters['request_ids'] = $_POST['groupr'];
|
||||||
|
|
||||||
|
$context['group_requests'] = list_getGroupRequests(0, $modSettings['defaultMaxMessages'], 'lgr.id_request', $where, $where_parameters);
|
||||||
|
|
||||||
|
// Let obExit etc sort things out.
|
||||||
|
obExit();
|
||||||
|
}
|
||||||
|
// Otherwise we do something!
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Get the details of all the members concerned...
|
||||||
|
$request = $smcFunc['db_query']('', '
|
||||||
|
SELECT lgr.id_request, lgr.id_member, lgr.id_group, mem.email_address, mem.id_group AS primary_group,
|
||||||
|
mem.additional_groups AS additional_groups, mem.lngfile, mem.member_name, mem.notify_types,
|
||||||
|
mg.hidden, mg.group_name
|
||||||
|
FROM {db_prefix}log_group_requests AS lgr
|
||||||
|
INNER JOIN {db_prefix}members AS mem ON (mem.id_member = lgr.id_member)
|
||||||
|
INNER JOIN {db_prefix}membergroups AS mg ON (mg.id_group = lgr.id_group)
|
||||||
|
WHERE ' . $where . '
|
||||||
|
AND lgr.id_request IN ({array_int:request_list})
|
||||||
|
ORDER BY mem.lngfile',
|
||||||
|
array(
|
||||||
|
'request_list' => $_POST['groupr'],
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$email_details = array();
|
||||||
|
$group_changes = array();
|
||||||
|
while ($row = $smcFunc['db_fetch_assoc']($request))
|
||||||
|
{
|
||||||
|
$row['lngfile'] = empty($row['lngfile']) || empty($modSettings['userLanguage']) ? $language : $row['lngfile'];
|
||||||
|
|
||||||
|
// If we are approving work out what their new group is.
|
||||||
|
if ($_POST['req_action'] == 'approve')
|
||||||
|
{
|
||||||
|
// For people with more than one request at once.
|
||||||
|
if (isset($group_changes[$row['id_member']]))
|
||||||
|
{
|
||||||
|
$row['additional_groups'] = $group_changes[$row['id_member']]['add'];
|
||||||
|
$row['primary_group'] = $group_changes[$row['id_member']]['primary'];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$row['additional_groups'] = explode(',', $row['additional_groups']);
|
||||||
|
|
||||||
|
// Don't have it already?
|
||||||
|
if ($row['primary_group'] == $row['id_group'] || in_array($row['id_group'], $row['additional_groups']))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Should it become their primary?
|
||||||
|
if ($row['primary_group'] == 0 && $row['hidden'] == 0)
|
||||||
|
$row['primary_group'] = $row['id_group'];
|
||||||
|
else
|
||||||
|
$row['additional_groups'][] = $row['id_group'];
|
||||||
|
|
||||||
|
// Add them to the group master list.
|
||||||
|
$group_changes[$row['id_member']] = array(
|
||||||
|
'primary' => $row['primary_group'],
|
||||||
|
'add' => $row['additional_groups'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add required information to email them.
|
||||||
|
if ($row['notify_types'] != 4)
|
||||||
|
$email_details[] = array(
|
||||||
|
'rid' => $row['id_request'],
|
||||||
|
'member_id' => $row['id_member'],
|
||||||
|
'member_name' => $row['member_name'],
|
||||||
|
'group_id' => $row['id_group'],
|
||||||
|
'group_name' => $row['group_name'],
|
||||||
|
'email' => $row['email_address'],
|
||||||
|
'language' => $row['lngfile'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$smcFunc['db_free_result']($request);
|
||||||
|
|
||||||
|
// Remove the evidence...
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
DELETE FROM {db_prefix}log_group_requests
|
||||||
|
WHERE id_request IN ({array_int:request_list})',
|
||||||
|
array(
|
||||||
|
'request_list' => $_POST['groupr'],
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Ensure everyone who is online gets their changes right away.
|
||||||
|
updateSettings(array('settings_updated' => time()));
|
||||||
|
|
||||||
|
if (!empty($email_details))
|
||||||
|
{
|
||||||
|
require_once($sourcedir . '/Subs-Post.php');
|
||||||
|
|
||||||
|
// They are being approved?
|
||||||
|
if ($_POST['req_action'] == 'approve')
|
||||||
|
{
|
||||||
|
// Make the group changes.
|
||||||
|
foreach ($group_changes as $id => $groups)
|
||||||
|
{
|
||||||
|
// Sanity check!
|
||||||
|
foreach ($groups['add'] as $key => $value)
|
||||||
|
if ($value == 0 || trim($value) == '')
|
||||||
|
unset($groups['add'][$key]);
|
||||||
|
|
||||||
|
$smcFunc['db_query']('', '
|
||||||
|
UPDATE {db_prefix}members
|
||||||
|
SET id_group = {int:primary_group}, additional_groups = {string:additional_groups}
|
||||||
|
WHERE id_member = {int:selected_member}',
|
||||||
|
array(
|
||||||
|
'primary_group' => $groups['primary'],
|
||||||
|
'selected_member' => $id,
|
||||||
|
'additional_groups' => implode(',', $groups['add']),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$lastLng = $user_info['language'];
|
||||||
|
foreach ($email_details as $email)
|
||||||
|
{
|
||||||
|
$replacements = array(
|
||||||
|
'USERNAME' => $email['member_name'],
|
||||||
|
'GROUPNAME' => $email['group_name'],
|
||||||
|
);
|
||||||
|
|
||||||
|
$emaildata = loadEmailTemplate('mc_group_approve', $replacements, $email['language']);
|
||||||
|
|
||||||
|
sendmail($email['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Otherwise, they are getting rejected (With or without a reason).
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Same as for approving, kind of.
|
||||||
|
$lastLng = $user_info['language'];
|
||||||
|
foreach ($email_details as $email)
|
||||||
|
{
|
||||||
|
$custom_reason = isset($_POST['groupreason']) && isset($_POST['groupreason'][$email['rid']]) ? $_POST['groupreason'][$email['rid']] : '';
|
||||||
|
|
||||||
|
$replacements = array(
|
||||||
|
'USERNAME' => $email['member_name'],
|
||||||
|
'GROUPNAME' => $email['group_name'],
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!empty($custom_reason))
|
||||||
|
$replacements['REASON'] = $custom_reason;
|
||||||
|
|
||||||
|
$emaildata = loadEmailTemplate(empty($custom_reason) ? 'mc_group_reject' : 'mc_group_reject_reason', $replacements, $email['language']);
|
||||||
|
|
||||||
|
sendmail($email['email'], $emaildata['subject'], $emaildata['body'], null, null, false, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore the current language.
|
||||||
|
loadLanguage('ModerationCenter');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We're going to want this for making our list.
|
||||||
|
require_once($sourcedir . '/Subs-List.php');
|
||||||
|
|
||||||
|
// This is all the information required for a group listing.
|
||||||
|
$listOptions = array(
|
||||||
|
'id' => 'group_request_list',
|
||||||
|
'title' => $txt['mc_group_requests'],
|
||||||
|
'width' => '100%',
|
||||||
|
'items_per_page' => $modSettings['defaultMaxMessages'],
|
||||||
|
'no_items_label' => $txt['mc_groupr_none_found'],
|
||||||
|
'base_href' => $scripturl . '?action=groups;sa=requests',
|
||||||
|
'default_sort_col' => 'member',
|
||||||
|
'get_items' => array(
|
||||||
|
'function' => 'list_getGroupRequests',
|
||||||
|
'params' => array(
|
||||||
|
$where,
|
||||||
|
$where_parameters,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'get_count' => array(
|
||||||
|
'function' => 'list_getGroupRequestCount',
|
||||||
|
'params' => array(
|
||||||
|
$where,
|
||||||
|
$where_parameters,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'columns' => array(
|
||||||
|
'member' => array(
|
||||||
|
'header' => array(
|
||||||
|
'value' => $txt['mc_groupr_member'],
|
||||||
|
),
|
||||||
|
'data' => array(
|
||||||
|
'db' => 'member_link',
|
||||||
|
),
|
||||||
|
'sort' => array(
|
||||||
|
'default' => 'mem.member_name',
|
||||||
|
'reverse' => 'mem.member_name DESC',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'group' => array(
|
||||||
|
'header' => array(
|
||||||
|
'value' => $txt['mc_groupr_group'],
|
||||||
|
),
|
||||||
|
'data' => array(
|
||||||
|
'db' => 'group_link',
|
||||||
|
),
|
||||||
|
'sort' => array(
|
||||||
|
'default' => 'mg.group_name',
|
||||||
|
'reverse' => 'mg.group_name DESC',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'reason' => array(
|
||||||
|
'header' => array(
|
||||||
|
'value' => $txt['mc_groupr_reason'],
|
||||||
|
),
|
||||||
|
'data' => array(
|
||||||
|
'db' => 'reason',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'action' => array(
|
||||||
|
'header' => array(
|
||||||
|
'value' => '<input type="checkbox" class="input_check" onclick="invertAll(this, this.form);" />',
|
||||||
|
'style' => 'width: 4%;',
|
||||||
|
),
|
||||||
|
'data' => array(
|
||||||
|
'sprintf' => array(
|
||||||
|
'format' => '<input type="checkbox" name="groupr[]" value="%1$d" class="input_check" />',
|
||||||
|
'params' => array(
|
||||||
|
'id' => false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'style' => 'text-align: center;',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'form' => array(
|
||||||
|
'href' => $scripturl . '?action=groups;sa=requests',
|
||||||
|
'include_sort' => true,
|
||||||
|
'include_start' => true,
|
||||||
|
'hidden_fields' => array(
|
||||||
|
$context['session_var'] => $context['session_id'],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'additional_rows' => array(
|
||||||
|
array(
|
||||||
|
'position' => 'bottom_of_list',
|
||||||
|
'value' => '
|
||||||
|
<select name="req_action" onchange="if (this.value != 0 && (this.value == \'reason\' || confirm(\'' . $txt['mc_groupr_warning'] . '\'))) this.form.submit();">
|
||||||
|
<option value="0">' . $txt['with_selected'] . ':</option>
|
||||||
|
<option value="0">---------------------</option>
|
||||||
|
<option value="approve">' . $txt['mc_groupr_approve'] . '</option>
|
||||||
|
<option value="reject">' . $txt['mc_groupr_reject'] . '</option>
|
||||||
|
<option value="reason">' . $txt['mc_groupr_reject_w_reason'] . '</option>
|
||||||
|
</select>
|
||||||
|
<input type="submit" name="go" value="' . $txt['go'] . '" onclick="var sel = document.getElementById(\'req_action\'); if (sel.value != 0 && sel.value != \'reason\' && !confirm(\'' . $txt['mc_groupr_warning'] . '\')) return false;" class="button_submit" />',
|
||||||
|
'align' => 'right',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create the request list.
|
||||||
|
createList($listOptions);
|
||||||
|
|
||||||
|
$context['default_list'] = 'group_request_list';
|
||||||
|
}
|
||||||
|
|
||||||
|
function list_getGroupRequestCount($where, $where_parameters)
|
||||||
|
{
|
||||||
|
global $smcFunc;
|
||||||
|
|
||||||
|
$request = $smcFunc['db_query']('', '
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM {db_prefix}log_group_requests AS lgr
|
||||||
|
WHERE ' . $where,
|
||||||
|
array_merge($where_parameters, array(
|
||||||
|
))
|
||||||
|
);
|
||||||
|
list ($totalRequests) = $smcFunc['db_fetch_row']($request);
|
||||||
|
$smcFunc['db_free_result']($request);
|
||||||
|
|
||||||
|
return $totalRequests;
|
||||||
|
}
|
||||||
|
|
||||||
|
function list_getGroupRequests($start, $items_per_page, $sort, $where, $where_parameters)
|
||||||
|
{
|
||||||
|
global $smcFunc, $txt, $scripturl;
|
||||||
|
|
||||||
|
$request = $smcFunc['db_query']('', '
|
||||||
|
SELECT lgr.id_request, lgr.id_member, lgr.id_group, lgr.time_applied, lgr.reason,
|
||||||
|
mem.member_name, mg.group_name, mg.online_color, mem.real_name
|
||||||
|
FROM {db_prefix}log_group_requests AS lgr
|
||||||
|
INNER JOIN {db_prefix}members AS mem ON (mem.id_member = lgr.id_member)
|
||||||
|
INNER JOIN {db_prefix}membergroups AS mg ON (mg.id_group = lgr.id_group)
|
||||||
|
WHERE ' . $where . '
|
||||||
|
ORDER BY {raw:sort}
|
||||||
|
LIMIT ' . $start . ', ' . $items_per_page,
|
||||||
|
array_merge($where_parameters, array(
|
||||||
|
'sort' => $sort,
|
||||||
|
))
|
||||||
|
);
|
||||||
|
$group_requests = array();
|
||||||
|
while ($row = $smcFunc['db_fetch_assoc']($request))
|
||||||
|
{
|
||||||
|
$group_requests[] = array(
|
||||||
|
'id' => $row['id_request'],
|
||||||
|
'member_link' => '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['real_name'] . '</a>',
|
||||||
|
'group_link' => '<span style="color: ' . $row['online_color'] . '">' . $row['group_name'] . '</span>',
|
||||||
|
'reason' => censorText($row['reason']),
|
||||||
|
'time_submitted' => timeformat($row['time_applied']),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$smcFunc['db_free_result']($request);
|
||||||
|
|
||||||
|
return $group_requests;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
111
Sources/Help.php
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple Machines Forum (SMF)
|
||||||
|
*
|
||||||
|
* @package SMF
|
||||||
|
* @author Simple Machines http://www.simplemachines.org
|
||||||
|
* @copyright 2011 Simple Machines
|
||||||
|
* @license http://www.simplemachines.org/about/smf/license.php BSD
|
||||||
|
*
|
||||||
|
* @version 2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('SMF'))
|
||||||
|
die('Hacking attempt...');
|
||||||
|
|
||||||
|
/* This file has the important job of taking care of help messages and the
|
||||||
|
help center. It does this with two simple functions:
|
||||||
|
|
||||||
|
void ShowHelp()
|
||||||
|
- loads information needed for the help section.
|
||||||
|
- accesed by ?action=help.
|
||||||
|
- uses the Help template and Manual language file.
|
||||||
|
|
||||||
|
void ShowAdminHelp()
|
||||||
|
- shows a popup for administrative or user help.
|
||||||
|
- uses the help parameter to decide what string to display and where
|
||||||
|
to get the string from. ($helptxt or $txt?)
|
||||||
|
- loads the ManagePermissions language file if the help starts with
|
||||||
|
permissionhelp.
|
||||||
|
- uses the Help template, popup sub template, no layers.
|
||||||
|
- accessed via ?action=helpadmin;help=??.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Redirect to the user help ;).
|
||||||
|
function ShowHelp()
|
||||||
|
{
|
||||||
|
global $scripturl, $context, $txt;
|
||||||
|
|
||||||
|
loadTemplate('Help');
|
||||||
|
loadLanguage('Manual');
|
||||||
|
|
||||||
|
// We need to know where our wiki is.
|
||||||
|
$context['wiki_url'] = 'http://wiki.simplemachines.org/smf';
|
||||||
|
|
||||||
|
// Sections were are going to link...
|
||||||
|
$context['manual_sections'] = array(
|
||||||
|
'registering' => 'Registering',
|
||||||
|
'logging_in' => 'Logging_In',
|
||||||
|
'profile' => 'Profile',
|
||||||
|
'search' => 'Search',
|
||||||
|
'posting' => 'Posting',
|
||||||
|
'bbc' => 'Bulletin_board_code',
|
||||||
|
'personal_messages' => 'Personal_messages',
|
||||||
|
'memberlist' => 'Memberlist',
|
||||||
|
'calendar' => 'Calendar',
|
||||||
|
'features' => 'Features',
|
||||||
|
);
|
||||||
|
|
||||||
|
// Build the link tree.
|
||||||
|
$context['linktree'][] = array(
|
||||||
|
'url' => $scripturl . '?action=help',
|
||||||
|
'name' => $txt['help'],
|
||||||
|
);
|
||||||
|
|
||||||
|
// Lastly, some minor template stuff.
|
||||||
|
$context['page_title'] = $txt['manual_smf_user_help'];
|
||||||
|
$context['sub_template'] = 'manual';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show some of the more detailed help to give the admin an idea...
|
||||||
|
function ShowAdminHelp()
|
||||||
|
{
|
||||||
|
global $txt, $helptxt, $context, $scripturl;
|
||||||
|
|
||||||
|
if (!isset($_GET['help']) || !is_string($_GET['help']))
|
||||||
|
fatal_lang_error('no_access', false);
|
||||||
|
|
||||||
|
if (!isset($helptxt))
|
||||||
|
$helptxt = array();
|
||||||
|
|
||||||
|
// Load the admin help language file and template.
|
||||||
|
loadLanguage('Help');
|
||||||
|
|
||||||
|
// Permission specific help?
|
||||||
|
if (isset($_GET['help']) && substr($_GET['help'], 0, 14) == 'permissionhelp')
|
||||||
|
loadLanguage('ManagePermissions');
|
||||||
|
|
||||||
|
loadTemplate('Help');
|
||||||
|
|
||||||
|
// Set the page title to something relevant.
|
||||||
|
$context['page_title'] = $context['forum_name'] . ' - ' . $txt['help'];
|
||||||
|
|
||||||
|
// Don't show any template layers, just the popup sub template.
|
||||||
|
$context['template_layers'] = array();
|
||||||
|
$context['sub_template'] = 'popup';
|
||||||
|
|
||||||
|
// What help string should be used?
|
||||||
|
if (isset($helptxt[$_GET['help']]))
|
||||||
|
$context['help_text'] = $helptxt[$_GET['help']];
|
||||||
|
elseif (isset($txt[$_GET['help']]))
|
||||||
|
$context['help_text'] = $txt[$_GET['help']];
|
||||||
|
else
|
||||||
|
$context['help_text'] = $_GET['help'];
|
||||||
|
|
||||||
|
// Does this text contain a link that we should fill in?
|
||||||
|
if (preg_match('~%([0-9]+\$)?s\?~', $context['help_text'], $match))
|
||||||
|
$context['help_text'] = sprintf($context['help_text'], $scripturl, $context['session_id'], $context['session_var']);
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|