aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB/includes
diff options
context:
space:
mode:
Diffstat (limited to 'phpBB/includes')
-rw-r--r--phpBB/includes/acm/acm_file.php56
-rw-r--r--phpBB/includes/acp/acp_attachments.php296
-rw-r--r--phpBB/includes/acp/acp_ban.php4
-rw-r--r--phpBB/includes/acp/acp_bbcodes.php41
-rw-r--r--phpBB/includes/acp/acp_board.php338
-rw-r--r--phpBB/includes/acp/acp_bots.php12
-rw-r--r--phpBB/includes/acp/acp_captcha.php114
-rw-r--r--phpBB/includes/acp/acp_database.php119
-rw-r--r--phpBB/includes/acp/acp_disallow.php14
-rw-r--r--phpBB/includes/acp/acp_email.php16
-rw-r--r--phpBB/includes/acp/acp_forums.php260
-rw-r--r--phpBB/includes/acp/acp_groups.php56
-rw-r--r--phpBB/includes/acp/acp_icons.php116
-rwxr-xr-xphpBB/includes/acp/acp_inactive.php184
-rw-r--r--phpBB/includes/acp/acp_jabber.php15
-rw-r--r--phpBB/includes/acp/acp_language.php185
-rw-r--r--phpBB/includes/acp/acp_main.php220
-rw-r--r--phpBB/includes/acp/acp_modules.php81
-rw-r--r--phpBB/includes/acp/acp_permission_roles.php25
-rw-r--r--phpBB/includes/acp/acp_permissions.php76
-rw-r--r--phpBB/includes/acp/acp_php_info.php2
-rw-r--r--phpBB/includes/acp/acp_profile.php104
-rw-r--r--phpBB/includes/acp/acp_prune.php22
-rw-r--r--phpBB/includes/acp/acp_ranks.php6
-rw-r--r--phpBB/includes/acp/acp_reasons.php48
-rw-r--r--phpBB/includes/acp/acp_search.php23
-rw-r--r--phpBB/includes/acp/acp_styles.php116
-rw-r--r--phpBB/includes/acp/acp_update.php61
-rw-r--r--phpBB/includes/acp/acp_users.php497
-rw-r--r--phpBB/includes/acp/acp_words.php8
-rw-r--r--phpBB/includes/acp/auth.php59
-rwxr-xr-xphpBB/includes/acp/info/acp_inactive.php37
-rw-r--r--phpBB/includes/acp/info/acp_update.php37
-rw-r--r--phpBB/includes/auth.php136
-rw-r--r--phpBB/includes/auth/auth_apache.php11
-rw-r--r--phpBB/includes/auth/auth_db.php2
-rw-r--r--phpBB/includes/auth/auth_ldap.php10
-rw-r--r--phpBB/includes/bbcode.php10
-rw-r--r--phpBB/includes/cache.php52
-rw-r--r--phpBB/includes/captcha/captcha_gd.php3424
-rw-r--r--phpBB/includes/captcha/captcha_non_gd.php1
-rw-r--r--phpBB/includes/constants.php26
-rw-r--r--phpBB/includes/db/dbal.php125
-rw-r--r--phpBB/includes/db/firebird.php111
-rw-r--r--phpBB/includes/db/mssql.php128
-rw-r--r--phpBB/includes/db/mssql_odbc.php133
-rw-r--r--phpBB/includes/db/mysql.php133
-rw-r--r--phpBB/includes/db/mysql4.php443
-rw-r--r--phpBB/includes/db/mysqli.php95
-rw-r--r--phpBB/includes/db/oracle.php180
-rw-r--r--phpBB/includes/db/postgres.php134
-rw-r--r--phpBB/includes/db/sqlite.php91
-rw-r--r--phpBB/includes/diff/diff.php781
-rw-r--r--phpBB/includes/diff/engine.php512
-rw-r--r--phpBB/includes/diff/renderer.php832
-rw-r--r--phpBB/includes/functions.php748
-rw-r--r--phpBB/includes/functions_admin.php276
-rw-r--r--phpBB/includes/functions_compress.php57
-rw-r--r--phpBB/includes/functions_display.php232
-rw-r--r--phpBB/includes/functions_jabber.php942
-rw-r--r--phpBB/includes/functions_messenger.php321
-rw-r--r--phpBB/includes/functions_module.php8
-rw-r--r--phpBB/includes/functions_posting.php221
-rw-r--r--phpBB/includes/functions_privmsgs.php168
-rw-r--r--phpBB/includes/functions_profile_fields.php52
-rw-r--r--phpBB/includes/functions_template.php135
-rw-r--r--phpBB/includes/functions_transfer.php80
-rw-r--r--phpBB/includes/functions_upload.php78
-rw-r--r--phpBB/includes/functions_user.php611
-rw-r--r--phpBB/includes/mcp/mcp_forum.php14
-rw-r--r--phpBB/includes/mcp/mcp_front.php2
-rw-r--r--phpBB/includes/mcp/mcp_main.php25
-rwxr-xr-xphpBB/includes/mcp/mcp_notes.php6
-rw-r--r--phpBB/includes/mcp/mcp_post.php132
-rw-r--r--phpBB/includes/mcp/mcp_queue.php57
-rwxr-xr-xphpBB/includes/mcp/mcp_reports.php19
-rw-r--r--phpBB/includes/mcp/mcp_topic.php13
-rwxr-xr-xphpBB/includes/mcp/mcp_warn.php10
-rw-r--r--phpBB/includes/message_parser.php263
-rw-r--r--phpBB/includes/search/fulltext_mysql.php10
-rwxr-xr-xphpBB/includes/search/fulltext_native.php216
-rwxr-xr-xphpBB/includes/search/search.php4
-rw-r--r--phpBB/includes/session.php346
-rw-r--r--phpBB/includes/template.php36
-rw-r--r--phpBB/includes/ucp/info/ucp_attachments.php2
-rw-r--r--phpBB/includes/ucp/info/ucp_prefs.php2
-rw-r--r--phpBB/includes/ucp/info/ucp_profile.php2
-rw-r--r--phpBB/includes/ucp/ucp_activate.php16
-rw-r--r--phpBB/includes/ucp/ucp_attachments.php9
-rw-r--r--phpBB/includes/ucp/ucp_confirm.php32
-rw-r--r--phpBB/includes/ucp/ucp_groups.php15
-rw-r--r--phpBB/includes/ucp/ucp_main.php68
-rw-r--r--phpBB/includes/ucp/ucp_pm.php15
-rw-r--r--phpBB/includes/ucp/ucp_pm_compose.php96
-rw-r--r--phpBB/includes/ucp/ucp_pm_options.php18
-rw-r--r--phpBB/includes/ucp/ucp_pm_viewfolder.php21
-rw-r--r--phpBB/includes/ucp/ucp_pm_viewmessage.php46
-rw-r--r--phpBB/includes/ucp/ucp_prefs.php116
-rw-r--r--phpBB/includes/ucp/ucp_profile.php278
-rw-r--r--phpBB/includes/ucp/ucp_register.php204
-rw-r--r--phpBB/includes/ucp/ucp_remind.php11
-rw-r--r--phpBB/includes/ucp/ucp_resend.php22
-rw-r--r--phpBB/includes/ucp/ucp_zebra.php37
-rw-r--r--phpBB/includes/utf/data/case_fold_c.php1
-rw-r--r--phpBB/includes/utf/data/case_fold_f.php1
-rw-r--r--phpBB/includes/utf/data/case_fold_s.php1
-rw-r--r--phpBB/includes/utf/utf_normalizer.php1017
-rw-r--r--phpBB/includes/utf/utf_tools.php897
108 files changed, 9440 insertions, 9187 deletions
diff --git a/phpBB/includes/acm/acm_file.php b/phpBB/includes/acm/acm_file.php
index 175ef0ad81..b6af055399 100644
--- a/phpBB/includes/acm/acm_file.php
+++ b/phpBB/includes/acm/acm_file.php
@@ -80,6 +80,16 @@ class acm
@flock($fp, LOCK_UN);
fclose($fp);
}
+ else
+ {
+ // Now, this occurred how often? ... phew, just tell the user then...
+ if (!@is_writeable($this->cache_dir))
+ {
+ trigger_error($this->cache_dir . ' is NOT writeable.', E_USER_ERROR);
+ }
+
+ trigger_error('Not able to open ' . $this->cache_dir . 'data_global.' . $phpEx, E_USER_ERROR);
+ }
$this->is_modified = false;
}
@@ -132,7 +142,7 @@ class acm
*/
function get($var_name)
{
- if ($var_name{0} == '_')
+ if ($var_name[0] == '_')
{
global $phpEx;
@@ -155,7 +165,7 @@ class acm
*/
function put($var_name, $var, $ttl = 31536000)
{
- if ($var_name{0} == '_')
+ if ($var_name[0] == '_')
{
global $phpEx;
@@ -176,6 +186,32 @@ class acm
}
/**
+ * Purge cache data
+ */
+ function purge()
+ {
+ // Purge all phpbb cache files
+ $dir = opendir($this->cache_dir);
+ while (($entry = readdir($dir)) !== false)
+ {
+ if (strpos($entry, 'sql_') !== 0 && strpos($entry, 'data_') !== 0 && strpos($entry, 'ctpl_') !== 0 && strpos($entry, 'tpl_') !== 0)
+ {
+ continue;
+ }
+
+ @unlink($this->cache_dir . $entry);
+ }
+ @closedir($dir);
+
+ unset($this->vars);
+ unset($this->var_expires);
+ unset($this->sql_rowset);
+ unset($this->sql_row_pointer);
+
+ $this->is_modified = false;
+ }
+
+ /**
* Destroy cache data
*/
function destroy($var_name, $table = '')
@@ -213,7 +249,7 @@ class acm
return;
}
- if ($var_name{0} == '_')
+ if ($var_name[0] == '_')
{
@unlink($this->cache_dir . 'data' . $var_name . ".$phpEx");
}
@@ -233,7 +269,7 @@ class acm
*/
function _exists($var_name)
{
- if ($var_name{0} == '_')
+ if ($var_name[0] == '_')
{
global $phpEx;
return file_exists($this->cache_dir . 'data' . $var_name . ".$phpEx");
@@ -345,7 +381,7 @@ class acm
}
$db->sql_freeresult($query_result);
- fwrite($fp, "<?php\n\n/*\n$query\n*/\n\n\$expired = (time() > " . (time() + $ttl) . ") ? true : false;\nif (\$expired) { return; }\n\n\$this->sql_rowset[\$query_id] = array(" . implode(',', $lines) . ') ?>');
+ fwrite($fp, "<?php\n\n/*\n" . str_replace('*/', '*\/', $query) . "\n*/\n\n\$expired = (time() > " . (time() + $ttl) . ") ? true : false;\nif (\$expired) { return; }\n\n\$this->sql_rowset[\$query_id] = array(" . implode(',', $lines) . ') ?>');
@flock($fp, LOCK_UN);
fclose($fp);
@@ -375,14 +411,6 @@ class acm
}
/**
- * Fetch the number of rows from cache (database)
- */
- function sql_numrows($query_id)
- {
- return sizeof($this->sql_rowset[$query_id]);
- }
-
- /**
* Fetch a field from the current row of a cached database result (database)
*/
function sql_fetchfield($query_id, $field)
@@ -398,7 +426,7 @@ class acm
/**
* Seek a specific row in an a cached database result (database)
*/
- function sql_rowseek($query_id, $rownum)
+ function sql_rowseek($rownum, $query_id)
{
if ($rownum >= sizeof($this->sql_rowset[$query_id]))
{
diff --git a/phpBB/includes/acp/acp_attachments.php b/phpBB/includes/acp/acp_attachments.php
index 1089a06152..59694b294e 100644
--- a/phpBB/includes/acp/acp_attachments.php
+++ b/phpBB/includes/acp/acp_attachments.php
@@ -46,7 +46,8 @@ class acp_attachments
break;
default:
- trigger_error('NO_MODE');
+ trigger_error('NO_MODE', E_USER_ERROR);
+ break;
}
$this->tpl_name = 'acp_attachments';
@@ -86,31 +87,42 @@ class acp_attachments
'img_max_width' => false, 'img_max_height' => false, 'img_link_width' => false, 'img_link_height' => false,
'legend1' => 'ACP_ATTACHMENT_SETTINGS',
- 'allow_attachments' => array('lang' => 'ALLOW_ATTACHMENTS', 'type' => 'radio:yes_no', 'explain' => false),
- 'allow_pm_attach' => array('lang' => 'ALLOW_PM_ATTACHMENTS', 'type' => 'radio:yes_no', 'explain' => false),
- 'upload_path' => array('lang' => 'UPLOAD_DIR', 'type' => 'text:25:100', 'explain' => true),
- 'display_order' => array('lang' => 'DISPLAY_ORDER', 'type' => 'custom', 'method' => 'display_order', 'explain' => true),
- 'attachment_quota' => array('lang' => 'ATTACH_QUOTA', 'type' => 'custom', 'method' => 'max_filesize', 'explain' => true),
- 'max_filesize' => array('lang' => 'ATTACH_MAX_FILESIZE', 'type' => 'custom', 'method' => 'max_filesize', 'explain' => true),
- 'max_filesize_pm' => array('lang' => 'ATTACH_MAX_PM_FILESIZE','type' => 'custom', 'method' => 'max_filesize', 'explain' => true),
- 'max_attachments' => array('lang' => 'MAX_ATTACHMENTS', 'type' => 'text:3:3', 'explain' => false),
- 'max_attachments_pm' => array('lang' => 'MAX_ATTACHMENTS_PM', 'type' => 'text:3:3', 'explain' => false),
- 'secure_downloads' => array('lang' => 'SECURE_DOWNLOADS', 'type' => 'radio:yes_no', 'explain' => true),
- 'secure_allow_deny' => array('lang' => 'SECURE_ALLOW_DENY', 'type' => 'custom', 'method' => 'select_allow_deny', 'explain' => true),
- 'secure_allow_empty_referer' => array('lang' => 'SECURE_EMPTY_REFERRER', 'type' => 'radio:yes_no', 'explain' => true),
+ 'allow_attachments' => array('lang' => 'ALLOW_ATTACHMENTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'allow_pm_attach' => array('lang' => 'ALLOW_PM_ATTACHMENTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'upload_path' => array('lang' => 'UPLOAD_DIR', 'validate' => 'wpath', 'type' => 'text:25:100', 'explain' => true),
+ 'display_order' => array('lang' => 'DISPLAY_ORDER', 'validate' => 'bool', 'type' => 'custom', 'method' => 'display_order', 'explain' => true),
+ 'attachment_quota' => array('lang' => 'ATTACH_QUOTA', 'validate' => 'int', 'type' => 'custom', 'method' => 'max_filesize', 'explain' => true),
+ 'max_filesize' => array('lang' => 'ATTACH_MAX_FILESIZE', 'validate' => 'int', 'type' => 'custom', 'method' => 'max_filesize', 'explain' => true),
+ 'max_filesize_pm' => array('lang' => 'ATTACH_MAX_PM_FILESIZE','validate' => 'int', 'type' => 'custom', 'method' => 'max_filesize', 'explain' => true),
+ 'max_attachments' => array('lang' => 'MAX_ATTACHMENTS', 'validate' => 'int', 'type' => 'text:3:3', 'explain' => false),
+ 'max_attachments_pm' => array('lang' => 'MAX_ATTACHMENTS_PM', 'validate' => 'int', 'type' => 'text:3:3', 'explain' => false),
+ 'secure_downloads' => array('lang' => 'SECURE_DOWNLOADS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'secure_allow_deny' => array('lang' => 'SECURE_ALLOW_DENY', 'validate' => 'int', 'type' => 'custom', 'method' => 'select_allow_deny', 'explain' => true),
+ 'secure_allow_empty_referer' => array('lang' => 'SECURE_EMPTY_REFERRER', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'legend2' => $l_legend_cat_images,
- 'img_display_inlined' => array('lang' => 'DISPLAY_INLINED', 'type' => 'radio:yes_no', 'explain' => true),
- 'img_create_thumbnail' => array('lang' => 'CREATE_THUMBNAIL', 'type' => 'radio:yes_no', 'explain' => true),
- 'img_min_thumb_filesize' => array('lang' => 'MIN_THUMB_FILESIZE', 'type' => 'text:7:15', 'explain' => true, 'append' => ' ' . $user->lang['BYTES']),
- 'img_imagick' => array('lang' => 'IMAGICK_PATH', 'type' => 'text:20:200', 'explain' => true, 'append' => '&nbsp;&nbsp;<span>[ <a href="' . $this->u_action . '&amp;action=imgmagick">' . $user->lang['SEARCH_IMAGICK'] . '</a> ]</span>'),
- 'img_max' => array('lang' => 'MAX_IMAGE_SIZE', 'type' => 'dimension:3:4', 'explain' => true),
- 'img_link' => array('lang' => 'IMAGE_LINK_SIZE', 'type' => 'dimension:3:4', 'explain' => true),
+ 'img_display_inlined' => array('lang' => 'DISPLAY_INLINED', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'img_create_thumbnail' => array('lang' => 'CREATE_THUMBNAIL', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'img_max_thumb_width' => array('lang' => 'MAX_THUMB_WIDTH', 'validate' => 'int', 'type' => 'text:7:15', 'explain' => true, 'append' => ' px'),
+ 'img_min_thumb_filesize' => array('lang' => 'MIN_THUMB_FILESIZE', 'validate' => 'int', 'type' => 'text:7:15', 'explain' => true, 'append' => ' ' . $user->lang['BYTES']),
+ 'img_imagick' => array('lang' => 'IMAGICK_PATH', 'validate' => 'string', 'type' => 'text:20:200', 'explain' => true, 'append' => '&nbsp;&nbsp;<span>[ <a href="' . $this->u_action . '&amp;action=imgmagick">' . $user->lang['SEARCH_IMAGICK'] . '</a> ]</span>'),
+ 'img_max' => array('lang' => 'MAX_IMAGE_SIZE', 'validate' => 'int', 'type' => 'dimension:3:4', 'explain' => true),
+ 'img_link' => array('lang' => 'IMAGE_LINK_SIZE', 'validate' => 'int', 'type' => 'dimension:3:4', 'explain' => true),
)
);
$this->new_config = $config;
$cfg_array = (isset($_REQUEST['config'])) ? request_var('config', array('' => '')) : $this->new_config;
+ $error = array();
+
+ // We validate the complete config if whished
+ validate_config_vars($display_vars['vars'], $cfg_array, $error);
+
+ // Do not write values if there is an error
+ if (sizeof($error))
+ {
+ $submit = false;
+ }
// We go through the display_vars to make sure no one is trying to set variables he/she is not allowed to...
foreach ($display_vars['vars'] as $config_name => $null)
@@ -197,7 +209,9 @@ class acp_attachments
$template->assign_vars(array(
'S_SECURE_DOWNLOADS' => $this->new_config['secure_downloads'],
'S_DEFINED_IPS' => ($defined_ips != '') ? true : false,
+ 'S_WARNING' => (sizeof($error)) ? true : false,
+ 'WARNING_MSG' => implode('<br />', $error),
'DEFINED_IPS' => $defined_ips,
'L_SECURE_TITLE' => $user->lang['DEFINE_' . $allow_deny . '_IPS'],
@@ -403,12 +417,12 @@ class acp_attachments
if ($action != 'add' && $action != 'edit')
{
- trigger_error('WRONG_MODE');
+ trigger_error('NO_MODE', E_USER_ERROR);
}
if (!$group_id && $action == 'edit')
{
- trigger_error('NO_EXT_GROUP_SPECIFIED');
+ trigger_error($user->lang['NO_EXT_GROUP_SPECIFIED'] . adm_back_link($this->u_action), E_USER_WARNING);
}
if ($group_id)
@@ -437,7 +451,7 @@ class acp_attachments
{
$sql = 'SELECT group_id
FROM ' . EXTENSION_GROUPS_TABLE . "
- WHERE LOWER(group_name) = '" . $db->sql_escape(strtolower($new_group_name)) . "'";
+ WHERE LOWER(group_name) = '" . $db->sql_escape(utf8_strtolower($new_group_name)) . "'";
$result = $db->sql_query($sql);
if ($db->sql_fetchrow($result))
@@ -521,15 +535,16 @@ class acp_attachments
}
$cat_lang = array(
- ATTACHMENT_CATEGORY_NONE => $user->lang['NO_FILE_CAT'],
- ATTACHMENT_CATEGORY_IMAGE => $user->lang['CAT_IMAGES'],
- ATTACHMENT_CATEGORY_WM => $user->lang['CAT_WM_FILES'],
- ATTACHMENT_CATEGORY_RM => $user->lang['CAT_RM_FILES']
+ ATTACHMENT_CATEGORY_NONE => $user->lang['NO_FILE_CAT'],
+ ATTACHMENT_CATEGORY_IMAGE => $user->lang['CAT_IMAGES'],
+ ATTACHMENT_CATEGORY_WM => $user->lang['CAT_WM_FILES'],
+ ATTACHMENT_CATEGORY_RM => $user->lang['CAT_RM_FILES'],
+ ATTACHMENT_CATEGORY_FLASH => $user->lang['CAT_FLASH_FILES'],
+ ATTACHMENT_CATEGORY_QUICKTIME => $user->lang['CAT_QUICKTIME_FILES'],
);
$group_id = request_var('g', 0);
$action = (isset($_POST['add'])) ? 'add' : $action;
-// $action = (($action == 'add' || $action == 'edit') && $submit && !sizeof($error)) ? 'show' : $action;
switch ($action)
{
@@ -578,7 +593,7 @@ class acp_attachments
if (!$group_id)
{
- trigger_error($user->lang['NO_EXTENSION_GROUP'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_EXT_GROUP_SPECIFIED'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$sql = 'SELECT *
@@ -770,7 +785,7 @@ class acp_attachments
if (!$group_id)
{
- trigger_error($user->lang['NO_EXTENSION_GROUP'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_EXT_GROUP_SPECIFIED'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$sql = 'UPDATE ' . EXTENSION_GROUPS_TABLE . '
@@ -823,24 +838,45 @@ class acp_attachments
$add_files = (isset($_POST['add'])) ? array_keys(request_var('add', array('' => 0))) : array();
$post_ids = request_var('post_id', array('' => 0));
- foreach ($delete_files as $delete)
+ if (sizeof($delete_files))
{
- phpbb_unlink($delete);
- phpbb_unlink($delete, 'thumbnail');
+ $sql = 'SELECT *
+ FROM ' . ATTACHMENTS_TABLE . '
+ WHERE ' . $db->sql_in_set('attach_id', $delete_files) . '
+ AND is_orphan = 1';
+ $result = $db->sql_query($sql);
+
+ $delete_files = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ phpbb_unlink($row['physical_filename']);
+
+ if ($row['thumbnail'])
+ {
+ phpbb_unlink($row['physical_filename'], 'thumbnail');
+ }
+
+ $delete_files[$row['attach_id']] = $row['real_filename'];
+ }
+ $db->sql_freeresult($result);
}
if (sizeof($delete_files))
{
+ $sql = 'DELETE FROM ' . ATTACHMENTS_TABLE . '
+ WHERE ' . $db->sql_in_set('attach_id', array_keys($delete_files));
+ $db->sql_query($sql);
+
add_log('admin', 'LOG_ATTACH_ORPHAN_DEL', implode(', ', $delete_files));
$notify[] = sprintf($user->lang['LOG_ATTACH_ORPHAN_DEL'], implode(', ', $delete_files));
}
$upload_list = array();
- foreach ($add_files as $file)
+ foreach ($add_files as $attach_id)
{
- if (!in_array($file, $delete_files) && $post_ids[$file])
+ if (!in_array($attach_id, array_keys($delete_files)) && !empty($post_ids[$attach_id]))
{
- $upload_list[$post_ids[$file]] = $file;
+ $upload_list[$attach_id] = $post_ids[$attach_id];
}
}
unset($add_files);
@@ -849,13 +885,10 @@ class acp_attachments
{
$template->assign_var('S_UPLOADING_FILES', true);
- include_once($phpbb_root_path . 'includes/message_parser.' . $phpEx);
- $message_parser = new parse_message();
-
$sql = 'SELECT forum_id, forum_name
FROM ' . FORUMS_TABLE;
$result = $db->sql_query($sql);
-
+
$forum_names = array();
while ($row = $db->sql_fetchrow($result))
{
@@ -863,30 +896,67 @@ class acp_attachments
}
$db->sql_freeresult($result);
- $sql = 'SELECT forum_id, topic_id, post_id
+ $sql = 'SELECT forum_id, topic_id, post_id, poster_id
FROM ' . POSTS_TABLE . '
- WHERE ' . $db->sql_in_set('post_id', array_keys($upload_list));
+ WHERE ' . $db->sql_in_set('post_id', $upload_list);
+ $result = $db->sql_query($sql);
+
+ $post_info = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $post_info[$row['post_id']] = $row;
+ }
+ $db->sql_freeresult($result);
+
+ // Select those attachments we want to change...
+ $sql = 'SELECT *
+ FROM ' . ATTACHMENTS_TABLE . '
+ WHERE ' . $db->sql_in_set('attach_id', array_keys($upload_list)) . '
+ AND is_orphan = 1';
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
- $return = true;
+ $post_row = $post_info[$upload_list[$row['attach_id']]];
- if ($auth->acl_get('f_attach', $row['forum_id']))
+ $template->assign_block_vars('upload', array(
+ 'FILE_INFO' => sprintf($user->lang['UPLOADING_FILE_TO'], $row['real_filename'], $post_row['post_id']),
+ 'S_DENIED' => (!$auth->acl_get('f_attach', $post_row['forum_id'])) ? true : false,
+ 'L_DENIED' => (!$auth->acl_get('f_attach', $post_row['forum_id'])) ? sprintf($user->lang['UPLOAD_DENIED_FORUM'], $forum_names[$row['forum_id']]) : '')
+ );
+
+ if (!$auth->acl_get('f_attach', $post_row['forum_id']))
{
- $return = $this->upload_file($row['post_id'], $row['topic_id'], $row['forum_id'], $config['upload_path'], $upload_list[$row['post_id']]);
+ continue;
}
- $template->assign_block_vars('upload', array(
- 'FILE_INFO' => sprintf($user->lang['UPLOADING_FILE_TO'], $upload_list[$row['post_id']], $row['post_id']),
- 'S_DENIED' => (!$auth->acl_get('f_attach', $row['forum_id'])) ? true : false,
- 'L_DENIED' => (!$auth->acl_get('f_attach', $row['forum_id'])) ? sprintf($user->lang['UPLOAD_DENIED_FORUM'], $forum_names[$row['forum_id']]) : '',
- 'ERROR_MSG' => ($return === true) ? false : $return)
+ // Adjust attachment entry
+ $sql_ary = array(
+ 'in_message' => 0,
+ 'is_orphan' => 0,
+ 'poster_id' => $post_row['poster_id'],
+ 'post_msg_id' => $post_row['post_id'],
+ 'topic_id' => $post_row['topic_id'],
);
+
+ $sql = 'UPDATE ' . ATTACHMENTS_TABLE . '
+ SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
+ WHERE attach_id = ' . $row['attach_id'];
+ $db->sql_query($sql);
+
+ $sql = 'UPDATE ' . POSTS_TABLE . '
+ SET post_attachment = 1
+ WHERE post_id = ' . $post_row['post_id'];
+ $db->sql_query($sql);
+
+ $sql = 'UPDATE ' . TOPICS_TABLE . '
+ SET topic_attachment = 1
+ WHERE topic_id = ' . $post_row['topic_id'];
+ $db->sql_query($sql);
+
+ add_log('admin', 'LOG_ATTACH_FILEUPLOAD', $post_row['post_id'], $row['real_filename']);
}
$db->sql_freeresult($result);
-
- unset($message_parser);
}
}
@@ -894,43 +964,31 @@ class acp_attachments
'S_ORPHAN' => true)
);
- $attach_filelist = array();
-
- $dir = @opendir($phpbb_root_path . $config['upload_path']);
- while (($file = @readdir($dir)) !== false)
- {
- if (is_file($phpbb_root_path . $config['upload_path'] . '/' . $file) && filesize($phpbb_root_path . $config['upload_path'] . '/' . $file) && $file{0} != '.' && $file != 'index.htm' && !preg_match('#^thumb\_#', $file))
- {
- $attach_filelist[$file] = $file;
- }
- }
- @closedir($dir);
-
- $sql = 'SELECT physical_filename
- FROM ' . ATTACHMENTS_TABLE;
+ // Just get the files with is_orphan set and older than 3 hours
+ $sql = 'SELECT *
+ FROM ' . ATTACHMENTS_TABLE . '
+ WHERE is_orphan = 1
+ AND filetime < ' . (time() - 3*60*60) . '
+ ORDER BY filetime DESC';
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
- unset($attach_filelist[$row['physical_filename']]);
- }
- $db->sql_freeresult($result);
-
- $i = 0;
- foreach ($attach_filelist as $file)
- {
- $filesize = @filesize($phpbb_root_path . $config['upload_path'] . '/' . $file);
- $size_lang = ($filesize >= 1048576) ? $user->lang['MB'] : ( ($filesize >= 1024) ? $user->lang['KB'] : $user->lang['BYTES'] );
- $filesize = ($filesize >= 1048576) ? round((round($filesize / 1048576 * 100) / 100), 2) : (($filesize >= 1024) ? round((round($filesize / 1024 * 100) / 100), 2) : $filesize);
+ $size_lang = ($row['filesize'] >= 1048576) ? $user->lang['MB'] : (($row['filesize'] >= 1024) ? $user->lang['KB'] : $user->lang['BYTES']);
+ $row['filesize'] = ($row['filesize'] >= 1048576) ? round((round($row['filesize'] / 1048576 * 100) / 100), 2) : (($row['filesize'] >= 1024) ? round((round($row['filesize'] / 1024 * 100) / 100), 2) : $row['filesize']);
$template->assign_block_vars('orphan', array(
- 'FILESIZE' => $filesize . ' ' . $size_lang,
- 'U_FILE' => $phpbb_root_path . $config['upload_path'] . '/' . $file,
- 'FILE' => $file,
- 'POST_IDS' => (!empty($post_ids[$file])) ? $post_ids[$file] : '')
+ 'FILESIZE' => $row['filesize'] . ' ' . $size_lang,
+ 'FILETIME' => $user->format_date($row['filetime']),
+ 'REAL_FILENAME' => basename($row['real_filename']),
+ 'PHYSICAL_FILENAME' => basename($row['physical_filename']),
+ 'ATTACH_ID' => $row['attach_id'],
+ 'POST_IDS' => (!empty($post_ids[$row['attach_id']])) ? $post_ids[$row['attach_id']] : '',
+ 'U_FILE' => append_sid($phpbb_root_path . 'download.' . $phpEx, 'id=' . $row['attach_id']))
);
}
-
+ $db->sql_freeresult($result);
+
break;
}
@@ -959,10 +1017,12 @@ class acp_attachments
global $db, $user;
$types = array(
- ATTACHMENT_CATEGORY_NONE => $user->lang['NO_FILE_CAT'],
- ATTACHMENT_CATEGORY_IMAGE => $user->lang['CAT_IMAGES'],
- ATTACHMENT_CATEGORY_WM => $user->lang['CAT_WM_FILES'],
- ATTACHMENT_CATEGORY_RM => $user->lang['CAT_RM_FILES']
+ ATTACHMENT_CATEGORY_NONE => $user->lang['NO_FILE_CAT'],
+ ATTACHMENT_CATEGORY_IMAGE => $user->lang['CAT_IMAGES'],
+ ATTACHMENT_CATEGORY_WM => $user->lang['CAT_WM_FILES'],
+ ATTACHMENT_CATEGORY_RM => $user->lang['CAT_RM_FILES'],
+ ATTACHMENT_CATEGORY_FLASH => $user->lang['CAT_FLASH_FILES'],
+ ATTACHMENT_CATEGORY_QUICKTIME => $user->lang['CAT_QUICKTIME_FILES'],
);
if ($group_id)
@@ -1079,70 +1139,6 @@ class acp_attachments
return $group_select;
}
- /**
- * Upload already uploaded file... huh? are you kidding?
- */
- function upload_file($post_id, $topic_id, $forum_id, $upload_dir, $filename)
- {
- global $message_parser, $db, $user, $phpbb_root_path;
-
- $message_parser->attachment_data = array();
-
- $message_parser->filename_data['filecomment'] = '';
- $message_parser->filename_data['filename'] = $phpbb_root_path . $upload_dir . '/' . basename($filename);
-
- $filedata = upload_attachment('local', $forum_id, true, $phpbb_root_path . $upload_dir . '/' . basename($filename));
-
- if ($filedata['post_attach'] && !sizeof($filedata['error']))
- {
- $message_parser->attachment_data = array(
- 'post_msg_id' => $post_id,
- 'poster_id' => $user->data['user_id'],
- 'topic_id' => $topic_id,
- 'in_message' => 0,
- 'physical_filename' => $filedata['physical_filename'],
- 'real_filename' => $filedata['real_filename'],
- 'attach_comment' => $message_parser->filename_data['filecomment'],
- 'extension' => $filedata['extension'],
- 'mimetype' => $filedata['mimetype'],
- 'filesize' => $filedata['filesize'],
- 'filetime' => $filedata['filetime'],
- 'thumbnail' => $filedata['thumbnail']
- );
-
- $message_parser->filename_data['filecomment'] = '';
- $filedata['post_attach'] = false;
-
- // Submit Attachment
- $attach_sql = $message_parser->attachment_data;
-
- $db->sql_transaction('begin');
-
- $sql = 'INSERT INTO ' . ATTACHMENTS_TABLE . ' ' . $db->sql_build_array('INSERT', $attach_sql);
- $db->sql_query($sql);
-
- $sql = 'UPDATE ' . POSTS_TABLE . "
- SET post_attachment = 1
- WHERE post_id = $post_id";
- $db->sql_query($sql);
-
- $sql = 'UPDATE ' . TOPICS_TABLE . "
- SET topic_attachment = 1
- WHERE topic_id = $topic_id";
- $db->sql_query($sql);
-
- $db->sql_transaction('commit');
-
- add_log('admin', 'LOG_ATTACH_FILEUPLOAD', $post_id, $filename);
-
- return true;
- }
- else if (sizeof($filedata['error']))
- {
- return sprintf($user->lang['ADMIN_UPLOAD_ERROR'], implode('<br />', $filedata['error']));
- }
- }
-
/**
* Search Imagick
*/
@@ -1369,7 +1365,7 @@ class acp_attachments
add_log('admin', $log_entry, $ip_list_log);
}
- trigger_error($user->lang['SECURE_DOWNLOAD_UPDATE_SUCCESS']);
+ trigger_error($user->lang['SECURE_DOWNLOAD_UPDATE_SUCCESS'] . adm_back_link($this->u_action));
}
else if (isset($_POST['unsecuresubmit']))
{
@@ -1398,7 +1394,7 @@ class acp_attachments
add_log('admin', 'LOG_DOWNLOAD_REMOVE_IP', $l_unip_list);
}
- trigger_error($user->lang['SECURE_DOWNLOAD_UPDATE_SUCCESS']);
+ trigger_error($user->lang['SECURE_DOWNLOAD_UPDATE_SUCCESS'] . adm_back_link($this->u_action));
}
}
diff --git a/phpBB/includes/acp/acp_ban.php b/phpBB/includes/acp/acp_ban.php
index 420deb975f..a4e860b7bc 100644
--- a/phpBB/includes/acp/acp_ban.php
+++ b/phpBB/includes/acp/acp_ban.php
@@ -189,7 +189,7 @@ class acp_ban
$template->assign_block_vars('ban_reason', array(
'BAN_ID' => $ban_id,
'REASON' => $reason,
- 'A_REASON' => addslashes(html_entity_decode($reason)))
+ 'A_REASON' => addslashes(htmlspecialchars_decode($reason)))
);
}
}
@@ -201,7 +201,7 @@ class acp_ban
$template->assign_block_vars('ban_give_reason', array(
'BAN_ID' => $ban_id,
'REASON' => $reason,
- 'A_REASON' => addslashes(html_entity_decode($reason)))
+ 'A_REASON' => addslashes(htmlspecialchars_decode($reason)))
);
}
}
diff --git a/phpBB/includes/acp/acp_bbcodes.php b/phpBB/includes/acp/acp_bbcodes.php
index cdfe8e42eb..e4ea02ad4d 100644
--- a/phpBB/includes/acp/acp_bbcodes.php
+++ b/phpBB/includes/acp/acp_bbcodes.php
@@ -47,13 +47,13 @@ class acp_bbcodes
if (!$row)
{
- trigger_error('BBCODE_NOT_EXIST');
+ trigger_error($user->lang['BBCODE_NOT_EXIST'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$bbcode_match = $row['bbcode_match'];
$bbcode_tpl = htmlspecialchars($row['bbcode_tpl']);
$display_on_posting = $row['display_on_posting'];
- $bbcode_helpline = html_entity_decode($row['bbcode_helpline']);
+ $bbcode_helpline = $row['bbcode_helpline'];
break;
case 'modify':
@@ -66,7 +66,7 @@ class acp_bbcodes
if (!$row)
{
- trigger_error('BBCODE_NOT_EXIST');
+ trigger_error($user->lang['BBCODE_NOT_EXIST'] . adm_back_link($this->u_action), E_USER_WARNING);
}
// No break here
@@ -75,8 +75,8 @@ class acp_bbcodes
$display_on_posting = request_var('display_on_posting', 0);
$bbcode_match = request_var('bbcode_match', '');
- $bbcode_tpl = html_entity_decode(request_var('bbcode_tpl', ''));
- $bbcode_helpline = htmlspecialchars(request_var('bbcode_helpline', ''));
+ $bbcode_tpl = htmlspecialchars_decode(request_var('bbcode_tpl', ''));
+ $bbcode_helpline = request_var('bbcode_helpline', '');
break;
}
@@ -127,9 +127,11 @@ class acp_bbcodes
$info = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
- if ($info['test'] === '1' || in_array(strtolower($data['bbcode_tag']), $hard_coded))
+ // Grab the end, interrogate the last closing tag
+ preg_match('#\[/([^[]*)]$#', $bbcode_match, $regs);
+ if ($info['test'] === '1' || in_array(strtolower($data['bbcode_tag']), $hard_coded) || in_array(strtolower($regs[1]), $hard_coded))
{
- trigger_error('BBCODE_INVALID_TAG_NAME');
+ trigger_error($user->lang['BBCODE_INVALID_TAG_NAME'] . adm_back_link($this->u_action), E_USER_WARNING);
}
}
@@ -170,12 +172,13 @@ class acp_bbcodes
if ($bbcode_id > 1511)
{
- trigger_error('TOO_MANY_BBCODES');
+ trigger_error($user->lang['TOO_MANY_BBCODES'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$sql_ary['bbcode_id'] = (int) $bbcode_id;
$db->sql_query('INSERT INTO ' . BBCODES_TABLE . $db->sql_build_array('INSERT', $sql_ary));
+ $cache->destroy('sql', BBCODES_TABLE);
$lang = 'BBCODE_ADDED';
$log_action = 'LOG_BBCODE_ADD';
@@ -186,6 +189,7 @@ class acp_bbcodes
SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
WHERE bbcode_id = ' . $bbcode_id;
$db->sql_query($sql);
+ $cache->destroy('sql', BBCODES_TABLE);
$lang = 'BBCODE_EDITED';
$log_action = 'LOG_BBCODE_EDIT';
@@ -208,8 +212,21 @@ class acp_bbcodes
if ($row)
{
- $db->sql_query('DELETE FROM ' . BBCODES_TABLE . " WHERE bbcode_id = $bbcode_id");
- add_log('admin', 'LOG_BBCODE_DELETE', $row['bbcode_tag']);
+ if (confirm_box(true))
+ {
+ $db->sql_query('DELETE FROM ' . BBCODES_TABLE . " WHERE bbcode_id = $bbcode_id");
+ $cache->destroy('sql', BBCODES_TABLE);
+ add_log('admin', 'LOG_BBCODE_DELETE', $row['bbcode_tag']);
+ }
+ else
+ {
+ confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array(
+ 'bbcode' => $bbcode_id,
+ 'i' => $id,
+ 'mode' => $mode,
+ 'action' => $action))
+ );
+ }
}
break;
@@ -290,7 +307,7 @@ class acp_bbcodes
if (preg_match_all('/(?<!\\\\)\$([0-9]+)/', $replace, $repad))
{
$repad = $pad + sizeof(array_unique($repad[0]));
- $replace = preg_replace('/(?<!\\\\)\$([0-9]+)/e', "'\$' . (\$1 + \$pad)", $replace);
+ $replace = preg_replace('/(?<!\\\\)\$([0-9]+)/e', "'\${' . (\$1 + \$pad) . '}'", $replace);
$pad = $repad;
}
@@ -320,7 +337,7 @@ class acp_bbcodes
$fp_replace = str_replace($token, $replace, $fp_replace);
$sp_match = str_replace(preg_quote($token, '!'), '(.*?)', $sp_match);
- $sp_replace = str_replace($token, '$' . ($n + 1), $sp_replace);
+ $sp_replace = str_replace($token, '${' . ($n + 1) . '}', $sp_replace);
}
$fp_match = '!' . $fp_match . '!' . $modifiers;
diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php
index 49e4b1eb1c..84cc8ddd1c 100644
--- a/phpBB/includes/acp/acp_board.php
+++ b/phpBB/includes/acp/acp_board.php
@@ -27,6 +27,7 @@ class acp_board
$action = request_var('action', '');
$submit = (isset($_POST['submit'])) ? true : false;
+ // Validation types are: string, int, bool, rpath (relative), rwpath (realtive, writeable), path (relative path, but able to escape the root), wpath (writeable)
switch ($mode)
{
case 'settings':
@@ -34,19 +35,19 @@ class acp_board
'title' => 'ACP_BOARD_SETTINGS',
'vars' => array(
'legend1' => 'ACP_BOARD_SETTINGS',
- 'sitename' => array('lang' => 'SITE_NAME', 'type' => 'text:40:255', 'explain' => false),
- 'site_desc' => array('lang' => 'SITE_DESC', 'type' => 'text:40:255', 'explain' => false),
- 'board_disable' => array('lang' => 'DISABLE_BOARD', 'type' => 'custom', 'method' => 'board_disable', 'explain' => true),
+ 'sitename' => array('lang' => 'SITE_NAME', 'validate' => 'string', 'type' => 'text:40:255', 'explain' => false),
+ 'site_desc' => array('lang' => 'SITE_DESC', 'validate' => 'string', 'type' => 'text:40:255', 'explain' => false),
+ 'board_disable' => array('lang' => 'DISABLE_BOARD', 'validate' => 'bool', 'type' => 'custom', 'method' => 'board_disable', 'explain' => true),
'board_disable_msg' => false,
- 'default_lang' => array('lang' => 'DEFAULT_LANGUAGE', 'type' => 'select', 'function' => 'language_select', 'params' => array('{CONFIG_VALUE}'), 'explain' => false),
- 'default_dateformat' => array('lang' => 'DEFAULT_DATE_FORMAT', 'type' => 'custom', 'method' => 'dateformat_select', 'explain' => true),
- 'board_timezone' => array('lang' => 'SYSTEM_TIMEZONE', 'type' => 'select', 'function' => 'tz_select', 'params' => array('{CONFIG_VALUE}', 1), 'explain' => false),
- 'board_dst' => array('lang' => 'SYSTEM_DST', 'type' => 'radio:yes_no', 'explain' => false),
- 'default_style' => array('lang' => 'DEFAULT_STYLE', 'type' => 'select', 'function' => 'style_select', 'params' => array('{CONFIG_VALUE}', 1), 'explain' => false),
- 'override_user_style' => array('lang' => 'OVERRIDE_STYLE', 'type' => 'radio:yes_no', 'explain' => true),
+ 'default_lang' => array('lang' => 'DEFAULT_LANGUAGE', 'validate' => 'string', 'type' => 'select', 'function' => 'language_select', 'params' => array('{CONFIG_VALUE}'), 'explain' => false),
+ 'default_dateformat' => array('lang' => 'DEFAULT_DATE_FORMAT', 'validate' => 'string', 'type' => 'custom', 'method' => 'dateformat_select', 'explain' => true),
+ 'board_timezone' => array('lang' => 'SYSTEM_TIMEZONE', 'validate' => 'string', 'type' => 'select', 'function' => 'tz_select', 'params' => array('{CONFIG_VALUE}', 1), 'explain' => false),
+ 'board_dst' => array('lang' => 'SYSTEM_DST', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'default_style' => array('lang' => 'DEFAULT_STYLE', 'validate' => 'int', 'type' => 'select', 'function' => 'style_select', 'params' => array('{CONFIG_VALUE}', 1), 'explain' => false),
+ 'override_user_style' => array('lang' => 'OVERRIDE_STYLE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'legend2' => 'WARNINGS',
- 'warnings_expire_days' => array('lang' => 'WARNINGS_EXPIRE', 'type' => 'text:3:4', 'explain' => true),
+ 'warnings_expire_days' => array('lang' => 'WARNINGS_EXPIRE', 'validate' => 'int', 'type' => 'text:3:4', 'explain' => true),
)
);
break;
@@ -56,29 +57,25 @@ class acp_board
'title' => 'ACP_BOARD_FEATURES',
'vars' => array(
'legend1' => 'ACP_BOARD_FEATURES',
- 'allow_privmsg' => array('lang' => 'BOARD_PM', 'type' => 'radio:yes_no', 'explain' => true),
- 'allow_topic_notify' => array('lang' => 'ALLOW_TOPIC_NOTIFY', 'type' => 'radio:yes_no', 'explain' => false),
- 'allow_forum_notify' => array('lang' => 'ALLOW_FORUM_NOTIFY', 'type' => 'radio:yes_no', 'explain' => false),
- 'allow_namechange' => array('lang' => 'ALLOW_NAME_CHANGE', 'type' => 'radio:yes_no', 'explain' => false),
- 'allow_attachments' => array('lang' => 'ALLOW_ATTACHMENTS', 'type' => 'radio:yes_no', 'explain' => false),
- 'allow_pm_attach' => array('lang' => 'ALLOW_PM_ATTACHMENTS', 'type' => 'radio:yes_no', 'explain' => false),
- 'allow_bbcode' => array('lang' => 'ALLOW_BBCODE', 'type' => 'radio:yes_no', 'explain' => false),
- 'allow_smilies' => array('lang' => 'ALLOW_SMILIES', 'type' => 'radio:yes_no', 'explain' => false),
- 'allow_sig' => array('lang' => 'ALLOW_SIG', 'type' => 'radio:yes_no', 'explain' => false),
- 'allow_sig_bbcode' => array('lang' => 'ALLOW_SIG_BBCODE', 'type' => 'radio:yes_no', 'explain' => false),
- 'allow_sig_img' => array('lang' => 'ALLOW_SIG_IMG', 'type' => 'radio:yes_no', 'explain' => false),
- 'allow_sig_flash' => array('lang' => 'ALLOW_SIG_FLASH', 'type' => 'radio:yes_no', 'explain' => false),
- 'allow_sig_smilies' => array('lang' => 'ALLOW_SIG_SMILIES', 'type' => 'radio:yes_no', 'explain' => false),
- 'allow_nocensors' => array('lang' => 'ALLOW_NO_CENSORS', 'type' => 'radio:yes_no', 'explain' => true),
- 'allow_bookmarks' => array('lang' => 'ALLOW_BOOKMARKS', 'type' => 'radio:yes_no', 'explain' => true),
+ 'allow_privmsg' => array('lang' => 'BOARD_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'allow_topic_notify' => array('lang' => 'ALLOW_TOPIC_NOTIFY', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'allow_forum_notify' => array('lang' => 'ALLOW_FORUM_NOTIFY', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'allow_namechange' => array('lang' => 'ALLOW_NAME_CHANGE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'allow_attachments' => array('lang' => 'ALLOW_ATTACHMENTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'allow_pm_attach' => array('lang' => 'ALLOW_PM_ATTACHMENTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'allow_bbcode' => array('lang' => 'ALLOW_BBCODE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'allow_smilies' => array('lang' => 'ALLOW_SMILIES', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'allow_sig' => array('lang' => 'ALLOW_SIG', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'allow_nocensors' => array('lang' => 'ALLOW_NO_CENSORS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'allow_bookmarks' => array('lang' => 'ALLOW_BOOKMARKS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'legend2' => 'ACP_LOAD_SETTINGS',
- 'load_birthdays' => array('lang' => 'YES_BIRTHDAYS', 'type' => 'radio:yes_no', 'explain' => false),
- 'load_moderators' => array('lang' => 'YES_MODERATORS', 'type' => 'radio:yes_no', 'explain' => false),
- 'load_jumpbox' => array('lang' => 'YES_JUMPBOX', 'type' => 'radio:yes_no', 'explain' => false),
- 'load_cpf_memberlist' => array('lang' => 'LOAD_CPF_MEMBERLIST', 'type' => 'radio:yes_no', 'explain' => false),
- 'load_cpf_viewprofile' => array('lang' => 'LOAD_CPF_VIEWPROFILE', 'type' => 'radio:yes_no', 'explain' => false),
- 'load_cpf_viewtopic' => array('lang' => 'LOAD_CPF_VIEWTOPIC', 'type' => 'radio:yes_no', 'explain' => false),
+ 'load_birthdays' => array('lang' => 'YES_BIRTHDAYS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'load_moderators' => array('lang' => 'YES_MODERATORS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'load_jumpbox' => array('lang' => 'YES_JUMPBOX', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'load_cpf_memberlist' => array('lang' => 'LOAD_CPF_MEMBERLIST', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'load_cpf_viewprofile' => array('lang' => 'LOAD_CPF_VIEWPROFILE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'load_cpf_viewtopic' => array('lang' => 'LOAD_CPF_VIEWTOPIC', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
)
);
break;
@@ -90,14 +87,14 @@ class acp_board
'legend1' => 'ACP_AVATAR_SETTINGS',
'avatar_min_height' => false, 'avatar_min_width' => false, 'avatar_max_height' => false, 'avatar_max_width' => false,
- 'allow_avatar_local' => array('lang' => 'ALLOW_LOCAL', 'type' => 'radio:yes_no', 'explain' => false),
- 'allow_avatar_remote' => array('lang' => 'ALLOW_REMOTE', 'type' => 'radio:yes_no', 'explain' => true),
- 'allow_avatar_upload' => array('lang' => 'ALLOW_UPLOAD', 'type' => 'radio:yes_no', 'explain' => false),
- 'avatar_filesize' => array('lang' => 'MAX_FILESIZE', 'type' => 'text:4:10', 'explain' => true, 'append' => ' ' . $user->lang['BYTES']),
- 'avatar_min' => array('lang' => 'MIN_AVATAR_SIZE', 'type' => 'dimension:3:4', 'explain' => true),
- 'avatar_max' => array('lang' => 'MAX_AVATAR_SIZE', 'type' => 'dimension:3:4', 'explain' => true),
- 'avatar_path' => array('lang' => 'AVATAR_STORAGE_PATH', 'type' => 'text:20:255', 'explain' => true),
- 'avatar_gallery_path' => array('lang' => 'AVATAR_GALLERY_PATH', 'type' => 'text:20:255', 'explain' => true)
+ 'allow_avatar_local' => array('lang' => 'ALLOW_LOCAL', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'allow_avatar_remote' => array('lang' => 'ALLOW_REMOTE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'allow_avatar_upload' => array('lang' => 'ALLOW_UPLOAD', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'avatar_filesize' => array('lang' => 'MAX_FILESIZE', 'validate' => 'int', 'type' => 'text:4:10', 'explain' => true, 'append' => ' ' . $user->lang['BYTES']),
+ 'avatar_min' => array('lang' => 'MIN_AVATAR_SIZE', 'validate' => 'int', 'type' => 'dimension:3:4', 'explain' => true),
+ 'avatar_max' => array('lang' => 'MAX_AVATAR_SIZE', 'validate' => 'int', 'type' => 'dimension:3:4', 'explain' => true),
+ 'avatar_path' => array('lang' => 'AVATAR_STORAGE_PATH', 'validate' => 'rwpath', 'type' => 'text:20:255', 'explain' => true),
+ 'avatar_gallery_path' => array('lang' => 'AVATAR_GALLERY_PATH', 'validate' => 'rpath', 'type' => 'text:20:255', 'explain' => true)
)
);
break;
@@ -108,23 +105,23 @@ class acp_board
'lang' => 'ucp',
'vars' => array(
'legend1' => 'GENERAL_SETTINGS',
- 'allow_privmsg' => array('lang' => 'BOARD_PM', 'type' => 'radio:yes_no', 'explain' => true),
- 'pm_max_boxes' => array('lang' => 'BOXES_MAX', 'type' => 'text:4:4', 'explain' => true),
- 'pm_max_msgs' => array('lang' => 'BOXES_LIMIT', 'type' => 'text:4:4', 'explain' => true),
- 'full_folder_action' => array('lang' => 'FULL_FOLDER_ACTION', 'type' => 'select', 'method' => 'full_folder_select', 'explain' => true),
- 'pm_edit_time' => array('lang' => 'PM_EDIT_TIME', 'type' => 'text:3:3', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']),
+ 'allow_privmsg' => array('lang' => 'BOARD_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'pm_max_boxes' => array('lang' => 'BOXES_MAX', 'validate' => 'int', 'type' => 'text:4:4', 'explain' => true),
+ 'pm_max_msgs' => array('lang' => 'BOXES_LIMIT', 'validate' => 'int', 'type' => 'text:4:4', 'explain' => true),
+ 'full_folder_action' => array('lang' => 'FULL_FOLDER_ACTION', 'validate' => 'int', 'type' => 'select', 'method' => 'full_folder_select', 'explain' => true),
+ 'pm_edit_time' => array('lang' => 'PM_EDIT_TIME', 'validate' => 'int', 'type' => 'text:3:3', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']),
'legend2' => 'GENERAL_OPTIONS',
- 'allow_mass_pm' => array('lang' => 'ALLOW_MASS_PM', 'type' => 'radio:yes_no', 'explain' => false),
- 'auth_bbcode_pm' => array('lang' => 'ALLOW_BBCODE_PM', 'type' => 'radio:yes_no', 'explain' => false),
- 'auth_smilies_pm' => array('lang' => 'ALLOW_SMILIES_PM', 'type' => 'radio:yes_no', 'explain' => false),
- 'allow_pm_attach' => array('lang' => 'ALLOW_PM_ATTACHMENTS', 'type' => 'radio:yes_no', 'explain' => false),
- 'allow_sig_pm' => array('lang' => 'ALLOW_SIG_PM', 'type' => 'radio:yes_no', 'explain' => false),
- 'print_pm' => array('lang' => 'ALLOW_PRINT_PM', 'type' => 'radio:yes_no', 'explain' => false),
- 'forward_pm' => array('lang' => 'ALLOW_FORWARD_PM', 'type' => 'radio:yes_no', 'explain' => false),
- 'auth_img_pm' => array('lang' => 'ALLOW_IMG_PM', 'type' => 'radio:yes_no', 'explain' => false),
- 'auth_flash_pm' => array('lang' => 'ALLOW_FLASH_PM', 'type' => 'radio:yes_no', 'explain' => false),
- 'enable_pm_icons' => array('lang' => 'ENABLE_PM_ICONS', 'type' => 'radio:yes_no', 'explain' => false)
+ 'allow_mass_pm' => array('lang' => 'ALLOW_MASS_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'auth_bbcode_pm' => array('lang' => 'ALLOW_BBCODE_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'auth_smilies_pm' => array('lang' => 'ALLOW_SMILIES_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'allow_pm_attach' => array('lang' => 'ALLOW_PM_ATTACHMENTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'allow_sig_pm' => array('lang' => 'ALLOW_SIG_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'print_pm' => array('lang' => 'ALLOW_PRINT_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'forward_pm' => array('lang' => 'ALLOW_FORWARD_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'auth_img_pm' => array('lang' => 'ALLOW_IMG_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'auth_flash_pm' => array('lang' => 'ALLOW_FLASH_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'enable_pm_icons' => array('lang' => 'ENABLE_PM_ICONS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false)
)
);
break;
@@ -134,31 +131,32 @@ class acp_board
'title' => 'ACP_POST_SETTINGS',
'vars' => array(
'legend1' => 'GENERAL_OPTIONS',
- 'allow_topic_notify' => array('lang' => 'ALLOW_TOPIC_NOTIFY', 'type' => 'radio:yes_no', 'explain' => false),
- 'allow_forum_notify' => array('lang' => 'ALLOW_FORUM_NOTIFY', 'type' => 'radio:yes_no', 'explain' => false),
- 'allow_bbcode' => array('lang' => 'ALLOW_BBCODE', 'type' => 'radio:yes_no', 'explain' => false),
- 'allow_smilies' => array('lang' => 'ALLOW_SMILIES', 'type' => 'radio:yes_no', 'explain' => false),
- 'allow_nocensors' => array('lang' => 'ALLOW_NO_CENSORS', 'type' => 'radio:yes_no', 'explain' => true),
- 'allow_bookmarks' => array('lang' => 'ALLOW_BOOKMARKS', 'type' => 'radio:yes_no', 'explain' => true),
- 'enable_post_confirm' => array('lang' => 'VISUAL_CONFIRM_POST', 'type' => 'radio:yes_no', 'explain' => true),
+ 'allow_topic_notify' => array('lang' => 'ALLOW_TOPIC_NOTIFY', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'allow_forum_notify' => array('lang' => 'ALLOW_FORUM_NOTIFY', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'allow_bbcode' => array('lang' => 'ALLOW_BBCODE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'allow_smilies' => array('lang' => 'ALLOW_SMILIES', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'allow_post_links' => array('lang' => 'ALLOW_POST_LINKS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'allow_nocensors' => array('lang' => 'ALLOW_NO_CENSORS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'allow_bookmarks' => array('lang' => 'ALLOW_BOOKMARKS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'enable_post_confirm' => array('lang' => 'VISUAL_CONFIRM_POST', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'legend2' => 'POSTING',
'bump_type' => false,
- 'edit_time' => array('lang' => 'EDIT_TIME', 'type' => 'text:3:3', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']),
- 'display_last_edited' => array('lang' => 'DISPLAY_LAST_EDITED', 'type' => 'radio:yes_no', 'explain' => true),
- 'flood_interval' => array('lang' => 'FLOOD_INTERVAL', 'type' => 'text:3:4', 'explain' => true),
- 'bump_interval' => array('lang' => 'BUMP_INTERVAL', 'type' => 'custom', 'method' => 'bump_interval', 'explain' => true),
- 'topics_per_page' => array('lang' => 'TOPICS_PER_PAGE', 'type' => 'text:3:4', 'explain' => false),
- 'posts_per_page' => array('lang' => 'POSTS_PER_PAGE', 'type' => 'text:3:4', 'explain' => false),
- 'hot_threshold' => array('lang' => 'HOT_THRESHOLD', 'type' => 'text:3:4', 'explain' => false),
- 'max_poll_options' => array('lang' => 'MAX_POLL_OPTIONS', 'type' => 'text:4:4', 'explain' => false),
- 'max_post_chars' => array('lang' => 'CHAR_LIMIT', 'type' => 'text:4:6', 'explain' => true),
- 'max_post_smilies' => array('lang' => 'SMILIES_LIMIT', 'type' => 'text:4:4', 'explain' => true),
- 'max_post_urls' => array('lang' => 'MAX_POST_URLS', 'type' => 'text:5:4', 'explain' => true),
- 'max_post_font_size' => array('lang' => 'MAX_POST_FONT_SIZE', 'type' => 'text:5:4', 'explain' => true),
- 'max_quote_depth' => array('lang' => 'QUOTE_DEPTH_LIMIT', 'type' => 'text:4:4', 'explain' => true),
- 'max_post_img_width' => array('lang' => 'MAX_POST_IMG_WIDTH', 'type' => 'text:5:4', 'explain' => true),
- 'max_post_img_height' => array('lang' => 'MAX_POST_IMG_HEIGHT', 'type' => 'text:5:4', 'explain' => true),
+ 'edit_time' => array('lang' => 'EDIT_TIME', 'validate' => 'int', 'type' => 'text:3:3', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']),
+ 'display_last_edited' => array('lang' => 'DISPLAY_LAST_EDITED', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'flood_interval' => array('lang' => 'FLOOD_INTERVAL', 'validate' => 'int', 'type' => 'text:3:4', 'explain' => true),
+ 'bump_interval' => array('lang' => 'BUMP_INTERVAL', 'validate' => 'int', 'type' => 'custom', 'method' => 'bump_interval', 'explain' => true),
+ 'topics_per_page' => array('lang' => 'TOPICS_PER_PAGE', 'validate' => 'int', 'type' => 'text:3:4', 'explain' => false),
+ 'posts_per_page' => array('lang' => 'POSTS_PER_PAGE', 'validate' => 'int', 'type' => 'text:3:4', 'explain' => false),
+ 'hot_threshold' => array('lang' => 'HOT_THRESHOLD', 'validate' => 'int', 'type' => 'text:3:4', 'explain' => false),
+ 'max_poll_options' => array('lang' => 'MAX_POLL_OPTIONS', 'validate' => 'int', 'type' => 'text:4:4', 'explain' => false),
+ 'max_post_chars' => array('lang' => 'CHAR_LIMIT', 'validate' => 'int', 'type' => 'text:4:6', 'explain' => true),
+ 'max_post_smilies' => array('lang' => 'SMILIES_LIMIT', 'validate' => 'int', 'type' => 'text:4:4', 'explain' => true),
+ 'max_post_urls' => array('lang' => 'MAX_POST_URLS', 'validate' => 'int', 'type' => 'text:5:4', 'explain' => true),
+ 'max_post_font_size' => array('lang' => 'MAX_POST_FONT_SIZE', 'validate' => 'int', 'type' => 'text:5:4', 'explain' => true),
+ 'max_quote_depth' => array('lang' => 'QUOTE_DEPTH_LIMIT', 'validate' => 'int', 'type' => 'text:4:4', 'explain' => true),
+ 'max_post_img_width' => array('lang' => 'MAX_POST_IMG_WIDTH', 'validate' => 'int', 'type' => 'text:5:4', 'explain' => true),
+ 'max_post_img_height' => array('lang' => 'MAX_POST_IMG_HEIGHT', 'validate' => 'int', 'type' => 'text:5:4', 'explain' => true),
)
);
break;
@@ -168,19 +166,20 @@ class acp_board
'title' => 'ACP_SIGNATURE_SETTINGS',
'vars' => array(
'legend1' => 'GENERAL_OPTIONS',
- 'allow_sig' => array('lang' => 'ALLOW_SIG', 'type' => 'radio:yes_no', 'explain' => false),
- 'allow_sig_bbcode' => array('lang' => 'ALLOW_SIG_BBCODE', 'type' => 'radio:yes_no', 'explain' => false),
- 'allow_sig_img' => array('lang' => 'ALLOW_SIG_IMG', 'type' => 'radio:yes_no', 'explain' => false),
- 'allow_sig_flash' => array('lang' => 'ALLOW_SIG_FLASH', 'type' => 'radio:yes_no', 'explain' => false),
- 'allow_sig_smilies' => array('lang' => 'ALLOW_SIG_SMILIES', 'type' => 'radio:yes_no', 'explain' => false),
+ 'allow_sig' => array('lang' => 'ALLOW_SIG', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'allow_sig_bbcode' => array('lang' => 'ALLOW_SIG_BBCODE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'allow_sig_img' => array('lang' => 'ALLOW_SIG_IMG', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'allow_sig_flash' => array('lang' => 'ALLOW_SIG_FLASH', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'allow_sig_smilies' => array('lang' => 'ALLOW_SIG_SMILIES', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'allow_sig_links' => array('lang' => 'ALLOW_SIG_LINKS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'legend2' => 'GENERAL_SETTINGS',
- 'max_sig_chars' => array('lang' => 'MAX_SIG_LENGTH', 'type' => 'text:5:4', 'explain' => true),
- 'max_sig_urls' => array('lang' => 'MAX_SIG_URLS', 'type' => 'text:5:4', 'explain' => true),
- 'max_sig_font_size' => array('lang' => 'MAX_SIG_FONT_SIZE', 'type' => 'text:5:4', 'explain' => true),
- 'max_sig_smilies' => array('lang' => 'MAX_SIG_SMILIES', 'type' => 'text:5:4', 'explain' => true),
- 'max_sig_img_width' => array('lang' => 'MAX_SIG_IMG_WIDTH', 'type' => 'text:5:4', 'explain' => true),
- 'max_sig_img_height' => array('lang' => 'MAX_SIG_IMG_HEIGHT', 'type' => 'text:5:4', 'explain' => true),
+ 'max_sig_chars' => array('lang' => 'MAX_SIG_LENGTH', 'validate' => 'int', 'type' => 'text:5:4', 'explain' => true),
+ 'max_sig_urls' => array('lang' => 'MAX_SIG_URLS', 'validate' => 'int', 'type' => 'text:5:4', 'explain' => true),
+ 'max_sig_font_size' => array('lang' => 'MAX_SIG_FONT_SIZE', 'validate' => 'int', 'type' => 'text:5:4', 'explain' => true),
+ 'max_sig_smilies' => array('lang' => 'MAX_SIG_SMILIES', 'validate' => 'int', 'type' => 'text:5:4', 'explain' => true),
+ 'max_sig_img_width' => array('lang' => 'MAX_SIG_IMG_WIDTH', 'validate' => 'int', 'type' => 'text:5:4', 'explain' => true),
+ 'max_sig_img_height' => array('lang' => 'MAX_SIG_IMG_HEIGHT', 'validate' => 'int', 'type' => 'text:5:4', 'explain' => true),
)
);
break;
@@ -193,24 +192,24 @@ class acp_board
'max_name_chars' => false,
'max_pass_chars' => false,
- 'require_activation' => array('lang' => 'ACC_ACTIVATION', 'type' => 'custom', 'method' => 'select_acc_activation', 'explain' => true),
- 'min_name_chars' => array('lang' => 'USERNAME_LENGTH', 'type' => 'custom', 'method' => 'username_length', 'explain' => true),
- 'min_pass_chars' => array('lang' => 'PASSWORD_LENGTH', 'type' => 'custom', 'method' => 'password_length', 'explain' => true),
- 'allow_name_chars' => array('lang' => 'USERNAME_CHARS', 'type' => 'select', 'method' => 'select_username_chars', 'explain' => true),
- 'pass_complex' => array('lang' => 'PASSWORD_TYPE', 'type' => 'select', 'method' => 'select_password_chars', 'explain' => true),
- 'chg_passforce' => array('lang' => 'FORCE_PASS_CHANGE', 'type' => 'text:3:3', 'explain' => true),
+ 'require_activation' => array('lang' => 'ACC_ACTIVATION', 'validate' => 'int', 'type' => 'custom', 'method' => 'select_acc_activation', 'explain' => true),
+ 'min_name_chars' => array('lang' => 'USERNAME_LENGTH', 'validate' => 'int', 'type' => 'custom', 'method' => 'username_length', 'explain' => true),
+ 'min_pass_chars' => array('lang' => 'PASSWORD_LENGTH', 'validate' => 'int', 'type' => 'custom', 'method' => 'password_length', 'explain' => true),
+ 'allow_name_chars' => array('lang' => 'USERNAME_CHARS', 'validate' => 'string', 'type' => 'select', 'method' => 'select_username_chars', 'explain' => true),
+ 'pass_complex' => array('lang' => 'PASSWORD_TYPE', 'validate' => 'string', 'type' => 'select', 'method' => 'select_password_chars', 'explain' => true),
+ 'chg_passforce' => array('lang' => 'FORCE_PASS_CHANGE', 'validate' => 'int', 'type' => 'text:3:3', 'explain' => true),
'legend2' => 'GENERAL_OPTIONS',
- 'allow_namechange' => array('lang' => 'ALLOW_NAME_CHANGE', 'type' => 'radio:yes_no', 'explain' => false),
- 'allow_emailreuse' => array('lang' => 'ALLOW_EMAIL_REUSE', 'type' => 'radio:yes_no', 'explain' => true),
- 'enable_confirm' => array('lang' => 'VISUAL_CONFIRM_REG', 'type' => 'radio:yes_no', 'explain' => true),
- 'max_login_attempts' => array('lang' => 'MAX_LOGIN_ATTEMPTS', 'type' => 'text:3:3', 'explain' => true),
- 'max_reg_attempts' => array('lang' => 'REG_LIMIT', 'type' => 'text:4:4', 'explain' => true),
+ 'allow_namechange' => array('lang' => 'ALLOW_NAME_CHANGE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'allow_emailreuse' => array('lang' => 'ALLOW_EMAIL_REUSE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'enable_confirm' => array('lang' => 'VISUAL_CONFIRM_REG', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'max_login_attempts' => array('lang' => 'MAX_LOGIN_ATTEMPTS', 'validate' => 'int', 'type' => 'text:3:3', 'explain' => true),
+ 'max_reg_attempts' => array('lang' => 'REG_LIMIT', 'validate' => 'int', 'type' => 'text:4:4', 'explain' => true),
'legend3' => 'COPPA',
- 'coppa_enable' => array('lang' => 'ENABLE_COPPA', 'type' => 'radio:yes_no', 'explain' => true),
- 'coppa_mail' => array('lang' => 'COPPA_MAIL', 'type' => 'textarea:5:40', 'explain' => true),
- 'coppa_fax' => array('lang' => 'COPPA_FAX', 'type' => 'text:25:100', 'explain' => false),
+ 'coppa_enable' => array('lang' => 'ENABLE_COPPA', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'coppa_mail' => array('lang' => 'COPPA_MAIL', 'validate' => 'string', 'type' => 'textarea:5:40', 'explain' => true),
+ 'coppa_fax' => array('lang' => 'COPPA_FAX', 'validate' => 'string', 'type' => 'text:25:100', 'explain' => false),
)
);
break;
@@ -220,10 +219,10 @@ class acp_board
'title' => 'ACP_COOKIE_SETTINGS',
'vars' => array(
'legend1' => 'ACP_COOKIE_SETTINGS',
- 'cookie_domain' => array('lang' => 'COOKIE_DOMAIN', 'type' => 'text::255', 'explain' => false),
- 'cookie_name' => array('lang' => 'COOKIE_NAME', 'type' => 'text::16', 'explain' => false),
- 'cookie_path' => array('lang' => 'COOKIE_PATH', 'type' => 'text::255', 'explain' => false),
- 'cookie_secure' => array('lang' => 'COOKIE_SECURE', 'type' => 'radio:disabled_enabled', 'explain' => true)
+ 'cookie_domain' => array('lang' => 'COOKIE_DOMAIN', 'validate' => 'string', 'type' => 'text::255', 'explain' => false),
+ 'cookie_name' => array('lang' => 'COOKIE_NAME', 'validate' => 'string', 'type' => 'text::16', 'explain' => false),
+ 'cookie_path' => array('lang' => 'COOKIE_PATH', 'validate' => 'string', 'type' => 'text::255', 'explain' => false),
+ 'cookie_secure' => array('lang' => 'COOKIE_SECURE', 'validate' => 'bool', 'type' => 'radio:disabled_enabled', 'explain' => true)
)
);
break;
@@ -233,28 +232,28 @@ class acp_board
'title' => 'ACP_LOAD_SETTINGS',
'vars' => array(
'legend1' => 'GENERAL_SETTINGS',
- 'limit_load' => array('lang' => 'LIMIT_LOAD', 'type' => 'text:4:4', 'explain' => true),
- 'session_length' => array('lang' => 'SESSION_LENGTH', 'type' => 'text:5:5', 'explain' => true),
- 'active_sessions' => array('lang' => 'LIMIT_SESSIONS', 'type' => 'text:4:4', 'explain' => true),
- 'load_online_time' => array('lang' => 'ONLINE_LENGTH', 'type' => 'text:4:3', 'explain' => true),
+ 'limit_load' => array('lang' => 'LIMIT_LOAD', 'validate' => 'int', 'type' => 'text:4:4', 'explain' => true),
+ 'session_length' => array('lang' => 'SESSION_LENGTH', 'validate' => 'int', 'type' => 'text:5:5', 'explain' => true),
+ 'active_sessions' => array('lang' => 'LIMIT_SESSIONS', 'validate' => 'int', 'type' => 'text:4:4', 'explain' => true),
+ 'load_online_time' => array('lang' => 'ONLINE_LENGTH', 'validate' => 'int', 'type' => 'text:4:3', 'explain' => true),
'legend2' => 'GENERAL_OPTIONS',
- 'load_db_track' => array('lang' => 'YES_POST_MARKING', 'type' => 'radio:yes_no', 'explain' => true),
- 'load_db_lastread' => array('lang' => 'YES_READ_MARKING', 'type' => 'radio:yes_no', 'explain' => true),
- 'load_anon_lastread' => array('lang' => 'YES_ANON_READ_MARKING', 'type' => 'radio:yes_no', 'explain' => true),
- 'load_online' => array('lang' => 'YES_ONLINE', 'type' => 'radio:yes_no', 'explain' => true),
- 'load_online_guests' => array('lang' => 'YES_ONLINE_GUESTS', 'type' => 'radio:yes_no', 'explain' => true),
- 'load_onlinetrack' => array('lang' => 'YES_ONLINE_TRACK', 'type' => 'radio:yes_no', 'explain' => true),
- 'load_birthdays' => array('lang' => 'YES_BIRTHDAYS', 'type' => 'radio:yes_no', 'explain' => false),
- 'load_moderators' => array('lang' => 'YES_MODERATORS', 'type' => 'radio:yes_no', 'explain' => false),
- 'load_jumpbox' => array('lang' => 'YES_JUMPBOX', 'type' => 'radio:yes_no', 'explain' => false),
- 'load_user_activity' => array('lang' => 'LOAD_USER_ACTIVITY', 'type' => 'radio:yes_no', 'explain' => true),
- 'load_tplcompile' => array('lang' => 'RECOMPILE_TEMPLATES', 'type' => 'radio:yes_no', 'explain' => true),
+ 'load_db_track' => array('lang' => 'YES_POST_MARKING', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'load_db_lastread' => array('lang' => 'YES_READ_MARKING', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'load_anon_lastread' => array('lang' => 'YES_ANON_READ_MARKING', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'load_online' => array('lang' => 'YES_ONLINE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'load_online_guests' => array('lang' => 'YES_ONLINE_GUESTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'load_onlinetrack' => array('lang' => 'YES_ONLINE_TRACK', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'load_birthdays' => array('lang' => 'YES_BIRTHDAYS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'load_moderators' => array('lang' => 'YES_MODERATORS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'load_jumpbox' => array('lang' => 'YES_JUMPBOX', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'load_user_activity' => array('lang' => 'LOAD_USER_ACTIVITY', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'load_tplcompile' => array('lang' => 'RECOMPILE_TEMPLATES', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'legend3' => 'CUSTOM_PROFILE_FIELDS',
- 'load_cpf_memberlist' => array('lang' => 'LOAD_CPF_MEMBERLIST', 'type' => 'radio:yes_no', 'explain' => false),
- 'load_cpf_viewprofile' => array('lang' => 'LOAD_CPF_VIEWPROFILE', 'type' => 'radio:yes_no', 'explain' => false),
- 'load_cpf_viewtopic' => array('lang' => 'LOAD_CPF_VIEWTOPIC', 'type' => 'radio:yes_no', 'explain' => false),
+ 'load_cpf_memberlist' => array('lang' => 'LOAD_CPF_MEMBERLIST', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'load_cpf_viewprofile' => array('lang' => 'LOAD_CPF_VIEWPROFILE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
+ 'load_cpf_viewtopic' => array('lang' => 'LOAD_CPF_VIEWTOPIC', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
)
);
break;
@@ -264,7 +263,7 @@ class acp_board
'title' => 'ACP_AUTH_SETTINGS',
'vars' => array(
'legend1' => 'ACP_AUTH_SETTINGS',
- 'auth_method' => array('lang' => 'AUTH_METHOD', 'type' => 'select', 'method' => 'select_auth_method', 'explain' => false)
+ 'auth_method' => array('lang' => 'AUTH_METHOD', 'validate' => 'string', 'type' => 'select', 'method' => 'select_auth_method', 'explain' => false)
)
);
break;
@@ -274,20 +273,20 @@ class acp_board
'title' => 'ACP_SERVER_SETTINGS',
'vars' => array(
'legend1' => 'ACP_SERVER_SETTINGS',
- 'send_encoding' => array('lang' => 'SEND_ENCODING', 'type' => 'radio:yes_no', 'explain' => true),
- 'gzip_compress' => array('lang' => 'ENABLE_GZIP', 'type' => 'radio:yes_no', 'explain' => false),
+ 'send_encoding' => array('lang' => 'SEND_ENCODING', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'gzip_compress' => array('lang' => 'ENABLE_GZIP', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
'legend2' => 'PATH_SETTINGS',
- 'smilies_path' => array('lang' => 'SMILIES_PATH', 'type' => 'text:20:255', 'explain' => true),
- 'icons_path' => array('lang' => 'ICONS_PATH', 'type' => 'text:20:255', 'explain' => true),
- 'upload_icons_path' => array('lang' => 'UPLOAD_ICONS_PATH', 'type' => 'text:20:255', 'explain' => true),
- 'ranks_path' => array('lang' => 'RANKS_PATH', 'type' => 'text:20:255', 'explain' => true),
+ 'smilies_path' => array('lang' => 'SMILIES_PATH', 'validate' => 'rpath', 'type' => 'text:20:255', 'explain' => true),
+ 'icons_path' => array('lang' => 'ICONS_PATH', 'validate' => 'rpath', 'type' => 'text:20:255', 'explain' => true),
+ 'upload_icons_path' => array('lang' => 'UPLOAD_ICONS_PATH', 'validate' => 'rpath', 'type' => 'text:20:255', 'explain' => true),
+ 'ranks_path' => array('lang' => 'RANKS_PATH', 'validate' => 'rpath', 'type' => 'text:20:255', 'explain' => true),
'legend3' => 'SERVER_URL_SETTINGS',
- 'force_server_vars' => array('lang' => 'FORCE_SERVER_VARS', 'type' => 'radio:yes_no', 'explain' => true),
- 'server_protocol' => array('lang' => 'SERVER_PROTOCOL', 'type' => 'text:10:10', 'explain' => true),
- 'server_name' => array('lang' => 'SERVER_NAME', 'type' => 'text:40:255', 'explain' => true),
- 'server_port' => array('lang' => 'SERVER_PORT', 'type' => 'text:5:5', 'explain' => true),
+ 'force_server_vars' => array('lang' => 'FORCE_SERVER_VARS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'server_protocol' => array('lang' => 'SERVER_PROTOCOL', 'validate' => 'string', 'type' => 'text:10:10', 'explain' => true),
+ 'server_name' => array('lang' => 'SERVER_NAME', 'validate' => 'string', 'type' => 'text:40:255', 'explain' => true),
+ 'server_port' => array('lang' => 'SERVER_PORT', 'validate' => 'int', 'type' => 'text:5:5', 'explain' => true),
)
);
break;
@@ -297,14 +296,16 @@ class acp_board
'title' => 'ACP_SECURITY_SETTINGS',
'vars' => array(
'legend1' => 'ACP_SECURITY_SETTINGS',
- 'allow_autologin' => array('lang' => 'ALLOW_AUTOLOGIN', 'type' => 'radio:yes_no', 'explain' => true),
- 'max_autologin_time' => array('lang' => 'AUTOLOGIN_LENGTH', 'type' => 'text:5:5', 'explain' => true),
- 'ip_check' => array('lang' => 'IP_VALID', 'type' => 'custom', 'method' => 'select_ip_check', 'explain' => true),
- 'browser_check' => array('lang' => 'BROWSER_VALID', 'type' => 'radio:yes_no', 'explain' => true),
- 'pass_complex' => array('lang' => 'PASSWORD_TYPE', 'type' => 'select', 'method' => 'select_password_chars', 'explain' => true),
- 'chg_passforce' => array('lang' => 'FORCE_PASS_CHANGE', 'type' => 'text:3:3', 'explain' => true),
- 'max_login_attempts' => array('lang' => 'MAX_LOGIN_ATTEMPTS', 'type' => 'text:3:3', 'explain' => true),
- 'tpl_allow_php' => array('lang' => 'TPL_ALLOW_PHP', 'type' => 'radio:yes_no', 'explain' => true),
+ 'allow_autologin' => array('lang' => 'ALLOW_AUTOLOGIN', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'max_autologin_time' => array('lang' => 'AUTOLOGIN_LENGTH', 'validate' => 'int', 'type' => 'text:5:5', 'explain' => true),
+ 'ip_check' => array('lang' => 'IP_VALID', 'validate' => 'int', 'type' => 'custom', 'method' => 'select_ip_check', 'explain' => true),
+ 'browser_check' => array('lang' => 'BROWSER_VALID', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'check_dnsbl' => array('lang' => 'CHECK_DNSBL', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'email_check_mx' => array('lang' => 'EMAIL_CHECK_MX', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'pass_complex' => array('lang' => 'PASSWORD_TYPE', 'validate' => 'string', 'type' => 'select', 'method' => 'select_password_chars', 'explain' => true),
+ 'chg_passforce' => array('lang' => 'FORCE_PASS_CHANGE', 'validate' => 'int', 'type' => 'text:3:3', 'explain' => true),
+ 'max_login_attempts' => array('lang' => 'MAX_LOGIN_ATTEMPTS', 'validate' => 'int', 'type' => 'text:3:3', 'explain' => true),
+ 'tpl_allow_php' => array('lang' => 'TPL_ALLOW_PHP', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
)
);
break;
@@ -314,28 +315,29 @@ class acp_board
'title' => 'ACP_EMAIL_SETTINGS',
'vars' => array(
'legend1' => 'GENERAL_SETTINGS',
- 'email_enable' => array('lang' => 'ENABLE_EMAIL', 'type' => 'radio:enabled_disabled', 'explain' => true),
- 'board_email_form' => array('lang' => 'BOARD_EMAIL_FORM', 'type' => 'radio:enabled_disabled', 'explain' => true),
- 'email_function_name' => array('lang' => 'EMAIL_FUNCTION_NAME', 'type' => 'text:20:50', 'explain' => true),
- 'email_package_size' => array('lang' => 'EMAIL_PACKAGE_SIZE', 'type' => 'text:5:5', 'explain' => true),
- 'board_contact' => array('lang' => 'CONTACT_EMAIL', 'type' => 'text:25:100', 'explain' => true),
- 'board_email' => array('lang' => 'ADMIN_EMAIL', 'type' => 'text:25:100', 'explain' => true),
- 'board_email_sig' => array('lang' => 'EMAIL_SIG', 'type' => 'textarea:5:30', 'explain' => true),
- 'board_hide_emails' => array('lang' => 'BOARD_HIDE_EMAILS', 'type' => 'radio:yes_no', 'explain' => true),
+ 'email_enable' => array('lang' => 'ENABLE_EMAIL', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true),
+ 'board_email_form' => array('lang' => 'BOARD_EMAIL_FORM', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true),
+ 'email_function_name' => array('lang' => 'EMAIL_FUNCTION_NAME', 'validate' => 'string', 'type' => 'text:20:50', 'explain' => true),
+ 'email_package_size' => array('lang' => 'EMAIL_PACKAGE_SIZE', 'validate' => 'int', 'type' => 'text:5:5', 'explain' => true),
+ 'board_contact' => array('lang' => 'CONTACT_EMAIL', 'validate' => 'string', 'type' => 'text:25:100', 'explain' => true),
+ 'board_email' => array('lang' => 'ADMIN_EMAIL', 'validate' => 'string', 'type' => 'text:25:100', 'explain' => true),
+ 'board_email_sig' => array('lang' => 'EMAIL_SIG', 'validate' => 'string', 'type' => 'textarea:5:30', 'explain' => true),
+ 'board_hide_emails' => array('lang' => 'BOARD_HIDE_EMAILS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'legend2' => 'SMTP_SETTINGS',
- 'smtp_delivery' => array('lang' => 'USE_SMTP', 'type' => 'radio:yes_no', 'explain' => true),
- 'smtp_host' => array('lang' => 'SMTP_SERVER', 'type' => 'text:25:50', 'explain' => false),
- 'smtp_port' => array('lang' => 'SMTP_PORT', 'type' => 'text:4:5', 'explain' => true),
- 'smtp_auth_method' => array('lang' => 'SMTP_AUTH_METHOD', 'type' => 'select', 'method' => 'mail_auth_select', 'explain' => true),
- 'smtp_username' => array('lang' => 'SMTP_USERNAME', 'type' => 'text:25:255', 'explain' => true),
- 'smtp_password' => array('lang' => 'SMTP_PASSWORD', 'type' => 'password:25:255', 'explain' => true)
+ 'smtp_delivery' => array('lang' => 'USE_SMTP', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
+ 'smtp_host' => array('lang' => 'SMTP_SERVER', 'validate' => 'string', 'type' => 'text:25:50', 'explain' => false),
+ 'smtp_port' => array('lang' => 'SMTP_PORT', 'validate' => 'int', 'type' => 'text:4:5', 'explain' => true),
+ 'smtp_auth_method' => array('lang' => 'SMTP_AUTH_METHOD', 'validate' => 'string', 'type' => 'select', 'method' => 'mail_auth_select', 'explain' => true),
+ 'smtp_username' => array('lang' => 'SMTP_USERNAME', 'validate' => 'string', 'type' => 'text:25:255', 'explain' => true),
+ 'smtp_password' => array('lang' => 'SMTP_PASSWORD', 'validate' => 'string', 'type' => 'password:25:255', 'explain' => true)
)
);
break;
default:
- trigger_error('NO_MODE');
+ trigger_error('NO_MODE', E_USER_ERROR);
+ break;
}
if (isset($display_vars['lang']))
@@ -345,6 +347,20 @@ class acp_board
$this->new_config = $config;
$cfg_array = (isset($_REQUEST['config'])) ? request_var('config', array('' => ''), true) : $this->new_config;
+ if (isset($_REQUEST['config']))
+ {
+ utf8_normalize_nfc(&$cfg_array);
+ }
+ $error = array();
+
+ // We validate the complete config if whished
+ validate_config_vars($display_vars['vars'], $cfg_array, $error);
+
+ // Do not write values if there is an error
+ if (sizeof($error))
+ {
+ $submit = false;
+ }
// We go through the display_vars to make sure no one is trying to set variables he/she is not allowed to...
foreach ($display_vars['vars'] as $config_name => $null)
@@ -448,14 +464,14 @@ class acp_board
{
set_config($config_name, $config_value);
}
- trigger_error($error . adm_back_link($this->u_action));
+ trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING);
}
}
set_config('auth_method', $cfg_array['auth_method']);
}
else
{
- trigger_error('NO_AUTH_PLUGIN');
+ trigger_error('NO_AUTH_PLUGIN', E_USER_ERROR);
}
}
}
@@ -473,6 +489,10 @@ class acp_board
$template->assign_vars(array(
'L_TITLE' => $user->lang[$display_vars['title']],
'L_TITLE_EXPLAIN' => $user->lang[$display_vars['title'] . '_EXPLAIN'],
+
+ 'S_ERROR' => (sizeof($error)) ? true : false,
+ 'ERROR_MSG' => implode('<br />', $error),
+
'U_ACTION' => $this->u_action)
);
diff --git a/phpBB/includes/acp/acp_bots.php b/phpBB/includes/acp/acp_bots.php
index f24a6b7b12..2dbcc463e9 100644
--- a/phpBB/includes/acp/acp_bots.php
+++ b/phpBB/includes/acp/acp_bots.php
@@ -142,6 +142,12 @@ class acp_bots
}
$bot_row['bot_ip'] = str_replace(' ', '', $bot_row['bot_ip']);
+ // Make sure the admin is not adding a bot with an user agent similar to his one
+ if ($bot_row['bot_agent'] && substr($user->data['session_browser'], 0, 149) === substr($bot_row['bot_agent'], 0, 149))
+ {
+ $error[] = $user->lang['ERR_BOT_AGENT_MATCHES_UA'];
+ }
+
if (!sizeof($error))
{
$db->sql_transaction('begin');
@@ -159,7 +165,7 @@ class acp_bots
if (!$group_row)
{
- trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action . "&amp;id=$bot_id&amp;action=$action"));
+ trigger_error($user->lang['NO_BOT_GROUP'] . adm_back_link($this->u_action . "&amp;id=$bot_id&amp;action=$action"), E_USER_WARNING);
}
$user_id = user_add(array(
@@ -197,7 +203,7 @@ class acp_bots
if (!$row)
{
- trigger_error($user->lang['NO_BOT'] . adm_back_link($this->u_action . "&amp;id=$bot_id&amp;action=$action"));
+ trigger_error($user->lang['NO_BOT'] . adm_back_link($this->u_action . "&amp;id=$bot_id&amp;action=$action"), E_USER_WARNING);
}
$sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array(
@@ -237,7 +243,7 @@ class acp_bots
if (!$bot_row)
{
- trigger_error($user->lang['NO_BOT'] . adm_back_link($this->u_action . "&amp;id=$bot_id&amp;action=$action"));
+ trigger_error($user->lang['NO_BOT'] . adm_back_link($this->u_action . "&amp;id=$bot_id&amp;action=$action"), E_USER_WARNING);
}
$bot_row['bot_lang'] = $bot_row['user_lang'];
diff --git a/phpBB/includes/acp/acp_captcha.php b/phpBB/includes/acp/acp_captcha.php
index 3ac354004a..7cef658e93 100644
--- a/phpBB/includes/acp/acp_captcha.php
+++ b/phpBB/includes/acp/acp_captcha.php
@@ -21,91 +21,37 @@ class acp_captcha
$user->add_lang('acp/board');
- $config_vars = array('enable_confirm' => 'REG_ENABLE',
- 'enable_post_confirm' => 'POST_ENABLE',
- 'policy_overlap' => 'OVERLAP_ENABLE',
- 'policy_overlap_noise_pixel' => 'OVERLAP_NOISE_PIXEL',
- 'policy_overlap_noise_line' => 'OVERLAP_NOISE_LINE_ENABLE',
- 'policy_entropy' => 'ENTROPY_ENABLE',
- 'policy_entropy_noise_pixel' => 'ENTROPY_NOISE_PIXEL',
- 'policy_entropy_noise_line' => 'ENTROPY_NOISE_LINE_ENABLE',
- 'policy_shape' => 'SHAPE_ENABLE',
- 'policy_shape_noise_pixel' => 'SHAPE_NOISE_PIXEL',
- 'policy_shape_noise_line' => 'SHAPE_NOISE_LINE_ENABLE',
- 'policy_3dbitmap' => 'THREEDBITMAP_ENABLE',
- 'policy_cells' => 'CELLS_ENABLE',
- 'policy_stencil' => 'STENCIL_ENABLE',
- 'policy_composite' => 'COMPOSITE_ENABLE'
- );
-
- $policy_modules = array('policy_entropy', 'policy_3dbitmap', 'policy_overlap', 'policy_shape', 'policy_cells', 'policy_stencil', 'policy_composite');
-
- switch ($mode)
+ $config_vars = array(
+ 'enable_confirm' => 'REG_ENABLE',
+ 'enable_post_confirm' => 'POST_ENABLE',
+ 'captcha_gd' => 'CAPTCHA_GD',
+ 'captcha_gd_noise' => 'CAPTCHA_GD_NOISE',
+ );
+
+ $this->tpl_name = 'acp_captcha';
+ $this->page_title = 'ACP_VC_SETTINGS';
+ $submit = request_var('submit', '');
+ if ($submit)
{
- case 'visual':
- $this->tpl_name = 'acp_captcha';
- $this->page_title = 'ACP_VC_SETTINGS';
- $submit = request_var('submit', '');
- if ($submit)
- {
- $config_vars = array_keys($config_vars);
- foreach ($config_vars as $config_var)
- {
- set_config($config_var, request_var($config_var, ''));
- }
- trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action));
- }
- else
- {
- $array = array();
-
- foreach ($config_vars as $config_var => $template_var)
- {
- $array[$template_var] = $config[$config_var];
- }
- $template->assign_vars($array);
-
-
- if (@extension_loaded('gd'))
- {
- $template->assign_var('GD', true);
- foreach ($policy_modules as $module_name)
- {
- $template->assign_var('U_' . strtoupper($module_name), sprintf($user->lang['CAPTCHA_EXPLAIN'], '<a href="' . append_sid("{$phpbb_root_path}adm/index.$phpEx", 'i=captcha&amp;mode=img&amp;policy=' . $module_name) . '" target="_blank">', '</a>'));
- }
- if (function_exists('imagettfbbox') && function_exists('imagettftext'))
- {
- $template->assign_var('TTF', true);
- }
- }
- }
- break;
-
- case 'img':
- $policy = request_var('policy', '');
-
- if (!@extension_loaded('gd'))
- {
- trigger_error($user->lang['NO_GD']);
- }
-
- if (!($policy === 'policy_entropy' || $policy === 'policy_3dbitmap') && (!function_exists('imagettfbbox') || !function_exists('imagettftext')))
- {
- trigger_error($user->lang['NO_TTF']);
- }
-
- if (!in_array($policy, $policy_modules))
- {
- trigger_error($user->lang['BAD_POLICY']);
- }
-
- $user->add_lang('ucp');
-
- include($phpbb_root_path . 'includes/captcha/captcha_gd.' . $phpEx);
-
- $captcha = new captcha();
- $captcha->execute(gen_rand_string(), $policy);
- break;
+ $config_vars = array_keys($config_vars);
+ foreach ($config_vars as $config_var)
+ {
+ set_config($config_var, request_var($config_var, ''));
+ }
+ trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action));
+ }
+ else
+ {
+ $array = array();
+
+ if (@extension_loaded('gd') && function_exists('imagettfbbox') && function_exists('imagettftext'))
+ {
+ $template->assign_var('GD', true);
+ }
+ foreach ($config_vars as $config_var => $template_var)
+ {
+ $template->assign_var($template_var, $config[$config_var]);
+ }
}
}
}
diff --git a/phpBB/includes/acp/acp_database.php b/phpBB/includes/acp/acp_database.php
index 59ccb342fd..cbd654fbcc 100644
--- a/phpBB/includes/acp/acp_database.php
+++ b/phpBB/includes/acp/acp_database.php
@@ -68,7 +68,9 @@ class acp_database
@set_time_limit(1200);
- $filename = 'backup_' . time();
+ $time = time();
+
+ $filename = 'backup_' . $time;
// We set up the info needed for our on-the-fly creation :D
switch ($format)
@@ -111,7 +113,7 @@ class acp_database
if (!$fp)
{
- trigger_error('Unable to write temporary file to storage folder');
+ trigger_error('Unable to write temporary file to storage folder', E_USER_ERROR);
}
}
@@ -128,10 +130,10 @@ class acp_database
$sql_data .= "#\n";
$sql_data .= "# phpBB Backup Script\n";
$sql_data .= "# Dump of tables for $table_prefix\n";
- $sql_data .= "# DATE : " . gmdate("d-m-Y H:i:s", $filename) . " GMT\n";
+ $sql_data .= "# DATE : " . gmdate("d-m-Y H:i:s", $time) . " GMT\n";
$sql_data .= "#\n";
- switch (SQL_LAYER)
+ switch ($db->sql_layer)
{
case 'sqlite':
$sql_data .= "BEGIN TRANSACTION;\n";
@@ -149,12 +151,37 @@ class acp_database
break;
}
+ if ($structure && $db->sql_layer == 'firebird')
+ {
+ $sql = 'SELECT RDB$FUNCTION_NAME, RDB$DESCRIPTION
+ FROM RDB$FUNCTIONS
+ ORDER BY RDB$FUNCTION_NAME';
+ $result = $db->sql_query($sql);
+
+ $rows = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $sql = 'SELECT F.RDB$FUNCTION_NAME, F.RDB$MODULE_NAME, F.RDB$ENTRYPOINT, F.RDB$RETURN_ARGUMENT, F.RDB$DESCRIPTION, FA.RDB$ARGUMENT_POSITION, FA.RDB$MECHANISM, FA.RDB$FIELD_TYPE, FA.RDB$FIELD_SCALE, FA.RDB$FIELD_LENGTH, FA.RDB$FIELD_SUB_TYPE, C.RDB$BYTES_PER_CHARACTER, C.RDB$CHARACTER_SET_NAME ,FA.RDB$FIELD_PRECISION
+ FROM RDB$FUNCTIONS F
+ LEFT JOIN RDB$FUNCTION_ARGUMENTS FA ON F.RDB$FUNCTION_NAME = FA.RDB$FUNCTION_NAME
+ LEFT JOIN RDB$CHARACTER_SETS C ON FA.RDB$CHARACTER_SET_ID = C.RDB$CHARACTER_SET_ID
+ WHERE (F.RDB$FUNCTION_NAME = ' . $row['FUNCTION_NAME'] . ')
+ ORDER BY FA.RDB$ARGUMENT_POSITION';
+ $result2 = $db->sql_query($sql);
+ while ($row2 = $db->sql_fetchrow($result2))
+ {
+ }
+ $db->sql_freeresult($result2);
+ }
+ $db->sql_freeresult($result);
+ }
+
foreach ($table as $table_name)
{
// Get the table structure
if ($structure)
{
- switch (SQL_LAYER)
+ switch ($db->sql_layer)
{
case 'mysqli':
case 'mysql4':
@@ -197,27 +224,12 @@ class acp_database
}
$sql_data .= $this->get_table_structure($table_name);
}
- // We might wanna empty out all that junk :D
else
{
- switch (SQL_LAYER)
- {
- case 'mysqli':
- case 'mysql4':
- case 'mysql':
- case 'mssql':
- case 'mssql_odbc':
- case 'oracle':
- case 'postgres':
- case 'firebird':
- $sql_data .= 'TRUNCATE TABLE ' . $table_name . ";\n";
- break;
-
- case 'sqlite':
- $sql_data .= 'DELETE FROM ' . $table_name . ";\n";
- break;
- }
+ // We might wanna empty out all that junk :D
+ $sql_data .= (($db->sql_layer == 'sqlite') ? 'DELETE FROM ' : 'TRUNCATE TABLE ') . $table_name . ";\n";
}
+
// Now write the data for the first time. :)
if ($store == true)
{
@@ -243,7 +255,7 @@ class acp_database
{
$sql_data .= "\n";
- switch (SQL_LAYER)
+ switch ($db->sql_layer)
{
case 'mysqli':
@@ -263,8 +275,8 @@ class acp_database
$field_set[$j] = $field[$j]->name;
}
- $search = array('\\', "'", "\x00", "\x0a", "\x0d", "\x1a");
- $replace = array('\\\\\\\\', "''", '\0', '\n', '\r', '\Z');
+ $search = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"');
+ $replace = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"');
$fields = implode(', ', $field_set);
$values = array();
$schema_insert = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES (';
@@ -336,8 +348,8 @@ class acp_database
$field_set[$j] = $field[$j]->name;
}
- $search = array('\\', "'", "\x00", "\x0a", "\x0d", "\x1a");
- $replace = array('\\\\\\\\', "''", '\0', '\n', '\r', '\Z');
+ $search = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"');
+ $replace = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"');
$fields = implode(', ', $field_set);
$schema_insert = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES (';
@@ -406,7 +418,7 @@ class acp_database
$column_list = array();
$table_cols = explode(',', trim($matches[1]));
- foreach($table_cols as $declaration)
+ foreach ($table_cols as $declaration)
{
$entities = preg_split('#\s+#', trim($declaration));
$column_name = preg_replace('/"?([^"]+)"?/', '\1', $entities[0]);
@@ -442,7 +454,7 @@ class acp_database
{
$row_data = "''";
}
- else if (strpos($col_types[$row_name], 'text') !== false || strpos($col_types[$row_name], 'char') !== false)
+ else if (strpos($col_types[$row_name], 'text') !== false || strpos($col_types[$row_name], 'char') !== false || strpos($col_types[$row_name], 'blob') !== false)
{
$row_data = "'" . $row_data . "'";
}
@@ -516,7 +528,7 @@ class acp_database
{
$str_val = $row[$ary_name[$i]];
- if (preg_match('#char|text|bool#i', $ary_type[$i]))
+ if (preg_match('#char|text|bool|bytea#i', $ary_type[$i]))
{
$str_quote = "'";
$str_empty = '';
@@ -637,7 +649,7 @@ class acp_database
{
$str_val = $row[$ary_name[$i]];
- if (preg_match('#char|text|bool#i', $ary_type[$i]))
+ if (preg_match('#char|text|bool|varbinary#i', $ary_type[$i]))
{
$str_quote = "'";
$str_empty = '';
@@ -748,7 +760,7 @@ class acp_database
{
$str_val = $row[$ary_name[$i]];
- if (preg_match('#char|text|bool#i', $ary_type[$i]))
+ if (preg_match('#char|text|bool|varbinary#i', $ary_type[$i]))
{
$str_quote = "'";
$str_empty = '';
@@ -843,7 +855,7 @@ class acp_database
{
$str_val = $row[strtolower($ary_name[$i])];
- if (preg_match('#char|text|bool#i', $ary_type[$i]))
+ if (preg_match('#char|text|bool|varbinary#i', $ary_type[$i]))
{
$str_quote = "'";
$str_empty = '';
@@ -927,7 +939,7 @@ class acp_database
{
$str_val = $row[$ary_name[$i]];
- if (preg_match('#char|text|bool#i', $ary_type[$i]))
+ if (preg_match('#char|text|bool|raw#i', $ary_type[$i]))
{
$str_quote = "'";
$str_empty = '';
@@ -989,7 +1001,7 @@ class acp_database
}
}
- switch (SQL_LAYER)
+ switch ($db->sql_layer)
{
case 'sqlite':
case 'postgres':
@@ -1024,12 +1036,12 @@ class acp_database
unset($sql_data);
add_log('admin', 'LOG_DB_BACKUP');
- trigger_error($user->lang['BACKUP_SUCCESS']);
+ trigger_error($user->lang['BACKUP_SUCCESS'] . adm_back_link($this->u_action));
break;
default:
$tables = array();
- switch (SQL_LAYER)
+ switch ($db->sql_layer)
{
case 'sqlite':
$sql = "SELECT name
@@ -1167,13 +1179,13 @@ class acp_database
if (!(file_exists($file_name) && is_readable($file_name)))
{
- trigger_error($user->lang['BACKUP_INVALID']);
+ trigger_error($user->lang['BACKUP_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
}
if ($delete)
{
unlink($file_name);
- trigger_error($user->lang['BACKUP_DELETE']);
+ trigger_error($user->lang['BACKUP_DELETE'] . adm_back_link($this->u_action));
}
$data = file_get_contents($file_name);
@@ -1220,13 +1232,13 @@ class acp_database
remove_remarks($data);
// SQLite gets improved performance when you shove all of these disk write queries at once :D
- if (SQL_LAYER == 'sqlite')
+ if ($db->sql_layer == 'sqlite')
{
$db->sql_query($data);
}
else
{
- switch (SQL_LAYER)
+ switch ($db->sql_layer)
{
case 'firebird':
$delim = ';;';
@@ -1263,7 +1275,7 @@ class acp_database
}
}
add_log('admin', 'LOG_DB_RESTORE');
- trigger_error($user->lang['RESTORE_SUCCESS']);
+ trigger_error($user->lang['RESTORE_SUCCESS'] . adm_back_link($this->u_action));
break;
default:
@@ -1324,7 +1336,7 @@ class acp_database
$sql_data = '';
- switch (SQL_LAYER)
+ switch ($db->sql_layer)
{
case 'mysqli':
case 'mysql4':
@@ -1370,11 +1382,22 @@ class acp_database
{
$kname = $row['Key_name'];
- if ($kname != 'PRIMARY' && $row['Non_unique'] == 0)
+ if ($kname != 'PRIMARY')
{
- $kname = "UNIQUE|$kname";
+ if ($row['Index_type'] == 'FULLTEXT')
+ {
+ $kname = "FULLTEXT|$kname";
+ }
+ else if ($row['Non_unique'] == 0)
+ {
+ $kname = "UNIQUE|$kname";
+ }
}
+ if ($row['Sub_part'])
+ {
+ $row['Column_name'] .= '(' . $row['Sub_part'] . ')';
+ }
$index[$kname][] = $row['Column_name'];
}
$db->sql_freeresult($result);
@@ -1391,6 +1414,10 @@ class acp_database
{
$line .= 'UNIQUE ' . substr($key, 7) . ' (' . implode(', ', $columns) . ')';
}
+ else if (strpos($key, 'FULLTEXT') === 0)
+ {
+ $line .= 'FULLTEXT ' . substr($key, 9) . ' (' . implode(', ', $columns) . ')';
+ }
else
{
$line .= "KEY $key (" . implode(', ', $columns) . ')';
diff --git a/phpBB/includes/acp/acp_disallow.php b/phpBB/includes/acp/acp_disallow.php
index 1fdc2f8551..adb7270332 100644
--- a/phpBB/includes/acp/acp_disallow.php
+++ b/phpBB/includes/acp/acp_disallow.php
@@ -37,12 +37,14 @@ class acp_disallow
if (!$disallowed_user)
{
- trigger_error($user->lang['NO_USERNAME_SPECIFIED'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_USERNAME_SPECIFIED'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$sql = 'INSERT INTO ' . DISALLOW_TABLE . ' ' . $db->sql_build_array('INSERT', array('disallow_username' => $disallowed_user));
$db->sql_query($sql);
+ $cache->destroy('disallowed_usernames');
+
$message = $user->lang['DISALLOW_SUCCESSFUL'];
add_log('admin', 'LOG_DISALLOW_ADD', str_replace('%', '*', $disallowed_user));
@@ -54,16 +56,18 @@ class acp_disallow
if (!$disallowed_id)
{
- trigger_error($user->lang['NO_USERNAME_SPECIFIED'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_USERNAME_SPECIFIED'] . adm_back_link($this->u_action), E_USER_WARNING);
}
- $sql = 'DELETE FROM ' . DISALLOW_TABLE . "
- WHERE disallow_id = $disallowed_id";
+ $sql = 'DELETE FROM ' . DISALLOW_TABLE . '
+ WHERE disallow_id = ' . $disallowed_id;
$db->sql_query($sql);
+ $cache->destroy('disallowed_usernames');
+
add_log('admin', 'LOG_DISALLOW_DELETE');
- trigger_error($user->lang['DISALLOWED_DELETED'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['DISALLOWED_DELETED'] . adm_back_link($this->u_action), E_USER_WARNING);
}
// Grab the current list of disallowed usernames...
diff --git a/phpBB/includes/acp/acp_email.php b/phpBB/includes/acp/acp_email.php
index c20640bd54..5b79451634 100644
--- a/phpBB/includes/acp/acp_email.php
+++ b/phpBB/includes/acp/acp_email.php
@@ -28,7 +28,7 @@ class acp_email
$submit = (isset($_POST['submit'])) ? true : false;
$error = array();
- $usernames = request_var('usernames', '');
+ $usernames = request_var('usernames', '', true);
$group_id = request_var('g', 0);
$subject = request_var('subject', '', true);
$message = request_var('message', '', true);
@@ -57,7 +57,7 @@ class acp_email
{
$sql = 'SELECT username, user_email, user_jabber, user_notify_type, user_lang
FROM ' . USERS_TABLE . '
- WHERE ' . $db->sql_in_set('username', explode("\n", $usernames)) . '
+ WHERE ' . $db->sql_in_set('username_clean', array_map('utf8_clean_string', explode("\n", $usernames))) . '
AND user_allow_massemail = 1
ORDER BY user_lang, user_notify_type'; // , SUBSTRING(user_email FROM INSTR(user_email, '@'))
}
@@ -87,7 +87,7 @@ class acp_email
if (!$row)
{
$db->sql_freeresult($result);
- trigger_error($user->lang['NO_USER'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_USER'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$i = $j = 0;
@@ -150,15 +150,13 @@ class acp_email
$messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']);
$messenger->headers('X-AntiAbuse: User IP - ' . $user->ip);
- $messenger->subject(html_entity_decode($subject));
+ $messenger->subject(htmlspecialchars_decode($subject));
$messenger->replyto($config['board_email']);
$messenger->set_mail_priority($priority);
$messenger->assign_vars(array(
- 'SITENAME' => $config['sitename'],
'CONTACT_EMAIL' => $config['board_contact'],
- 'EMAIL_SIG' => str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']),
- 'MESSAGE' => html_entity_decode($message))
+ 'MESSAGE' => htmlspecialchars_decode($message))
);
if (!($messenger->send($used_method)))
@@ -185,12 +183,13 @@ class acp_email
if (!$errored)
{
$message = ($use_queue) ? $user->lang['EMAIL_SENT_QUEUE'] : $user->lang['EMAIL_SENT'];
+ trigger_error($message . adm_back_link($this->u_action));
}
else
{
$message = sprintf($user->lang['EMAIL_SEND_ERROR'], '<a href="' . append_sid("{$phpbb_admin_path}index.$phpEx", 'i=logs&amp;mode=critical') . '">', '</a>');
+ trigger_error($message . adm_back_link($this->u_action), E_USER_WARNING);
}
- trigger_error($message . adm_back_link($this->u_action));
}
}
@@ -216,6 +215,7 @@ class acp_email
'S_GROUP_OPTIONS' => $select_list,
'USERNAMES' => $usernames,
'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&amp;form=acp_email&amp;field=usernames'),
+ 'UA_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=acp_email&field=usernames', false),
'SUBJECT' => $subject,
'MESSAGE' => $message,
'S_PRIORITY_OPTIONS' => $s_priority_options)
diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php
index 5964a285e7..7f4dde7211 100644
--- a/phpBB/includes/acp/acp_forums.php
+++ b/phpBB/includes/acp/acp_forums.php
@@ -36,11 +36,19 @@ class acp_forums
// Check additional permissions
switch ($action)
{
+ case 'progress_bar':
+ $start = request_var('start', 0);
+ $total = request_var('total', 0);
+
+ $this->display_progress_bar($start, $total);
+ exit;
+ break;
+
case 'delete':
if (!$auth->acl_get('a_forumdel'))
{
- trigger_error($user->lang['NO_PERMISSION_FORUM_DELETE'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id));
+ trigger_error($user->lang['NO_PERMISSION_FORUM_DELETE'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
}
break;
@@ -49,7 +57,7 @@ class acp_forums
if (!$auth->acl_get('a_forumadd'))
{
- trigger_error($user->lang['NO_PERMISSION_FORUM_ADD'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id));
+ trigger_error($user->lang['NO_PERMISSION_FORUM_ADD'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
}
break;
@@ -94,23 +102,24 @@ class acp_forums
'forum_type' => request_var('forum_type', FORUM_POST),
'type_action' => request_var('type_action', ''),
'forum_status' => request_var('forum_status', ITEM_UNLOCKED),
+ 'forum_parents' => '',
'forum_name' => request_var('forum_name', '', true),
'forum_link' => request_var('forum_link', ''),
'forum_link_track' => request_var('forum_link_track', false),
'forum_desc' => request_var('forum_desc', '', true),
'forum_desc_uid' => '',
- 'forum_desc_options' => 0,
+ 'forum_desc_options' => 7,
'forum_desc_bitfield' => '',
'forum_rules' => request_var('forum_rules', '', true),
'forum_rules_uid' => '',
- 'forum_rules_options' => 0,
+ 'forum_rules_options' => 7,
'forum_rules_bitfield' => '',
'forum_rules_link' => request_var('forum_rules_link', ''),
'forum_image' => request_var('forum_image', ''),
'forum_style' => request_var('forum_style', 0),
'display_on_index' => request_var('display_on_index', false),
'forum_topics_per_page' => request_var('topics_per_page', 0),
- 'enable_indexing' => request_var('enable_indexing',true),
+ 'enable_indexing' => request_var('enable_indexing', true),
'enable_icons' => request_var('enable_icons', false),
'enable_prune' => request_var('enable_prune', false),
'enable_post_review' => request_var('enable_post_review', true),
@@ -202,34 +211,8 @@ class acp_forums
$db->sql_freeresult($result);
// Now insert the data
- switch (SQL_LAYER)
- {
- case 'mysql':
- case 'mysql4':
- case 'mysqli':
- if (sizeof($users_sql_ary))
- {
- $db->sql_query('INSERT INTO ' . ACL_USERS_TABLE . ' ' . $db->sql_build_array('MULTI_INSERT', $users_sql_ary));
- }
-
- if (sizeof($groups_sql_ary))
- {
- $db->sql_query('INSERT INTO ' . ACL_GROUPS_TABLE . ' ' . $db->sql_build_array('MULTI_INSERT', $groups_sql_ary));
- }
- break;
-
- default:
- foreach ($users_sql_ary as $ary)
- {
- $db->sql_query('INSERT INTO ' . ACL_USERS_TABLE . ' ' . $db->sql_build_array('INSERT', $ary));
- }
-
- foreach ($groups_sql_ary as $ary)
- {
- $db->sql_query('INSERT INTO ' . ACL_GROUPS_TABLE . ' ' . $db->sql_build_array('INSERT', $ary));
- }
- break;
- }
+ $db->sql_multi_insert(ACL_USERS_TABLE, $users_sql_ary);
+ $db->sql_multi_insert(ACL_GROUPS_TABLE, $groups_sql_ary);
}
$auth->acl_clear_prefetch();
@@ -265,7 +248,7 @@ class acp_forums
if (!$forum_id)
{
- trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id));
+ trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
}
$sql = 'SELECT *
@@ -277,7 +260,7 @@ class acp_forums
if (!$row)
{
- trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id));
+ trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
}
$move_forum_name = $this->move_forum_by($row, $action, 1);
@@ -293,7 +276,7 @@ class acp_forums
case 'sync':
if (!$forum_id)
{
- trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id));
+ trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
}
$sql = 'SELECT forum_name, forum_type
@@ -305,10 +288,76 @@ class acp_forums
if (!$row)
{
- trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id));
+ trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
+ }
+
+ sync('forum', 'forum_id', $forum_id, false, true);
+ $cache->destroy('sql', FORUMS_TABLE);
+
+ $url = $this->u_action . "&amp;parent_id={$this->parent_id}&amp;f=$forum_id&amp;action=sync_topic";
+ meta_refresh(0, $url);
+
+ $sql = 'SELECT forum_topics_real
+ FROM ' . FORUMS_TABLE . "
+ WHERE forum_id = $forum_id";
+ $result = $db->sql_query($sql);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ $template->assign_vars(array(
+ 'U_PROGRESS_BAR' => $this->u_action . '&amp;action=progress_bar',
+ 'UA_PROGRESS_BAR' => str_replace('&amp;', '&', $this->u_action) . '&action=progress_bar',
+ 'S_CONTINUE_SYNC' => true,
+ 'L_PROGRESS_EXPLAIN' => sprintf($user->lang['SYNC_IN_PROGRESS_EXPLAIN'], 0, $row['forum_topics_real']))
+ );
+
+// add_log('admin', 'LOG_FORUM_SYNC', $row['forum_name']);
+
+ return;
+
+ break;
+
+ case 'sync_topic':
+
+ @set_time_limit(0);
+
+ $sql = 'SELECT forum_name, forum_topics_real
+ FROM ' . FORUMS_TABLE . "
+ WHERE forum_id = $forum_id";
+ $result = $db->sql_query($sql);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ if ($row['forum_topics_real'])
+ {
+ $start = request_var('start', 0);
+
+ $batch_size = 3000;
+ $end = $start + $batch_size;
+
+ // Sync all topics in batch mode...
+ sync('topic_approved', 'range', 'topic_id BETWEEN ' . $start . ' AND ' . $end, true, false);
+ sync('topic', 'range', 'topic_id BETWEEN ' . $start . ' AND ' . $end, true, true);
+
+ if ($end < $row['forum_topics_real'])
+ {
+ $start += $batch_size;
+
+ $url = $this->u_action . "&amp;parent_id={$this->parent_id}&amp;f=$forum_id&amp;action=sync_topic&amp;start=$start&amp;total={$row['forum_topics_real']}";
+
+ meta_refresh(0, $url);
+
+ $template->assign_vars(array(
+ 'U_PROGRESS_BAR' => $this->u_action . "&amp;action=progress_bar&amp;start=$start&amp;total={$row['forum_topics_real']}",
+ 'UA_PROGRESS_BAR' => str_replace('&amp;', '&', $this->u_action) . "&action=progress_bar&start=$start&total={$row['forum_topics_real']}",
+ 'S_CONTINUE_SYNC' => true,
+ 'L_PROGRESS_EXPLAIN' => sprintf($user->lang['SYNC_IN_PROGRESS_EXPLAIN'], $start, $row['forum_topics_real']))
+ );
+
+ return;
+ }
}
- sync('forum', 'forum_id', $forum_id);
add_log('admin', 'LOG_FORUM_SYNC', $row['forum_name']);
$cache->destroy('sql', FORUMS_TABLE);
@@ -322,12 +371,12 @@ class acp_forums
if ($update)
{
$forum_data['forum_flags'] = 0;
- $forum_data['forum_flags'] += (request_var('forum_link_track', false)) ? 1 : 0;
- $forum_data['forum_flags'] += (request_var('prune_old_polls', false)) ? 2 : 0;
- $forum_data['forum_flags'] += (request_var('prune_announce', false)) ? 4 : 0;
- $forum_data['forum_flags'] += (request_var('prune_sticky', false)) ? 8 : 0;
- $forum_data['forum_flags'] += ($forum_data['show_active']) ? 16 : 0;
- $forum_data['forum_flags'] += (request_var('enable_post_review', true)) ? 32 : 0;
+ $forum_data['forum_flags'] += (request_var('forum_link_track', false)) ? FORUM_FLAG_LINK_TRACK : 0;
+ $forum_data['forum_flags'] += (request_var('prune_old_polls', false)) ? FORUM_FLAG_PRUNE_POLL : 0;
+ $forum_data['forum_flags'] += (request_var('prune_announce', false)) ? FORUM_FLAG_PRUNE_ANNOUNCE : 0;
+ $forum_data['forum_flags'] += (request_var('prune_sticky', false)) ? FORUM_FLAG_PRUNE_STICKY : 0;
+ $forum_data['forum_flags'] += ($forum_data['show_active']) ? FORUM_FLAG_ACTIVE_TOPICS : 0;
+ $forum_data['forum_flags'] += (request_var('enable_post_review', true)) ? FORUM_FLAG_POST_REVIEW : 0;
}
// Show form to create/modify a forum
@@ -389,7 +438,7 @@ class acp_forums
'prune_days' => 7,
'prune_viewed' => 7,
'prune_freq' => 1,
- 'forum_flags' => 0,
+ 'forum_flags' => FORUM_FLAG_POST_REVIEW,
'forum_password' => '',
'forum_password_confirm'=> '',
);
@@ -543,12 +592,12 @@ class acp_forums
'S_TOPIC_ICONS' => ($forum_data['enable_icons']) ? true : false,
'S_DISPLAY_ON_INDEX' => ($forum_data['display_on_index']) ? true : false,
'S_PRUNE_ENABLE' => ($forum_data['enable_prune']) ? true : false,
- 'S_FORUM_LINK_TRACK' => ($forum_data['forum_flags'] & 1) ? true : false,
- 'S_PRUNE_OLD_POLLS' => ($forum_data['forum_flags'] & 2) ? true : false,
- 'S_PRUNE_ANNOUNCE' => ($forum_data['forum_flags'] & 4) ? true : false,
- 'S_PRUNE_STICKY' => ($forum_data['forum_flags'] & 8) ? true : false,
- 'S_DISPLAY_ACTIVE_TOPICS' => ($forum_data['forum_flags'] & 16) ? true : false,
- 'S_ENABLE_POST_REVIEW' => ($forum_data['forum_flags'] & 32) ? true : false,
+ 'S_FORUM_LINK_TRACK' => ($forum_data['forum_flags'] & FORUM_FLAG_LINK_TRACK) ? true : false,
+ 'S_PRUNE_OLD_POLLS' => ($forum_data['forum_flags'] & FORUM_FLAG_PRUNE_POLL) ? true : false,
+ 'S_PRUNE_ANNOUNCE' => ($forum_data['forum_flags'] & FORUM_FLAG_PRUNE_ANNOUNCE) ? true : false,
+ 'S_PRUNE_STICKY' => ($forum_data['forum_flags'] & FORUM_FLAG_PRUNE_STICKY) ? true : false,
+ 'S_DISPLAY_ACTIVE_TOPICS' => ($forum_data['forum_flags'] & FORUM_FLAG_ACTIVE_TOPICS) ? true : false,
+ 'S_ENABLE_POST_REVIEW' => ($forum_data['forum_flags'] & FORUM_FLAG_POST_REVIEW) ? true : false,
)
);
@@ -560,7 +609,7 @@ class acp_forums
if (!$forum_id)
{
- trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id));
+ trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
}
$forum_data = $this->get_forum_info($forum_id);
@@ -634,7 +683,7 @@ class acp_forums
// Jumpbox
$forum_box = make_forum_select($this->parent_id, false, false, false, false); //make_forum_select($this->parent_id);
- if ($action == 'sync')
+ if ($action == 'sync' || $action == 'sync_topic')
{
$template->assign_var('S_RESYNCED', true);
}
@@ -677,6 +726,8 @@ class acp_forums
$template->assign_block_vars('forums', array(
'FOLDER_IMAGE' => $folder_image,
+ 'FORUM_IMAGE' => ($row['forum_image']) ? '<img src="' . $phpbb_root_path . $row['forum_image'] . '" alt="" />' : '',
+ 'FORUM_IMAGE_SRC' => ($row['forum_image']) ? $phpbb_root_path . $row['forum_image'] : '',
'FORUM_NAME' => $row['forum_name'],
'FORUM_DESCRIPTION' => generate_text_for_display($row['forum_desc'], $row['forum_desc_uid'], $row['forum_desc_bitfield'], $row['forum_desc_options']),
'FORUM_TOPICS' => $row['forum_topics'],
@@ -716,7 +767,10 @@ class acp_forums
'NAVIGATION' => $navigation,
'FORUM_BOX' => $forum_box,
'U_SEL_ACTION' => $this->u_action,
- 'U_ACTION' => $this->u_action . '&amp;parent_id=' . $this->parent_id)
+ 'U_ACTION' => $this->u_action . '&amp;parent_id=' . $this->parent_id,
+
+ 'U_PROGRESS_BAR' => $this->u_action . '&amp;action=progress_bar',
+ 'UA_PROGRESS_BAR' => str_replace('&amp;', '&', $this->u_action) . '&action=progress_bar')
);
}
@@ -779,12 +833,12 @@ class acp_forums
// 16 = show active topics
// 32 = enable post review
$forum_data['forum_flags'] = 0;
- $forum_data['forum_flags'] += ($forum_data['forum_link_track']) ? 1 : 0;
- $forum_data['forum_flags'] += ($forum_data['prune_old_polls']) ? 2 : 0;
- $forum_data['forum_flags'] += ($forum_data['prune_announce']) ? 4 : 0;
- $forum_data['forum_flags'] += ($forum_data['prune_sticky']) ? 8 : 0;
- $forum_data['forum_flags'] += ($forum_data['show_active']) ? 16 : 0;
- $forum_data['forum_flags'] += ($forum_data['enable_post_review']) ? 32 : 0;
+ $forum_data['forum_flags'] += ($forum_data['forum_link_track']) ? FORUM_FLAG_LINK_TRACK : 0;
+ $forum_data['forum_flags'] += ($forum_data['prune_old_polls']) ? FORUM_FLAG_PRUNE_POLL : 0;
+ $forum_data['forum_flags'] += ($forum_data['prune_announce']) ? FORUM_FLAG_PRUNE_ANNOUNCE : 0;
+ $forum_data['forum_flags'] += ($forum_data['prune_sticky']) ? FORUM_FLAG_PRUNE_STICKY : 0;
+ $forum_data['forum_flags'] += ($forum_data['show_active']) ? FORUM_FLAG_ACTIVE_TOPICS : 0;
+ $forum_data['forum_flags'] += ($forum_data['enable_post_review']) ? FORUM_FLAG_POST_REVIEW : 0;
// Unset data that are not database fields
$forum_data_sql = $forum_data;
@@ -821,7 +875,7 @@ class acp_forums
if (!$row)
{
- trigger_error($user->lang['PARENT_NOT_EXIST'] . adm_back_link($this->u_action . '&amp;' . $this->parent_id));
+ trigger_error($user->lang['PARENT_NOT_EXIST'] . adm_back_link($this->u_action . '&amp;' . $this->parent_id), E_USER_WARNING);
}
$sql = 'UPDATE ' . FORUMS_TABLE . '
@@ -885,7 +939,8 @@ class acp_forums
return array($user->lang['NO_FORUM_ACTION']);
}
- $forum_data_sql['forum_posts'] = $forum_data_sql['forum_topics'] = $forum_data_sql['forum_topics_real'] = 0;
+ $forum_data_sql['forum_posts'] = $forum_data_sql['forum_topics'] = $forum_data_sql['forum_topics_real'] = $forum_data_sql['forum_last_post_id'] = $forum_data_sql['forum_last_poster_id'] = $forum_data_sql['forum_last_post_time'] = 0;
+ $forum_data_sql['forum_last_poster_name'] = $forum_data_sql['forum_last_poster_colour'] = '';
}
if (sizeof($errors))
@@ -1018,7 +1073,7 @@ class acp_forums
{
global $db;
- $table_ary = array(ACL_GROUPS_TABLE, ACL_USERS_TABLE, LOG_TABLE, POSTS_TABLE, TOPICS_TABLE, DRAFTS_TABLE, TOPICS_TRACK_TABLE);
+ $table_ary = array(LOG_TABLE, POSTS_TABLE, TOPICS_TABLE, DRAFTS_TABLE, TOPICS_TRACK_TABLE);
foreach ($table_ary as $table)
{
@@ -1121,6 +1176,14 @@ class acp_forums
$sql = 'DELETE FROM ' . FORUMS_TABLE . '
WHERE ' . $db->sql_in_set('forum_id', $forum_ids);
$db->sql_query($sql);
+
+ $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . '
+ WHERE ' . $db->sql_in_set('forum_id', $forum_ids);
+ $db->sql_query($sql);
+
+ $sql = 'DELETE FROM ' . ACL_USERS_TABLE . '
+ WHERE ' . $db->sql_in_set('forum_id', $forum_ids);
+ $db->sql_query($sql);
}
else if ($action_subforums == 'move')
{
@@ -1167,6 +1230,14 @@ class acp_forums
$sql = 'DELETE FROM ' . FORUMS_TABLE . "
WHERE forum_id = $forum_id";
$db->sql_query($sql);
+
+ $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . "
+ WHERE forum_id = $forum_id";
+ $db->sql_query($sql);
+
+ $sql = 'DELETE FROM ' . ACL_USERS_TABLE . "
+ WHERE forum_id = $forum_id";
+ $db->sql_query($sql);
}
}
@@ -1181,6 +1252,14 @@ class acp_forums
$sql = 'DELETE FROM ' . FORUMS_TABLE . "
WHERE forum_id = $forum_id";
$db->sql_query($sql);
+
+ $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . "
+ WHERE forum_id = $forum_id";
+ $db->sql_query($sql);
+
+ $sql = 'DELETE FROM ' . ACL_USERS_TABLE . "
+ WHERE forum_id = $forum_id";
+ $db->sql_query($sql);
}
// Resync tree
@@ -1290,7 +1369,21 @@ class acp_forums
delete_attachments('topic', $topic_ids, false);
- switch (SQL_LAYER)
+ // Before we remove anything we make sure we are able to adjust the post counts later. ;)
+ $sql = 'SELECT poster_id
+ FROM ' . POSTS_TABLE . '
+ WHERE forum_id = ' . $forum_id . '
+ AND post_postcount = 1';
+ $result = $db->sql_query($sql);
+
+ $post_counts = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $post_counts[$row['poster_id']] = (!empty($post_counts[$row['poster_id']])) ? $post_counts[$row['poster_id']] + 1 : 1;
+ }
+ $db->sql_freeresult($result);
+
+ switch ($db->sql_layer)
{
case 'mysql4':
case 'mysqli':
@@ -1365,18 +1458,18 @@ class acp_forums
foreach ($tables as $table)
{
- $db->sql_query("DELETE FROM $table WHERE " . $db->sql_in_set($field, $id_list));
+ $db->sql_query("DELETE FROM $table WHERE " . $db->sql_in_set($field, $ids));
}
}
}
while ($row);
}
- unset($ids, $id_list);
+ unset($ids);
break;
}
- $table_ary = array(ACL_GROUPS_TABLE, ACL_USERS_TABLE, FORUMS_ACCESS_TABLE, FORUMS_TRACK_TABLE, FORUMS_WATCH_TABLE, LOG_TABLE, MODERATOR_CACHE_TABLE, POSTS_TABLE, TOPICS_TABLE, TOPICS_TRACK_TABLE);
+ $table_ary = array(FORUMS_ACCESS_TABLE, FORUMS_TRACK_TABLE, FORUMS_WATCH_TABLE, LOG_TABLE, MODERATOR_CACHE_TABLE, POSTS_TABLE, TOPICS_TABLE, TOPICS_TRACK_TABLE);
foreach ($table_ary as $table)
{
@@ -1391,6 +1484,18 @@ class acp_forums
$db->sql_query("UPDATE $table SET forum_id = 0 WHERE forum_id = $forum_id");
}
+ // Adjust users post counts
+ if (sizeof($post_counts))
+ {
+ foreach ($post_counts as $poster_id => $substract)
+ {
+ $sql = 'UPDATE ' . USERS_TABLE . '
+ SET user_posts = user_posts - ' . $substract . '
+ WHERE user_id = ' . $poster_id;
+ $db->sql_query($sql);
+ }
+ }
+
$db->sql_transaction('commit');
// Make sure the overall post/topic count is correct...
@@ -1513,6 +1618,27 @@ class acp_forums
return $target['forum_name'];
}
+
+ /**
+ * Display progress bar for syncinc forums
+ */
+ function display_progress_bar($start, $total)
+ {
+ global $template, $user;
+
+ adm_page_header($user->lang['SYNC_IN_PROGRESS']);
+
+ $template->set_filenames(array(
+ 'body' => 'progress_bar.html')
+ );
+
+ $template->assign_vars(array(
+ 'L_PROGRESS' => $user->lang['SYNC_IN_PROGRESS'],
+ 'L_PROGRESS_EXPLAIN' => ($start && $total) ? sprintf($user->lang['SYNC_IN_PROGRESS_EXPLAIN'], $start, $total) : $user->lang['SYNC_IN_PROGRESS'])
+ );
+
+ adm_page_footer();
+ }
}
?> \ No newline at end of file
diff --git a/phpBB/includes/acp/acp_groups.php b/phpBB/includes/acp/acp_groups.php
index 9f7e68bfe5..9df1c52d65 100644
--- a/phpBB/includes/acp/acp_groups.php
+++ b/phpBB/includes/acp/acp_groups.php
@@ -30,7 +30,7 @@ class acp_groups
$action = (isset($_POST['add'])) ? 'add' : ((isset($_POST['addusers'])) ? 'addusers' : request_var('action', ''));
$group_id = request_var('g', 0);
$mark_ary = request_var('mark', array(0));
- $name_ary = request_var('usernames', '');
+ $name_ary = request_var('usernames', '', true);
$leader = request_var('leader', 0);
$default = request_var('default', 0);
$start = request_var('start', 0);
@@ -52,7 +52,7 @@ class acp_groups
if (!$group_row)
{
- trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING);
}
}
@@ -64,11 +64,11 @@ class acp_groups
case 'promote':
if (!$group_id)
{
- trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING);
}
// Approve, demote or promote
- group_user_attributes($action, $group_id, $mark_ary, false, ($group_id) ? $group_row['group_name'] : false);
+ group_user_attributes($action, $group_id, $mark_ary, false, $group_row['group_name']);
switch ($action)
{
@@ -85,13 +85,15 @@ class acp_groups
break;
}
+ group_update_listings($group_id);
+
trigger_error($user->lang[$message] . adm_back_link($this->u_action . '&amp;action=list&amp;g=' . $group_id));
break;
case 'default':
if (!$group_id)
{
- trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING);
}
if (confirm_box(true))
@@ -134,6 +136,8 @@ class acp_groups
group_user_attributes('default', $group_id, $mark_ary, false, $group_row['group_name'], $group_row);
}
+ group_update_listings($group_id);
+
trigger_error($user->lang['GROUP_DEFS_UPDATED'] . adm_back_link($this->u_action . '&amp;action=list&amp;g=' . $group_id));
}
else
@@ -155,7 +159,7 @@ class acp_groups
{
if (!$group_id)
{
- trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$error = '';
@@ -165,7 +169,7 @@ class acp_groups
case 'delete':
if (!$auth->acl_get('a_groupdel'))
{
- trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$error = group_delete($group_id, $group_row['group_name']);
@@ -180,7 +184,7 @@ class acp_groups
if ($error)
{
- trigger_error($user->lang[$error] . adm_back_link($back_link));
+ trigger_error($user->lang[$error] . adm_back_link($back_link), E_USER_WARNING);
}
$message = ($action == 'delete') ? 'GROUP_DELETED' : 'GROUP_USERS_REMOVE';
@@ -201,12 +205,12 @@ class acp_groups
case 'addusers':
if (!$group_id)
{
- trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING);
}
if (!$name_ary)
{
- trigger_error($user->lang['NO_USERS'] . adm_back_link($this->u_action . '&amp;action=list&amp;g=' . $group_id));
+ trigger_error($user->lang['NO_USERS'] . adm_back_link($this->u_action . '&amp;action=list&amp;g=' . $group_id), E_USER_WARNING);
}
$name_ary = array_unique(explode("\n", $name_ary));
@@ -214,10 +218,10 @@ class acp_groups
// Add user/s to group
if ($error = group_user_add($group_id, false, $name_ary, $group_row['group_name'], $default, $leader, 0, $group_row))
{
- trigger_error($user->lang[$error] . adm_back_link($this->u_action . '&amp;action=list&amp;g=' . $group_id));
+ trigger_error($user->lang[$error] . adm_back_link($this->u_action . '&amp;action=list&amp;g=' . $group_id), E_USER_WARNING);
}
- $message = ($action == 'addleaders') ? 'GROUP_MODS_ADDED' : 'GROUP_USERS_ADDED';
+ $message = ($leader) ? 'GROUP_MODS_ADDED' : 'GROUP_USERS_ADDED';
trigger_error($user->lang[$message] . adm_back_link($this->u_action . '&amp;action=list&amp;g=' . $group_id));
break;
@@ -228,12 +232,12 @@ class acp_groups
if ($action == 'edit' && !$group_id)
{
- trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING);
}
if ($action == 'add' && !$auth->acl_get('a_groupadd'))
{
- trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$error = array();
@@ -313,7 +317,7 @@ class acp_groups
{
if (isset($group_row['group_avatar']) && $group_row['group_avatar'])
{
- avatar_delete($group_row['group_avatar']);
+ avatar_delete('group', $group_row);
}
}
@@ -364,24 +368,7 @@ class acp_groups
$db->sql_freeresult($result);
// Now insert the data
- if (sizeof($groups_sql_ary))
- {
- switch (SQL_LAYER)
- {
- case 'mysql':
- case 'mysql4':
- case 'mysqli':
- $db->sql_query('INSERT INTO ' . ACL_GROUPS_TABLE . ' ' . $db->sql_build_array('MULTI_INSERT', $groups_sql_ary));
- break;
-
- default:
- foreach ($groups_sql_ary as $ary)
- {
- $db->sql_query('INSERT INTO ' . ACL_GROUPS_TABLE . ' ' . $db->sql_build_array('INSERT', $ary));
- }
- break;
- }
- }
+ $db->sql_multi_insert(ACL_GROUPS_TABLE, $groups_sql_ary);
$auth->acl_clear_prefetch();
}
@@ -542,7 +529,7 @@ class acp_groups
if (!$group_id)
{
- trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$this->page_title = 'GROUP_MEMBERS';
@@ -614,6 +601,7 @@ class acp_groups
'U_ACTION' => $this->u_action . "&amp;g=$group_id",
'U_BACK' => $this->u_action,
'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&amp;form=list&amp;field=usernames'),
+ 'UA_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=list&field=usernames', false),
'U_DEFAULT_ALL' => "{$this->u_action}&amp;action=default&amp;g=$group_id")
);
diff --git a/phpBB/includes/acp/acp_icons.php b/phpBB/includes/acp/acp_icons.php
index 66aec3a90d..4636b067c2 100644
--- a/phpBB/includes/acp/acp_icons.php
+++ b/phpBB/includes/acp/acp_icons.php
@@ -60,7 +60,7 @@ class acp_icons
if ($action == 'edit' || $action == 'add' || $action == 'import')
{
$imglist = filelist($phpbb_root_path . $img_path, '');
-
+
foreach ($imglist as $path => $img_ary)
{
foreach ($img_ary as $img)
@@ -108,6 +108,7 @@ class acp_icons
ORDER BY {$fields}_order " . (($icon_id || $action == 'add') ? 'DESC' : 'ASC');
$result = $db->sql_query($sql);
+ $data = array();
while ($row = $db->sql_fetchrow($result))
{
if ($action == 'add')
@@ -135,14 +136,13 @@ class acp_icons
}
$after_txt = ($mode == 'smilies') ? $row['code'] : $row['icons_url'];
- $order_list = '<option value="' . ($row[$fields . '_order']) . '"' . $selected . '>' . sprintf($user->lang['AFTER_' . $lang], ' -&gt; ' . htmlspecialchars($after_txt)) . '</option>' . $order_list;
+ $order_list = '<option value="' . ($row[$fields . '_order'] + 1) . '"' . $selected . '>' . sprintf($user->lang['AFTER_' . $lang], ' -&gt; ' . htmlspecialchars($after_txt)) . '</option>' . $order_list;
}
}
$db->sql_freeresult($result);
$order_list = '<option value="1"' . ((!isset($after)) ? ' selected="selected"' : '') . '>' . $user->lang['FIRST'] . '</option>' . $order_list;
- $data = array();
if ($action == 'add')
{
$data = $_images;
@@ -242,11 +242,32 @@ class acp_icons
);
}
+ // Image_order holds the 'new' order value
if (!empty($image_order[$image]))
{
$img_sql = array_merge($img_sql, array(
- $fields . '_order' => $image_order[$image] . '.5')
+ $fields . '_order' => $image_order[$image])
);
+
+ // Since we always add 'after' an item, we just need to increase all following + the current by one
+ $sql = "UPDATE $table
+ SET {$fields}_order = {$fields}_order + 1
+ WHERE {$fields}_order >= {$image_order[$image]}";
+ $db->sql_query($sql);
+
+ // If we adjust the order, we need to adjust all other orders too - they became inaccurate...
+ foreach ($image_order as $_image => $_order)
+ {
+ if ($_image == $image)
+ {
+ continue;
+ }
+
+ if ($_order >= $image_order[$image])
+ {
+ $image_order[$_image]++;
+ }
+ }
}
if ($action == 'modify')
@@ -261,45 +282,6 @@ class acp_icons
$sql = "INSERT INTO $table " . $db->sql_build_array('INSERT', $img_sql);
$db->sql_query($sql);
}
-
- $update = false;
-
- if ($action == 'modify' && !empty($image_order[$image]))
- {
- $update = true;
-
- $sql = "SELECT {$fields}_order
- FROM $table
- WHERE {$fields}_id = " . $image_id[$image];
- $result = $db->sql_query($sql);
- $order_old = (int) $db->sql_fetchfield($fields . '_order');
- $db->sql_freeresult($result);
-
- if ($order_old == $image_order[$image])
- {
- $update = false;
- }
-
- if ($order_old > $image_order[$image])
- {
- $sign = '+';
- $where = $fields . '_order >= ' . $image_order[$image] . " AND {$fields}_order < $order_old";
- }
- else if ($order_old < $image_order[$image])
- {
- $sign = '-';
- $where = "{$fields}_order > $order_old AND {$fields}_order < " . $image_order[$image];
- $sql[$fields . '_order'] = $image_order[$image] - 1;
- }
- }
-
- if ($update)
- {
- $sql = "UPDATE $table
- SET {$fields}_order = {$fields}_order $sign 1
- WHERE $where";
- $db->sql_query($sql);
- }
}
}
@@ -329,7 +311,7 @@ class acp_icons
// The user has already selected a smilies_pak file
if ($current == 'delete')
{
- $db->sql_query(((SQL_LAYER != 'sqlite') ? 'TRUNCATE TABLE ' : 'DELETE FROM ') . $table);
+ $db->sql_query((($db->sql_layer != 'sqlite') ? 'TRUNCATE TABLE ' : 'DELETE FROM ') . $table);
switch ($mode)
{
@@ -363,7 +345,7 @@ class acp_icons
if (!($pak_ary = @file($phpbb_root_path . $img_path . '/' . $pak)))
{
- trigger_error($user->lang['PAK_FILE_NOT_READABLE'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['PAK_FILE_NOT_READABLE'] . adm_back_link($this->u_action), E_USER_WARNING);
}
foreach ($pak_ary as $pak_entry)
@@ -374,7 +356,7 @@ class acp_icons
if ((sizeof($data[1]) != 4 && $mode == 'icons') ||
(sizeof($data[1]) != 6 && $mode == 'smilies'))
{
- trigger_error($user->lang['WRONG_PAK_TYPE'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['WRONG_PAK_TYPE'] . adm_back_link($this->u_action), E_USER_WARNING);
}
// Stripslash here because it got addslashed before... (on export)
@@ -523,7 +505,7 @@ class acp_icons
}
else
{
- trigger_error($user->lang['NO_' . strtoupper($fields) . '_EXPORT'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_' . strtoupper($fields) . '_EXPORT'] . adm_back_link($this->u_action), E_USER_WARNING);
}
break;
@@ -562,14 +544,40 @@ class acp_icons
case 'move_up':
case 'move_down':
- $image_order = request_var('order', 0);
- $order_total = $image_order * 2 + (($action == 'move_up') ? -1 : 1);
+ // Get current order id...
+ $sql = "SELECT {$fields}_order as current_order
+ FROM $table
+ WHERE {$fields}_id = $icon_id";
+ $result = $db->sql_query($sql);
+ $current_order = (int) $db->sql_fetchfield('current_order');
+ $db->sql_freeresult($result);
+
+ if ($current_order == 0 && $action == 'move_up')
+ {
+ break;
+ }
+
+ // on move_down, switch position with next order_id...
+ // on move_up, switch position with previous order_id...
+ $switch_order_id = ($action == 'move_down') ? $current_order + 1 : $current_order - 1;
- $sql = 'UPDATE ' . $table . '
- SET ' . $fields . "_order = $order_total - " . $fields . '_order
- WHERE ' . $fields . "_order IN ($image_order, " . (($action == 'move_up') ? $image_order - 1 : $image_order + 1) . ')';
+ //
+ $sql = "UPDATE $table
+ SET {$fields}_order = $current_order
+ WHERE {$fields}_order = $switch_order_id
+ AND {$fields}_id <> $icon_id";
$db->sql_query($sql);
+ // Only update the other entry too if the previous entry got updated
+ if ($db->sql_affectedrows())
+ {
+ $sql = "UPDATE $table
+ SET {$fields}_order = $switch_order_id
+ WHERE {$fields}_order = $current_order
+ AND {$fields}_id = $icon_id";
+ $db->sql_query($sql);
+ }
+
$cache->destroy('icons');
$cache->destroy('sql', $table);
@@ -640,8 +648,8 @@ class acp_icons
'EMOTION' => (isset($row['emotion'])) ? $row['emotion'] : '',
'U_EDIT' => $this->u_action . '&amp;action=edit&amp;id=' . $row[$fields . '_id'],
'U_DELETE' => $this->u_action . '&amp;action=delete&amp;id=' . $row[$fields . '_id'],
- 'U_MOVE_UP' => $this->u_action . '&amp;action=move_up&amp;order=' . $row[$fields . '_order'],
- 'U_MOVE_DOWN' => $this->u_action . '&amp;action=move_down&amp;order=' . $row[$fields . '_order'])
+ 'U_MOVE_UP' => $this->u_action . '&amp;action=move_up&amp;id=' . $row[$fields . '_id'],
+ 'U_MOVE_DOWN' => $this->u_action . '&amp;action=move_down&amp;id=' . $row[$fields . '_id'])
);
if (!$spacer && !$row['display_on_posting'])
diff --git a/phpBB/includes/acp/acp_inactive.php b/phpBB/includes/acp/acp_inactive.php
new file mode 100755
index 0000000000..2834d25181
--- /dev/null
+++ b/phpBB/includes/acp/acp_inactive.php
@@ -0,0 +1,184 @@
+<?php
+/**
+*
+* @package acp
+* @version $Id$
+* @copyright (c) 2006 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+/**
+* @package acp
+*/
+class acp_inactive
+{
+ var $u_action;
+ var $p_master;
+
+ function acp_inactive(&$p_master)
+ {
+ $this->p_master = &$p_master;
+ }
+
+ function main($id, $mode)
+ {
+ global $config, $db, $user, $auth, $template;
+ global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix;
+
+ $user->add_lang('memberlist');
+
+ $action = request_var('action', '');
+ $mark = (isset($_REQUEST['mark'])) ? request_var('mark', array(0)) : array();
+ $start = request_var('start', 0);
+
+ // Sort keys
+ $sort_days = request_var('st', 0);
+ $sort_key = request_var('sk', 'i');
+ $sort_dir = request_var('sd', 'd');
+
+ if (sizeof($mark))
+ {
+ switch ($action)
+ {
+ case 'activate':
+ case 'delete':
+ $sql = 'SELECT username
+ FROM ' . USERS_TABLE . '
+ WHERE ' . $db->sql_in_set('user_id', $mark);
+ $result = $db->sql_query($sql);
+
+ $user_affected = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $user_affected[] = $row['username'];
+ }
+ $db->sql_freeresult($result);
+
+ if ($action == 'activate')
+ {
+ include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx);
+ user_active_flip('activate', $mark);
+ }
+ else if ($action == 'delete')
+ {
+ if (!$auth->acl_get('a_userdel'))
+ {
+ trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
+ }
+
+ $sql = 'DELETE FROM ' . USER_GROUP_TABLE . ' WHERE ' . $db->sql_in_set('user_id', $mark);
+ $db->sql_query($sql);
+ $sql = 'DELETE FROM ' . USERS_TABLE . ' WHERE ' . $db->sql_in_set('user_id', $mark);
+ $db->sql_query($sql);
+
+ add_log('admin', 'LOG_INACTIVE_' . strtoupper($action), implode(', ', $user_affected));
+ }
+
+ break;
+
+ case 'remind':
+ if (empty($config['email_enable']))
+ {
+ trigger_error($user->lang['EMAIL_DISABLED'] . adm_back_link($this->u_action), E_USER_WARNING);
+ }
+
+ $sql = 'SELECT user_id, username, user_email, user_lang, user_jabber, user_notify_type, user_regdate, user_actkey
+ FROM ' . USERS_TABLE . '
+ WHERE ' . $db->sql_in_set('user_id', $mark);
+ $result = $db->sql_query($sql);
+
+ if ($row = $db->sql_fetchrow($result))
+ {
+ // Send the messages
+ include_once($phpbb_root_path . 'includes/functions_messenger.'.$phpEx);
+
+ $messenger = new messenger();
+
+ $board_url = generate_board_url() . "/ucp.$phpEx?mode=activate";
+
+ $usernames = array();
+ do
+ {
+ $messenger->template('user_remind_inactive', $row['user_lang']);
+
+ $messenger->replyto($config['board_email']);
+ $messenger->to($row['user_email'], $row['username']);
+ $messenger->im($row['user_jabber'], $row['username']);
+
+ $messenger->assign_vars(array(
+ 'USERNAME' => htmlspecialchars_decode($row['username']),
+ 'REGISTER_DATE' => $user->format_date($row['user_regdate']),
+ 'U_ACTIVATE' => "$board_url&mode=activate&u=" . $row['user_id'] . '&k=' . $row['user_actkey'])
+ );
+
+ $messenger->send($row['user_notify_type']);
+
+ $usernames[] = $row['username'];
+ }
+ while ($row = $db->sql_fetchrow($result));
+
+ $messenger->save_queue();
+
+ add_log('admin', 'LOG_INACTIVE_REMIND', implode(', ', $usernames));
+ unset($usernames);
+ }
+ $db->sql_freeresult($result);
+
+ break;
+ }
+ }
+
+ // Sorting
+ $limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']);
+ $sort_by_text = array('i' => $user->lang['SORT_INACTIVE'], 'j' => $user->lang['SORT_REG_DATE'], 'l' => $user->lang['SORT_LAST_VISIT'], 'r' => $user->lang['SORT_REASON'], 'u' => $user->lang['SORT_USERNAME']);
+ $sort_by_sql = array('i' => 'user_inactive_time', 'j' => 'user_regdate', 'l' => 'user_lastvisit', 'r' => 'user_inactive_reason', 'u' => 'username');
+
+ $s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = '';
+ gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param);
+
+ // Define where and sort sql for use in displaying logs
+ $sql_where = ($sort_days) ? (time() - ($sort_days * 86400)) : 0;
+ $sql_sort = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC');
+
+ $inactive = array();
+ $inactive_count = 0;
+
+ view_inactive_users($inactive, $inactive_count, $config['topics_per_page'], $start, $sql_where, $sql_sort);
+
+ foreach ($inactive as $row)
+ {
+ $template->assign_block_vars('inactive', array(
+ 'INACTIVE_DATE' => $user->format_date($row['user_inactive_time']),
+ 'JOINED' => $user->format_date($row['user_regdate']),
+ 'LAST_VISIT' => (!$row['user_lastvisit']) ? ' - ' : $user->format_date($row['user_lastvisit']),
+ 'REASON' => $row['inactive_reason'],
+ 'USER_ID' => $row['user_id'],
+ 'USERNAME' => $row['username'],
+ 'U_USER_ADMIN' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=users&amp;mode=overview&amp;u={$row['user_id']}"))
+ );
+ }
+
+ $option_ary = array('activate' => 'ACTIVATE', 'delete' => 'DELETE');
+ if ($config['email_enable'])
+ {
+ $option_ary += array('remind' => 'REMIND');
+ }
+
+ $template->assign_vars(array(
+ 'S_INACTIVE_USERS' => true,
+ 'S_INACTIVE_OPTIONS' => build_select($option_ary),
+
+ 'S_LIMIT_DAYS' => $s_limit_days,
+ 'S_SORT_KEY' => $s_sort_key,
+ 'S_SORT_DIR' => $s_sort_dir,
+ 'S_ON_PAGE' => on_page($inactive_count, $config['topics_per_page'], $start),
+ 'PAGINATION' => generate_pagination($this->u_action . "&amp;$u_sort_param", $inactive_count, $config['topics_per_page'], $start, true),
+ ));
+
+ $this->tpl_name = 'acp_inactive';
+ $this->page_title = 'ACP_INACTIVE_USERS';
+ }
+}
+
+?> \ No newline at end of file
diff --git a/phpBB/includes/acp/acp_jabber.php b/phpBB/includes/acp/acp_jabber.php
index 7c7e4586e0..afb2ba329a 100644
--- a/phpBB/includes/acp/acp_jabber.php
+++ b/phpBB/includes/acp/acp_jabber.php
@@ -44,16 +44,9 @@ class acp_jabber
$jab_resource = request_var('jab_resource', $config['jab_resource']);
$jab_package_size = request_var('jab_package_size', $config['jab_package_size']);
- $jabber = new jabber();
+ $jabber = new jabber($jab_host, $jab_port, $jab_username, $jab_password, $jab_resource);
$error = array();
- // Setup the basis vars for jabber connection
- $jabber->server = $jab_host;
- $jabber->port = ($jab_port) ? $jab_port : 5222;
- $jabber->username = $jab_username;
- $jabber->password = $jab_password;
- $jabber->resource = $jab_resource;
-
$message = $user->lang['JAB_SETTINGS_CHANGED'];
$log = 'JAB_SETTINGS_CHANGED';
@@ -65,7 +58,7 @@ class acp_jabber
{
if (!$jabber->connect())
{
- trigger_error($user->lang['ERR_JAB_CONNECT'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['ERR_JAB_CONNECT'] . adm_back_link($this->u_action), E_USER_WARNING);
}
// First we'll try to authorise using this account, if that fails we'll try to create it.
@@ -94,12 +87,12 @@ class acp_jabber
{
if (!$jabber->connect())
{
- trigger_error($user->lang['ERR_JAB_CONNECT'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['ERR_JAB_CONNECT'] . adm_back_link($this->u_action), E_USER_WARNING);
}
if (!$jabber->send_auth())
{
- trigger_error($user->lang['ERR_JAB_AUTH'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['ERR_JAB_AUTH'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$jabber->send_presence(NULL, NULL, 'online');
diff --git a/phpBB/includes/acp/acp_language.php b/phpBB/includes/acp/acp_language.php
index 29aabe240f..61310cff01 100644
--- a/phpBB/includes/acp/acp_language.php
+++ b/phpBB/includes/acp/acp_language.php
@@ -47,8 +47,10 @@ class acp_language
$missing_file = request_var('missing_file', array('' => 0));
list($_REQUEST['language_file'], ) = array_keys($missing_file);
}
-
- list($this->language_directory, $this->language_file) = explode('|', request_var('language_file', '|common.' . $phpEx));
+
+ $selected_lang_file = request_var('language_file', '|common.' . $phpEx);
+
+ list($this->language_directory, $this->language_file) = explode('|', $selected_lang_file);
$this->language_directory = basename($this->language_directory);
$this->language_file = basename($this->language_file);
@@ -76,7 +78,8 @@ class acp_language
break;
default:
- trigger_error($user->lang['INVALID_UPLOAD_METHOD']);
+ trigger_error($user->lang['INVALID_UPLOAD_METHOD'], E_USER_ERROR);
+ break;
}
$test_connection = $transfer->open_session();
@@ -124,7 +127,7 @@ class acp_language
if (!$lang_id)
{
- trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$sql = 'SELECT *
@@ -153,14 +156,14 @@ class acp_language
case 'download_file':
case 'upload_data':
- if (!$lang_id || !isset($_POST['entry']) || !is_array($_POST['entry']))
+ if (!$lang_id || empty($_POST['entry']))
{
- trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING);
}
if (!$this->language_file || (!$this->language_directory && !in_array($this->language_file, $this->main_files)))
{
- trigger_error($user->lang['NO_FILE_SELECTED'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_FILE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$sql = 'SELECT *
@@ -187,7 +190,7 @@ class acp_language
{
if (!@mkdir($dir, 0777))
{
- trigger_error("Could not create directory $dir");
+ trigger_error("Could not create directory $dir", E_USER_ERROR);
}
@chmod($dir, 0777);
}
@@ -200,7 +203,7 @@ class acp_language
if (!$fp)
{
- trigger_error($user->lang['UNABLE_TO_WRITE_FILE']);
+ trigger_error(sprintf($user->lang['UNABLE_TO_WRITE_FILE'], $filename) . adm_back_link($this->u_action . '&amp;id=' . $lang_id . '&amp;language_file=' . urlencode($selected_lang_file)), E_USER_WARNING);
}
if ($this->language_directory == 'email')
@@ -284,6 +287,8 @@ class acp_language
$file = request_var('file', '');
$dir = request_var('dir', '');
+ $selected_lang_file = $dir . '|' . $file;
+
$old_file = '/' . $this->get_filename($row['lang_iso'], $dir, $file, false, true);
$lang_path = 'language/' . $row['lang_iso'] . '/' . (($dir) ? $dir . '/' : '');
@@ -301,12 +306,13 @@ class acp_language
break;
default:
- trigger_error($user->lang['INVALID_UPLOAD_METHOD']);
+ trigger_error($user->lang['INVALID_UPLOAD_METHOD'], E_USER_ERROR);
+ break;
}
if (($result = $transfer->open_session()) !== true)
{
- trigger_error($user->lang[$result] . adm_back_link($this->u_action));
+ trigger_error($user->lang[$result] . adm_back_link($this->u_action . '&amp;action=details&amp;id=' . $lang_id . '&amp;language_file=' . urlencode($selected_lang_file)), E_USER_WARNING);
}
$transfer->rename($lang_path . $file, $lang_path . $file . '.bak');
@@ -318,7 +324,7 @@ class acp_language
add_log('admin', 'LOG_LANGUAGE_FILE_REPLACED', $file);
- trigger_error($user->lang['UPLOAD_COMPLETED']);
+ trigger_error($user->lang['UPLOAD_COMPLETED'] . adm_back_link($this->u_action . '&amp;action=details&amp;id=' . $lang_id . '&amp;language_file=' . urlencode($selected_lang_file)));
}
$action = 'details';
@@ -329,7 +335,7 @@ class acp_language
if (!$lang_id)
{
- trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$this->page_title = 'LANGUAGE_PACK_DETAILS';
@@ -362,28 +368,28 @@ class acp_language
case 'email':
if (!in_array($this->language_file, $email_files))
{
- trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&amp;action=details&amp;id=' . $lang_id));
+ trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&amp;action=details&amp;id=' . $lang_id), E_USER_WARNING);
}
break;
case 'acp':
if (!in_array($this->language_file, $acp_files))
{
- trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&amp;action=details&amp;id=' . $lang_id));
+ trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&amp;action=details&amp;id=' . $lang_id), E_USER_WARNING);
}
break;
case 'mods':
if (!in_array($this->language_file, $mods_files))
{
- trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&amp;action=details&amp;id=' . $lang_id));
+ trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&amp;action=details&amp;id=' . $lang_id), E_USER_WARNING);
}
break;
default:
if (!in_array($this->language_file, $this->main_files))
{
- trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&amp;action=details&amp;id=' . $lang_id));
+ trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&amp;action=details&amp;id=' . $lang_id), E_USER_WARNING);
}
}
@@ -491,7 +497,7 @@ class acp_language
'S_MISSING_FILES' => true,
'L_MISSING_FILES' => sprintf($user->lang['THOSE_MISSING_LANG_FILES'], $lang_entries['lang_local_name']),
'MISSING_FILES' => implode('<br />', $missing_files))
- );
+ );
}
if ($is_missing_var)
@@ -500,7 +506,7 @@ class acp_language
'S_MISSING_VARS' => true,
'L_MISSING_VARS_EXPLAIN' => sprintf($user->lang['THOSE_MISSING_LANG_VARIABLES'], $lang_entries['lang_local_name']),
'U_MISSING_ACTION' => $this->u_action . "&amp;action=$action&amp;id=$lang_id")
- );
+ );
foreach ($missing_vars as $file => $vars)
{
@@ -532,7 +538,7 @@ class acp_language
$selected = (!$this->language_directory && $this->language_file == $file) ? ' selected="selected"' : '';
$s_lang_options .= '<option value="|' . $file . '"' . $selected . '>' . $prefix . $file . '</option>';
}
-
+
// Help Files
$s_lang_options .= '<option value="|common.' . $phpEx . '" class="sep">' . $user->lang['HELP_FILES'] . '</option>';
foreach ($this->main_files as $file)
@@ -559,7 +565,7 @@ class acp_language
}
$s_lang_options .= '<option value="|common.' . $phpEx . '" class="sep">' . $user->lang[strtoupper($check) . '_FILES'] . '</option>';
-
+
foreach (${$check . '_files'} as $file)
{
$prefix = (file_exists($phpbb_root_path . $this->get_filename($lang_iso, $check, $file, true, true))) ? '* ' : '';
@@ -599,6 +605,7 @@ class acp_language
unset($help);
}
}
+
$print_message = (($this->language_directory) ? $this->language_directory . '/' : '') . $this->language_file;
}
@@ -611,7 +618,7 @@ class acp_language
'PRINT_MESSAGE' => $print_message,
)
);
-
+
if (!$is_email_file)
{
$method = ($is_help_file) ? 'print_help_entries' : 'print_language_entries';
@@ -622,7 +629,7 @@ class acp_language
{
$tpl .= $this->$method($missing_vars[$name], '* ');
}
-
+
$tpl .= $this->$method($lang);
$template->assign_var('TPL', $tpl);
@@ -633,20 +640,21 @@ class acp_language
$template->assign_vars(array(
'LANG' => $lang)
);
+
unset($lang);
}
return;
-
+
break;
case 'delete':
-
+
if (!$lang_id)
{
- trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING);
}
-
+
$sql = 'SELECT *
FROM ' . LANG_TABLE . '
WHERE lang_id = ' . $lang_id;
@@ -656,18 +664,18 @@ class acp_language
if ($row['lang_iso'] == $config['default_lang'])
{
- trigger_error($user->lang['NO_REMOVE_DEFAULT_LANG'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_REMOVE_DEFAULT_LANG'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$db->sql_query('DELETE FROM ' . LANG_TABLE . ' WHERE lang_id = ' . $lang_id);
$sql = 'UPDATE ' . USERS_TABLE . "
- SET user_lang = '{$config['default_lang']}'
- WHERE user_lang = '{$row['lang_iso']}'";
+ SET user_lang = '" . $db->sql_escape($config['default_lang']) . "'
+ WHERE user_lang = '" . $db->sql_escape($row['lang_iso']) . "'";
$db->sql_query($sql);
-
+
add_log('admin', 'LOG_LANGUAGE_PACK_DELETED', $row['lang_english_name']);
-
+
trigger_error(sprintf($user->lang['LANGUAGE_PACK_DELETED'], $row['lang_english_name']) . adm_back_link($this->u_action));
break;
@@ -677,7 +685,7 @@ class acp_language
if (!$lang_iso || !file_exists("{$phpbb_root_path}language/$lang_iso/iso.txt"))
{
- trigger_error($user->lang['LANGUAGE_PACK_NOT_EXIST'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['LANGUAGE_PACK_NOT_EXIST'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$file = file("{$phpbb_root_path}language/$lang_iso/iso.txt");
@@ -685,8 +693,8 @@ class acp_language
$lang_pack = array(
'iso' => $lang_iso,
'name' => trim(htmlspecialchars($file[0])),
- 'local_name'=> trim(htmlspecialchars($file[1])),
- 'author' => trim(htmlspecialchars($file[2]))
+ 'local_name'=> trim(htmlspecialchars($file[1], ENT_COMPAT, 'UTF-8')),
+ 'author' => trim(htmlspecialchars($file[2], ENT_COMPAT, 'UTF-8'))
);
unset($file);
@@ -694,18 +702,19 @@ class acp_language
FROM ' . LANG_TABLE . "
WHERE lang_iso = '" . $db->sql_escape($lang_iso) . "'";
$result = $db->sql_query($sql);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
- if ($row = $db->sql_fetchrow($result))
+ if ($row)
{
- trigger_error($user->lang['LANGUAGE_PACK_ALREADY_INSTALLED'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['LANGUAGE_PACK_ALREADY_INSTALLED'] . adm_back_link($this->u_action), E_USER_WARNING);
}
- $db->sql_freeresult($result);
if (!$lang_pack['name'] || !$lang_pack['local_name'])
{
- trigger_error($user->lang['INVALID_LANGUAGE_PACK'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['INVALID_LANGUAGE_PACK'] . adm_back_link($this->u_action), E_USER_WARNING);
}
-
+
// Add language pack
$sql_ary = array(
'lang_iso' => $lang_pack['iso'],
@@ -716,18 +725,18 @@ class acp_language
);
$db->sql_query('INSERT INTO ' . LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
-
+
add_log('admin', 'LOG_LANGUAGE_PACK_INSTALLED', $lang_pack['name']);
-
+
trigger_error(sprintf($user->lang['LANGUAGE_PACK_INSTALLED'], $lang_pack['name']) . adm_back_link($this->u_action));
break;
case 'download':
-
+
if (!$lang_id)
{
- trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$sql = 'SELECT *
@@ -747,7 +756,7 @@ class acp_language
{
continue;
}
-
+
$methods[] = $type;
}
@@ -768,7 +777,7 @@ class acp_language
'U_ACTION' => $this->u_action . "&amp;action=$action&amp;id=$lang_id",
'RADIO_BUTTONS' => $radio_buttons)
);
-
+
return;
}
@@ -820,9 +829,9 @@ class acp_language
$this->add_to_archive($compress, $mod_files, $row['lang_iso'], 'mods');
// Write ISO File
- $iso_src = html_entity_decode($row['lang_english_name']) . "\n";
- $iso_src .= html_entity_decode($row['lang_local_name']) . "\n";
- $iso_src .= html_entity_decode($row['lang_author']);
+ $iso_src = htmlspecialchars_decode($row['lang_english_name']) . "\n";
+ $iso_src .= htmlspecialchars_decode($row['lang_local_name']) . "\n";
+ $iso_src .= htmlspecialchars_decode($row['lang_author']);
$compress->add_data($iso_src, 'language/' . $row['lang_iso'] . '/iso.txt');
// index.html files
@@ -838,7 +847,7 @@ class acp_language
$compress->close();
$compress->download('lang_' . $row['lang_iso']);
- @unlink($phpbb_root_path . 'store/lang_' . $row['lang_iso'] . '.' . $use_method);
+ @unlink($phpbb_root_path . 'store/lang_' . $row['lang_iso'] . $use_method);
exit;
@@ -870,18 +879,16 @@ class acp_language
$tagstyle = ($row['lang_iso'] == $config['default_lang']) ? '*' : '';
$template->assign_block_vars('lang', array(
- 'U_DETAILS' => $this->u_action . "&amp;action=details&amp;id={$row['lang_id']}",
- 'U_DOWNLOAD' => $this->u_action . "&amp;action=download&amp;id={$row['lang_id']}",
- 'U_DELETE' => $this->u_action . "&amp;action=delete&amp;id={$row['lang_id']}",
-
- 'ENGLISH_NAME' => $row['lang_english_name'],
- 'TAG' => $tagstyle,
- 'LOCAL_NAME' => $row['lang_local_name'],
- 'ISO' => $row['lang_iso'],
- 'USED_BY' => (isset($lang_count[$row['lang_iso']])) ? $lang_count[$row['lang_iso']] : 0,
-
- )
- );
+ 'U_DETAILS' => $this->u_action . "&amp;action=details&amp;id={$row['lang_id']}",
+ 'U_DOWNLOAD' => $this->u_action . "&amp;action=download&amp;id={$row['lang_id']}",
+ 'U_DELETE' => $this->u_action . "&amp;action=delete&amp;id={$row['lang_id']}",
+
+ 'ENGLISH_NAME' => $row['lang_english_name'],
+ 'TAG' => $tagstyle,
+ 'LOCAL_NAME' => $row['lang_local_name'],
+ 'ISO' => $row['lang_iso'],
+ 'USED_BY' => (isset($lang_count[$row['lang_iso']])) ? $lang_count[$row['lang_iso']] : 0,
+ ));
}
$db->sql_freeresult($result);
@@ -890,7 +897,7 @@ class acp_language
while (($file = readdir($dp)) !== false)
{
- if ($file{0} != '.' && file_exists("{$phpbb_root_path}language/$file/iso.txt"))
+ if ($file[0] != '.' && file_exists("{$phpbb_root_path}language/$file/iso.txt"))
{
if (!in_array($file, $installed))
{
@@ -917,14 +924,14 @@ class acp_language
foreach ($new_ary as $iso => $lang_ary)
{
$template->assign_block_vars('notinst', array(
- 'ISO' => $lang_ary['iso'],
- 'LOCAL_NAME' => $lang_ary['local_name'],
- 'NAME' => $lang_ary['name'],
+ 'ISO' => htmlspecialchars($lang_ary['iso']),
+ 'LOCAL_NAME' => htmlspecialchars($lang_ary['local_name'], ENT_COMPAT, 'UTF-8'),
+ 'NAME' => htmlspecialchars($lang_ary['name'], ENT_COMPAT, 'UTF-8'),
'U_INSTALL' => $this->u_action . '&amp;action=install&amp;iso=' . urlencode($lang_ary['iso']))
);
}
}
-
+
unset($new_ary);
}
@@ -942,7 +949,7 @@ class acp_language
* {FILENAME} [{LANG_NAME}]
*
* @package language
-* @copyright (c) 2005 phpBB Group
+* @copyright (c) 2006 phpBB Group
* @author {CHANGED} - {AUTHOR}
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
@@ -958,6 +965,8 @@ if (empty($lang) || !is_array($lang))
// DEVELOPERS PLEASE NOTE
//
+// All language files should use UTF-8 as their encoding and the files must not contain a BOM.
+//
// Placeholders can now contain order information, e.g. instead of
// \'Page %s of %s\' you can (and should) write \'Page %1$s of %2$s\', this allows
// translators to re-order the output of data while ensuring it remains correct
@@ -1032,7 +1041,7 @@ $lang = array_merge($lang, array(
{
$tpl .= '
<tr>
- <td class="row3" colspan="2">' . $key_prefix . '<b>' . $key . '</b></td>
+ <td class="row3" colspan="2">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '<b>' . htmlspecialchars($key, ENT_COMPAT, 'UTF-8') . '</b></td>
</tr>';
foreach ($value as $_key => $_value)
@@ -1041,23 +1050,23 @@ $lang = array_merge($lang, array(
{
$tpl .= '
<tr>
- <td class="row3" colspan="2">' . $key_prefix . '&nbsp; &nbsp;<b>' . $_key . '</b></td>
+ <td class="row3" colspan="2">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '&nbsp; &nbsp;<b>' . htmlspecialchars($_key, ENT_COMPAT, 'UTF-8') . '</b></td>
</tr>';
foreach ($_value as $__key => $__value)
{
$tpl .= '
<tr>
- <td class="row1" style="white-space: nowrap;">' . $key_prefix . '<b>' . $__key . '</b></td>
+ <td class="row1" style="white-space: nowrap;">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '<b>' . htmlspecialchars($__key, ENT_COMPAT, 'UTF-8') . '</b></td>
<td class="row2">';
if ($input_field)
{
- $tpl .= '<input type="text" name="entry[' . $key . '][' . $_key . '][' . $__key . ']" value="' . htmlspecialchars($__value) . '" size="50" />';
+ $tpl .= '<input type="text" name="entry[' . htmlspecialchars($key, ENT_COMPAT, 'UTF-8') . '][' . htmlspecialchars($_key, ENT_COMPAT, 'UTF-8') . '][' . htmlspecialchars($__key, ENT_COMPAT, 'UTF-8') . ']" value="' . htmlspecialchars($__value, ENT_COMPAT, 'UTF-8') . '" size="50" />';
}
else
{
- $tpl .= '<b>' . htmlspecialchars($__value) . '</b>';
+ $tpl .= '<b>' . htmlspecialchars($__value, ENT_COMPAT, 'UTF-8') . '</b>';
}
$tpl .= '</td>
@@ -1068,16 +1077,16 @@ $lang = array_merge($lang, array(
{
$tpl .= '
<tr>
- <td class="row1" style="white-space: nowrap;">' . $key_prefix . '<b>' . $_key . '</b></td>
+ <td class="row1" style="white-space: nowrap;">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '<b>' . htmlspecialchars($_key, ENT_COMPAT, 'UTF-8') . '</b></td>
<td class="row2">';
-
+
if ($input_field)
{
- $tpl .= '<input type="text" name="entry[' . $key . '][' . $_key . ']" value="' . htmlspecialchars($_value) . '" size="50" />';
+ $tpl .= '<input type="text" name="entry[' . htmlspecialchars($key, ENT_COMPAT, 'UTF-8') . '][' . htmlspecialchars($_key, ENT_COMPAT, 'UTF-8') . ']" value="' . htmlspecialchars($_value, ENT_COMPAT, 'UTF-8') . '" size="50" />';
}
else
{
- $tpl .= '<b>' . htmlspecialchars($_value) . '</b>';
+ $tpl .= '<b>' . htmlspecialchars($_value, ENT_COMPAT, 'UTF-8') . '</b>';
}
$tpl .= '</td>
@@ -1094,16 +1103,16 @@ $lang = array_merge($lang, array(
{
$tpl .= '
<tr>
- <td class="row1" style="white-space: nowrap;">' . $key_prefix . '<b>' . $key . '</b></td>
+ <td class="row1" style="white-space: nowrap;">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '<b>' . htmlspecialchars($key, ENT_COMPAT, 'UTF-8') . '</b></td>
<td class="row2">';
if ($input_field)
{
- $tpl .= '<input type="text" name="entry[' . $key . ']" value="' . htmlspecialchars($value) . '" size="50" />';
+ $tpl .= '<input type="text" name="entry[' . htmlspecialchars($key, ENT_COMPAT, 'UTF-8') . ']" value="' . htmlspecialchars($value, ENT_COMPAT, 'UTF-8') . '" size="50" />';
}
else
{
- $tpl .= '<b>' . htmlspecialchars($value) . '</b>';
+ $tpl .= '<b>' . htmlspecialchars($value, ENT_COMPAT, 'UTF-8') . '</b>';
}
$tpl .= '</td>
@@ -1127,23 +1136,23 @@ $lang = array_merge($lang, array(
{
$tpl .= '
<tr>
- <td class="row3" colspan="2">' . $key_prefix . '<b>' . $key . '</b></td>
+ <td class="row3" colspan="2">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '<b>' . htmlspecialchars($key, ENT_COMPAT, 'UTF-8') . '</b></td>
</tr>';
foreach ($value as $_key => $_value)
{
$tpl .= '
<tr>
- <td class="row1" style="width: 10%; white-space: nowrap;">' . $key_prefix . '<b>' . $_key . '</b></td>
+ <td class="row1" style="width: 10%; white-space: nowrap;">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '<b>' . htmlspecialchars($_key, ENT_COMPAT, 'UTF-8') . '</b></td>
<td class="row2">';
if ($text_field)
{
- $tpl .= '<textarea name="entry[' . $key . '][' . $_key . ']" cols="80" rows="5" style="width: 90%;">' . htmlspecialchars($_value) . '</textarea>';
+ $tpl .= '<textarea name="entry[' . htmlspecialchars($key, ENT_COMPAT, 'UTF-8') . '][' . htmlspecialchars($_key, ENT_COMPAT, 'UTF-8') . ']" cols="80" rows="5" style="width: 90%;">' . htmlspecialchars($_value, ENT_COMPAT, 'UTF-8') . '</textarea>';
}
else
{
- $tpl .= '<b>' . htmlspecialchars($_value) . '</b>';
+ $tpl .= '<b>' . htmlspecialchars($_value, ENT_COMPAT, 'UTF-8') . '</b>';
}
$tpl .= '</td>
@@ -1159,23 +1168,23 @@ $lang = array_merge($lang, array(
{
$tpl .= '
<tr>
- <td class="row1" style="width: 10%; white-space: nowrap;">' . $key_prefix . '<b>' . $key . '</b></td>
+ <td class="row1" style="width: 10%; white-space: nowrap;">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '<b>' . htmlspecialchars($key, ENT_COMPAT, 'UTF-8') . '</b></td>
<td class="row2">';
if ($text_field)
{
- $tpl .= '<textarea name="entry[' . $key . ']" cols="80" rows="5" style="width: 90%;">' . htmlspecialchars($value) . '</textarea>';
+ $tpl .= '<textarea name="entry[' . htmlspecialchars($key, ENT_COMPAT, 'UTF-8') . ']" cols="80" rows="5" style="width: 90%;">' . htmlspecialchars($value, ENT_COMPAT, 'UTF-8') . '</textarea>';
}
else
{
- $tpl .= '<b>' . htmlspecialchars($value) . '</b>';
+ $tpl .= '<b>' . htmlspecialchars($value, ENT_COMPAT, 'UTF-8') . '</b>';
}
$tpl .= '</td>
</tr>';
}
}
-
+
return $tpl;
}
diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php
index bab08bc0ff..a321057fa2 100644
--- a/phpBB/includes/acp/acp_main.php
+++ b/phpBB/includes/acp/acp_main.php
@@ -20,131 +20,43 @@ class acp_main
global $config, $db, $user, $auth, $template;
global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix;
- $action = request_var('action', '');
- $mark = (isset($_REQUEST['mark'])) ? request_var('mark', array(0)) : array();
-
- if (sizeof($mark))
+ // Show restore permissions notice
+ if ($user->data['user_perm_from'] && $auth->acl_get('a_switchperm'))
{
- switch ($action)
- {
- case 'activate':
- case 'delete':
-
- if (!$auth->acl_get('a_user'))
- {
- trigger_error($user->lang['NO_ADMIN']);
- }
-
- $sql = 'SELECT username
- FROM ' . USERS_TABLE . '
- WHERE ' . $db->sql_in_set('user_id', $mark);
- $result = $db->sql_query($sql);
-
- $user_affected = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $user_affected[] = $row['username'];
- }
- $db->sql_freeresult($result);
-
- if ($action == 'activate')
- {
- include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx);
-
- foreach ($mark as $user_id)
- {
- user_active_flip($user_id, USER_INACTIVE);
- }
-
- set_config('num_users', $config['num_users'] + sizeof($mark), true);
-
- // Update latest username
- update_last_username();
- }
- else if ($action == 'delete')
- {
- if (!$auth->acl_get('a_userdel'))
- {
- trigger_error($user->lang['NO_ADMIN']);
- }
-
- $sql = 'DELETE FROM ' . USER_GROUP_TABLE . ' WHERE ' . $db->sql_in_set('user_id', $mark);
- $db->sql_query($sql);
- $sql = 'DELETE FROM ' . USERS_TABLE . ' WHERE ' . $db->sql_in_set('user_id', $mark);
- $db->sql_query($sql);
-
- add_log('admin', 'LOG_INDEX_' . strtoupper($action), implode(', ', $user_affected));
- }
-
- break;
-
- case 'remind':
- if (!$auth->acl_get('a_user'))
- {
- trigger_error($user->lang['NO_ADMIN']);
- }
-
- if (empty($config['email_enable']))
- {
- trigger_error($user->lang['EMAIL_DISABLED']);
- }
-
- $sql = 'SELECT user_id, username, user_email, user_lang, user_jabber, user_notify_type, user_regdate, user_actkey
- FROM ' . USERS_TABLE . '
- WHERE ' . $db->sql_in_set('user_id', $mark);
- $result = $db->sql_query($sql);
-
- if ($row = $db->sql_fetchrow($result))
- {
- // Send the messages
- include_once($phpbb_root_path . 'includes/functions_messenger.'.$phpEx);
-
- $messenger = new messenger();
+ $this->tpl_name = 'acp_main';
+ $this->page_title = 'ACP_MAIN';
- $board_url = generate_board_url() . "/ucp.$phpEx?mode=activate";
- $sig = str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']);
-
- $usernames = array();
- do
- {
- $messenger->template('user_remind_inactive', $row['user_lang']);
-
- $messenger->replyto($config['board_email']);
- $messenger->to($row['user_email'], $row['username']);
- $messenger->im($row['user_jabber'], $row['username']);
-
- $messenger->assign_vars(array(
- 'EMAIL_SIG' => $sig,
- 'USERNAME' => html_entity_decode($row['username']),
- 'SITENAME' => $config['sitename'],
- 'REGISTER_DATE' => $user->format_date($row['user_regdate']),
-
- 'U_ACTIVATE' => "$board_url&mode=activate&u=" . $row['user_id'] . '&k=' . $row['user_actkey'])
- );
-
- $messenger->send($row['user_notify_type']);
+ $sql = 'SELECT user_id, username, user_colour
+ FROM ' . USERS_TABLE . '
+ WHERE user_id = ' . $user->data['user_perm_from'];
+ $result = $db->sql_query($sql);
+ $user_row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
- $usernames[] = $row['username'];
- }
- while ($row = $db->sql_fetchrow($result));
+ $perm_from = '<strong' . (($user_row['user_colour']) ? ' style="color: #' . $user_row['user_colour'] . '">' : '>');
+ $perm_from .= ($user_row['user_id'] != ANONYMOUS) ? '<a href="' . append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&amp;u=' . $user_row['user_id']) . '">' : '';
+ $perm_from .= $user_row['username'];
+ $perm_from .= ($user_row['user_id'] != ANONYMOUS) ? '</a>' : '';
+ $perm_from .= '</strong>';
- $messenger->save_queue();
+ $template->assign_vars(array(
+ 'S_RESTORE_PERMISSIONS' => true,
+ 'U_RESTORE_PERMISSIONS' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=restore_perm'),
+ 'PERM_FROM' => $perm_from,
+ 'L_PERMISSIONS_TRANSFERED_EXPLAIN' => sprintf($user->lang['PERMISSIONS_TRANSFERED_EXPLAIN'], $perm_from, append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=restore_perm')),
+ ));
- add_log('admin', 'LOG_INDEX_REMIND', implode(', ', $usernames));
- unset($usernames);
- }
- $db->sql_freeresult($result);
-
- break;
- }
+ return;
}
+ $action = request_var('action', '');
+
switch ($action)
{
case 'online':
if (!$auth->acl_get('a_board'))
{
- trigger_error($user->lang['NO_ADMIN']);
+ trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
}
set_config('record_online_users', 1, true);
@@ -155,47 +67,47 @@ class acp_main
case 'stats':
if (!$auth->acl_get('a_board'))
{
- trigger_error($user->lang['NO_ADMIN']);
+ trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$sql = 'SELECT COUNT(post_id) AS stat
FROM ' . POSTS_TABLE . '
WHERE post_approved = 1';
$result = $db->sql_query($sql);
-
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
+
set_config('num_posts', (int) $row['stat'], true);
$sql = 'SELECT COUNT(topic_id) AS stat
FROM ' . TOPICS_TABLE . '
WHERE topic_approved = 1';
$result = $db->sql_query($sql);
-
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
+
set_config('num_topics', (int) $row['stat'], true);
$sql = 'SELECT COUNT(user_id) AS stat
FROM ' . USERS_TABLE . '
WHERE user_type IN (' . USER_NORMAL . ',' . USER_FOUNDER . ')';
$result = $db->sql_query($sql);
-
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
+
set_config('num_users', (int) $row['stat'], true);
$sql = 'SELECT COUNT(attach_id) as stat
- FROM ' . ATTACHMENTS_TABLE;
+ FROM ' . ATTACHMENTS_TABLE . '
+ WHERE is_orphan = 0';
$result = $db->sql_query($sql);
-
set_config('num_files', (int) $db->sql_fetchfield('stat'), true);
$db->sql_freeresult($result);
$sql = 'SELECT SUM(filesize) as stat
- FROM ' . ATTACHMENTS_TABLE;
+ FROM ' . ATTACHMENTS_TABLE . '
+ WHERE is_orphan = 0';
$result = $db->sql_query($sql);
-
set_config('upload_dir_size', (int) $db->sql_fetchfield('stat'), true);
$db->sql_freeresult($result);
@@ -205,7 +117,7 @@ class acp_main
case 'user':
if (!$auth->acl_get('a_board'))
{
- trigger_error($user->lang['NO_ADMIN']);
+ trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$sql = 'SELECT COUNT(post_id) AS num_posts, poster_id
@@ -227,7 +139,7 @@ class acp_main
case 'date':
if (!$auth->acl_get('a_board'))
{
- trigger_error($user->lang['NO_ADMIN']);
+ trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
}
set_config('board_startdate', time() - 1);
@@ -235,7 +147,7 @@ class acp_main
break;
case 'db_track':
- $db->sql_query(((SQL_LAYER != 'sqlite') ? 'TRUNCATE TABLE ' : 'DELETE FROM ') . TOPICS_POSTED_TABLE);
+ $db->sql_query((($db->sql_layer != 'sqlite') ? 'TRUNCATE TABLE ' : 'DELETE FROM ') . TOPICS_POSTED_TABLE);
// This can get really nasty... therefore we only do the last six months
$get_from_time = time() - (6 * 4 * 7 * 24 * 60 * 60);
@@ -290,24 +202,7 @@ class acp_main
}
unset($posted);
- if (sizeof($sql_ary))
- {
- switch (SQL_LAYER)
- {
- case 'mysql':
- case 'mysql4':
- case 'mysqli':
- $db->sql_query('INSERT INTO ' . TOPICS_POSTED_TABLE . ' ' . $db->sql_build_array('MULTI_INSERT', $sql_ary));
- break;
-
- default:
- foreach ($sql_ary as $ary)
- {
- $db->sql_query('INSERT INTO ' . TOPICS_POSTED_TABLE . ' ' . $db->sql_build_array('INSERT', $ary));
- }
- break;
- }
- }
+ $db->sql_multi_insert(TOPICS_POSTED_TABLE, $sql_ary);
}
add_log('admin', 'LOG_RESYNC_POST_MARKING');
@@ -337,7 +232,7 @@ class acp_main
{
while (($file = readdir($avatar_dir)) !== false)
{
- if ($file{0} != '.' && $file != 'CVS' && strpos($file, 'index.') === false)
+ if ($file[0] != '.' && $file != 'CVS' && strpos($file, 'index.') === false)
{
$avatar_dir_size += filesize($phpbb_root_path . $config['avatar_path'] . '/' . $file);
}
@@ -375,6 +270,21 @@ class acp_main
$files_per_day = $total_files;
}
+ if ($config['allow_attachments'] || $config['allow_pm_attach'])
+ {
+ $sql = 'SELECT COUNT(attach_id) AS total_orphan
+ FROM ' . ATTACHMENTS_TABLE . '
+ WHERE is_orphan = 1
+ AND filetime < ' . (time() - 3*60*60);
+ $result = $db->sql_query($sql);
+ $total_orphan = (int) $db->sql_fetchfield('total_orphan');
+ $db->sql_freeresult($result);
+ }
+ else
+ {
+ $total_orphan = false;
+ }
+
$dbsize = get_database_size();
$s_action_options = build_select(array('online' => 'RESET_ONLINE', 'date' => 'RESET_DATE', 'stats' => 'RESYNC_STATS', 'user' => 'RESYNC_POSTCOUNTS', 'db_track' => 'RESYNC_POST_MARKING'));
@@ -391,11 +301,14 @@ class acp_main
'AVATAR_DIR_SIZE' => $avatar_dir_size,
'DBSIZE' => $dbsize,
'UPLOAD_DIR_SIZE' => $upload_dir_size,
+ 'TOTAL_ORPHAN' => $total_orphan,
+ 'S_TOTAL_ORPHAN' => ($total_orphan === false) ? false : true,
'GZIP_COMPRESSION' => ($config['gzip_compress']) ? $user->lang['ON'] : $user->lang['OFF'],
'DATABASE_INFO' => $db->sql_server_info(),
'U_ACTION' => append_sid("{$phpbb_admin_path}index.$phpEx"),
'U_ADMIN_LOG' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=logs&amp;mode=admin'),
+ 'U_INACTIVE_USERS' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=inactive&amp;mode=list'),
'S_ACTION_OPTIONS' => ($auth->acl_get('a_board')) ? $s_action_options : '',
)
@@ -421,17 +334,18 @@ class acp_main
if ($auth->acl_get('a_user'))
{
- $sql = 'SELECT user_id, username, user_regdate, user_lastvisit
- FROM ' . USERS_TABLE . '
- WHERE user_type = ' . USER_INACTIVE . '
- ORDER BY user_regdate ASC';
- $result = $db->sql_query($sql);
+ $inactive = array();
+ $inactive_count = 0;
- while ($row = $db->sql_fetchrow($result))
+ view_inactive_users($inactive, $inactive_count, 10);
+
+ foreach ($inactive as $row)
{
$template->assign_block_vars('inactive', array(
- 'DATE' => $user->format_date($row['user_regdate']),
+ 'INACTIVE_DATE' => $user->format_date($row['user_inactive_time']),
+ 'JOINED' => $user->format_date($row['user_regdate']),
'LAST_VISIT' => (!$row['user_lastvisit']) ? ' - ' : $user->format_date($row['user_lastvisit']),
+ 'REASON' => $row['inactive_reason'],
'USER_ID' => $row['user_id'],
'USERNAME' => $row['username'],
'U_USER_ADMIN' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=users&amp;mode=overview&amp;u={$row['user_id']}"))
@@ -450,12 +364,6 @@ class acp_main
);
}
- // Display debug_extra notice
- if (defined('DEBUG_EXTRA'))
- {
- $template->assign_var('S_DEBUG_EXTRA', true);
- }
-
// Warn if install is still present
if (file_exists($phpbb_root_path . 'install'))
{
diff --git a/phpBB/includes/acp/acp_modules.php b/phpBB/includes/acp/acp_modules.php
index 7c72a1ca6b..1323c7aee4 100644
--- a/phpBB/includes/acp/acp_modules.php
+++ b/phpBB/includes/acp/acp_modules.php
@@ -24,6 +24,7 @@
class acp_modules
{
var $module_class = '';
+ var $parent_id;
var $u_action;
function main($id, $mode)
@@ -51,7 +52,7 @@ class acp_modules
$this->page_title = strtoupper($this->module_class);
- $parent_id = request_var('parent_id', 0);
+ $this->parent_id = request_var('parent_id', 0);
$module_id = request_var('m', 0);
$action = request_var('action', '');
$errors = array();
@@ -61,9 +62,9 @@ class acp_modules
case 'delete':
if (!$module_id)
{
- trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&amp;parent_id=' . $parent_id));
+ trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
}
-
+
if (confirm_box(true))
{
$errors = $this->delete_module($module_id);
@@ -71,7 +72,7 @@ class acp_modules
if (!sizeof($errors))
{
$this->remove_cache_file();
- trigger_error($user->lang['MODULE_DELETED'] . adm_back_link($this->u_action . '&amp;parent_id=' . $parent_id));
+ trigger_error($user->lang['MODULE_DELETED'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id));
}
}
else
@@ -79,7 +80,7 @@ class acp_modules
confirm_box(false, 'DELETE_MODULE', build_hidden_fields(array(
'i' => $id,
'mode' => $mode,
- 'parent_id' => $parent_id,
+ 'parent_id' => $this->parent_id,
'module_id' => $module_id,
'action' => $action,
)));
@@ -91,9 +92,9 @@ class acp_modules
case 'disable':
if (!$module_id)
{
- trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&amp;parent_id=' . $parent_id));
+ trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
}
-
+
$sql = 'UPDATE ' . MODULES_TABLE . '
SET module_enabled = ' . (($action == 'enable') ? 1 : 0) . "
WHERE module_id = $module_id";
@@ -108,7 +109,7 @@ class acp_modules
case 'move_down':
if (!$module_id)
{
- trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&amp;parent_id=' . $parent_id));
+ trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
}
$sql = 'SELECT *
@@ -121,7 +122,7 @@ class acp_modules
if (!$row)
{
- trigger_error($user->lang['NO_MODULE'] . adm_back_link($this->u_action . '&amp;parent_id=' . $parent_id));
+ trigger_error($user->lang['NO_MODULE'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
}
$move_module_name = $this->move_module_by($row, $action, 1);
@@ -156,7 +157,7 @@ class acp_modules
'module_basename' => $module_basename,
'module_enabled' => 0,
'module_display' => (isset($fileinfo['modes'][$module_mode]['display'])) ? $fileinfo['modes'][$module_mode]['display'] : 1,
- 'parent_id' => $parent_id,
+ 'parent_id' => $this->parent_id,
'module_class' => $this->module_class,
'module_langname' => $fileinfo['modes'][$module_mode]['title'],
'module_mode' => $module_mode,
@@ -169,7 +170,7 @@ class acp_modules
{
$this->remove_cache_file();
- trigger_error($user->lang['MODULE_ADDED'] . adm_back_link($this->u_action . '&amp;parent_id=' . $parent_id));
+ trigger_error($user->lang['MODULE_ADDED'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id));
}
}
}
@@ -178,7 +179,7 @@ class acp_modules
confirm_box(false, 'ADD_MODULE', build_hidden_fields(array(
'i' => $id,
'mode' => $mode,
- 'parent_id' => $parent_id,
+ 'parent_id' => $this->parent_id,
'action' => 'quickadd',
'quick_install' => $quick_install,
)));
@@ -190,7 +191,7 @@ class acp_modules
if (!$module_id)
{
- trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&amp;parent_id=' . $parent_id));
+ trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
}
$module_row = $this->get_module_row($module_id);
@@ -228,7 +229,7 @@ class acp_modules
{
if (!$module_data['module_langname'])
{
- trigger_error($user->lang['NO_MODULE_LANGNAME'] . adm_back_link($this->u_action . '&amp;parent_id=' . $parent_id));
+ trigger_error($user->lang['NO_MODULE_LANGNAME'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
}
$module_type = request_var('module_type', 'category');
@@ -257,7 +258,7 @@ class acp_modules
{
$this->remove_cache_file();
- trigger_error((($action == 'add') ? $user->lang['MODULE_ADDED'] : $user->lang['MODULE_EDITED']) . adm_back_link($this->u_action . '&amp;parent_id=' . $parent_id));
+ trigger_error((($action == 'add') ? $user->lang['MODULE_ADDED'] : $user->lang['MODULE_EDITED']) . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id));
}
}
@@ -306,8 +307,8 @@ class acp_modules
'S_CAT_OPTIONS' => $s_cat_option . $this->make_module_select($module_data['parent_id'], ($action == 'edit') ? $module_row['module_id'] : false, false, false, false, true),
'S_MODULE_NAMES' => $s_name_options,
'S_MODULE_MODES' => $s_mode_options,
- 'U_BACK' => $this->u_action . '&amp;parent_id=' . $parent_id,
- 'U_EDIT_ACTION' => $this->u_action . '&amp;parent_id=' . $parent_id,
+ 'U_BACK' => $this->u_action . '&amp;parent_id=' . $this->parent_id,
+ 'U_EDIT_ACTION' => $this->u_action . '&amp;parent_id=' . $this->parent_id,
'L_TITLE' => $user->lang[strtoupper($action) . '_MODULE'],
@@ -341,7 +342,7 @@ class acp_modules
);
}
- if (!$parent_id)
+ if (!$this->parent_id)
{
$navigation = strtoupper($this->module_class);
}
@@ -349,12 +350,13 @@ class acp_modules
{
$navigation = '<a href="' . $this->u_action . '">' . strtoupper($this->module_class) . '</a>';
- $modules_nav = $this->get_module_branch($parent_id, 'parents', 'descending');
+ $modules_nav = $this->get_module_branch($this->parent_id, 'parents', 'descending');
+
foreach ($modules_nav as $row)
{
$langname = $this->lang_name($row['module_langname']);
- if ($row['module_id'] == $parent_id)
+ if ($row['module_id'] == $this->parent_id)
{
$navigation .= ' -&gt; ' . $langname;
}
@@ -366,11 +368,11 @@ class acp_modules
}
// Jumpbox
- $module_box = $this->make_module_select($parent_id, false, false, false, false);
+ $module_box = $this->make_module_select($this->parent_id, false, false, false, false);
$sql = 'SELECT *
FROM ' . MODULES_TABLE . "
- WHERE parent_id = $parent_id
+ WHERE parent_id = {$this->parent_id}
AND module_class = '" . $db->sql_escape($this->module_class) . "'
ORDER BY left_id";
$result = $db->sql_query($sql);
@@ -390,14 +392,17 @@ class acp_modules
$module_image = (!$row['module_basename'] || $row['left_id'] + 1 != $row['right_id']) ? '<img src="images/icon_subfolder.gif" width="46" height="25" alt="' . $user->lang['CATEGORY'] . '" />' : '<img src="images/icon_folder.gif" width="46" height="25" alt="' . $user->lang['MODULE'] . '" />';
}
- $url = $this->u_action . '&amp;parent_id=' . $parent_id . '&amp;m=' . $row['module_id'];
-
+ $url = $this->u_action . '&amp;parent_id=' . $this->parent_id . '&amp;m=' . $row['module_id'];
+
$template->assign_block_vars('modules', array(
'MODULE_IMAGE' => $module_image,
'MODULE_TITLE' => $langname,
'MODULE_ENABLED' => ($row['module_enabled']) ? true : false,
'MODULE_DISPLAYED' => ($row['module_display']) ? true : false,
+ 'S_ACP_CAT_SYSTEM' => ($this->module_class == 'acp' && $row['module_langname'] == 'ACP_CAT_SYSTEM') ? true : false,
+ 'S_ACP_MODULE_MANAGEMENT' => ($this->module_class == 'acp' && ($row['module_basename'] == 'modules' || $row['module_langname'] == 'ACP_MODULE_MANAGEMENT')) ? true : false,
+
'U_MODULE' => $this->u_action . '&amp;parent_id=' . $row['module_id'],
'U_MOVE_UP' => $url . '&amp;action=move_up',
'U_MOVE_DOWN' => $url . '&amp;action=move_down',
@@ -409,11 +414,11 @@ class acp_modules
}
while ($row = $db->sql_fetchrow($result));
}
- else if ($parent_id)
+ else if ($this->parent_id)
{
- $row = $this->get_module_row($parent_id);
+ $row = $this->get_module_row($this->parent_id);
- $url = $this->u_action . '&amp;parent_id=' . $parent_id . '&amp;m=' . $row['module_id'];
+ $url = $this->u_action . '&amp;parent_id=' . $this->parent_id . '&amp;m=' . $row['module_id'];
$template->assign_vars(array(
'S_NO_MODULES' => true,
@@ -449,11 +454,11 @@ class acp_modules
}
$template->assign_vars(array(
- 'U_SEL_ACTION' => $this->u_action,
- 'U_ACTION' => $this->u_action . '&amp;parent_id=' . $parent_id,
- 'NAVIGATION' => $navigation,
- 'MODULE_BOX' => $module_box,
- 'PARENT_ID' => $parent_id,
+ 'U_SEL_ACTION' => $this->u_action,
+ 'U_ACTION' => $this->u_action . '&amp;parent_id=' . $this->parent_id,
+ 'NAVIGATION' => $navigation,
+ 'MODULE_BOX' => $module_box,
+ 'PARENT_ID' => $this->parent_id,
'S_INSTALL_OPTIONS' => $s_install_options,
)
);
@@ -476,7 +481,7 @@ class acp_modules
if (!$row)
{
- trigger_error($user->lang['NO_MODULE']);
+ trigger_error($user->lang['NO_MODULE'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
}
return $row;
@@ -721,7 +726,7 @@ class acp_modules
return 'PARENT_NO_EXIST';
}
- trigger_error($user->lang['PARENT_NO_EXIST']);
+ trigger_error($user->lang['PARENT_NO_EXIST'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
}
$sql = 'UPDATE ' . MODULES_TABLE . "
@@ -1007,6 +1012,14 @@ class acp_modules
return $this->lang_name($target['module_langname']);
}
+
+ /**
+ * Check if the module or her childs hold the management module(s)
+ */
+ function is_management_module($module_id)
+ {
+
+ }
}
?> \ No newline at end of file
diff --git a/phpBB/includes/acp/acp_permission_roles.php b/phpBB/includes/acp/acp_permission_roles.php
index 2026aebaf0..004d9f55af 100644
--- a/phpBB/includes/acp/acp_permission_roles.php
+++ b/phpBB/includes/acp/acp_permission_roles.php
@@ -26,7 +26,7 @@ class acp_permission_roles
$auth_admin = new auth_admin();
$user->add_lang('acp/permissions');
- $user->add_lang('acp/permissions_phpbb');
+ add_permission_language();
$this->tpl_name = 'acp_permission_roles';
@@ -58,7 +58,8 @@ class acp_permission_roles
break;
default:
- trigger_error('INVALID_MODE');
+ trigger_error('NO_MODE', E_USER_ERROR);
+ break;
}
$template->assign_vars(array(
@@ -75,7 +76,7 @@ class acp_permission_roles
if (!$role_id)
{
- trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$sql = 'SELECT *
@@ -87,7 +88,7 @@ class acp_permission_roles
if (!$role_row)
{
- trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING);
}
if (confirm_box(true))
@@ -112,7 +113,7 @@ class acp_permission_roles
case 'edit':
if (!$role_id)
{
- trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING);
}
// Get role we edit
@@ -125,7 +126,7 @@ class acp_permission_roles
if (!$role_row)
{
- trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING);
}
// no break;
@@ -138,22 +139,22 @@ class acp_permission_roles
if (!$role_name)
{
- trigger_error($user->lang['NO_ROLE_NAME_SPECIFIED'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_ROLE_NAME_SPECIFIED'] . adm_back_link($this->u_action), E_USER_WARNING);
}
// if we add/edit a role we check the name to be unique among the settings...
$sql = 'SELECT role_id
FROM ' . ACL_ROLES_TABLE . "
WHERE role_type = '" . $db->sql_escape($permission_type) . "'
- AND LOWER(role_name) = '" . $db->sql_escape(strtolower($role_name)) . "'";
+ AND role_name = '" . $db->sql_escape($role_name) . "'";
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
// Make sure we only print out the error if we add the role or change it's name
- if ($row && ($mode == 'add' || ($mode == 'edit' && strtolower($role_row['role_name']) != strtolower($role_name))))
+ if ($row && ($mode == 'add' || ($mode == 'edit' && $role_row['role_name'] != $role_name)))
{
- trigger_error(sprintf($user->lang['ROLE_NAME_ALREADY_EXIST'], $role_name) . adm_back_link($this->u_action));
+ trigger_error(sprintf($user->lang['ROLE_NAME_ALREADY_EXIST'], $role_name) . adm_back_link($this->u_action), E_USER_WARNING);
}
$sql_ary = array(
@@ -252,7 +253,7 @@ class acp_permission_roles
{
if (!$role_id)
{
- trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$sql = 'SELECT *
@@ -279,7 +280,7 @@ class acp_permission_roles
if (!$role_row)
{
- trigger_error($user->lang['NO_PRESET_SELECTED'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$template->assign_vars(array(
diff --git a/phpBB/includes/acp/acp_permissions.php b/phpBB/includes/acp/acp_permissions.php
index ee4b2a1ade..5354d70f72 100644
--- a/phpBB/includes/acp/acp_permissions.php
+++ b/phpBB/includes/acp/acp_permissions.php
@@ -27,7 +27,7 @@ class acp_permissions
$auth_admin = new auth_admin();
$user->add_lang('acp/permissions');
- $user->add_lang('acp/permissions_phpbb');
+ add_permission_language();
$this->tpl_name = 'acp_permissions';
@@ -47,7 +47,7 @@ class acp_permissions
return;
}
- trigger_error('NO_MODE');
+ trigger_error('NO_MODE', E_USER_ERROR);
}
// Set some vars
@@ -59,8 +59,8 @@ class acp_permissions
$subforum_id = request_var('subforum_id', 0);
$forum_id = request_var('forum_id', array(0));
- $username = request_var('username', array(''));
- $usernames = request_var('usernames', '');
+ $username = request_var('username', array(''), true);
+ $usernames = request_var('usernames', '', true);
$user_id = request_var('user_id', array(0));
$group_id = request_var('group_id', array(0));
@@ -70,7 +70,7 @@ class acp_permissions
if ($select_all_groups)
{
// Add default groups to selection
- $sql_and = (!$config['coppa_enable']) ? " AND group_name NOT IN ('INACTIVE_COPPA', 'REGISTERED_COPPA')" : '';
+ $sql_and = (!$config['coppa_enable']) ? " AND group_name <> 'REGISTERED_COPPA'" : '';
$sql = 'SELECT group_id
FROM ' . GROUPS_TABLE . '
@@ -98,7 +98,7 @@ class acp_permissions
if (!sizeof($user_id))
{
- trigger_error($user->lang['SELECTED_USER_NOT_EXIST'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['SELECTED_USER_NOT_EXIST'] . adm_back_link($this->u_action), E_USER_WARNING);
}
}
unset($username);
@@ -190,7 +190,8 @@ class acp_permissions
break;
default:
- trigger_error('INVALID_MODE');
+ trigger_error('NO_MODE', E_USER_ERROR);
+ break;
}
$template->assign_vars(array(
@@ -203,7 +204,7 @@ class acp_permissions
if (!in_array($permission_type, $this->permission_dropdown))
{
- trigger_error($user->lang['WRONG_PERMISSION_TYPE'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['WRONG_PERMISSION_TYPE'] . adm_back_link($this->u_action), E_USER_WARNING);
}
@@ -237,14 +238,14 @@ class acp_permissions
}
else
{
- trigger_error($user->lang['NO_USER_GROUP_SELECTED'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_USER_GROUP_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING);
}
break;
case 'apply_permissions':
if (!isset($_POST['setting']))
{
- trigger_error($user->lang['NO_AUTH_SETTING_FOUND'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_AUTH_SETTING_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$this->set_permissions($mode, $permission_type, $auth_admin, $user_id, $group_id);
@@ -253,7 +254,7 @@ class acp_permissions
case 'apply_all_permissions':
if (!isset($_POST['setting']))
{
- trigger_error($user->lang['NO_AUTH_SETTING_FOUND'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_AUTH_SETTING_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$this->set_all_permissions($mode, $permission_type, $auth_admin, $user_id, $group_id);
@@ -330,7 +331,8 @@ class acp_permissions
$template->assign_vars(array(
'S_SELECT_USER' => true,
- 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&amp;form=select_victim&amp;field=username'))
+ 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&amp;form=select_victim&amp;field=username'),
+ 'UA_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=select_victim&field=username', false))
);
break;
@@ -392,17 +394,23 @@ class acp_permissions
'S_DEFINED_USER_OPTIONS' => $items['user_ids_options'],
'S_DEFINED_GROUP_OPTIONS' => $items['group_ids_options'],
'S_ADD_GROUP_OPTIONS' => group_select_options(false, $items['group_ids']),
- 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&amp;form=add_user&amp;field=username'))
+ 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&amp;form=add_user&amp;field=username'),
+ 'UA_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=add_user&field=username', false))
);
break;
}
+ // The S_ALLOW_SELECT parameter below is a measure to lower memory usage.
+ // If there are more than 5 forums selected the admin is not able to select all users/groups too.
+ // We need to see if the number of forums can be increased or need to be decreased.
+
$template->assign_vars(array(
'U_ACTION' => $this->u_action,
'ANONYMOUS_USER_ID' => ANONYMOUS,
'S_SELECT_VICTIM' => true,
+ 'S_ALLOW_ALL_SELECT' => (sizeof($forum_id) > 5) ? false : true,
'S_CAN_SELECT_USER' => ($auth->acl_get('a_authusers')) ? true : false,
'S_CAN_SELECT_GROUP' => ($auth->acl_get('a_authgroups')) ? true : false,
'S_HIDDEN_FIELDS' => $s_hidden_fields)
@@ -436,7 +444,7 @@ class acp_permissions
// Do not allow forum_ids being set and no other setting defined (will bog down the server too much)
if (sizeof($forum_id) && !sizeof($user_id) && !sizeof($group_id))
{
- trigger_error($user->lang['ONLY_FORUM_DEFINED'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['ONLY_FORUM_DEFINED'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$template->assign_vars(array(
@@ -566,7 +574,7 @@ class acp_permissions
if (!sizeof($ids))
{
- trigger_error($user->lang['SELECTED_' . strtoupper($mode) . '_NOT_EXIST'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['SELECTED_' . strtoupper($mode) . '_NOT_EXIST'] . adm_back_link($this->u_action), E_USER_WARNING);
}
}
@@ -585,7 +593,7 @@ class acp_permissions
// Check the permission setting again
if (!$auth->acl_get('a_' . str_replace('_', '', $permission_type) . 'auth') || !$auth->acl_get('a_auth' . $ug_type . 's'))
{
- trigger_error($user->lang['NO_ADMIN'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$ug_id = $forum_id = 0;
@@ -643,7 +651,7 @@ class acp_permissions
// Remove users who are now moderators or admins from everyones foes list
if ($permission_type == 'm_' || $permission_type == 'a_')
{
- $this->update_foes();
+ update_foes();
}
$this->log_action($mode, 'add', $permission_type, $ug_type, $ug_id, $forum_id);
@@ -664,7 +672,7 @@ class acp_permissions
// Check the permission setting again
if (!$auth->acl_get('a_' . str_replace('_', '', $permission_type) . 'auth') || !$auth->acl_get('a_auth' . $ug_type . 's'))
{
- trigger_error($user->lang['NO_ADMIN'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$auth_settings = (isset($_POST['setting'])) ? $_POST['setting'] : array();
@@ -710,7 +718,7 @@ class acp_permissions
// Remove users who are now moderators or admins from everyones foes list
if ($permission_type == 'm_' || $permission_type == 'a_')
{
- $this->update_foes();
+ update_foes();
}
$this->log_action($mode, 'add', $permission_type, $ug_type, $ug_ids, $forum_ids);
@@ -769,7 +777,7 @@ class acp_permissions
// Check the permission setting again
if (!$auth->acl_get('a_' . str_replace('_', '', $permission_type) . 'auth') || !$auth->acl_get('a_auth' . $ug_type . 's'))
{
- trigger_error($user->lang['NO_ADMIN'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$auth_admin->acl_delete($ug_type, (($ug_type == 'user') ? $user_id : $group_id), (sizeof($forum_id) ? $forum_id : false), $permission_type);
@@ -840,32 +848,6 @@ class acp_permissions
}
/**
- * Update foes - remove moderators and administrators from foe lists...
- */
- function update_foes()
- {
- global $db, $auth;
-
- $perms = array();
- foreach ($auth->acl_get_list(false, array('a_', 'm_'), false) as $forum_id => $forum_ary)
- {
- foreach ($forum_ary as $auth_option => $user_ary)
- {
- $perms = array_merge($perms, $user_ary);
- }
- }
-
- if (sizeof($perms))
- {
- $sql = 'DELETE FROM ' . ZEBRA_TABLE . '
- WHERE ' . $db->sql_in_set('zebra_id', array_unique($perms)) . '
- AND foe = 1';
- $db->sql_query($sql);
- }
- unset($perms);
- }
-
- /**
* Display a complete trace tree for the selected permission to determine where settings are set/unset
*/
function permission_trace($user_id, $forum_id, $permission)
@@ -888,7 +870,7 @@ class acp_permissions
if (!$userdata)
{
- trigger_error('NO_USERS');
+ trigger_error('NO_USERS', E_USER_ERROR);
}
$forum_name = false;
diff --git a/phpBB/includes/acp/acp_php_info.php b/phpBB/includes/acp/acp_php_info.php
index 44917bd8fc..fe223b623e 100644
--- a/phpBB/includes/acp/acp_php_info.php
+++ b/phpBB/includes/acp/acp_php_info.php
@@ -22,7 +22,7 @@ class acp_php_info
if ($mode != 'info')
{
- trigger_error('NO_MODE');
+ trigger_error('NO_MODE', E_USER_ERROR);
}
$this->tpl_name = 'acp_php_info';
diff --git a/phpBB/includes/acp/acp_profile.php b/phpBB/includes/acp/acp_profile.php
index c361c47c2e..9ce7f3ed92 100644
--- a/phpBB/includes/acp/acp_profile.php
+++ b/phpBB/includes/acp/acp_profile.php
@@ -91,7 +91,7 @@ class acp_profile
if (!$field_id)
{
- trigger_error($user->lang['NO_FIELD_ID'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_FIELD_ID'] . adm_back_link($this->u_action), E_USER_WARNING);
}
if (confirm_box(true))
@@ -107,7 +107,7 @@ class acp_profile
$db->sql_query('DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . " WHERE field_id = $field_id");
$db->sql_query('DELETE FROM ' . PROFILE_LANG_TABLE . " WHERE field_id = $field_id");
- switch (SQL_LAYER)
+ switch ($db->sql_layer)
{
case 'sqlite':
$sql = "SELECT sql
@@ -119,6 +119,8 @@ class acp_profile
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
+ $db->sql_transaction('begin');
+
// Create a temp table and populate it, destroy the existing one
$db->sql_query(preg_replace('#CREATE\s+TABLE\s+"?' . PROFILE_FIELDS_DATA_TABLE . '"?#i', 'CREATE TEMPORARY TABLE ' . PROFILE_FIELDS_DATA_TABLE . '_temp', $row['sql']));
$db->sql_query('INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . '_temp SELECT * FROM ' . PROFILE_FIELDS_DATA_TABLE);
@@ -127,12 +129,13 @@ class acp_profile
preg_match('#\((.*)\)#s', $row['sql'], $matches);
$new_table_cols = trim($matches[1]);
- $old_table_cols = explode(',', $new_table_cols);
+ $old_table_cols = preg_split('/,(?=[\\sa-z])/im', $new_table_cols);
$column_list = array();
- foreach($old_table_cols as $declaration)
+
+ foreach ($old_table_cols as $declaration)
{
$entities = preg_split('#\s+#', trim($declaration));
- if ($entities[0] !== '_' . $field_ident)
+ if ($entities[0] !== 'pf_' . $field_ident)
{
$column_list[] = $entities[0];
}
@@ -140,16 +143,18 @@ class acp_profile
$columns = implode(',', $column_list);
- $new_table_cols = preg_replace('/' . '_' . $field_ident . '[^,]+,/', '', $new_table_cols);
+ $new_table_cols = preg_replace('/' . 'pf_' . $field_ident . '[^,]+,/', '', $new_table_cols);
// create a new table and fill it up. destroy the temp one
$db->sql_query('CREATE TABLE ' . PROFILE_FIELDS_DATA_TABLE . ' (' . $new_table_cols . ');');
$db->sql_query('INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . PROFILE_FIELDS_DATA_TABLE . '_temp;');
$db->sql_query('DROP TABLE ' . PROFILE_FIELDS_DATA_TABLE . '_temp');
+
+ $db->sql_transaction('commit');
break;
default:
- $db->sql_query('ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " DROP _$field_ident");
+ $db->sql_query('ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " DROP pf_$field_ident");
}
$order = 0;
@@ -192,7 +197,7 @@ class acp_profile
if (!$field_id)
{
- trigger_error($user->lang['NO_FIELD_ID'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_FIELD_ID'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$sql = 'SELECT lang_id
@@ -204,7 +209,7 @@ class acp_profile
if (!in_array($default_lang_id, $lang_defs['entry'][$field_id]))
{
- trigger_error($user->lang['DEFAULT_LANGUAGE_NOT_FILLED'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['DEFAULT_LANGUAGE_NOT_FILLED'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$sql = 'UPDATE ' . PROFILE_FIELDS_TABLE . "
@@ -229,7 +234,7 @@ class acp_profile
if (!$field_id)
{
- trigger_error($user->lang['NO_FIELD_ID'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_FIELD_ID'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$sql = 'UPDATE ' . PROFILE_FIELDS_TABLE . "
@@ -275,7 +280,7 @@ class acp_profile
{
if (!$field_id)
{
- trigger_error($user->lang['NO_FIELD_ID'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_FIELD_ID'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$sql = 'SELECT l.*, f.*
@@ -289,7 +294,7 @@ class acp_profile
if (!$field_row)
{
- trigger_error($user->lang['FIELD_NOT_FOUND'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['FIELD_NOT_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$field_type = $field_row['field_type'];
@@ -319,7 +324,7 @@ class acp_profile
if (!$field_type)
{
- trigger_error($user->lang['NO_FIELD_TYPE'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_FIELD_TYPE'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$field_row = array_merge($default_values[$field_type], array(
@@ -359,7 +364,7 @@ class acp_profile
$cp->vars['lang_name'] = request_var('lang_name', $field_row['lang_name'], true);
$cp->vars['lang_explain'] = request_var('lang_explain', $field_row['lang_explain'], true);
$cp->vars['lang_default_value'] = request_var('lang_default_value', $field_row['lang_default_value'], true);
-
+
// Field option...
if (isset($_REQUEST['field_option']))
{
@@ -525,7 +530,8 @@ class acp_profile
}
}
- if ($submit && $step == 1)
+ // Check for general issues in every step
+ if ($submit) // && $step == 1
{
// Check values for step 1
if ($cp->vars['field_ident'] == '')
@@ -538,16 +544,39 @@ class acp_profile
$error[] = $user->lang['INVALID_CHARS_FIELD_IDENT'];
}
+ if (strlen($cp->vars['field_ident']) > 17)
+ {
+ $error[] = $user->lang['INVALID_FIELD_IDENT_LEN'];
+ }
+
if ($cp->vars['lang_name'] == '')
{
$error[] = $user->lang['EMPTY_USER_FIELD_NAME'];
}
- if ($field_type == FIELD_BOOL || $field_type == FIELD_DROPDOWN)
+ if ($field_type == FIELD_DROPDOWN && !sizeof($cp->vars['lang_options']))
+ {
+ $error[] = $user->lang['NO_FIELD_ENTRIES'];
+ }
+
+ if ($field_type == FIELD_BOOL && (empty($cp->vars['lang_options'][0]) || empty($cp->vars['lang_options'][1])))
{
- if (!sizeof($cp->vars['lang_options']))
+ $error[] = $user->lang['NO_FIELD_ENTRIES'];
+ }
+
+ // Check for already existing field ident
+ if ($action != 'edit')
+ {
+ $sql = 'SELECT field_ident
+ FROM ' . PROFILE_FIELDS_TABLE . "
+ WHERE field_ident = '" . $db->sql_escape($cp->vars['field_ident']) . "'";
+ $result = $db->sql_query($sql);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ if ($row)
{
- $error[] = $user->lang['NO_FIELD_ENTRIES'];
+ $error[] = $user->lang['FIELD_IDENT_ALREADY_EXIST'];
}
}
}
@@ -730,12 +759,20 @@ class acp_profile
ORDER BY field_order';
$result = $db->sql_query($sql);
+ $s_one_need_edit = false;
while ($row = $db->sql_fetchrow($result))
{
$active_lang = (!$row['field_active']) ? 'ACTIVATE' : 'DEACTIVATE';
$active_value = (!$row['field_active']) ? 'activate' : 'deactivate';
$id = $row['field_id'];
+ $s_need_edit = (sizeof($lang_defs['diff'][$row['field_id']])) ? true : false;
+
+ if ($s_need_edit)
+ {
+ $s_one_need_edit = true;
+ }
+
$template->assign_block_vars('fields', array(
'FIELD_IDENT' => $row['field_ident'],
'FIELD_TYPE' => $user->lang['FIELD_' . strtoupper($cp->profile_types[$row['field_type']])],
@@ -743,15 +780,22 @@ class acp_profile
'L_ACTIVATE_DEACTIVATE' => $user->lang[$active_lang],
'U_ACTIVATE_DEACTIVATE' => $this->u_action . "&amp;action=$active_value&amp;field_id=$id",
'U_EDIT' => $this->u_action . "&amp;action=edit&amp;field_id=$id",
+ 'U_TRANSLATE' => $this->u_action . "&amp;action=edit&amp;field_id=$id&amp;step=3",
'U_DELETE' => $this->u_action . "&amp;action=delete&amp;field_id=$id",
'U_MOVE_UP' => $this->u_action . "&amp;action=move_up&amp;order={$row['field_order']}",
'U_MOVE_DOWN' => $this->u_action . "&amp;action=move_down&amp;order={$row['field_order']}",
- 'S_NEED_EDIT' => (sizeof($lang_defs['diff'][$row['field_id']])) ? true : false)
+ 'S_NEED_EDIT' => $s_need_edit)
);
}
$db->sql_freeresult($result);
+ // At least one option field needs editing?
+ if ($s_one_need_edit)
+ {
+ $template->assign_var('S_NEED_EDIT', true);
+ }
+
$s_select_type = '';
foreach ($cp->profile_types as $key => $value)
{
@@ -831,12 +875,11 @@ class acp_profile
$lang_options[$lang_id]['lang_iso'] = $lang_iso;
foreach ($options as $field => $field_type)
{
- $value = ($action == 'create') ? request_var('l_' . $field, '', true) : $cp->vars['l_' . $field];
-
+ $value = ($action == 'create') ? request_var('l_' . $field, array(0 => ''), true) : $cp->vars['l_' . $field];
+
if ($field == 'lang_options')
{
-
- $var = ($action == 'create' || !is_array($cp->vars['lang_options'][$lang_id])) ? $cp->vars['lang_options'] : $cp->vars['lang_options'][$lang_id];
+ $var = ($action == 'create' || !is_array($cp->vars['l_lang_options'][$lang_id])) ? $cp->vars['lang_options'] : $cp->vars['lang_options'][$lang_id];
switch ($field_type)
{
@@ -948,7 +991,7 @@ class acp_profile
if ($action == 'create')
{
- $field_ident = '_' . $field_ident;
+ $field_ident = 'pf_' . $field_ident;
$profile_sql[] = $this->add_field_ident($field_ident, $field_type);
}
@@ -1003,10 +1046,11 @@ class acp_profile
}
}
- $cp->vars['l_lang_name'] = request_var('l_lang_name', '', true);
- $cp->vars['l_lang_explain'] = request_var('l_lang_explain', '', true);
- $cp->vars['l_lang_default_value'] = request_var('l_lang_default_value', '', true);
- $cp->vars['l_lang_options'] = request_var('l_lang_options', '', true);
+ // These are always arrays because the key is the language id...
+ $cp->vars['l_lang_name'] = request_var('l_lang_name', array(0 => ''), true);
+ $cp->vars['l_lang_explain'] = request_var('l_lang_explain', array(0 => ''), true);
+ $cp->vars['l_lang_default_value'] = request_var('l_lang_default_value', array(0 => ''), true);
+ $cp->vars['l_lang_options'] = request_var('l_lang_options', array(0 => ''), true);
if ($cp->vars['lang_options'])
{
@@ -1155,7 +1199,7 @@ class acp_profile
}
else
{
- add_log('admin', 'LOG_PROFILE_FIELD_CREATE', substr($field_ident, 1) . ':' . $cp->vars['lang_name']);
+ add_log('admin', 'LOG_PROFILE_FIELD_CREATE', substr($field_ident, 3) . ':' . $cp->vars['lang_name']);
trigger_error($user->lang['ADDED_PROFILE_FIELD'] . adm_back_link($this->u_action));
}
}
@@ -1215,7 +1259,7 @@ class acp_profile
{
global $db;
- switch (SQL_LAYER)
+ switch ($db->sql_layer)
{
case 'mysql':
case 'mysql4':
diff --git a/phpBB/includes/acp/acp_prune.php b/phpBB/includes/acp/acp_prune.php
index 4752e7bafe..e71fe33557 100644
--- a/phpBB/includes/acp/acp_prune.php
+++ b/phpBB/includes/acp/acp_prune.php
@@ -155,7 +155,7 @@ class acp_prune
if (!$row)
{
$db->sql_freeresult($result);
- trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$forum_list = $s_hidden_fields = '';
@@ -196,17 +196,18 @@ class acp_prune
{
if (confirm_box(true))
{
- $users = request_var('users', '');
+ $users = request_var('users', '', true);
$action = request_var('action', 'deactivate');
$deleteposts = request_var('deleteposts', 0);
if ($users)
{
- $where_sql = ' AND ' . $db->sql_in_set('username', explode("\n", $users));
+ $users = explode("\n", $users);
+ $where_sql = ' AND ' . $db->sql_in_set('username_clean', array_map('utf8_clean_string', $users));
}
else
{
- $username = request_var('username', '');
+ $username = request_var('username', '', true);
$email = request_var('email', '');
$joined_select = request_var('joined_select', 'lt');
@@ -224,7 +225,7 @@ class acp_prune
$sort_by_types = array('username', 'user_email', 'user_posts', 'user_regdate', 'user_lastvisit');
$where_sql = '';
- $where_sql .= ($username) ? " AND username LIKE '" . $db->sql_escape(str_replace('*', '%', $username)) . "'" : '';
+ $where_sql .= ($username) ? " AND username_clean LIKE '" . $db->sql_escape(str_replace('*', '%', utf8_clean_string($username))) . "'" : '';
$where_sql .= ($email) ? " AND user_email LIKE '" . $db->sql_escape(str_replace('*', '%', $email)) . "' " : '';
$where_sql .= (sizeof($joined)) ? " AND user_regdate " . $key_match[$joined_select] . ' ' . gmmktime(0, 0, 0, (int) $joined[1], (int) $joined[2], (int) $joined[0]) : '';
$where_sql .= ($count) ? " AND user_posts " . $key_match[$count_select] . " $count " : '';
@@ -244,7 +245,8 @@ class acp_prune
$db->sql_freeresult($result);
// Do not prune founder members
- $sql = 'SELECT username, user_id FROM ' . USERS_TABLE . '
+ $sql = 'SELECT user_id, username
+ FROM ' . USERS_TABLE . '
WHERE user_id <> ' . ANONYMOUS . '
AND user_type <> ' . USER_FOUNDER . "
$where_sql";
@@ -267,11 +269,7 @@ class acp_prune
{
if ($action == 'deactivate')
{
- foreach ($user_ids as $user_id)
- {
- user_active_flip($user_id, USER_NORMAL, false, false, true);
- }
-
+ user_active_flip('deactivate', $user_ids);
$l_log = 'LOG_PRUNE_USER_DEAC';
}
else if ($action == 'delete')
@@ -309,7 +307,7 @@ class acp_prune
'prune' => 1,
'users' => request_var('users', ''),
- 'username' => request_var('username', ''),
+ 'username' => request_var('username', '', true),
'email' => request_var('email', ''),
'joined_select' => request_var('joined_select', ''),
'joined' => request_var('joined', ''),
diff --git a/phpBB/includes/acp/acp_ranks.php b/phpBB/includes/acp/acp_ranks.php
index 59505c34c2..db96b173e8 100644
--- a/phpBB/includes/acp/acp_ranks.php
+++ b/phpBB/includes/acp/acp_ranks.php
@@ -48,14 +48,14 @@ class acp_ranks
if (!$rank_title)
{
- trigger_error($user->lang['NO_RANK_TITLE'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_RANK_TITLE'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$sql_ary = array(
'rank_title' => $rank_title,
'rank_special' => $special_rank,
'rank_min' => $min_posts,
- 'rank_image' => html_entity_decode($rank_image)
+ 'rank_image' => htmlspecialchars_decode($rank_image)
);
if ($rank_id)
@@ -96,7 +96,7 @@ class acp_ranks
}
else
{
- trigger_error($user->lang['MUST_SELECT_RANK'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['MUST_SELECT_RANK'] . adm_back_link($this->u_action), E_USER_WARNING);
}
break;
diff --git a/phpBB/includes/acp/acp_reasons.php b/phpBB/includes/acp/acp_reasons.php
index 402663ad90..72419de1ef 100644
--- a/phpBB/includes/acp/acp_reasons.php
+++ b/phpBB/includes/acp/acp_reasons.php
@@ -61,11 +61,11 @@ class acp_reasons
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
- if ($row['reason_title'] == 'other')
+ if (strtolower($row['reason_title']) == 'other')
{
$reason_row['reason_title'] = 'other';
}
- else if (strtolower($row['reason_title']) != strtolower($reason_row['reason_title']))
+ else if ($row['reason_title'] != $reason_row['reason_title'])
{
$check_double = true;
}
@@ -76,12 +76,12 @@ class acp_reasons
{
$sql = 'SELECT reason_id
FROM ' . REPORTS_REASONS_TABLE . "
- WHERE LOWER(reason_title) = '" . strtolower($db->sql_escape($reason_row['reason_title'])) . "'";
+ WHERE reason_title = '" . $db->sql_escape($reason_row['reason_title']) . "'";
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
- if ($row)
+ if ($row || ($action == 'add' && strtolower($reason_row['reason_title']) == 'other'))
{
$error[] = $user->lang['REASON_ALREADY_EXIST'];
}
@@ -137,7 +137,7 @@ class acp_reasons
if (!$reason_row)
{
- trigger_error($user->lang['NO_REASON'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_REASON'] . adm_back_link($this->u_action), E_USER_WARNING);
}
}
@@ -159,10 +159,14 @@ class acp_reasons
'REASON_TITLE' => $reason_row['reason_title'],
'REASON_DESCRIPTION' => $reason_row['reason_description'],
-
- 'S_EDIT_REASON' => true,
- 'S_TRANSLATED' => $translated,
- 'S_ERROR' => (sizeof($error)) ? true : false,
+
+ 'TRANSLATED_TITLE' => ($translated) ? $user->lang['report_reasons']['TITLE'][strtoupper($reason_row['reason_title'])] : '',
+ 'TRANSLATED_DESCRIPTION'=> ($translated) ? $user->lang['report_reasons']['DESCRIPTION'][strtoupper($reason_row['reason_title'])] : '',
+
+ 'S_AVAILABLE_TITLES' => implode(', ', array_map('htmlspecialchars', array_keys($user->lang['report_reasons']['TITLE']))),
+ 'S_EDIT_REASON' => true,
+ 'S_TRANSLATED' => $translated,
+ 'S_ERROR' => (sizeof($error)) ? true : false,
)
);
@@ -180,12 +184,12 @@ class acp_reasons
if (!$reason_row)
{
- trigger_error($user->lang['NO_REASON'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_REASON'] . adm_back_link($this->u_action), E_USER_WARNING);
}
- if ($reason_row['reason_title'] == 'other')
+ if (strtolower($reason_row['reason_title']) == 'other')
{
- trigger_error($user->lang['NO_REMOVE_DEFAULT_REASON'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_REMOVE_DEFAULT_REASON'] . adm_back_link($this->u_action), E_USER_WARNING);
}
// Let the deletion be confirmed...
@@ -193,12 +197,12 @@ class acp_reasons
{
$sql = 'SELECT reason_id
FROM ' . REPORTS_REASONS_TABLE . "
- WHERE reason_title = 'other'";
+ WHERE LOWER(reason_title) = 'other'";
$result = $db->sql_query($sql);
$other_reason_id = (int) $db->sql_fetchfield('reason_id');
$db->sql_freeresult($result);
- switch (SQL_LAYER)
+ switch ($db->sql_layer)
{
// The ugly one!
case 'mysqli':
@@ -214,9 +218,17 @@ class acp_reasons
case 'mssql':
case 'mssql_odbc':
// Change the reports using this reason to 'other'
- $sql = 'UPDATE ' . REPORTS_TABLE . '
- SET reason_id = ' . $other_reason_id . ", report_text = '" . $db->sql_escape($reason_row['reason_description']) . "\n\n' + report_text
- WHERE reason_id = $reason_id";
+ $sql = "DECLARE @ptrval binary(16)
+
+ SELECT @ptrval = TEXTPTR(report_text)
+ FROM " . REPORTS_TABLE . "
+ WHERE reason_id = " . $reason_id . "
+
+ UPDATETEXT " . REPORTS_TABLE . ".report_text @ptrval 0 0 '" . $db->sql_escape($reason_row['reason_description']) . "\n\n'
+
+ UPDATE " . REPORTS_TABLE . '
+ SET reason_id = ' . $other_reason_id . "
+ WHERE reason_id = $reason_id";
break;
// Teh standard
@@ -319,7 +331,7 @@ class acp_reasons
// If the reason is defined within the language file, we will use the localized version, else just use the database entry...
if (isset($user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])]) && isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])]))
{
- $row['reson_description'] = $user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])];
+ $row['reason_description'] = $user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])];
$row['reason_title'] = $user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])];
$translated = true;
diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php
index b7c37772ed..6b1eefe8e6 100644
--- a/phpBB/includes/acp/acp_search.php
+++ b/phpBB/includes/acp/acp_search.php
@@ -152,7 +152,7 @@ class acp_search
}
else
{
- trigger_error($error);
+ trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING);
}
}
else
@@ -168,7 +168,7 @@ class acp_search
}
else
{
- trigger_error($error);
+ trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING);
}
}
@@ -228,7 +228,8 @@ class acp_search
break;
default:
- trigger_error('NO_ACTION');
+ trigger_error('NO_ACTION', E_USER_ERROR);
+ break;
}
if (empty($this->state[0]))
@@ -240,7 +241,7 @@ class acp_search
$error = false;
if ($this->init_search($this->state[0], $this->search, $error))
{
- trigger_error($error);
+ trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING);
}
$action = &$this->state[1];
@@ -262,7 +263,7 @@ class acp_search
{
$this->state = array('');
$this->save_state();
- trigger_error($error . adm_back_link($this->u_action) . $this->close_popup_js());
+ trigger_error($error . adm_back_link($this->u_action) . $this->close_popup_js(), E_USER_WARNING);
}
}
else
@@ -294,7 +295,7 @@ class acp_search
if ($post_counter <= $this->max_post_id)
{
- redirect($this->u_action . '&amp;action=delete', 3);
+ redirect($this->u_action . '&amp;action=delete');
}
}
@@ -314,12 +315,12 @@ class acp_search
{
$this->state = array('');
$this->save_state();
- trigger_error($error . adm_back_link($this->u_action) . $this->close_popup_js());
+ trigger_error($error . adm_back_link($this->u_action) . $this->close_popup_js(), E_USER_WARNING);
}
}
else
{
- $sql = 'SELECT post_id, post_subject, post_text, post_encoding, poster_id, forum_id
+ $sql = 'SELECT post_id, post_subject, post_text, poster_id, forum_id
FROM ' . POSTS_TABLE . '
WHERE post_id >= ' . (int) ($post_counter + 1) . '
AND post_id < ' . (int) ($post_counter + $this->batch_size);
@@ -327,7 +328,7 @@ class acp_search
while ($row = $db->sql_fetchrow($result))
{
- $this->search->index('post', $row['post_id'], $row['post_text'], $row['post_subject'], $row['post_encoding'], $row['poster_id'], $row['forum_id']);
+ $this->search->index('post', $row['post_id'], $row['post_text'], $row['post_subject'], $row['poster_id'], $row['forum_id']);
}
$db->sql_freeresult($result);
@@ -338,7 +339,7 @@ class acp_search
if ($post_counter <= $this->max_post_id)
{
- redirect($this->u_action . '&amp;action=create', 3);
+ redirect($this->u_action . '&amp;action=create');
}
}
@@ -440,7 +441,7 @@ class acp_search
adm_page_header($user->lang[$l_type]);
$template->set_filenames(array(
- 'body' => 'search_index_progress_bar.html')
+ 'body' => 'progress_bar.html')
);
$template->assign_vars(array(
diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php
index 48277dc487..4377dd7e20 100644
--- a/phpBB/includes/acp/acp_styles.php
+++ b/phpBB/includes/acp/acp_styles.php
@@ -191,7 +191,7 @@ pagination_sep = \'{PAGINATION_SEP}\'
if ($style_id == $config['default_style'])
{
- trigger_error($user->lang['DEACTIVATE_DEFAULT'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['DEACTIVATE_DEFAULT'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$sql = 'UPDATE ' . STYLES_TABLE . '
@@ -234,7 +234,7 @@ pagination_sep = \'{PAGINATION_SEP}\'
if (!$template_row)
{
- trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
}
if (confirm_box(true))
@@ -311,12 +311,12 @@ pagination_sep = \'{PAGINATION_SEP}\'
if (!$theme_row)
{
- trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING);
}
if (!$theme_row['theme_storedb'])
{
- trigger_error($user->lang['THEME_ERR_REFRESH_FS'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['THEME_ERR_REFRESH_FS'] . adm_back_link($this->u_action), E_USER_WARNING);
}
if (confirm_box(true))
@@ -369,7 +369,7 @@ pagination_sep = \'{PAGINATION_SEP}\'
if (!$imageset_row)
{
- trigger_error($user->lang['NO_IMAGESET'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_IMAGESET'] . adm_back_link($this->u_action), E_USER_WARNING);
}
if (confirm_box(true))
@@ -397,9 +397,12 @@ pagination_sep = \'{PAGINATION_SEP}\'
}
unset($cfg_data);
- $sql = 'UPDATE ' . STYLES_IMAGESET_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . "
- WHERE imageset_id = $style_id";
- $db->sql_query($sql);
+ if (sizeof($sql_ary))
+ {
+ $sql = 'UPDATE ' . STYLES_IMAGESET_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . "
+ WHERE imageset_id = $style_id";
+ $db->sql_query($sql);
+ }
$cache->destroy('sql', STYLES_IMAGESET_TABLE);
@@ -533,7 +536,7 @@ pagination_sep = \'{PAGINATION_SEP}\'
while (($file = readdir($dp)) !== false)
{
$subpath = ($mode != 'style') ? "$mode/" : '';
- if ($file{0} != '.' && file_exists("{$phpbb_root_path}styles/$file/$subpath$mode.cfg"))
+ if ($file[0] != '.' && file_exists("{$phpbb_root_path}styles/$file/$subpath$mode.cfg"))
{
if ($cfg = file("{$phpbb_root_path}styles/$file/$subpath$mode.cfg"))
{
@@ -590,7 +593,7 @@ pagination_sep = \'{PAGINATION_SEP}\'
$_POST['template_data'] = (isset($_POST['template_data']) && !empty($_POST['template_data'])) ? str_replace(array("\r\n", "\r"), array("\n", "\n"), $_POST['template_data']) : '';
$template_data = (STRIP) ? stripslashes($_POST['template_data']) : $_POST['template_data'];
- $template_file = request_var('template_file', '');
+ $template_file = request_var('template_file', '');
$text_rows = max(5, min(999, request_var('text_rows', 20)));
$save_changes = (isset($_POST['save'])) ? true : false;
@@ -602,12 +605,13 @@ pagination_sep = \'{PAGINATION_SEP}\'
FROM ' . STYLES_TEMPLATE_TABLE . "
WHERE template_id = $template_id";
$result = $db->sql_query($sql);
+ $template_info = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
- if (!($template_info = $db->sql_fetchrow($result)))
+ if (!$template_info)
{
- trigger_error($user->lang['NO_TEMPLATE']);
+ trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
}
- $db->sql_freeresult($result);
// save changes to the template if the user submitted any
if ($save_changes && $template_file)
@@ -621,7 +625,7 @@ pagination_sep = \'{PAGINATION_SEP}\'
{
if (!($fp = fopen($file, 'wb')))
{
- trigger_error($user->lang['NO_TEMPLATE']);
+ trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
}
fwrite($fp, $template_data);
fclose($fp);
@@ -674,7 +678,7 @@ pagination_sep = \'{PAGINATION_SEP}\'
{
if (!file_exists($template_path . "/$template_file") || !($template_data = file_get_contents($template_path . "/$template_file")))
{
- trigger_error($user->lang['NO_TEMPLATE']);
+ trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
}
}
}
@@ -779,7 +783,7 @@ pagination_sep = \'{PAGINATION_SEP}\'
'SELECTED_TEMPLATE' => $template_info['template_name'],
'TEMPLATE_FILE' => $template_file,
- 'TEMPLATE_DATA' => htmlentities($template_data),
+ 'TEMPLATE_DATA' => htmlspecialchars($template_data),
'TEXT_ROWS' => $text_rows)
);
}
@@ -801,12 +805,13 @@ pagination_sep = \'{PAGINATION_SEP}\'
FROM ' . STYLES_TEMPLATE_TABLE . "
WHERE template_id = $template_id";
$result = $db->sql_query($sql);
+ $template_row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
- if (!($template_row = $db->sql_fetchrow($result)))
+ if (!$template_row)
{
- trigger_error($user->lang['NO_TEMPLATE']);
+ trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
}
- $db->sql_freeresult($result);
// User wants to delete one or more files ...
if ($submit && $file_ary)
@@ -941,7 +946,7 @@ pagination_sep = \'{PAGINATION_SEP}\'
if (!($theme_info = $db->sql_fetchrow($result)))
{
- trigger_error($user->lang['NO_THEME']);
+ trigger_error($user->lang['NO_THEME'] . adm_bacl_link($this->u_action), E_USER_WARNING);
}
$db->sql_freeresult($result);
@@ -951,7 +956,7 @@ pagination_sep = \'{PAGINATION_SEP}\'
{
if (!file_exists($stylesheet_path) || !($stylesheet = file_get_contents($stylesheet_path)))
{
- trigger_error($user->lang['NO_THEME']);
+ trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING);
}
}
else
@@ -961,7 +966,7 @@ pagination_sep = \'{PAGINATION_SEP}\'
// Pull out a list of classes
$classes = array();
- if (preg_match_all('/^([a-z0-9\.:#> \t]+?)[ \t\n]*?\{.*?\}/msi', $stylesheet, $matches))
+ if (preg_match_all('/^([a-z0-9\.,:#> \t]+?)[ \t\n]*?\{.*?\}/msi', $stylesheet, $matches))
{
$classes = $matches[1];
}
@@ -1007,7 +1012,7 @@ pagination_sep = \'{PAGINATION_SEP}\'
// Used in an sprintf statement to generate appropriate output for rawcss mode
$map_elements = array(
'colors' => '%s',
- 'sizes' => '%d',
+ 'sizes' => '%1.10f',
'images' => 'url(\'./%s\')',
'repeat' => '%s',
'other' => '%s',
@@ -1015,11 +1020,11 @@ pagination_sep = \'{PAGINATION_SEP}\'
$units = array('px', '%', 'em', 'pt');
$repeat_types = array(
- '' => $user->lang['UNSET'],
- 'none' => $user->lang['REPEAT_NO'],
- 'repeat-x' => $user->lang['REPEAT_X'],
- 'repeat-y' => $user->lang['REPEAT_Y'],
- 'both' => $user->lang['REPEAT_ALL'],
+ '' => $user->lang['UNSET'],
+ 'none' => $user->lang['REPEAT_NO'],
+ 'repeat-x' => $user->lang['REPEAT_X'],
+ 'repeat-y' => $user->lang['REPEAT_Y'],
+ 'both' => $user->lang['REPEAT_ALL'],
);
// Fill css_data with the class contents from the stylesheet
@@ -1030,7 +1035,7 @@ pagination_sep = \'{PAGINATION_SEP}\'
if (!isset($matches[1]))
{
- trigger_error($user->lang['NO_CLASS']);
+ trigger_error($user->lang['NO_CLASS'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$css_data = implode(";\n", array_diff(array_map('trim', explode("\n", preg_replace("#;[\n]*#s", "\n", $matches[1]))), array('')));
@@ -1183,11 +1188,11 @@ pagination_sep = \'{PAGINATION_SEP}\'
$value = '';
$unit = '';
- // retrieve and validate date for this setting
+ // retrieve and validate data for this setting
switch ($type)
{
case 'sizes':
- $value = request_var($var, 0);
+ $value = request_var($var, 0.0);
$unit = request_var($var . '_unit', '');
if ((request_var($var, '') === '') || !in_array($unit, $units))
@@ -1227,7 +1232,7 @@ pagination_sep = \'{PAGINATION_SEP}\'
// use the element mapping to create raw css code
if ($value !== '')
{
- $css_data .= $match . ': ' . sprintf($map_elements[$type], $value) . $unit . ";\n";
+ $css_data .= $match . ': ' . ($type == 'sizes' ? rtrim(sprintf($map_elements[$type], $value), '0') : sprintf($map_elements[$type], $value)) . $unit . ";\n";
}
}
}
@@ -1262,7 +1267,7 @@ pagination_sep = \'{PAGINATION_SEP}\'
// check whether the custom class name is valid
if (!preg_match('/^[a-z0-9#:.\- ]+$/i', $add_custom))
{
- trigger_error($user->lang['THEME_ERR_CLASS_CHARS'] . adm_back_link($this->u_action . "&amp;action=edit&amp;id=$theme_id&amp;text_rows=$text_rows"));
+ trigger_error($user->lang['THEME_ERR_CLASS_CHARS'] . adm_back_link($this->u_action . "&amp;action=edit&amp;id=$theme_id&amp;text_rows=$text_rows"), E_USER_WARNING);
}
else
{
@@ -1278,7 +1283,7 @@ pagination_sep = \'{PAGINATION_SEP}\'
// write stylesheet to file
if (!($fp = fopen($stylesheet_path, 'wb')))
{
- trigger_error($user->lang['NO_THEME']);
+ trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING);
}
fwrite($fp, $stylesheet);
fclose($fp);
@@ -1348,16 +1353,19 @@ pagination_sep = \'{PAGINATION_SEP}\'
if ($imageset_id)
{
$sql_select = ($imgname) ? ", $imgname" : '';
+
$sql = "SELECT imageset_path, imageset_name, imageset_copyright$sql_select
FROM " . STYLES_IMAGESET_TABLE . "
WHERE imageset_id = $imageset_id";
$result = $db->sql_query($sql);
+ $imageset_row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
- if (!extract($db->sql_fetchrow($result)))
+ if (!$imageset_row)
{
- trigger_error($user->lang['NO_IMAGESET']);
+ trigger_error($user->lang['NO_IMAGESET'] . adm_back_link($this->u_action), E_USER_WARNING);
}
- $db->sql_freeresult($result);
+ extract($imageset_row);
// Check to see whether the selected image exists in the table
$valid_name = ($update) ? false : true;
@@ -1431,7 +1439,7 @@ pagination_sep = \'{PAGINATION_SEP}\'
$dp = opendir($dir);
while (($file = readdir($dp)) !== false)
{
- if (!is_file($dir . '/' . $file) && !is_link($dir . '/' . $file) && $file{0} != '.' && strtoupper($file) != 'CVS' && !sizeof($imagesetlist['lang']))
+ if (!is_file($dir . '/' . $file) && !is_link($dir . '/' . $file) && $file[0] != '.' && strtoupper($file) != 'CVS' && !sizeof($imagesetlist['lang']))
{
$dp2 = opendir("$dir/$file");
while (($file2 = readdir($dp2)) !== false)
@@ -1540,7 +1548,7 @@ pagination_sep = \'{PAGINATION_SEP}\'
if (!$style_row)
{
- trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING);
}
$sql = "SELECT {$mode}_id, {$mode}_name
@@ -1561,7 +1569,7 @@ pagination_sep = \'{PAGINATION_SEP}\'
}
else
{
- trigger_error($user->lang['ONLY_' . $l_prefix] . adm_back_link($this->u_action));
+ trigger_error($user->lang['ONLY_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING);
}
$db->sql_freeresult($result);
@@ -1719,7 +1727,7 @@ pagination_sep = \'{PAGINATION_SEP}\'
if (!$style_row)
{
- trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING);
}
$var_ary = array('style_id', 'style_name', 'style_copyright', 'template_id', 'template_name', 'template_path', 'template_copyright', 'template_storedb', 'bbcode_bitfield', 'theme_id', 'theme_name', 'theme_path', 'theme_copyright', 'theme_storedb', 'theme_mtime', 'theme_data', 'imageset_id', 'imageset_name', 'imageset_path', 'imageset_copyright');
@@ -1843,7 +1851,7 @@ pagination_sep = \'{PAGINATION_SEP}\'
{
foreach ($key_array as $key)
{
- $imageset_cfg .= "\n" . $key . ' = ' . str_replace("styles/{$style_row['imageset_path']}/imageset/", '{PATH}', $style_row[$key]);
+ $imageset_cfg .= "\nimg_" . $key . ' = ' . str_replace("styles/{$style_row['imageset_path']}/imageset/", '{PATH}', $style_row[$key]);
}
}
@@ -1951,7 +1959,7 @@ pagination_sep = \'{PAGINATION_SEP}\'
if (!$style_row)
{
- trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING);
}
$this->page_title = $l_prefix . '_EXPORT';
@@ -2021,7 +2029,7 @@ pagination_sep = \'{PAGINATION_SEP}\'
if (!$style_row)
{
- trigger_error($user->lang['NO_' . $l_type] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_' . $l_type] . adm_back_link($this->u_action), E_USER_WARNING);
}
$style_row['style_default'] = ($mode == 'style' && $config['default_style'] == $style_id) ? 1 : 0;
@@ -2057,12 +2065,12 @@ pagination_sep = \'{PAGINATION_SEP}\'
if (!sizeof($error))
{
// Check length settings
- if (strlen($name) > 30)
+ if (utf8_strlen($name) > 30)
{
$error[] = $user->lang[$l_type . '_ERR_NAME_LONG'];
}
- if (strlen($copyright) > 60)
+ if (utf8_strlen($copyright) > 60)
{
$error[] = $user->lang[$l_type . '_ERR_COPY_LONG'];
}
@@ -2308,7 +2316,7 @@ pagination_sep = \'{PAGINATION_SEP}\'
{
foreach ($matches[0] as $idx => $match)
{
- $stylesheet = str_replace($match, $this->load_css_file($theme_row['theme_path'], $matches[1][$idx]), $stylesheet);
+ $stylesheet = str_replace($match, acp_styles::load_css_file($theme_row['theme_path'], $matches[1][$idx]), $stylesheet);
}
}
@@ -2331,7 +2339,7 @@ pagination_sep = \'{PAGINATION_SEP}\'
{
if (!($fp = fopen("{$phpbb_root_path}styles/$template_path$pathfile$file", 'r')))
{
- trigger_error("Could not open {$phpbb_root_path}styles/$template_path$pathfile$file");
+ trigger_error("Could not open {$phpbb_root_path}styles/$template_path$pathfile$file", E_USER_ERROR);
}
$template_data = fread($fp, filesize("{$phpbb_root_path}styles/$template_path$pathfile$file"));
fclose($fp);
@@ -2396,7 +2404,7 @@ pagination_sep = \'{PAGINATION_SEP}\'
if (!($dp = @opendir("{$phpbb_root_path}cache")))
{
- trigger_error($user->lang['TEMPLATE_ERR_CACHE_READ']);
+ trigger_error($user->lang['TEMPLATE_ERR_CACHE_READ'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$file_ary = array();
@@ -2538,7 +2546,7 @@ pagination_sep = \'{PAGINATION_SEP}\'
}
else
{
- trigger_error($user->lang['NO_' . $l_type] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_' . $l_type] . adm_back_link($this->u_action), E_USER_WARNING);
}
$style_row['store_db'] = request_var('store_db', 0);
@@ -2822,12 +2830,12 @@ pagination_sep = \'{PAGINATION_SEP}\'
}
// Check length settings
- if (strlen($name) > 30)
+ if (utf8_strlen($name) > 30)
{
$error[] = $user->lang['STYLE_ERR_NAME_LONG'];
}
- if (strlen($copyright) > 60)
+ if (utf8_strlen($copyright) > 60)
{
$error[] = $user->lang['STYLE_ERR_COPY_LONG'];
}
@@ -2932,12 +2940,12 @@ pagination_sep = \'{PAGINATION_SEP}\'
}
// Check length settings
- if (strlen($name) > 30)
+ if (utf8_strlen($name) > 30)
{
$error[] = $user->lang[$l_type . '_ERR_NAME_LONG'];
}
- if (strlen($copyright) > 60)
+ if (utf8_strlen($copyright) > 60)
{
$error[] = $user->lang[$l_type . '_ERR_COPY_LONG'];
}
diff --git a/phpBB/includes/acp/acp_update.php b/phpBB/includes/acp/acp_update.php
new file mode 100644
index 0000000000..fac20449bc
--- /dev/null
+++ b/phpBB/includes/acp/acp_update.php
@@ -0,0 +1,61 @@
+<?php
+/**
+*
+* @package acp
+* @version $Id$
+* @copyright (c) 2005 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+/**
+* @package acp
+*/
+class acp_update
+{
+ var $u_action;
+
+ function main($id, $mode)
+ {
+ global $config, $db, $user, $auth, $template, $cache;
+ global $phpbb_root_path, $phpbb_admin_path, $phpEx;
+
+ $user->add_lang('install');
+
+ $this->tpl_name = 'acp_update';
+ $this->page_title = 'ACP_UPDATE';
+
+ // Get current and latest version
+ $errstr = '';
+ $errno = 0;
+
+ $info = get_remote_file('www.phpbb.com', '/updatecheck', '30x.txt', $errstr, $errno);
+
+ if ($info === false)
+ {
+ trigger_error($errstr . adm_back_link($this->u_action));
+ }
+
+ $info = explode("\n", $info);
+ $latest_version = trim($info[0]);
+
+ $announcement_url = trim($info[1]);
+ $update_archive_link = 'http://www.phpbb.com/files/releases/phpBB-' . $config['version'] . '_to_' . $latest_version . '.zip';
+ $update_link = append_sid($phpbb_root_path . 'install/index.' . $phpEx, 'mode=update');
+
+ $up_to_date = (version_compare(strtolower($config['version']), strtolower($latest_version), '<')) ? false : true;
+
+ $template->assign_vars(array(
+ 'S_UP_TO_DATE' => $up_to_date,
+ 'S_VERSION_CHECK' => true,
+ 'U_ACTION' => $this->u_action,
+
+ 'LATEST_VERSION' => $latest_version,
+ 'CURRENT_VERSION' => $config['version'],
+
+ 'UPDATE_INSTRUCTIONS' => sprintf($user->lang['UPDATE_INSTRUCTIONS'], $announcement_url, $update_archive_link, $update_link),
+ ));
+ }
+}
+
+?> \ No newline at end of file
diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php
index e658609c5f..30c4e27b63 100644
--- a/phpBB/includes/acp/acp_users.php
+++ b/phpBB/includes/acp/acp_users.php
@@ -34,7 +34,7 @@ class acp_users
include($phpbb_root_path . 'includes/functions_profile_fields.' . $phpEx);
$error = array();
- $username = request_var('username', '');
+ $username = request_var('username', '', true);
$user_id = request_var('u', 0);
$action = request_var('action', '');
@@ -53,7 +53,7 @@ class acp_users
if ($ipwhois = user_ipwhois($user_ip))
{
$ipwhois = preg_replace('#(\s)([\w\-\._\+]+@[\w\-\.]+)(\s)#', '\1<a href="mailto:\2">\2</a>\3', $ipwhois);
- $ipwhois = preg_replace('#(\s)(http:/{2}[^\s]*)(\s)#', '\1<a href="\2" target="_blank">\2</a>\3', $ipwhois);
+ $ipwhois = preg_replace('#(\s)(http:/{2}[^\s]*)(\s)#', '\1<a href="\2">\2</a>\3', $ipwhois);
}
$template->assign_vars(array(
@@ -75,6 +75,7 @@ class acp_users
'S_SELECT_USER' => true,
'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&amp;form=select_user&amp;field=username'),
+ 'UA_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=select_user&field=username', false),
)
);
@@ -85,14 +86,14 @@ class acp_users
{
$sql = 'SELECT user_id
FROM ' . USERS_TABLE . "
- WHERE username = '" . $db->sql_escape($username) . "'";
+ WHERE username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'";
$result = $db->sql_query($sql);
$user_id = (int) $db->sql_fetchfield('user_id');
$db->sql_freeresult($result);
if (!$user_id)
{
- trigger_error($user->lang['NO_USER'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_USER'] . adm_back_link($this->u_action), E_USER_WARNING);
}
}
@@ -108,7 +109,7 @@ class acp_users
if (!$user_row)
{
- trigger_error($user->lang['NO_USER'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_USER'] . adm_back_link($this->u_action), E_USER_WARNING);
}
// Generate overall "header" for user admin
@@ -139,7 +140,7 @@ class acp_users
// Prevent normal users/admins change/view founders if they are not a founder by themselves
if ($user->data['user_type'] != USER_FOUNDER && $user_row['user_type'] == USER_FOUNDER)
{
- trigger_error($user->lang['NOT_MANAGE_FOUNDER'] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
+ trigger_error($user->lang['NOT_MANAGE_FOUNDER'] . adm_back_link($this->u_action . '&amp;u=' . $user_id), E_USER_WARNING);
}
switch ($mode)
@@ -157,23 +158,23 @@ class acp_users
{
if (!$auth->acl_get('a_userdel'))
{
- trigger_error($user->lang['NO_ADMIN'] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
+ trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action . '&amp;u=' . $user_id), E_USER_WARNING);
}
// Check if the user wants to remove himself or the guest user account
if ($user_id == ANONYMOUS)
{
- trigger_error($user->lang['CANNOT_REMOVE_ANONYMOUS'] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
+ trigger_error($user->lang['CANNOT_REMOVE_ANONYMOUS'] . adm_back_link($this->u_action . '&amp;u=' . $user_id), E_USER_WARNING);
}
if ($user_id == $user->data['user_id'])
{
- trigger_error($user->lang['CANNOT_REMOVE_YOURSELF'] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
+ trigger_error($user->lang['CANNOT_REMOVE_YOURSELF'] . adm_back_link($this->u_action . '&amp;u=' . $user_id), E_USER_WARNING);
}
if (confirm_box(true))
{
- user_delete($delete_type, $user_id);
+ user_delete($delete_type, $user_id, $user_row['username']);
add_log('admin', 'LOG_USER_DELETED', $user_row['username']);
trigger_error($user->lang['USER_DELETED'] . adm_back_link($this->u_action));
@@ -201,7 +202,12 @@ class acp_users
if ($user_id == $user->data['user_id'])
{
- trigger_error($user->lang['CANNOT_BAN_YOURSELF'] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
+ trigger_error($user->lang['CANNOT_BAN_YOURSELF'] . adm_back_link($this->u_action . '&amp;u=' . $user_id), E_USER_WARNING);
+ }
+
+ if ($user_row['user_type'] == USER_FOUNDER)
+ {
+ trigger_error($user->lang['CANNOT_BAN_FOUNDER'] . adm_back_link($this->u_action . '&amp;u=' . $user_id), E_USER_WARNING);
}
$ban = array();
@@ -241,8 +247,8 @@ class acp_users
user_ban(substr($action, 3), $ban, 0, 0, 0, $user->lang[$reason]);
- add_log('admin', $log, $user->lang[$reason]);
- add_log('user', $user_id, $log, $user->lang[$reason]);
+ add_log('admin', $log, $user->lang[$reason], implode(', ', $ban));
+ add_log('user', $user_id, $log, $user->lang[$reason], implode(', ', $ban));
trigger_error($user->lang['BAN_SUCCESSFUL'] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
@@ -252,7 +258,17 @@ class acp_users
if ($user_id == $user->data['user_id'])
{
- trigger_error($user->lang['CANNOT_FORCE_REACT_YOURSELF'] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
+ trigger_error($user->lang['CANNOT_FORCE_REACT_YOURSELF'] . adm_back_link($this->u_action . '&amp;u=' . $user_id), E_USER_WARNING);
+ }
+
+ if ($user_row['user_type'] == USER_FOUNDER)
+ {
+ trigger_error($user->lang['CANNOT_FORCE_REACT_FOUNDER'] . adm_back_link($this->u_action . '&amp;u=' . $user_id), E_USER_WARNING);
+ }
+
+ if ($user_row['user_type'] == USER_IGNORE)
+ {
+ trigger_error($user->lang['CANNOT_FORCE_REACT_BOT'] . adm_back_link($this->u_action . '&amp;u=' . $user_id), E_USER_WARNING);
}
if ($config['email_enable'])
@@ -266,9 +282,14 @@ class acp_users
$key_len = ($key_len > 6) ? $key_len : 6;
$user_actkey = substr($user_actkey, 0, $key_len);
- if ($user_row['user_type'] != USER_INACTIVE)
+ if ($user_row['user_type'] == USER_NORMAL)
{
- user_active_flip($user_id, $user_row['user_type'], $user_actkey, $user_row['username']);
+ user_active_flip('deactivate', $user_id, INACTIVE_REMIND);
+
+ $sql = 'UPDATE ' . USERS_TABLE . "
+ SET user_actkey = '" . $db->sql_escape($user_actkey) . "'
+ WHERE user_id = $user_id";
+ $db->sql_query($sql);
}
$messenger = new messenger(false);
@@ -284,11 +305,8 @@ class acp_users
$messenger->headers('X-AntiAbuse: User IP - ' . $user->ip);
$messenger->assign_vars(array(
- 'SITENAME' => $config['sitename'],
- 'WELCOME_MSG' => sprintf($user->lang['WELCOME_SUBJECT'], $config['sitename']),
- 'USERNAME' => html_entity_decode($user_row['username']),
- 'EMAIL_SIG' => str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']),
-
+ 'WELCOME_MSG' => htmlspecialchars_decode(sprintf($user->lang['WELCOME_SUBJECT'], $config['sitename'])),
+ 'USERNAME' => htmlspecialchars_decode($user_row['username']),
'U_ACTIVATE' => "$server_url/ucp.$phpEx?mode=activate&u={$user_row['user_id']}&k=$user_actkey")
);
@@ -307,27 +325,26 @@ class acp_users
if ($user_id == $user->data['user_id'])
{
// It is only deactivation since the user is already activated (else he would not have reached this page)
- trigger_error($user->lang['CANNOT_DEACTIVATE_YOURSELF'] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
+ trigger_error($user->lang['CANNOT_DEACTIVATE_YOURSELF'] . adm_back_link($this->u_action . '&amp;u=' . $user_id), E_USER_WARNING);
}
- user_active_flip($user_id, $user_row['user_type'], false, $user_row['username']);
-
- $message = ($user_row['user_type'] == USER_INACTIVE) ? 'USER_ADMIN_ACTIVATED' : 'USER_ADMIN_DEACTIVED';
- $log = ($user_row['user_type'] == USER_INACTIVE) ? 'LOG_USER_ACTIVE' : 'LOG_USER_INACTIVE';
-
- add_log('user', $user_id, $log . '_USER');
-
- if ($user_row['user_type'] == USER_INACTIVE)
+ if ($user_row['user_type'] == USER_FOUNDER)
{
- set_config('num_users', $config['num_users'] + 1, true);
+ trigger_error($user->lang['CANNOT_DEACTIVATE_FOUNDER'] . adm_back_link($this->u_action . '&amp;u=' . $user_id), E_USER_WARNING);
}
- else
+
+ if ($user_row['user_type'] == USER_IGNORE)
{
- set_config('num_users', $config['num_users'] - 1, true);
+ trigger_error($user->lang['CANNOT_DEACTIVATE_BOT'] . adm_back_link($this->u_action . '&amp;u=' . $user_id), E_USER_WARNING);
}
- // Update latest username
- update_last_username();
+ user_active_flip('flip', $user_id);
+
+ $message = ($user_row['user_type'] == USER_INACTIVE) ? 'USER_ADMIN_ACTIVATED' : 'USER_ADMIN_DEACTIVED';
+ $log = ($user_row['user_type'] == USER_INACTIVE) ? 'LOG_USER_ACTIVE' : 'LOG_USER_INACTIVE';
+
+ add_log('admin', $log, $user_row['username']);
+ add_log('user', $user_id, $log . '_USER');
trigger_error($user->lang[$message] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
@@ -338,7 +355,7 @@ class acp_users
$sql_ary = array(
'user_sig' => '',
'user_sig_bbcode_uid' => '',
- 'user_sig_bbcode_bitfield' => 0
+ 'user_sig_bbcode_bitfield' => ''
);
$sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . "
@@ -369,7 +386,7 @@ class acp_users
// Delete old avatar if present
if ($user_row['user_avatar'] && $user_row['user_avatar_type'] != AVATAR_GALLERY)
{
- avatar_delete($user_row['user_avatar']);
+ avatar_delete('user', $user_row);
}
add_log('admin', 'LOG_USER_DEL_AVATAR', $user_row['username']);
@@ -599,32 +616,22 @@ class acp_users
break;
}
- $data = array();
-
// Handle registration info updates
- $var_ary = array(
- 'user' => (string) $user_row['username'],
- 'user_founder' => (int) (($user_row['user_type'] == USER_FOUNDER) ? 1 : 0),
- 'user_email' => (string) $user_row['user_email'],
- 'email_confirm' => (string) '',
- 'user_password' => (string) '',
- 'password_confirm' => (string) '',
- 'warnings' => (int) $user_row['user_warnings'],
+ $data = array(
+ 'username' => request_var('user', $user_row['username'], true),
+ 'user_founder' => request_var('user_founder', ($user_row['user_type'] == USER_FOUNDER) ? 1 : 0),
+ 'email' => request_var('user_email', $user_row['user_email']),
+ 'email_confirm' => request_var('email_confirm', ''),
+ 'user_password' => request_var('user_password', '', true),
+ 'password_confirm' => request_var('password_confirm', '', true),
+ 'warnings' => request_var('warnings', $user_row['user_warnings']),
);
- // Get the data from the form. Use data from the database if no info is provided
- foreach ($var_ary as $var => $default)
- {
- $data[$var] = request_var($var, $default);
- }
-
- // We use user within the form to circumvent auto filling
- $data['username'] = $data['user'];
- unset($data['user']);
-
- // Validation data
- $var_ary = array(
- 'user_password' => array('string', true, $config['min_pass_chars'], $config['max_pass_chars']),
+ // Validation data - we do not check the password complexity setting here
+ $check_ary = array(
+ 'user_password' => array(
+ array('string', true, $config['min_pass_chars'], $config['max_pass_chars']),
+ array('password')),
'password_confirm' => array('string', true, $config['min_pass_chars'], $config['max_pass_chars']),
'warnings' => array('num'),
);
@@ -632,7 +639,7 @@ class acp_users
// Check username if altered
if ($data['username'] != $user_row['username'])
{
- $var_ary += array(
+ $check_ary += array(
'username' => array(
array('string', false, $config['min_name_chars'], $config['max_name_chars']),
array('username', $user_row['username'])),
@@ -640,10 +647,10 @@ class acp_users
}
// Check email if altered
- if ($data['user_email'] != $user_row['user_email'])
+ if ($data['email'] != $user_row['user_email'])
{
- $var_ary += array(
- 'user_email' => array(
+ $check_ary += array(
+ 'email' => array(
array('string', false, 6, 60),
array('email', $user_row['user_email'])
),
@@ -651,14 +658,14 @@ class acp_users
);
}
- $error = validate_data($data, $var_ary);
+ $error = validate_data($data, $check_ary);
if ($data['user_password'] && $data['password_confirm'] != $data['user_password'])
{
$error[] = 'NEW_PASSWORD_ERROR';
}
- if ($data['user_email'] != $user_row['user_email'] && $data['email_confirm'] != $data['user_email'])
+ if ($data['email'] != $user_row['user_email'] && $data['email_confirm'] != $data['email'])
{
$error[] = 'NEW_EMAIL_ERROR';
}
@@ -667,7 +674,7 @@ class acp_users
$update_warning = ($user_row['user_warnings'] != $data['warnings']) ? true : false;
$update_username = ($user_row['username'] != $data['username']) ? $data['username'] : false;
$update_password = ($data['user_password'] && $user_row['user_password'] != md5($data['user_password'])) ? true : false;
- $update_email = ($data['user_email'] != $user_row['user_email']) ? $data['user_email'] : false;
+ $update_email = ($data['email'] != $user_row['user_email']) ? $data['email'] : false;
if (!sizeof($error))
{
@@ -686,6 +693,17 @@ class acp_users
// Setting a normal member to be a founder
if ($data['user_founder'] && $user_row['user_type'] != USER_FOUNDER)
{
+ // Make sure the user is not setting an Inactive or ignored user to be a founder
+ if ($user_row['user_type'] == USER_IGNORE)
+ {
+ trigger_error($user->lang['CANNOT_SET_FOUNDER_BOT'] . adm_back_link($this->u_action . '&amp;u=' . $user_id), E_USER_WARNING);
+ }
+
+ if ($user_row['user_type'] == USER_INACTIVE)
+ {
+ trigger_error($user->lang['CANNOT_SET_FOUNDER_INACTIVE'] . adm_back_link($this->u_action . '&amp;u=' . $user_id), E_USER_WARNING);
+ }
+
$sql_ary['user_type'] = USER_FOUNDER;
}
else if (!$data['user_founder'] && $user_row['user_type'] == USER_FOUNDER)
@@ -705,7 +723,7 @@ class acp_users
}
else
{
- trigger_error($user->lang['AT_LEAST_ONE_FOUNDER'] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
+ trigger_error($user->lang['AT_LEAST_ONE_FOUNDER'] . adm_back_link($this->u_action . '&amp;u=' . $user_id), E_USER_WARNING);
}
}
}
@@ -714,6 +732,7 @@ class acp_users
if ($update_username !== false)
{
$sql_ary['username'] = $update_username;
+ $sql_ary['username_clean'] = utf8_clean_string($update_username);
add_log('user', $user_id, 'LOG_USER_UPDATE_NAME', $user_row['username'], $update_username);
}
@@ -772,6 +791,7 @@ class acp_users
}
$user_char_ary = array('.*' => 'USERNAME_CHARS_ANY', '[\w]+' => 'USERNAME_ALPHA_ONLY', '[\w_\+\. \-\[\]]+' => 'USERNAME_ALPHA_SPACERS');
+ $pass_char_ary = array('.*' => 'PASS_TYPE_ANY', '[a-zA-Z]' => 'PASS_TYPE_CASE', '[a-zA-Z0-9]' => 'PASS_TYPE_ALPHA', '[a-zA-Z\W]' => 'PASS_TYPE_SYMBOL');
if ($user_id == $user->data['user_id'])
{
@@ -779,9 +799,21 @@ class acp_users
}
else
{
- $quick_tool_ary = array('banuser' => 'BAN_USER', 'banemail' => 'BAN_EMAIL', 'banip' => 'BAN_IP', 'active' => (($user_row['user_type'] == USER_INACTIVE) ? 'ACTIVATE' : 'DEACTIVATE'), 'delsig' => 'DEL_SIG', 'delavatar' => 'DEL_AVATAR', 'moveposts' => 'MOVE_POSTS', 'delposts' => 'DEL_POSTS', 'delattach' => 'DEL_ATTACH');
+ $quick_tool_ary = array();
+
+ if ($user_row['user_type'] != USER_FOUNDER)
+ {
+ $quick_tool_ary += array('banuser' => 'BAN_USER', 'banemail' => 'BAN_EMAIL', 'banip' => 'BAN_IP');
+ }
+
+ if ($user_row['user_type'] != USER_FOUNDER && $user_row['user_type'] != USER_IGNORE)
+ {
+ $quick_tool_ary += array('active' => (($user_row['user_type'] == USER_INACTIVE) ? 'ACTIVATE' : 'DEACTIVATE'));
+ }
- if ($config['email_enable'])
+ $quick_tool_ary += array('delsig' => 'DEL_SIG', 'delavatar' => 'DEL_AVATAR', 'moveposts' => 'MOVE_POSTS', 'delposts' => 'DEL_POSTS', 'delattach' => 'DEL_ATTACH');
+
+ if ($config['email_enable'] && ($user_row['user_type'] == USER_NORMAL || $user_row['user_type'] == USER_INACTIVE))
{
$quick_tool_ary['reactivate'] = 'FORCE';
}
@@ -793,9 +825,25 @@ class acp_users
$s_action_options .= '<option value="' . $value . '">' . $user->lang['USER_ADMIN_' . $lang] . '</option>';
}
+ if ($config['load_onlinetrack'])
+ {
+ $sql = 'SELECT MAX(session_time) AS session_time, MIN(session_viewonline) AS session_viewonline
+ FROM ' . SESSIONS_TABLE . "
+ WHERE session_user_id = $user_id";
+ $result = $db->sql_query($sql);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ $user_row['session_time'] = (isset($row['session_time'])) ? $row['session_time'] : 0;
+ $user_row['session_viewonline'] = (isset($row['session_viewonline'])) ? $row['session_viewonline'] : 0;
+ unset($row);
+ }
+
+ $last_visit = (!empty($user_row['session_time'])) ? $user_row['session_time'] : $user_row['user_lastvisit'];
+
$template->assign_vars(array(
- 'L_NAME_CHARS_EXPLAIN' => sprintf($user->lang[$user_char_ary[$config['allow_name_chars']] . '_EXPLAIN'], $config['min_name_chars'], $config['max_name_chars']),
- 'L_CHANGE_PASSWORD_EXPLAIN' => sprintf($user->lang['CHANGE_PASSWORD_EXPLAIN'], $config['min_pass_chars'], $config['max_pass_chars']),
+ 'L_NAME_CHARS_EXPLAIN' => sprintf($user->lang[$user_char_ary[str_replace('\\\\', '\\', $config['allow_name_chars'])] . '_EXPLAIN'], $config['min_name_chars'], $config['max_name_chars']),
+ 'L_CHANGE_PASSWORD_EXPLAIN' => sprintf($user->lang[$pass_char_ary[str_replace('\\\\', '\\', $config['pass_complex'])] . '_EXPLAIN'], $config['min_pass_chars'], $config['max_pass_chars']),
'S_FOUNDER' => ($user->data['user_type'] == USER_FOUNDER) ? true : false,
'S_OVERVIEW' => true,
@@ -803,6 +851,7 @@ class acp_users
'S_USER_FOUNDER' => ($user_row['user_type'] == USER_FOUNDER) ? true : false,
'S_ACTION_OPTIONS' => $s_action_options,
'S_OWN_ACCOUNT' => ($user_id == $user->data['user_id']) ? true : false,
+ 'S_USER_INACTIVE' => ($user_row['user_type'] == USER_INACTIVE) ? true : false,
'U_SHOW_IP' => $this->u_action . "&amp;u=$user_id&amp;ip=" . (($ip == 'ip') ? 'hostname' : 'ip'),
'U_WHOIS' => $this->u_action . "&amp;action=whois&amp;user_ip={$user_row['user_ip']}",
@@ -812,7 +861,7 @@ class acp_users
'USER' => $user_row['username'],
'USER_REGISTERED' => $user->format_date($user_row['user_regdate']),
'REGISTERED_IP' => ($ip == 'hostname') ? gethostbyaddr($user_row['user_ip']) : $user_row['user_ip'],
- 'USER_LASTACTIVE' => ($user_row['user_lastvisit']) ? $user->format_date($user_row['user_lastvisit']) : ' - ',
+ 'USER_LASTACTIVE' => ($last_visit) ? $user->format_date($last_visit) : ' - ',
'USER_EMAIL' => $user_row['user_email'],
'USER_WARNINGS' => $user_row['user_warnings'],
'USER_POSTS' => $user_row['user_posts'],
@@ -917,40 +966,45 @@ class acp_users
$cp = new custom_profile();
$cp_data = $cp_error = array();
- $data = array();
$sql = 'SELECT lang_id
FROM ' . LANG_TABLE . "
- WHERE lang_iso = '" . $db->sql_escape($user_row['user_lang']) . "'";
+ WHERE lang_iso = '" . $db->sql_escape($user->data['user_lang']) . "'";
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
$user_row['iso_lang_id'] = $row['lang_id'];
- if ($submit)
+ $data = array(
+ 'icq' => request_var('icq', $user_row['user_icq']),
+ 'aim' => request_var('aim', $user_row['user_aim']),
+ 'msn' => request_var('msn', $user_row['user_msnm']),
+ 'yim' => request_var('yim', $user_row['user_yim']),
+ 'jabber' => request_var('jabber', $user_row['user_jabber']),
+ 'website' => request_var('website', $user_row['user_website']),
+ 'location' => request_var('location', $user_row['user_from'], true),
+ 'occupation' => request_var('occupation', $user_row['user_occ'], true),
+ 'interests' => request_var('interests', $user_row['user_interests'], true),
+ 'bday_day' => 0,
+ 'bday_month' => 0,
+ 'bday_year' => 0,
+ );
+
+ utf8_normalize_nfc(array(&$data['location'], &$data['occupation'], &$data['interests']));
+
+ if ($user_row['user_birthday'])
{
- $var_ary = array(
- 'icq' => (string) '',
- 'aim' => (string) '',
- 'msn' => (string) '',
- 'yim' => (string) '',
- 'jabber' => (string) '',
- 'website' => (string) '',
- 'location' => (string) '',
- 'occupation' => (string) '',
- 'interests' => (string) '',
- 'bday_day' => 0,
- 'bday_month' => 0,
- 'bday_year' => 0,
- );
+ list($data['bday_day'], $data['bday_month'], $data['bday_year']) = explode('-', $user_row['user_birthday']);
+ }
- foreach ($var_ary as $var => $default)
- {
- $data[$var] = (in_array($var, array('location', 'occupation', 'interests'))) ? request_var($var, $default, true) : $data[$var] = request_var($var, $default);
- }
+ $data['bday_day'] = request_var('bday_day', $data['bday_day']);
+ $data['bday_month'] = request_var('bday_month', $data['bday_month']);
+ $data['bday_year'] = request_var('bday_year', $data['bday_year']);
- $var_ary = array(
+ if ($submit)
+ {
+ $error = validate_data($data, array(
'icq' => array(
array('string', true, 3, 15),
array('match', true, '#^[0-9]+$#i')),
@@ -969,9 +1023,7 @@ class acp_users
'bday_day' => array('num', true, 1, 31),
'bday_month' => array('num', true, 1, 12),
'bday_year' => array('num', true, 1901, gmdate('Y', time())),
- );
-
- $error = validate_data($data, $var_ary);
+ ));
// validate custom profile fields
$cp->submit_cp_field('profile', $user_row['iso_lang_id'], $cp_data, $cp_error);
@@ -1004,7 +1056,7 @@ class acp_users
// Update Custom Fields
if (sizeof($cp_data))
{
- switch (SQL_LAYER)
+ switch ($db->sql_layer)
{
case 'oracle':
case 'firebird':
@@ -1057,18 +1109,6 @@ class acp_users
$error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error);
}
- if (!isset($data['bday_day']))
- {
- if ($user_row['user_birthday'])
- {
- list($data['bday_day'], $data['bday_month'], $data['bday_year']) = explode('-', $user_row['user_birthday']);
- }
- else
- {
- $data['bday_day'] = $data['bday_month'] = $data['bday_year'] = 0;
- }
- }
-
$s_birthday_day_options = '<option value="0"' . ((!$data['bday_day']) ? ' selected="selected"' : '') . '>--</option>';
for ($i = 1; $i < 32; $i++)
{
@@ -1094,15 +1134,15 @@ class acp_users
unset($now);
$template->assign_vars(array(
- 'ICQ' => (isset($data['icq'])) ? $data['icq'] : $user_row['user_icq'],
- 'YIM' => (isset($data['yim'])) ? $data['yim'] : $user_row['user_yim'],
- 'AIM' => (isset($data['aim'])) ? $data['aim'] : $user_row['user_aim'],
- 'MSN' => (isset($data['msn'])) ? $data['msn'] : $user_row['user_msnm'],
- 'JABBER' => (isset($data['jabber'])) ? $data['jabber'] : $user_row['user_jabber'],
- 'WEBSITE' => (isset($data['website'])) ? $data['website']: $user_row['user_website'],
- 'LOCATION' => (isset($data['location'])) ? $data['location'] : $user_row['user_from'],
- 'OCCUPATION' => (isset($data['occupation'])) ? $data['occupation'] : $user_row['user_occ'],
- 'INTERESTS' => (isset($data['interests'])) ? $data['interests'] : $user_row['user_interests'],
+ 'ICQ' => $data['icq'],
+ 'YIM' => $data['yim'],
+ 'AIM' => $data['aim'],
+ 'MSN' => $data['msn'],
+ 'JABBER' => $data['jabber'],
+ 'WEBSITE' => $data['website'],
+ 'LOCATION' => $data['location'],
+ 'OCCUPATION' => $data['occupation'],
+ 'INTERESTS' => $data['interests'],
'S_BIRTHDAY_DAY_OPTIONS' => $s_birthday_day_options,
'S_BIRTHDAY_MONTH_OPTIONS' => $s_birthday_month_options,
@@ -1120,51 +1160,44 @@ class acp_users
case 'prefs':
- $data = array();
+ $data = array(
+ 'dateformat' => request_var('dateformat', $user_row['user_dateformat']),
+ 'lang' => request_var('lang', $user_row['user_lang']),
+ 'tz' => request_var('tz', (float) $user_row['user_timezone']),
+ 'style' => request_var('style', $user_row['user_style']),
+ 'dst' => request_var('dst', $user_row['user_dst']),
+ 'viewemail' => request_var('viewemail', $user_row['user_allow_viewemail']),
+ 'massemail' => request_var('massemail', $user_row['user_allow_massemail']),
+ 'hideonline' => request_var('hideonline', !$user_row['user_allow_viewonline']),
+ 'notifymethod' => request_var('notifymethod', $user_row['user_notify_type']),
+ 'notifypm' => request_var('notifypm', $user_row['user_notify_pm']),
+ 'popuppm' => request_var('popuppm', $this->optionget($user_row, 'popuppm')),
+ 'allowpm' => request_var('allowpm', $user_row['user_allow_pm']),
+
+ 'topic_sk' => request_var('topic_sk', ($user_row['user_topic_sortby_type']) ? $user_row['user_topic_sortby_type'] : 't'),
+ 'topic_sd' => request_var('topic_sd', ($user_row['user_topic_sortby_dir']) ? $user_row['user_topic_sortby_dir'] : 'd'),
+ 'topic_st' => request_var('topic_st', ($user_row['user_topic_show_days']) ? $user_row['user_topic_show_days'] : 0),
+
+ 'post_sk' => request_var('post_sk', ($user_row['user_post_sortby_type']) ? $user_row['user_post_sortby_type'] : 't'),
+ 'post_sd' => request_var('post_sd', ($user_row['user_post_sortby_dir']) ? $user_row['user_post_sortby_dir'] : 'a'),
+ 'post_st' => request_var('post_st', ($user_row['user_post_show_days']) ? $user_row['user_post_show_days'] : 0),
+
+ 'view_images' => request_var('view_images', $this->optionget($user_row, 'viewimg')),
+ 'view_flash' => request_var('view_flash', $this->optionget($user_row, 'viewflash')),
+ 'view_smilies' => request_var('view_smilies', $this->optionget($user_row, 'viewsmilies')),
+ 'view_sigs' => request_var('view_sigs', $this->optionget($user_row, 'viewsigs')),
+ 'view_avatars' => request_var('view_avatars', $this->optionget($user_row, 'viewavatars')),
+ 'view_wordcensor' => request_var('view_wordcensore', $this->optionget($user_row, 'viewcensors')),
+
+ 'bbcode' => request_var('bbcode', $this->optionget($user_row, 'bbcode')),
+ 'smilies' => request_var('smilies', $this->optionget($user_row, 'smilies')),
+ 'sig' => request_var('sig', $this->optionget($user_row, 'attachsig')),
+ 'notify' => request_var('notify', $user_row['user_notify']),
+ );
if ($submit)
{
- $var_ary = array(
- 'dateformat' => (string) $config['default_dateformat'],
- 'lang' => (string) $config['default_lang'],
- 'tz' => (float) $config['board_timezone'],
- 'style' => (int) $config['default_style'],
- 'dst' => (bool) $config['board_dst'],
- 'viewemail' => false,
- 'massemail' => true,
- 'hideonline' => false,
- 'notifymethod' => 0,
- 'notifypm' => true,
- 'popuppm' => false,
- 'allowpm' => true,
-
- 'topic_sk' => (string) 't',
- 'topic_sd' => (string) 'd',
- 'topic_st' => 0,
-
- 'post_sk' => (string) 't',
- 'post_sd' => (string) 'a',
- 'post_st' => 0,
-
- 'view_images' => true,
- 'view_flash' => false,
- 'view_smilies' => true,
- 'view_sigs' => true,
- 'view_avatars' => true,
- 'view_wordcensor' => false,
-
- 'bbcode' => true,
- 'smilies' => true,
- 'sig' => true,
- 'notify' => false,
- );
-
- foreach ($var_ary as $var => $default)
- {
- $data[$var] = request_var($var, $default);
- }
-
- $var_ary = array(
+ $error = validate_data($data, array(
'dateformat' => array('string', false, 3, 30),
'lang' => array('match', false, '#^[a-z_\-]{2,}$#i'),
'tz' => array('num', false, -14, 14),
@@ -1173,9 +1206,7 @@ class acp_users
'topic_sd' => array('string', false, 1, 1),
'post_sk' => array('string', false, 1, 1),
'post_sd' => array('string', false, 1, 1),
- );
-
- $error = validate_data($data, $var_ary);
+ ));
if (!sizeof($error))
{
@@ -1229,17 +1260,10 @@ class acp_users
$error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error);
}
- $notify_method = (isset($data['notifymethod'])) ? $data['notifymethod'] : $user_row['user_notify_type'];
- $dateformat = (isset($data['dateformat'])) ? $data['dateformat'] : $user_row['user_dateformat'];
- $lang = (isset($data['lang'])) ? $data['lang'] : $user_row['user_lang'];
- $style = (isset($data['style'])) ? $data['style'] : $user_row['user_style'];
- $tz = (isset($data['tz'])) ? $data['tz'] : $user_row['user_timezone'];
-
$dateformat_options = '';
-
foreach ($user->lang['dateformats'] as $format => $null)
{
- $dateformat_options .= '<option value="' . $format . '"' . (($format == $dateformat) ? ' selected="selected"' : '') . '>';
+ $dateformat_options .= '<option value="' . $format . '"' . (($format == $data['dateformat']) ? ' selected="selected"' : '') . '>';
$dateformat_options .= $user->format_date(time(), $format, true) . ((strpos($format, '|') !== false) ? ' [' . $user->lang['RELATIVE_DAYS'] . ']' : '');
$dateformat_options .= '</option>';
}
@@ -1247,22 +1271,13 @@ class acp_users
$s_custom = false;
$dateformat_options .= '<option value="custom"';
- if (!in_array($dateformat, array_keys($user->lang['dateformats'])))
+ if (!in_array($data['dateformat'], array_keys($user->lang['dateformats'])))
{
$dateformat_options .= ' selected="selected"';
$s_custom = true;
}
$dateformat_options .= '>' . $user->lang['CUSTOM_DATEFORMAT'] . '</option>';
- $topic_sk = (isset($data['topic_sk'])) ? $data['topic_sk'] : (($user_row['user_topic_sortby_type']) ? $user_row['user_topic_sortby_type'] : 't');
- $post_sk = (isset($data['post_sk'])) ? $data['post_sk'] : (($user_row['user_post_sortby_type']) ? $user_row['user_post_sortby_type'] : 't');
-
- $topic_sd = (isset($data['topic_sd'])) ? $data['topic_sd'] : (($user_row['user_topic_sortby_dir']) ? $user_row['user_topic_sortby_dir'] : 'd');
- $post_sd = (isset($data['post_sd'])) ? $data['post_sd'] : (($user_row['user_post_sortby_dir']) ? $user_row['user_post_sortby_dir'] : 'd');
-
- $topic_st = (isset($data['topic_st'])) ? $data['topic_st'] : (($user_row['user_topic_show_days']) ? $user_row['user_topic_show_days'] : 0);
- $post_st = (isset($data['post_st'])) ? $data['post_st'] : (($user_row['user_post_show_days']) ? $user_row['user_post_show_days'] : 0);
-
$sort_dir_text = array('a' => $user->lang['ASCENDING'], 'd' => $user->lang['DESCENDING']);
// Topic ordering options
@@ -1279,7 +1294,7 @@ class acp_users
${'s_limit_' . $sort_option . '_days'} = '<select name="' . $sort_option . '_st">';
foreach (${'limit_' . $sort_option . '_days'} as $day => $text)
{
- $selected = (${$sort_option . '_st'} == $day) ? ' selected="selected"' : '';
+ $selected = ($data[$sort_option . '_st'] == $day) ? ' selected="selected"' : '';
${'s_limit_' . $sort_option . '_days'} .= '<option value="' . $day . '"' . $selected . '>' . $text . '</option>';
}
${'s_limit_' . $sort_option . '_days'} .= '</select>';
@@ -1287,7 +1302,7 @@ class acp_users
${'s_sort_' . $sort_option . '_key'} = '<select name="' . $sort_option . '_sk">';
foreach (${'sort_by_' . $sort_option . '_text'} as $key => $text)
{
- $selected = (${$sort_option . '_sk'} == $key) ? ' selected="selected"' : '';
+ $selected = ($data[$sort_option . '_sk'] == $key) ? ' selected="selected"' : '';
${'s_sort_' . $sort_option . '_key'} .= '<option value="' . $key . '"' . $selected . '>' . $text . '</option>';
}
${'s_sort_' . $sort_option . '_key'} .= '</select>';
@@ -1295,7 +1310,7 @@ class acp_users
${'s_sort_' . $sort_option . '_dir'} = '<select name="' . $sort_option . '_sd">';
foreach ($sort_dir_text as $key => $value)
{
- $selected = (${$sort_option . '_sd'} == $key) ? ' selected="selected"' : '';
+ $selected = ($data[$sort_option . '_sd'] == $key) ? ' selected="selected"' : '';
${'s_sort_' . $sort_option . '_dir'} .= '<option value="' . $key . '"' . $selected . '>' . $value . '</option>';
}
${'s_sort_' . $sort_option . '_dir'} .= '</select>';
@@ -1303,28 +1318,28 @@ class acp_users
$template->assign_vars(array(
'S_PREFS' => true,
- 'S_JABBER_DISABLED' => ($config['jab_enable'] && $user->data['user_jabber'] && @extension_loaded('xml')) ? false : true,
+ 'S_JABBER_DISABLED' => ($config['jab_enable'] && $user_row['user_jabber'] && @extension_loaded('xml')) ? false : true,
- 'VIEW_EMAIL' => (isset($data['viewemail'])) ? $data['viewemail'] : $user_row['user_allow_viewemail'],
- 'MASS_EMAIL' => (isset($data['massemail'])) ? $data['massemail'] : $user_row['user_allow_massemail'],
- 'ALLOW_PM' => (isset($data['allowpm'])) ? $data['allowpm'] : $user_row['user_allow_pm'],
- 'HIDE_ONLINE' => (isset($data['hideonline'])) ? $data['hideonline'] : !$user_row['user_allow_viewonline'],
- 'NOTIFY_EMAIL' => ($notify_method == NOTIFY_EMAIL) ? true : false,
- 'NOTIFY_IM' => ($notify_method == NOTIFY_IM) ? true : false,
- 'NOTIFY_BOTH' => ($notify_method == NOTIFY_BOTH) ? true : false,
- 'NOTIFY_PM' => (isset($data['notifypm'])) ? $data['notifypm'] : $user_row['user_notify_pm'],
- 'POPUP_PM' => (isset($data['popuppm'])) ? $data['popuppm'] : $this->optionget($user_row, 'popuppm'),
- 'DST' => (isset($data['dst'])) ? $data['dst'] : $user_row['user_dst'],
- 'BBCODE' => (isset($data['bbcode'])) ? $data['bbcode'] : $this->optionget($user_row, 'bbcode'),
- 'SMILIES' => (isset($data['smilies'])) ? $data['smilies'] : $this->optionget($user_row, 'smilies'),
- 'ATTACH_SIG' => (isset($data['sig'])) ? $data['sig'] : $this->optionget($user_row, 'attachsig'),
- 'NOTIFY' => (isset($data['notify'])) ? $data['notify'] : $user_row['user_notify'],
- 'VIEW_IMAGES' => (isset($data['view_images'])) ? $data['view_images'] : $this->optionget($user_row, 'viewimg'),
- 'VIEW_FLASH' => (isset($data['view_flash'])) ? $data['view_flash'] : $this->optionget($user_row, 'viewflash'),
- 'VIEW_SMILIES' => (isset($data['view_smilies'])) ? $data['view_smilies'] : $this->optionget($user_row, 'viewsmilies'),
- 'VIEW_SIGS' => (isset($data['view_sigs'])) ? $data['view_sigs'] : $this->optionget($user_row, 'viewsigs'),
- 'VIEW_AVATARS' => (isset($data['view_avatars'])) ? $data['view_avatars'] : $this->optionget($user_row, 'viewavatars'),
- 'VIEW_WORDCENSOR' => (isset($data['view_wordcensor'])) ? $data['view_wordcensor'] : $this->optionget($user_row, 'viewcensors'),
+ 'VIEW_EMAIL' => $data['viewemail'],
+ 'MASS_EMAIL' => $data['massemail'],
+ 'ALLOW_PM' => $data['allowpm'],
+ 'HIDE_ONLINE' => $data['hideonline'],
+ 'NOTIFY_EMAIL' => ($data['notifymethod'] == NOTIFY_EMAIL) ? true : false,
+ 'NOTIFY_IM' => ($data['notifymethod'] == NOTIFY_IM) ? true : false,
+ 'NOTIFY_BOTH' => ($data['notifymethod'] == NOTIFY_BOTH) ? true : false,
+ 'NOTIFY_PM' => $data['notifypm'],
+ 'POPUP_PM' => $data['popuppm'],
+ 'DST' => $data['dst'],
+ 'BBCODE' => $data['bbcode'],
+ 'SMILIES' => $data['smilies'],
+ 'ATTACH_SIG' => $data['sig'],
+ 'NOTIFY' => $data['notify'],
+ 'VIEW_IMAGES' => $data['view_images'],
+ 'VIEW_FLASH' => $data['view_flash'],
+ 'VIEW_SMILIES' => $data['view_smilies'],
+ 'VIEW_SIGS' => $data['view_sigs'],
+ 'VIEW_AVATARS' => $data['view_avatars'],
+ 'VIEW_WORDCENSOR' => $data['view_wordcensor'],
'S_TOPIC_SORT_DAYS' => $s_limit_topic_days,
'S_TOPIC_SORT_KEY' => $s_sort_topic_key,
@@ -1333,15 +1348,15 @@ class acp_users
'S_POST_SORT_KEY' => $s_sort_post_key,
'S_POST_SORT_DIR' => $s_sort_post_dir,
- 'DATE_FORMAT' => $dateformat,
+ 'DATE_FORMAT' => $data['dateformat'],
'S_DATEFORMAT_OPTIONS' => $dateformat_options,
'S_CUSTOM_DATEFORMAT' => $s_custom,
'DEFAULT_DATEFORMAT' => $config['default_dateformat'],
'A_DEFAULT_DATEFORMAT' => addslashes($config['default_dateformat']),
- 'S_LANG_OPTIONS' => language_select($lang),
- 'S_STYLE_OPTIONS' => style_select($style),
- 'S_TZ_OPTIONS' => tz_select($tz, true),
+ 'S_LANG_OPTIONS' => language_select($data['lang']),
+ 'S_STYLE_OPTIONS' => style_select($data['style']),
+ 'S_TZ_OPTIONS' => tz_select($data['tz'], true),
)
);
@@ -1359,26 +1374,19 @@ class acp_users
{
$delete = request_var('delete', '');
- $var_ary = array(
- 'uploadurl' => (string) '',
- 'remotelink' => (string) '',
- 'width' => (string) '',
- 'height' => (string) '',
+ $data = array(
+ 'uploadurl' => request_var('uploadurl', ''),
+ 'remotelink' => request_var('remotelink', ''),
+ 'width' => request_var('width', ''),
+ 'height' => request_var('height', ''),
);
- foreach ($var_ary as $var => $default)
- {
- $data[$var] = request_var($var, $default);
- }
-
- $var_ary = array(
+ $error = validate_data($data, array(
'uploadurl' => array('string', true, 5, 255),
'remotelink' => array('string', true, 5, 255),
'width' => array('string', true, 1, 3),
'height' => array('string', true, 1, 3),
- );
-
- $error = validate_data($data, $var_ary);
+ ));
if (!sizeof($error))
{
@@ -1440,7 +1448,7 @@ class acp_users
// Delete old avatar if present
if ($user_row['user_avatar'] && $filename != $user_row['user_avatar'] && $user_row['user_avatar_type'] != AVATAR_GALLERY)
{
- avatar_delete($user_row['user_avatar']);
+ avatar_delete('user', $user_row);
}
}
@@ -1545,6 +1553,8 @@ class acp_users
$enable_urls = request_var('enable_urls', true);
$signature = request_var('signature', $user_row['user_sig'], true);
+ utf8_normalize_nfc(&$signature);
+
$preview = (isset($_POST['preview'])) ? true : false;
if ($submit || $preview)
@@ -1554,7 +1564,7 @@ class acp_users
$message_parser = new parse_message($signature);
// Allowing Quote BBCode
- $message_parser->parse($enable_bbcode, $enable_urls, $enable_smilies, $config['allow_sig_img'], $config['allow_sig_flash'], true, true, 'sig');
+ $message_parser->parse($enable_bbcode, ($config['allow_sig_links']) ? $enable_urls : false, $enable_smilies, $config['allow_sig_img'], $config['allow_sig_flash'], true, $config['allow_sig_links'], true, 'sig');
if (sizeof($message_parser->warn_msg))
{
@@ -1566,7 +1576,7 @@ class acp_users
$sql_ary = array(
'user_sig' => (string) $message_parser->message,
'user_sig_bbcode_uid' => (string) $message_parser->bbcode_uid,
- 'user_sig_bbcode_bitfield' => (int) $message_parser->bbcode_bitfield
+ 'user_sig_bbcode_bitfield' => (string) $message_parser->bbcode_bitfield
);
$sql = 'UPDATE ' . USERS_TABLE . '
@@ -1602,17 +1612,19 @@ class acp_users
'S_SMILIES_CHECKED' => (!$enable_smilies) ? 'checked="checked"' : '',
'S_MAGIC_URL_CHECKED' => (!$enable_urls) ? 'checked="checked"' : '',
- 'BBCODE_STATUS' => ($config['allow_sig_bbcode']) ? sprintf($user->lang['BBCODE_IS_ON'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '" onclick="target=\'_phpbbcode\';">', '</a>') : sprintf($user->lang['BBCODE_IS_OFF'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '" onclick="target=\'_phpbbcode\';">', '</a>'),
+ 'BBCODE_STATUS' => ($config['allow_sig_bbcode']) ? sprintf($user->lang['BBCODE_IS_ON'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>') : sprintf($user->lang['BBCODE_IS_OFF'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>'),
'SMILIES_STATUS' => ($config['allow_sig_smilies']) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'],
'IMG_STATUS' => ($config['allow_sig_img']) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'],
'FLASH_STATUS' => ($config['allow_sig_flash']) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'],
+ 'URL_STATUS' => ($config['allow_sig_links']) ? $user->lang['URL_IS_ON'] : $user->lang['URL_IS_OFF'],
'L_SIGNATURE_EXPLAIN' => sprintf($user->lang['SIGNATURE_EXPLAIN'], $config['max_sig_chars']),
'S_BBCODE_ALLOWED' => $config['allow_sig_bbcode'],
'S_SMILIES_ALLOWED' => $config['allow_sig_smilies'],
'S_BBCODE_IMG' => ($config['allow_sig_img']) ? true : false,
- 'S_BBCODE_FLASH' => ($config['allow_sig_flash']) ? true : false)
+ 'S_BBCODE_FLASH' => ($config['allow_sig_flash']) ? true : false,
+ 'S_LINKS_ALLOWED' => ($config['allow_sig_links']) ? true : false)
);
// Assigning custom bbcodes
@@ -1686,7 +1698,12 @@ class acp_users
$s_sort_dir .= '<option value="' . $key . '"' . $selected . '>' . $value . '</option>';
}
- $order_by = $sk_sql[$sort_key] . ' ' . (($sort_dir == 'a') ? 'ASC' : 'DESC');
+ if (!isset($sk_sql[$sort_key]))
+ {
+ $sort_key = 'a';
+ }
+
+ $order_by = $sk_sql[$sort_key] . ' ' . (($sort_dir == 'a') ? 'ASC' : 'DESC');
$sql = 'SELECT COUNT(attach_id) as num_attachments
FROM ' . ATTACHMENTS_TABLE . "
@@ -1772,12 +1789,12 @@ class acp_users
{
if (!$group_id)
{
- trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
+ trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action . '&amp;u=' . $user_id), E_USER_WARNING);
}
if ($error = group_user_del($group_id, $user_id))
{
- trigger_error($user->lang[$error] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
+ trigger_error($user->lang[$error] . adm_back_link($this->u_action . '&amp;u=' . $user_id), E_USER_WARNING);
}
$error = array();
@@ -1801,13 +1818,13 @@ class acp_users
{
if (!$group_id)
{
- trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
+ trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action . '&amp;u=' . $user_id), E_USER_WARNING);
}
// Add user/s to group
if ($error = group_user_add($group_id, $user_id))
{
- trigger_error($user->lang[$error] . adm_back_link($this->u_action . '&amp;u=' . $user_id));
+ trigger_error($user->lang[$error] . adm_back_link($this->u_action . '&amp;u=' . $user_id), E_USER_WARNING);
}
$error = array();
@@ -1847,11 +1864,11 @@ class acp_users
$s_group_options = '';
while ($row = $db->sql_fetchrow($result))
{
- if (!$config['coppa_enable'] && in_array($row['group_name'], array('INACTIVE_COPPA', 'REGISTERED_COPPA')))
+ if (!$config['coppa_enable'] && $row['group_name'] == 'REGISTERED_COPPA')
{
continue;
}
-
+
$s_group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '">' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . '</option>';
}
$db->sql_freeresult($result);
@@ -1899,14 +1916,14 @@ class acp_users
$auth_admin = new auth_admin();
$user->add_lang('acp/permissions');
- $user->add_lang('acp/permissions_phpbb');
+ add_permission_language();
// Select auth options
$sql = 'SELECT auth_option, is_local, is_global
FROM ' . ACL_OPTIONS_TABLE . "
WHERE auth_option LIKE '%\_'";
- if (SQL_LAYER == 'mssql' || SQL_LAYER == 'mssql_odbc')
+ if ($db->sql_layer == 'mssql' || $db->sql_layer == 'mssql_odbc')
{
$sql .= " ESCAPE '\\'";
}
@@ -1926,7 +1943,7 @@ class acp_users
FROM ' . ACL_OPTIONS_TABLE . "
WHERE auth_option LIKE '%\_'";
- if (SQL_LAYER == 'mssql' || SQL_LAYER == 'mssql_odbc')
+ if ($db->sql_layer == 'mssql' || $db->sql_layer == 'mssql_odbc')
{
$sql .= " ESCAPE '\\'";
}
diff --git a/phpBB/includes/acp/acp_words.php b/phpBB/includes/acp/acp_words.php
index cacea98d97..8fe99b8c80 100644
--- a/phpBB/includes/acp/acp_words.php
+++ b/phpBB/includes/acp/acp_words.php
@@ -40,7 +40,7 @@ class acp_words
if (!$word_id)
{
- trigger_error($user->lang['NO_WORD'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_WORD'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$sql = 'SELECT *
@@ -71,10 +71,12 @@ class acp_words
$word_id = request_var('id', 0);
$word = request_var('word', '', true);
$replacement = request_var('replacement', '', true);
+
+ utf8_normalize_nfc(array(&$word, &$replacement));
if (!$word || !$replacement)
{
- trigger_error($user->lang['ENTER_WORD'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['ENTER_WORD'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$sql_ary = array(
@@ -107,7 +109,7 @@ class acp_words
if (!$word_id)
{
- trigger_error($user->lang['NO_WORD'] . adm_back_link($this->u_action));
+ trigger_error($user->lang['NO_WORD'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$sql = 'SELECT word
diff --git a/phpBB/includes/acp/auth.php b/phpBB/includes/acp/auth.php
index 71d17bd40d..436e3f017b 100644
--- a/phpBB/includes/acp/auth.php
+++ b/phpBB/includes/acp/auth.php
@@ -724,24 +724,7 @@ class auth_admin extends auth
}
}
- if (sizeof($sql_ary))
- {
- switch (SQL_LAYER)
- {
- case 'mysql':
- case 'mysql4':
- case 'mysqli':
- $db->sql_query('INSERT INTO ' . ACL_OPTIONS_TABLE . ' ' . $db->sql_build_array('MULTI_INSERT', $sql_ary));
- break;
-
- default:
- foreach ($sql_ary as $ary)
- {
- $db->sql_query('INSERT INTO ' . ACL_OPTIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $ary));
- }
- break;
- }
- }
+ $db->sql_multi_insert(ACL_OPTIONS_TABLE, $sql_ary);
$cache->destroy('acl_options');
$this->acl_clear_prefetch();
@@ -874,24 +857,7 @@ class auth_admin extends auth
}
}
- if (sizeof($sql_ary))
- {
- switch (SQL_LAYER)
- {
- case 'mysql':
- case 'mysql4':
- case 'mysqli':
- $db->sql_query("INSERT INTO $table " . $db->sql_build_array('MULTI_INSERT', $sql_ary));
- break;
-
- default:
- foreach ($sql_ary as $ary)
- {
- $db->sql_query("INSERT INTO $table " . $db->sql_build_array('INSERT', $ary));
- }
- break;
- }
- }
+ $db->sql_multi_insert($table, $sql_ary);
if ($clear_prefetch)
{
@@ -956,21 +922,8 @@ class auth_admin extends auth
WHERE role_id = ' . $role_id;
$db->sql_query($sql);
- switch (SQL_LAYER)
- {
- case 'mysql':
- case 'mysql4':
- case 'mysqli':
- $db->sql_query('INSERT INTO ' . ACL_ROLES_DATA_TABLE . ' ' . $db->sql_build_array('MULTI_INSERT', $sql_ary));
- break;
-
- default:
- foreach ($sql_ary as $ary)
- {
- $db->sql_query('INSERT INTO ' . ACL_ROLES_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $ary));
- }
- break;
- }
+ // Now insert the new values
+ $db->sql_multi_insert(ACL_ROLES_DATA_TABLE, $sql_ary);
$this->acl_clear_prefetch();
}
@@ -1009,7 +962,9 @@ class auth_admin extends auth
// Get permission type
$sql = 'SELECT auth_option, auth_option_id
FROM ' . ACL_OPTIONS_TABLE . "
- WHERE auth_option LIKE '" . $db->sql_escape($permission_type) . "%'";
+ WHERE auth_option LIKE '" . $db->sql_escape(str_replace('_', "\_", $permission_type)) . "%'";
+ $sql .= ($db->sql_layer == 'mssql' || $db->sql_layer == 'mssql_odbc') ? " ESCAPE '\\'" : '';
+
$result = $db->sql_query($sql);
$auth_id_ary = array();
diff --git a/phpBB/includes/acp/info/acp_inactive.php b/phpBB/includes/acp/info/acp_inactive.php
new file mode 100755
index 0000000000..bee9d977d4
--- /dev/null
+++ b/phpBB/includes/acp/info/acp_inactive.php
@@ -0,0 +1,37 @@
+<?php
+/**
+*
+* @package acp
+* @version $Id$
+* @copyright (c) 2006 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+/**
+* @package module_install
+*/
+class acp_inactive_info
+{
+ function module()
+ {
+ return array(
+ 'filename' => 'acp_inactive',
+ 'title' => 'ACP_INACTIVE_USERS',
+ 'version' => '1.0.0',
+ 'modes' => array(
+ 'list' => array('title' => 'ACP_INACTIVE_USERS', 'auth' => 'acl_a_user', 'cat' => array('ACP_CAT_USERS')),
+ ),
+ );
+ }
+
+ function install()
+ {
+ }
+
+ function uninstall()
+ {
+ }
+}
+
+?> \ No newline at end of file
diff --git a/phpBB/includes/acp/info/acp_update.php b/phpBB/includes/acp/info/acp_update.php
new file mode 100644
index 0000000000..014d67ff2b
--- /dev/null
+++ b/phpBB/includes/acp/info/acp_update.php
@@ -0,0 +1,37 @@
+<?php
+/**
+*
+* @package acp
+* @version $Id$
+* @copyright (c) 2005 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+/**
+* @package module_install
+*/
+class acp_update_info
+{
+ function module()
+ {
+ return array(
+ 'filename' => 'acp_update',
+ 'title' => 'ACP_UPDATE',
+ 'version' => '1.0.0',
+ 'modes' => array(
+ 'version_check' => array('title' => 'ACP_VERSION_CHECK', 'auth' => 'acl_a_', 'cat' => array('ACP_AUTOMATION')),
+ ),
+ );
+ }
+
+ function install()
+ {
+ }
+
+ function uninstall()
+ {
+ }
+}
+
+?> \ No newline at end of file
diff --git a/phpBB/includes/auth.php b/phpBB/includes/auth.php
index 4e6a8af1d8..8ee4a23abb 100644
--- a/phpBB/includes/auth.php
+++ b/phpBB/includes/auth.php
@@ -396,7 +396,7 @@ class auth
$hold_str .= str_repeat("\n", $f - $last_f);
// Convert bitstring for storage - we do not use binary/bytes because PHP's string functions are not fully binary safe
- for ($i = 0; $i < strlen($bitstring); $i += 31)
+ for ($i = 0, $bit_length = strlen($bitstring); $i < $bit_length; $i += 31)
{
$hold_str .= str_pad(base_convert(str_pad(substr($bitstring, $i, 31), 31, 0, STR_PAD_RIGHT), 2, 36), 6, 0, STR_PAD_LEFT);
}
@@ -478,18 +478,11 @@ class auth
$sql_user = ($user_id !== false) ? ((!is_array($user_id)) ? "user_id = $user_id" : $db->sql_in_set('user_id', $user_id)) : '';
$sql_forum = ($forum_id !== false) ? ((!is_array($forum_id)) ? "AND a.forum_id = $forum_id" : 'AND ' . $db->sql_in_set('a.forum_id', $forum_id)) : '';
- $sql_opts = '';
+ $sql_opts = $sql_escape = '';
if ($opts !== false)
{
- if (!is_array($opts))
- {
- $sql_opts = (strpos($opts, '%') !== false) ? "AND ao.auth_option LIKE '" . $db->sql_escape($opts) . "'" : "AND ao.auth_option = '" . $db->sql_escape($opts) . "'";
- }
- else
- {
- $sql_opts = 'AND ' . $db->sql_in_set('ao.auth_option', $opts);
- }
+ $this->build_auth_option_statement('ao.auth_option', $opts, $sql_opts, $sql_escape);
}
$hold_ary = array();
@@ -519,7 +512,7 @@ class auth
'ORDER_BY' => 'a.forum_id, ao.auth_option'
));
- $result = $db->sql_query($sql);
+ $result = $db->sql_query($sql . $sql_escape);
while ($row = $db->sql_fetchrow($result))
{
@@ -595,18 +588,11 @@ class auth
$sql_user = ($user_id !== false) ? ((!is_array($user_id)) ? "user_id = $user_id" : $db->sql_in_set('user_id', $user_id)) : '';
$sql_forum = ($forum_id !== false) ? ((!is_array($forum_id)) ? "AND a.forum_id = $forum_id" : 'AND ' . $db->sql_in_set('a.forum_id', $forum_id)) : '';
- $sql_opts = '';
+ $sql_opts = $sql_escape = '';
if ($opts !== false)
{
- if (!is_array($opts))
- {
- $sql_opts = (strpos($opts, '%') !== false) ? "AND ao.auth_option LIKE '" . $db->sql_escape($opts) . "'" : "AND ao.auth_option = '" . $db->sql_escape($opts) . "'";
- }
- else
- {
- $sql_opts = 'AND ' . $db->sql_in_set('ao.auth_option', $opts);
- }
+ $this->build_auth_option_statement('ao.auth_option', $opts, $sql_opts, $sql_escape);
}
$hold_ary = array();
@@ -634,7 +620,7 @@ class auth
'ORDER_BY' => 'a.forum_id, ao.auth_option'
));
- $result = $db->sql_query($sql);
+ $result = $db->sql_query($sql . $sql_escape);
while ($row = $db->sql_fetchrow($result))
{
@@ -656,16 +642,11 @@ class auth
$sql_group = ($group_id !== false) ? ((!is_array($group_id)) ? "group_id = $group_id" : $db->sql_in_set('group_id', $group_id)) : '';
$sql_forum = ($forum_id !== false) ? ((!is_array($forum_id)) ? "AND a.forum_id = $forum_id" : 'AND ' . $db->sql_in_set('a.forum_id', $forum_id)) : '';
+ $sql_opts = $sql_escape = '';
+
if ($opts !== false)
{
- if (!is_array($opts))
- {
- $sql_opts = (strpos($opts, '%') !== false) ? "AND ao.auth_option LIKE '" . $db->sql_escape($opts) . "'" : "AND ao.auth_option = '" . $db->sql_escape($opts) . "'";
- }
- else
- {
- $sql_opts = 'AND ' . $db->sql_in_set('ao.auth_option', $opts);
- }
+ $this->build_auth_option_statement('ao.auth_option', $opts, $sql_opts, $sql_escape);
}
$hold_ary = array();
@@ -693,7 +674,7 @@ class auth
'ORDER_BY' => 'a.forum_id, ao.auth_option'
));
- $result = $db->sql_query($sql);
+ $result = $db->sql_query($sql . $sql_escape);
while ($row = $db->sql_fetchrow($result))
{
@@ -726,14 +707,14 @@ class auth
// we are going to use the user_add function so include functions_user.php if it wasn't defined yet
if (!function_exists('user_add'))
{
- include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx);
+ include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
}
user_add($login['user_row'], (isset($login['cp_data'])) ? $login['cp_data'] : false);
$sql = 'SELECT user_id, username, user_password, user_passchg, user_email, user_type
FROM ' . USERS_TABLE . "
- WHERE username = '" . $db->sql_escape($username) . "'";
+ WHERE username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'";
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
@@ -757,11 +738,36 @@ class auth
// If login succeeded, we will log the user in... else we pass the login array through...
if ($login['status'] == LOGIN_SUCCESS)
{
+ $old_session_id = $user->session_id;
+
+ if ($admin)
+ {
+ global $SID, $_SID;
+
+ $cookie_expire = time() - 31536000;
+ $user->set_cookie('u', '', $cookie_expire);
+ $user->set_cookie('sid', '', $cookie_expire);
+ unset($cookie_expire);
+
+ $SID = '?sid=';
+ $user->session_id = $_SID = '';
+ }
+
$result = $user->session_create($login['user_row']['user_id'], $admin, $autologin, $viewonline);
// Successful session creation
if ($result === true)
{
+ // If admin re-authentication we remove the old session entry because a new one has been created...
+ if ($admin)
+ {
+ // the login array is used because the user ids do not differ for re-authentication
+ $sql = 'DELETE FROM ' . SESSIONS_TABLE . "
+ WHERE session_id = '" . $db->sql_escape($old_session_id) . "'
+ AND session_user_id = {$login['user_row']['user_id']}";
+ $db->sql_query($sql);
+ }
+
return array(
'status' => LOGIN_SUCCESS,
'error_msg' => false,
@@ -781,6 +787,72 @@ class auth
trigger_error('Authentication method not found', E_USER_ERROR);
}
+
+ /**
+ * Fill auth_option statement for later querying based on the supplied options
+ */
+ function build_auth_option_statement($key, $auth_options, &$sql_opts, &$sql_escape)
+ {
+ global $db;
+
+ if (!is_array($auth_options))
+ {
+ if (strpos($auth_options, '%') !== false)
+ {
+ if (strpos($auth_options, '_') !== false)
+ {
+ $sql_opts = "AND $key LIKE '" . $db->sql_escape(str_replace('_', "\_", $auth_options)) . "'";
+ $sql_escape = ($db->sql_layer == 'mssql' || $db->sql_layer == 'mssql_odbc') ? " ESCAPE '\\'" : '';
+ }
+ else
+ {
+ $sql_opts = "AND $key LIKE '" . $db->sql_escape($auth_options) . "'";
+ }
+ }
+ else
+ {
+ $sql_opts = "AND $key = '" . $db->sql_escape($auth_options) . "'";
+ }
+ }
+ else
+ {
+ $is_like_expression = $is_underline = false;
+
+ foreach ($auth_options as $option)
+ {
+ if (strpos($option, '%') !== false)
+ {
+ $is_like_expression = true;
+ }
+
+ if (strpos($option, '_') !== false)
+ {
+ $is_underline = true;
+ }
+ }
+
+ if (!$is_like_expression)
+ {
+ $sql_opts = 'AND ' . $db->sql_in_set($key, $auth_options);
+ }
+ else
+ {
+ $sql = array();
+
+ foreach ($auth_options as $option)
+ {
+ $sql[] = $key . " LIKE '" . $db->sql_escape(str_replace('_', "\_", $option)) . "'";
+ }
+
+ $sql_opts = 'AND (' . implode(' OR ', $sql) . ')';
+
+ if ($is_underline)
+ {
+ $sql_escape = ($db->sql_layer == 'mssql' || $db->sql_layer == 'mssql_odbc') ? " ESCAPE '\\'" : '';
+ }
+ }
+ }
+ }
}
?> \ No newline at end of file
diff --git a/phpBB/includes/auth/auth_apache.php b/phpBB/includes/auth/auth_apache.php
index 3ee0f1347f..4c8293c707 100644
--- a/phpBB/includes/auth/auth_apache.php
+++ b/phpBB/includes/auth/auth_apache.php
@@ -136,12 +136,19 @@ function autologin_apache()
return ($row['user_type'] == USER_INACTIVE || $row['user_type'] == USER_IGNORE) ? array() : $row;
}
+ if (!function_exists('user_add'))
+ {
+ global $phpbb_root_path, $phpEx;
+
+ include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
+ }
+
// create the user if he does not exist yet
user_add(user_row_apache($php_auth_user, $php_auth_pw));
$sql = 'SELECT *
FROM ' . USERS_TABLE . "
- WHERE username = '" . $db->sql_escape($php_auth_user) . "'";
+ WHERE username_clean = '" . $db->sql_escape(utf8_clean_string($php_auth_user)) . "'";
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
@@ -178,7 +185,7 @@ function user_row_apache($username, $password)
// generate user account data
return array(
'username' => $username,
- 'user_password' => $password,
+ 'user_password' => md5($password),
'user_email' => '',
'group_id' => (int) $row['group_id'],
'user_type' => USER_NORMAL,
diff --git a/phpBB/includes/auth/auth_db.php b/phpBB/includes/auth/auth_db.php
index 9477fd92c3..618ad0a387 100644
--- a/phpBB/includes/auth/auth_db.php
+++ b/phpBB/includes/auth/auth_db.php
@@ -22,7 +22,7 @@ function login_db(&$username, &$password)
$sql = 'SELECT user_id, username, user_password, user_passchg, user_email, user_type, user_login_attempts
FROM ' . USERS_TABLE . "
- WHERE username = '" . $db->sql_escape($username) . "'";
+ WHERE username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'";
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
diff --git a/phpBB/includes/auth/auth_ldap.php b/phpBB/includes/auth/auth_ldap.php
index 889f6d8661..988da577c0 100644
--- a/phpBB/includes/auth/auth_ldap.php
+++ b/phpBB/includes/auth/auth_ldap.php
@@ -38,7 +38,7 @@ function init_ldap()
$search = @ldap_search(
$ldap,
$config['ldap_base_dn'],
- '(' . $config['ldap_uid'] . '=' . ldap_escape(html_entity_decode($user->data['username'])) . ')',
+ '(' . $config['ldap_uid'] . '=' . ldap_escape(htmlspecialchars_decode($user->data['username'])) . ')',
(empty($config['ldap_email'])) ? array($config['ldap_uid']) : array($config['ldap_uid'], $config['ldap_email']),
0,
1
@@ -98,7 +98,7 @@ function login_ldap(&$username, &$password)
$search = @ldap_search(
$ldap,
$config['ldap_base_dn'],
- '(' . $config['ldap_uid'] . '=' . ldap_escape(html_entity_decode($username)) . ')',
+ '(' . $config['ldap_uid'] . '=' . ldap_escape(htmlspecialchars_decode($username)) . ')',
(empty($config['ldap_email'])) ? array($config['ldap_uid']) : array($config['ldap_uid'], $config['ldap_email']),
0,
1
@@ -108,13 +108,13 @@ function login_ldap(&$username, &$password)
if (is_array($ldap_result) && sizeof($ldap_result) > 1)
{
- if (@ldap_bind($ldap, $ldap_result[0]['dn'], html_entity_decode($password)))
+ if (@ldap_bind($ldap, $ldap_result[0]['dn'], htmlspecialchars_decode($password)))
{
@ldap_close($ldap);
$sql ='SELECT user_id, username, user_password, user_passchg, user_email, user_type
FROM ' . USERS_TABLE . "
- WHERE username = '" . $db->sql_escape($username) . "'";
+ WHERE username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'";
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
@@ -159,7 +159,7 @@ function login_ldap(&$username, &$password)
// generate user account data
$ldap_user_row = array(
'username' => $username,
- 'user_password' => $password,
+ 'user_password' => md5($password),
'user_email' => (!empty($config['ldap_email'])) ? $ldap_result[0][$config['ldap_email']][0] : '',
'group_id' => (int) $row['group_id'],
'user_type' => USER_NORMAL,
diff --git a/phpBB/includes/bbcode.php b/phpBB/includes/bbcode.php
index 7293f07dc9..409aab18e4 100644
--- a/phpBB/includes/bbcode.php
+++ b/phpBB/includes/bbcode.php
@@ -155,6 +155,12 @@ class bbcode
while ($row = $db->sql_fetchrow($result))
{
+ // To circumvent replacing newlines with <br /> for the generated html,
+ // we just remove newlines here. We do not do this within the admin panel to
+ // let the admin lay out his html code nicely
+ $row['bbcode_tpl'] = str_replace(array("\n", "\r"), '', $row['bbcode_tpl']);
+ $row['second_pass_replace'] = str_replace(array("\n", "\r"), '', $row['second_pass_replace']);
+
$rowset[$row['bbcode_id']] = $row;
}
$db->sql_freeresult($result);
@@ -530,7 +536,7 @@ class bbcode
$username = str_replace('\"', '"', $username);
// remove newline at the beginning
- if ($quote{0} == "\n")
+ if ($quote[0] == "\n")
{
$quote = substr($quote, 1);
}
@@ -566,7 +572,7 @@ class bbcode
$code = str_replace(' ', ' &nbsp;', $code);
// remove newline at the beginning
- if (!empty($code) && $code{0} == "\n")
+ if (!empty($code) && $code[0] == "\n")
{
$code = substr($code, 1);
}
diff --git a/phpBB/includes/cache.php b/phpBB/includes/cache.php
index a3a251d194..6266d32c0f 100644
--- a/phpBB/includes/cache.php
+++ b/phpBB/includes/cache.php
@@ -70,13 +70,13 @@ class cache extends acm
* Obtain list of naughty words and build preg style replacement arrays for use by the
* calling script
*/
- function obtain_word_list(&$censors)
+ function obtain_word_list()
{
global $config, $user, $db;
if (!$user->optionget('viewcensors') && $config['allow_nocensors'])
{
- return false;
+ return array();
}
if (($censors = $this->get('word_censors')) === false)
@@ -96,13 +96,13 @@ class cache extends acm
$this->put('word_censors', $censors);
}
- return true;
+ return $censors;
}
/**
* Obtain currently listed icons
*/
- function obtain_icons(&$icons)
+ function obtain_icons()
{
if (($icons = $this->get('icons')) === false)
{
@@ -127,13 +127,13 @@ class cache extends acm
$this->put('icons', $icons);
}
- return;
+ return $icons;
}
/**
* Obtain ranks
*/
- function obtain_ranks(&$ranks)
+ function obtain_ranks()
{
if (($ranks = $this->get('ranks')) === false)
{
@@ -168,13 +168,13 @@ class cache extends acm
$this->put('ranks', $ranks);
}
- return;
+ return $ranks;
}
/**
* Obtain allowed extensions
*/
- function obtain_attach_extensions(&$extensions, $forum_id = false)
+ function obtain_attach_extensions($forum_id = false)
{
if (($extensions = $this->get('_extensions')) === false)
{
@@ -254,19 +254,19 @@ class cache extends acm
$extensions['_allowed_'] = array();
}
- return;
+ return $extensions;
}
/**
* Obtain active bots
*/
- function obtain_bots(&$bots)
+ function obtain_bots()
{
if (($bots = $this->get('bots')) === false)
{
global $db;
- switch (SQL_LAYER)
+ switch ($db->sql_layer)
{
case 'mssql':
case 'mssql_odbc':
@@ -280,7 +280,7 @@ class cache extends acm
$sql = 'SELECT user_id, bot_agent, bot_ip
FROM ' . BOTS_TABLE . '
WHERE bot_active = 1
- ORDER BY STRLEN(bot_agent) DESC';
+ ORDER BY CHAR_LENGTH(bot_agent) DESC';
break;
// LENGTH supported by MySQL, IBM DB2 and Oracle for sure...
@@ -303,7 +303,7 @@ class cache extends acm
$this->put('bots', $bots);
}
- return;
+ return $bots;
}
/**
@@ -354,6 +354,32 @@ class cache extends acm
return $parsed_items;
}
+
+ /**
+ * Obtain disallowed usernames
+ */
+ function obtain_disallowed_usernames()
+ {
+ if (($usernames = $this->get('_disallowed_usernames')) === false)
+ {
+ global $db;
+
+ $sql = 'SELECT disallow_username
+ FROM ' . DISALLOW_TABLE;
+ $result = $db->sql_query($sql);
+
+ $usernames = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $usernames[] = utf8_clean_string(str_replace('%', '.*?', preg_quote($row['disallow_username'], '$#')));
+ }
+ $db->sql_freeresult($result);
+
+ $this->put('_disallowed_usernames', $usernames);
+ }
+
+ return $usernames;
+ }
}
?> \ No newline at end of file
diff --git a/phpBB/includes/captcha/captcha_gd.php b/phpBB/includes/captcha/captcha_gd.php
index 8a2bf70242..e249a46c04 100644
--- a/phpBB/includes/captcha/captcha_gd.php
+++ b/phpBB/includes/captcha/captcha_gd.php
@@ -8,3420 +8,158 @@
*
*/
-
/**
-* Main gd based captcha class
-*
-* Thanks to Robert Hetzler (Xore)
+* Based on PHP-Class hn_captcha Version 1.3, released 11-Apr-2006
+* Original Author - Horst Nogajski, horst@nogajski.de
*
* @package VC
*/
class captcha
{
- /**
- * Create the image containing $code
- */
- function execute($code, $policy)
- {
- $this->$policy(str_split($code));
- }
-
- /**
- * Send image and destroy
- */
- function send_image(&$image)
- {
- header('Content-Type: image/png');
- header('Cache-control: no-cache, no-store');
- imagepng($image);
- imagedestroy($image);
- }
-
- /**
- *
- */
- function wave_height($x, $y, $factor = 1, $tweak = 1)
- {
- return ((sin($x / (3 * $factor)) + sin($y / (3 * $factor))) * 10 * $tweak);
- }
-
- /**
- *
- */
- function grid_height($x, $y, $factor = 1, $x_grid, $y_grid)
- {
- return ( (!($x % ($x_grid * $factor)) || !($y % ($y_grid * $factor))) ? 3 : 0);
- }
-
- /**
- *
- */
- function draw_shape($type, $img, $x_min, $y_min, $x_max, $y_max, $color)
- {
- switch ($type)
- {
- case 'Square':
- imagefilledpolygon($img, array($x_min, $y_max, $x_min, $y_min, $x_max, $y_min, $x_max, $y_max), 4, $color);
- break;
-
- case 'TriangleUp':
- imagefilledpolygon($img, array($x_min, $y_max, ($x_min + $x_max) / 2, $y_min, $x_max, $y_max), 3, $color);
- break;
-
- case 'TriangleDown':
- imagefilledpolygon($img, array($x_min, $y_min, ($x_min + $x_max) / 2, $y_max, $x_max, $y_min), 3, $color);
- break;
-
- case 'Circle':
- imagefilledellipse($img, ($x_min + $x_max) / 2, ($y_min + $y_max) / 2, $x_max - $x_min, $y_max - $y_min, $color);
- break;
- }
- }
-
- /**
- *
- */
- function draw_pattern($seed, $img, $x_min, $y_min, $x_max, $y_max, $colors, $thickness = 1)
- {
- $x_size = ($x_max - $x_min) / 4;
- $y_size = ($y_max - $y_min) / 4;
- $bitmap = substr($seed, 16, 4);
- $numcolors = sizeof($colors) - 1;
- for ($y = 0; $y < 4; ++$y)
- {
- $map = hexdec(substr($bitmap, $y, 1));
- for ($x = 0; $x < 4; ++$x)
- {
- if ($map & (1 << $x))
- {
- $char = hexdec(substr($seed, ($y << 2) + $x, 1));
- if (!($char >> 2))
- {
- switch ($char & 3)
- {
- case 0:
- $shape = 'Circle';
- break;
-
- case 1:
- $shape = 'Square';
- break;
-
- case 2:
- $shape = 'TriangleUp';
- break;
-
- case 3:
- $shape = 'TriangleDown';
- break;
- }
- $this->draw_shape($shape, $img, $x_min + ($x * $x_size), $y_min + ($y * $y_size), $x_min + (($x + 1) * $x_size), $y_min + (($y + 1) * $y_size), $colors[array_rand($colors)]);
- }
- }
- }
- }
-
- $cells = array();
- for ($i = 0; $i < 6; ++$i)
- {
- $cells = hexdec(substr($seed, 20 + ($i << 1), 2));
- $x1 = $cells & 3;
- $cells = $cells >> 2;
- $y1 = $cells & 3;
- $cells = $cells >> 2;
- $x2 = $cells & 3;
- $cells = $cells >> 2;
- $y2 = $cells & 3;
- $x1_real = $x_min + (($x1 + 0.5) * $x_size);
- $y1_real = $y_min + (($y1 + 0.5) * $y_size);
- $x2_real = $x_min + (($x2 + 0.5) * $x_size);
- $y2_real = $y_min + (($y2 + 0.5) * $y_size);
- if ($thickness > 1)
- {
- imagesetthickness($img, $thickness);
- }
- imageline($img, $x1_real, $y1_real, $x2_real, $y2_real, $colors[array_rand($colors)]);
- if ($thickness > 1)
- {
- imagesetthickness($img, 1);
- }
- }
- }
-
- /**
- *
- */
- function get_char_string()
- {
- static $chars = false;
- static $charcount = 0;
- if (!$chars)
- {
- $chars = array_merge(range('A', 'Z'), range('1', '9'));
- }
- $word = '';
- for ($i = mt_rand(6, 8); $i > 0; --$i)
- {
- $word .= $chars[array_rand($chars)];
- }
- return $word;
- }
-
- /**
- * shape
- */
- function policy_shape($code)
- {
- global $config, $user;
- // Generate image
- $img_x = 800;
- $img_y = 250;
- $img = imagecreatetruecolor($img_x, $img_y);
-
- // Generate colors
- $c = new color_manager($img, array(
- 'random' => true,
- 'min_saturation' => 70,
- 'min_value' => 65,
- ));
-
- $primaries = $c->color_scheme('background', 'tetradic', false);
-
- $noise = array_shift($primaries);
- $noise = $c->mono_range($noise, 'value', 5, false);
- $primaries = $c->mono_range($primaries, 'value', 5, false);
-
- // Generate code characters
- $characters = array();
- $sizes = array();
- $bounding_boxes = array();
- $width_avail = $img_x;
- $code_num = sizeof($code);
- $char_class = $this->captcha_char('char_ttf');
- for ( $i = 0; $i < $code_num; ++$i )
- {
- $characters[$i] = new $char_class($code[$i]);
- list($min, $max) = $characters[$i]->range();
- $sizes[$i] = mt_rand($min, $max / 2);
- $box = $characters[$i]->dimensions($sizes[$i]);
- $width_avail -= ($box[2] - $box[0]);
- $bounding_boxes[$i] = $box;
- }
-
- // Redistribute leftover x-space
- $offset = array();
- for ( $i = 0; $i < $code_num; ++$i )
- {
- $denom = ($code_num - $i);
- $denom = max(1.5, $denom);
- $offset[$i] = mt_rand(0, (1.5 * $width_avail) / $denom);
- $width_avail -= $offset[$i];
- }
-
- // Add some line noise
- if ($config['policy_shape_noise_line'])
- {
- $this->noise_line($img, 0, 0, $img_x, $img_y, $c->r('background'), $primaries, $noise);
- }
-
- $real = mt_rand(0, 3);
- $patterns = array('', '', '', '');
- for ($i = 32; $i > 0; --$i)
- {
- $patterns[$i & 3] .= str_pad(dechex(mt_rand(0, 65535)), 4, '0', STR_PAD_LEFT);
- }
-
-
- for ($i = 0; $i < 4; ++$i)
- {
- /*if ($i)
- {
- $y = 5 + ($i * 60);
- imageline($img, 550, $y, 650, $y, $fontcolors[0]);
- }*/
- $this->draw_pattern($patterns[$i], $img, 525, 10 + ($i * 60), 575, ($i + 1) * 60, $primaries);
- if ($i == $real)
- {
- $this->draw_pattern($patterns[$i], $img, 25, 25, 225, 225, $primaries, 3);
- for ($j = 0; $j < $code_num; ++$j)
- {
- $character = new $char_class($code[$j]);
- $character->drawchar(25, 600 + ($j * 25), 35 + ($i * 60), $img, $c->r('background'), $primaries);
- }
- }
- else
- {
- $word = $this->get_char_string();
- for ($j = strlen($word) - 1; $j >= 0; --$j)
- {
- $character = new $char_class(substr($word, $j, 1));
- $character->drawchar(25, 600 + ($j * 25), 35 + ($i * 60), $img, $c->r('background'), $primaries);
- }
- }
- }
-
- $count = sizeof($user->lang['CAPTCHA']['shape']);
- $line_height = $img_y / ($count + 1);
- for ($i = 0; $i < $count; ++$i)
- {
- $text = $user->lang['CAPTCHA']['shape'][$i];
- $line_width = strlen($text) * 4.5; // ( / 2, * 9 )
- imagestring($img, 6, ($img_x / 2) - $line_width - 1, $line_height * ($i + 1) - 1, $text, $c->r('black'));
- imagestring($img, 6, ($img_x / 2) - $line_width - 1, $line_height * ($i + 1) + 1, $text, $c->r('black'));
- imagestring($img, 6, ($img_x / 2) - $line_width + 1, $line_height * ($i + 1) + 1, $text, $c->r('black'));
- imagestring($img, 6, ($img_x / 2) - $line_width + 1, $line_height * ($i + 1) - 1, $text, $c->r('black'));
- imagestring($img, 6, ($img_x / 2) - $line_width, $line_height * ($i + 1), $text, $c->r('white'));
- }
-
-
- // Add some pixel noise
- if ($config['policy_shape_noise_pixel'])
- {
- $this->noise_pixel($img, 0, 0, $img_x, $img_y, $c->r('background'), $primaries, $noise, $config['policy_shape_noise_pixel']);
- }
-
- // Send image
- $this->send_image($img);
- }
-
- function policy_composite($code)
- {
- // Generate image
- $img_x = 800;
- $img_y = 250;
- $img = imagecreate($img_x, $img_y);
-
- $map = captcha_vectors();
- $fonts = captcha_load_ttf_fonts();
-
- // Generate basic colors
- $c = new color_manager($img, 'white');
- $c->allocate_named('primary', array(
- 'random' => true,
- 'min_saturation' => 50,
- 'min_value' => 75,
- ));
- $bg_colors = $c->color_scheme('primary', 'triadic', false);
- $text_colors = $c->mono_range('primary', 'saturation', 6);
- $bg_colors = $c->mono_range($bg_colors, 'saturation', 6);
-
- // Specificy image portion dimensions.
- $count = sizeof($code);
- $cellsize = $img_x / $count;
- $y_range = min($cellsize, $img_y);
- $y_max = $img_y - $y_range;
- $y_off = array(); // consecutive vertical offset of characters
- $color = array(); // color of characters
- $y_off[0] = mt_rand(0, $y_max);
- for ($i = 1; $i < $count; ++$i)
- {
- // each consective character can be as much as 50% closer to the top or bottom of the image as the previous
- $diff = mt_rand(-50, 50);
- if ($diff > 0)
- {
- $y_off[$i] = $y_off[$i - 1] + ((($y_max - $y_off[$i - 1]) * $diff) / 100);
- }
- else
- {
- $y_off[$i] = $y_off[$i - 1] * ((100 + $diff) / 100);
- }
- }
-
- $range = 0.075;
-
- $chars = array_merge(range('A', 'Z'), range('1', '9'));
-
- // draw some characters. if they're within the vector spec of the code character, color them differently
- for ($i = 0; $i < 8000; ++$i)
- {
- $degree = mt_rand(-30, 30);
- $x = mt_rand(0, $img_x - 1);
- $y = mt_rand(0, $img_y);
- $text = $chars[array_rand($chars)];
- $char = $x / $cellsize;
- $meta_x = ((($x % $cellsize) / $cellsize) * 1.5) - 0.25;
- $meta_y = (($img_y - $y) - $y_off[$char]) / $y_range;
- $font = $fonts[array_rand($fonts)];
-
- $distance = vector_distance($map[$code[$char]], $meta_x, $meta_y, $range);
-
- $switch = !(rand() % 100);
-
- imagettftext($img, 10, $degree, $x, $y,
- (($distance <= $range) xor $switch) ?
- $c->r_rand($text_colors) :
- $c->r_rand($bg_colors),
- $font, $text);
-
- }
-
- // Send image
- $this->send_image($img);
- }
-
- function policy_stencil($code)
- {
- // Generate image
- $img_x = 800;
- $img_y = 250;
- $img = imagecreatetruecolor($img_x, $img_y);
- $stencil = imagecreatetruecolor($img_x, $img_y);
-
- $map = captcha_vectors();
- $fonts = captcha_load_ttf_fonts();
-
- // Generate colors
- $c = new color_manager($img, 'black');
- $cs = new color_manager($stencil, 'gray');
-
- $c->allocate_named('primary', array(
- 'random' => true,
- 'min_saturation' => 75,
- 'min_value' => 80,
- ));
-
- $secondary = $c->color_scheme('primary', 'triadic', false);
-
- //imagefill($stencil, 0, 0, $black2);
- //imagefill($img, 0, 0, $white1);
-
- $chars = array_merge(range('A', 'Z'), range('1', '9'));
- $step = 20;
- $density = 4;
- for ($i = 0; $i < $img_x; $i += $step)
- {
- for ($j = 0; $j < $img_y; $j += $step)
- {
- for ($k = 0; $k < $density; ++$k)
- {
- $degree = mt_rand(-30, 30);
- $x = mt_rand($i, $i + $step);
- $y = mt_rand($j, $j + $step);
- $char = $chars[array_rand($chars)];
- $font = $fonts[array_rand($fonts)];
- imagettftext($stencil, mt_rand(20, 30), $degree, $x, $y, $cs->r('black'), $font, $char);
- }
- }
- }
-
- for ($i = 0; $i < 3; ++$i)
- {
- $degree1 = mt_rand(-30, 30);
- $degree2 = mt_rand(-30, 30);
- $x1 = mt_rand(0, $img_x - 1);
- $x2 = mt_rand(0, $img_x - 1);
- $y1 = mt_rand(0, $img_y);
- $y2 = mt_rand(0, $img_y);
- $char1 = $chars[array_rand($chars)];
- $char2 = $chars[array_rand($chars)];
- $font1 = $fonts[array_rand($fonts)];
- $font2 = $fonts[array_rand($fonts)];
-
- imagettftext($img, mt_rand(75, 100), $degree1, $x1, $y1, $secondary[0], $font1, $char1);
- imagettftext($img, mt_rand(75, 100), $degree2, $x2, $y2, $secondary[1], $font2, $char2);
- }
-
- $characters = array();
- $sizes = array();
- $bounding_boxes = array();
- $width_avail = $img_x;
- $code_num = sizeof($code);
- $char_class = $this->captcha_char('char_ttf');
- for ($i = 0; $i < $code_num; ++$i)
- {
- $characters[$i] = new $char_class($code[$i]);
- $sizes[$i] = mt_rand(75, 100);
- $box = $characters[$i]->dimensions($sizes[$i]);
- $width_avail -= ($box[2] - $box[0]);
- $bounding_boxes[$i] = $box;
- }
-
- //
- // Redistribute leftover x-space
- //
- $offset = array();
- for ($i = 0; $i < $code_num; ++$i)
- {
- $denom = ($code_num - $i);
- $denom = max(1.5, $denom);
- $offset[$i] = mt_rand(0, (1.5 * $width_avail) / $denom);
- $width_avail -= $offset[$i];
- }
-
- // Draw the text
- $xoffset = 0;
- for ($i = 0; $i < $code_num; ++$i)
- {
- $characters[$i] = new $char_class($code[$i]);
- $dimm = $bounding_boxes[$i];
- $xoffset += ($offset[$i] - $dimm[0]);
- $yoffset = mt_rand(-$dimm[1], $img_y - $dimm[3]);
- $characters[$i]->drawchar($sizes[$i], $xoffset, $yoffset, $img, $c->r('background'), array($c->r('primary')));
- $xoffset += $dimm[2];
- }
-
- for ($i = 0; $i < $img_x; ++$i)
- {
- for ($j = 0; $j < $img_y; ++$j)
- {
- // if the stencil is not black, set the pixel in the image to gray
- if (imagecolorat($stencil, $i, $j))
- {
- imagesetpixel($img, $i, $j, $c->r('gray'));
- }
- }
- }
-
- // Send image
- $this->send_image($img);
- }
-
- function policy_cells($code)
- {
- global $user;
- // Generate image
- $img_x = 800;
- $img_y = 250;
- $img = imagecreate($img_x, $img_y);
-
- $fonts = captcha_load_ttf_fonts();
-
- $map = captcha_vectors();
-
- //
- // Generate colors
- //
- $c = new color_manager($img, 'white');
-
- $c->allocate_named('primary', array(
- 'random' => true,
- 'min_saturation' => 30,
- 'min_value' => 65,
- ));
- $primaries = $c->color_scheme('primary', 'tetradic');
- $bg_colors = $c->mono_range($primaries, 'value', 4, false);
- shuffle($primaries);
- shuffle($bg_colors);
-
- // Randomize the characters on the right and the left
- $left_characters = array();
- $right_characters = array();
- $chars = array_merge(range('A', 'Z'), range('1', '9'));
- $chars_size = sizeof($chars) - 1;
- $alpha = range('A', 'Z');
- $alpha_size = sizeof($alpha) - 1;
- for ($i = 0; $i < 25; ++$i)
- {
- $left_characters[$i] = $alpha[mt_rand(0, $alpha_size)];
- $right_characters[$i] = $chars[mt_rand(0, $chars_size)];
- }
-
- // Pick locations for our code, shuffle the rest into 3 separate queues
- $code_count = sizeof($code);
- $code_order = range(0, 24);
- shuffle($code_order);
- $remaining = array_splice($code_order, $code_count);
- $lineups = array($code_order, array(), array(), array());
- for ($i = sizeof($remaining) - 1; $i >= 0; --$i)
- {
- $lineups[mt_rand(1, 3)][] = $remaining[$i];
- }
-
- // overwrite the randomized left and right values with our code, where applicable
- for ($i = 0; $i < $code_count; ++$i)
- {
- $left_characters[$code_order[$i]] = $i + 1;
- $right_characters[$code_order[$i]] = $code[$i];
- }
-
-
- $offset1 = 50;
- $offset2 = 550;
-
- // Draw the cells and right hand characters
- $xs = $ys = array();
- for ($i = 0; $i < 25; ++$i)
- {
- $xs[$i] = $offset1 + 20 + (($i % 5) * 40) + mt_rand(-13, 13);
- $ys[$i] = 45 + (intval($i / 5) * 40) + mt_rand(-13, 13);
-
- $bg = $c->r_rand($bg_colors);
-
- // fill the cells with the background colors
- imagefilledrectangle($img,
- $offset1 + 1 + (($i % 5) * 40), 26 + (intval($i / 5) * 40),
- $offset1 + 39 + (($i % 5) * 40), 64 + (intval($i / 5) * 40),
- $bg);
- imagefilledrectangle($img,
- $offset2 + 1 + (($i % 5) * 40), 26 + (intval($i / 5) * 40),
- $offset2 + 39 + (($i % 5) * 40), 64 + (intval($i / 5) * 40),
- $bg);
-
- $level = intval($i / 5);
- $pos = $i % 5;
- imagettftext($img, 12, 0,
- $offset2 + 15 + ($pos * 40), 50 + ($level * 40),
- $c->is_dark($bg) ? $c->r('white'): $c->r('black'), $fonts['genr102.ttf'], $right_characters[$i]);
- }
-
- // draw the lines that appear between nodes (visual hint)
- for ($k = 0; $k < 4; ++$k )
- {
- $lineup = $lineups[$k];
- for ($i = 1, $size = sizeof($lineup); $i < $size; ++$i )
- {
- imageline($img,
- $xs[$lineup[$i - 1]], $ys[$lineup[$i - 1]],
- $xs[$lineup[$i]], $ys[$lineup[$i]],
- $primaries[$k]);
- }
- }
-
- // draw the actual nodes
- $textcolor = $c->is_dark($primaries[0]) ? $c->r('white') : $c->r('black');
- for ($k = 0; $k < 4; ++$k )
- {
- for ($j = 0, $size = sizeof($lineups[$k]); $j < $size; ++$j )
- {
- $i = $lineups[$k][$j];
- imagefilledellipse($img,
- $xs[$i], $ys[$i],
- 20, 20,
- $primaries[$k]);
- imagettftext($img, 12, 0,
- $xs[$i] - 5, $ys[$i] + 5,
- $textcolor, $fonts['genr102.ttf'], $left_characters[$i]);
- }
- }
-
- // Draw poly behind explain text
- $points = mt_rand(3, 6);
- $arc = 360 / $points;
- $vertices = array();
- $c_x = $img_x / 2;
- $c_y = $img_y / 2;
- $radius = $img_y / 2.5;
- $start = deg2rad(mt_rand(0, 360));
- for ($i = 0; $i < $points; ++$i)
- {
- $rad = $start + deg2rad(($arc * $i) + mt_rand(-10, 10));
- $vertices[] = $c_x + (cos($rad) * $radius);
- $vertices[] = $c_y + (sin($rad) * $radius);
- }
- imagefilledpolygon($img, $vertices, $points, $primaries[mt_rand(0,3)]);
-
- // draw explain text
- $count = sizeof($user->lang['CAPTCHA']['cells']);
- $line_height = $img_y / ($count + 1);
- for ($i = 0; $i < $count; ++$i)
- {
- $text = $user->lang['CAPTCHA']['cells'][$i];
- $line_width = strlen($text) * 4.5; // ( / 2, * 9 )
- imagestring($img, 6, ($img_x / 2) - $line_width - 1, $line_height * ($i + 1) - 1, $text, $c->r('black'));
- imagestring($img, 6, ($img_x / 2) - $line_width - 1, $line_height * ($i + 1) + 1, $text, $c->r('black'));
- imagestring($img, 6, ($img_x / 2) - $line_width + 1, $line_height * ($i + 1) + 1, $text, $c->r('black'));
- imagestring($img, 6, ($img_x / 2) - $line_width + 1, $line_height * ($i + 1) - 1, $text, $c->r('black'));
- imagestring($img, 6, ($img_x / 2) - $line_width, $line_height * ($i + 1), $text, $c->r('white'));
- }
-
- // Send image
- $this->send_image($img);
- }
-
- /**
- * entropy
- */
- function policy_entropy($code)
+ function execute($code)
{
global $config;
- // Generate image
- $img_x = 800;
- $img_y = 250;
- $img = imagecreatetruecolor($img_x, $img_y);
-
- // Generate colors
- $c = new color_manager($img, array(
- 'random' => true,
- 'min_value' => 60,
- ), 'hsv');
-
- $scheme = $c->color_scheme('background', 'triadic', false);
- $scheme = $c->mono_range($scheme, 'both', 10, false);
- shuffle($scheme);
- $bg_colors = array_splice($scheme, mt_rand(6, 12));
+ $stats = gd_info();
- // Generate code characters
- $characters = $sizes = $bounding_boxes = array();
- $width_avail = $img_x;
- $code_num = sizeof($code);
-
- for ($i = 0; $i < $code_num; ++$i)
- {
- $char_class = $this->captcha_char();
- $characters[$i] = new $char_class($code[$i]);
-
- list($min, $max) = $characters[$i]->range();
- $sizes[$i] = mt_rand($min, $max);
- $box = $characters[$i]->dimensions($sizes[$i]);
- $width_avail -= ($box[2] - $box[0]);
- $bounding_boxes[$i] = $box;
- }
-
- // Redistribute leftover x-space
- $offset = array();
- for ($i = 0; $i < $code_num; ++$i)
+ if (substr($stats['GD Version'], 0, 7) === 'bundled')
{
- $denom = ($code_num - $i);
- $denom = max(1.5, $denom);
- $offset[$i] = mt_rand(0, (1.5 * $width_avail) / $denom);
- $width_avail -= $offset[$i];
+ $bundled = true;
}
-
- // Add some line noise
- if ($config['policy_entropy_noise_line'])
- {
- $this->noise_line($img, 0, 0, $img_x, $img_y, $c->r('background'), $scheme, $bg_colors);
- }
-
- // Draw the text
- $xoffset = 0;
- for ($i = 0; $i < $code_num; ++$i)
- {
- $dimm = $bounding_boxes[$i];
- $xoffset += ($offset[$i] - $dimm[0]);
- $yoffset = mt_rand(-$dimm[1], $img_y - $dimm[3]);
- $characters[$i]->drawchar($sizes[$i], $xoffset, $yoffset, $img, $c->r('background'), $scheme);
- $xoffset += $dimm[2];
- }
-
- // Add some pixel noise
- if ($config['policy_entropy_noise_pixel'])
- {
- $this->noise_pixel($img, 0, 0, $img_x, $img_y, $c->r('background'), $scheme, $bg_colors, $config['policy_entropy_noise_pixel']);
- }
-
- // Send image
- $this->send_image($img);
- }
-
- /**
- * 3dbitmap
- */
- function policy_3dbitmap($code)
- {
- // Generate image
- $img_x = 700;
- $img_y = 225;
- $img = imagecreatetruecolor($img_x, $img_y);
- $x_grid = mt_rand(6, 10);
- $y_grid = mt_rand(6, 10);
-
- // Ok, so lets cut to the chase. We could accurately represent this in 3d and
- // do all the appropriate linear transforms. my questions is... why bother?
- // The computational overhead is unnecessary when you consider the simple fact:
- // we're not here to accurately represent a model, but to just show off some random-ish
- // polygons
-
- // Conceive of 3 spaces.
- // 1) planar-space (discrete "pixel" grid)
- // 2) 3-space. (planar-space with z/height aspect)
- // 3) image space (pixels on the screen)
-
- // resolution of the planar-space we're embedding the text code in
- $plane_x = 90;
- $plane_y = 25;
-
- $subdivision_factor = 2;
-
- // $box is the 4 points in img_space that correspond to the corners of the plane in 3-space
- $box = array(array(), array(), array(), array());
-
- // Top left
- $box[0][0] = mt_rand(20, 40);
- $box[0][1] = mt_rand(40, 60);
-
- // Top right
- $box[1][0] = mt_rand($img_x - 80, $img_x - 60);
- $box[1][1] = mt_rand(10, 30);
-
- // Bottom right
- $box[2][0] = mt_rand($img_x - 40, $img_x - 20);
- $box[2][1] = mt_rand($img_y - 50, $img_y - 30);
-
- // Bottom left.
- // because we want to be able to make shortcuts in the 3d->2d,
- // we'll calculate the 4th point so that it forms a proper trapezoid
- $box[3][0] = $box[2][0] + $box[0][0] - $box[1][0];
- $box[3][1] = $box[2][1] + $box[0][1] - $box[1][1];
- $c = new color_manager($img, array(
- 'random' => true,
- 'min_saturation' => 50,
- 'min_value' => 65,
- ));
-
- $r1 = $c->random_color(array(
- 'min_value' => 20,
- 'max_value' => 50,
- ));
- $r2 = $c->random_color(array(
- 'min_value' => 70,
- 'max_value' => 100,
- ));
- $rdata = mt_rand(0,1) ? array(
- $c->colors[$r1],
- $c->colors[$r2],
- ) : array(
- $c->colors[$r2],
- $c->colors[$r1],
- );
-
- $colors = array();
- for ($i = 0; $i < 60; ++$i)
- {
- $colors[$i - 30] = $c->allocate(array(
- $rdata[0][0],
- (($i * $rdata[0][1]) + ((60 - $i) * $rdata[1][1])) / 60,
- (($i * $rdata[0][2]) + ((60 - $i) * $rdata[1][2])) / 60,
- ));
- }
-
- // $img_buffer is the last row of 3-space positions (converted to img-space), cached
- // (using this means we don't need to recalculate all 4 positions for each new polygon,
- // merely the newest point that we're adding, which is then cached.
- $img_buffer = array(array(), array());
-
- // In image-space, the x- and y-offset necessary to move one unit in the x-direction in planar-space
- $dxx = ($box[1][0] - $box[0][0]) / ($subdivision_factor * $plane_x);
- $dxy = ($box[1][1] - $box[0][1]) / ($subdivision_factor * $plane_x);
-
- // In image-space, the x- and y-offset necessary to move one unit in the y-direction in planar-space
- $dyx = ($box[3][0] - $box[0][0]) / ($subdivision_factor * $plane_y);
- $dyy = ($box[3][1] - $box[0][1]) / ($subdivision_factor * $plane_y);
-
- // Initial captcha-letter offset in planar-space
- $plane_offset_x = 2;
- $plane_offset_y = 5;
-
- // character map
- $map = captcha_bitmaps();
-
- // matrix
- $plane = array();
-
- // for each character, we'll silkscreen it into our boolean pixel plane
- for ($c = 0, $code_num = sizeof($code); $c < $code_num; ++$c)
- {
- $letter = $code[$c];
-
- for ($x = $map['width'] - 1; $x >= 0; --$x)
- {
- for ($y = $map['height'] - 1; $y >= 0; --$y)
- {
- if ($map['data'][$letter][$y][$x])
- {
- $plane[$y + $plane_offset_y + (($c & 1) ? 1 : -1)][$x + $plane_offset_x] = true;
- }
- }
- }
- $plane_offset_x += 11;
- }
-
- // calculate our first buffer, we can't actually draw polys with these yet
- // img_pos_prev == screen x,y location to our immediate left.
- // img_pos_cur == current screen x,y location
- // we calculate screen position of our
- // current cell based on the difference from the previous cell
- // rather than recalculating from absolute coordinates
- // What we cache into the $img_buffer contains the raised text coordinates.
- $img_pos_prev = $img_buffer[0][0] = $box[0];
- $cur_height = $prev_height = $this->wave_height(0, 0, $subdivision_factor);
- $full_x = $plane_x * $subdivision_factor;
- $full_y = $plane_y * $subdivision_factor;
-
- for ($x = 1; $x <= $full_x; ++$x)
- {
- $cur_height = $this->wave_height($x, 0, $subdivision_factor);
- $offset = $cur_height - $prev_height;
- $img_pos_cur = array($img_pos_prev[0] + $dxx,
- $img_pos_prev[1] + $dxy + $offset);
-
- $img_buffer[0][$x] = $img_pos_cur;
- $img_pos_prev = $img_pos_cur;
- $prev_height = $cur_height;
- }
-
- for ($y = 1; $y <= $full_y; ++$y)
- {
- // swap buffers
- $buffer_cur = $y & 1;
- $buffer_prev = 1 - $buffer_cur;
-
- $prev_height = $this->wave_height(0, $y, $subdivision_factor);
- $offset = $prev_height - $this->wave_height(0, $y - 1, $subdivision_factor);
- $img_pos_cur = array($img_buffer[$buffer_prev][0][0] + $dyx,
- $img_buffer[$buffer_prev][0][1] + $dyy + $offset);
- $img_pos_prev = $img_pos_cur;
-
- $img_buffer[$buffer_cur][0] = $img_pos_cur;
-
- for ($x = 1; $x <= $full_x; ++$x)
- {
- $cur_height = $this->wave_height($x, $y, $subdivision_factor) + $this->grid_height($x, $y, 1, $x_grid, $y_grid);
-
- //height is a z-factor, not a y-factor
- $offset = $cur_height - $prev_height;
- $img_pos_cur = array($img_pos_prev[0] + $dxx,
- $img_pos_prev[1] + $dxy + $offset);
-
- //(height is float, index it to an int, get closest color)
- $color = $colors[intval($cur_height)];
- $img_pos_prev = $img_pos_cur;
- $prev_height = $cur_height;
-
- $y_index_old = intval(($y - 1) / $subdivision_factor);
- $y_index_new = intval($y / $subdivision_factor);
- $x_index_old = intval(($x - 1) / $subdivision_factor);
- $x_index_new = intval($x / $subdivision_factor);
-
- if (!empty($plane[$y_index_new][$x_index_new]))
- {
- $offset2 = $this->wave_height($x, $y, $subdivision_factor, 1) - 30 - $cur_height;
- $img_pos_cur[1] += $offset2;
- $color = $colors[20];
- }
- $img_buffer[$buffer_cur][$x] = $img_pos_cur;
-
- // Smooth the edges as much as possible by having not more than one low<->high traingle per square
- // Otherwise, just
- $diag_down = (empty($plane[$y_index_old][$x_index_old]) == empty($plane[$y_index_new][$x_index_new]));
- $diag_up = (empty($plane[$y_index_old][$x_index_new]) == empty($plane[$y_index_new][$x_index_old]));
-
- // natural switching
- $mode = ($x + $y) & 1;
-
- // override if it requires it
- if ($diag_down != $diag_up)
- {
- $mode = $diag_up;
- }
-
- if ($mode)
- {
- // +-/ /
- // 1 |/ 2 /|
- // / /-+
- $poly1 = array_merge($img_buffer[$buffer_cur][$x - 1], $img_buffer[$buffer_prev][$x - 1], $img_buffer[$buffer_prev][$x]);
- $poly2 = array_merge($img_buffer[$buffer_cur][$x - 1], $img_buffer[$buffer_cur][$x], $img_buffer[$buffer_prev][$x]);
- }
- else
- {
- // \ \-+
- // 1 |\ 2 \|
- // +-\ \
- $poly1 = array_merge($img_buffer[$buffer_cur][$x - 1], $img_buffer[$buffer_prev][$x - 1], $img_buffer[$buffer_cur][$x]);
- $poly2 = array_merge($img_buffer[$buffer_prev][$x - 1], $img_buffer[$buffer_prev][$x], $img_buffer[$buffer_cur][$x]);
- }
-
- imagefilledpolygon($img, $poly1, 3, $color);
- imagefilledpolygon($img, $poly2, 3, $color);
- }
- }
-
- // Send image on it's merry way
- $this->send_image($img);
- }
-
- /**
- * overlap
- */
- function policy_overlap($code)
- {
- global $config;
- $char_size = 40;
- $overlap_factor = .32;
-
- // Generate image
- $img_x = 250;
- $img_y = 120;
- $img = imagecreatetruecolor($img_x, $img_y);
-
- // Generate colors
- $c = new color_manager($img, array(
- 'random' => true,
- 'min_saturation' => 70,
- 'min_value' => 65,
- ));
-
- $primaries = $c->color_scheme('background', 'triadic', false);
- $text = mt_rand(0, 1);
- $c->name_color('text', $primaries[$text]);
- $noise = $c->mono_range($primaries[1 - $text], 'both', 6, false);
-
- // Generate code characters
- $characters = $bounding_boxes = array();
- $width_avail = $img_x;
-
- // Get the character rendering scheme
- $char_class = $this->captcha_char('char_ttf');
- $code_num = sizeof($code);
-
- for ($i = 0; $i < $code_num; ++$i)
- {
- $characters[$i] = new $char_class($code[$i], array('angle' => 0));
- $box = $characters[$i]->dimensions($char_size);
- $width_avail -= ((1 - $overlap_factor) * ($box[2] - $box[0]));
- $bounding_boxes[$i] = $box;
- }
-
- // Redistribute leftover x-space
- $offset = mt_rand(0, $width_avail);
-
- // Add some line noise
- if ($config['policy_overlap_noise_line'])
- {
- $this->noise_line($img, 0, 0, $img_x, $img_y, $c->r('background'), array($c->r('text')), $noise);
- }
-
- // Draw the text
- $min = 10 - $bounding_boxes[0][1];
- $max = ($img_y - 10) - $bounding_boxes[0][3];
- $med = ($max + $min) / 2;
-
- $yoffset = mt_rand($med, $max);
- $char_num = sizeof($characters);
-
- imagesetthickness($img, 3);
- for ($i = 0; $i < $char_num; ++$i)
- {
- if ($i)
- {
- imageline($img, $old_x + mt_rand(-3, 3), $old_y - 70 + mt_rand(-3, 3), $offset + mt_rand(-3, 3), $yoffset - 70 + mt_rand(-3, 3), $c->r('text'));
- imageline($img, $old_x + mt_rand(-3, 3), $old_y + 30 + mt_rand(-3, 3), $offset + mt_rand(-3, 3), $yoffset + 30 + mt_rand(-3, 3), $c->r('text'));
- }
-
- $dimm = $bounding_boxes[$i];
- $offset -= $dimm[0];
- $characters[$i]->drawchar($char_size, $offset, $yoffset, $img, $c->r('background'), array($c->r('text')));
-
- $old_x = $offset;
- $old_y = $yoffset;
-
- $offset += $dimm[2];
- $offset -= (($dimm[2] - $dimm[0]) * $overlap_factor);
- $yoffset += ($i & 1) ? ((1 - $overlap_factor) * ($dimm[3] - $dimm[1])) : ((1 - $overlap_factor) * ($dimm[1] - $dimm[3]));
- }
-
- imagesetthickness($img, 1);
-
- // Add some medium pixel noise
- if ($config['policy_overlap_noise_pixel'])
- {
- $this->noise_pixel($img, 0, 0, $img_x, $img_y, $c->r('background'), array($c->r('text')), $noise, $config['policy_overlap_noise_pixel']);
- }
-
- // Send image
- $this->send_image($img);
- }
-
- /**
- * Noise pixel
- */
- function noise_pixel($img, $min_x, $min_y, $max_x, $max_y, $bg, $font, $non_font, $override = false)
- {
- $noise_modules = array('noise_pixel_light', 'noise_pixel_medium', 'noise_pixel_heavy');
-
- if ($override == false)
- {
- $override = array_rand($override);
- }
-
- // Use the module $override, else a random picked one...
- $module = $noise_modules[intval($override) - 1];
-
- switch ($module)
- {
- case 'noise_pixel_light':
-
- for ($x = $min_x; $x < $max_x; $x += mt_rand(9, 18))
- {
- for ($y = $min_y; $y < $max_y; $y += mt_rand(4, 9))
- {
- imagesetpixel($img, $x, $y, $non_font[array_rand($non_font)]);
- }
- }
-
- for ($y = $min_y; $y < $max_y; $y += mt_rand(9, 18))
- {
- for ($x = $min_x; $x < $max_x; $x += mt_rand(4, 9))
- {
- imagesetpixel($img, $x, $y, $non_font[array_rand($non_font)]);
- }
- }
-
- break;
-
- case 'noise_pixel_medium':
-
- for ($x = $min_x; $x < $max_x; $x += mt_rand(4, 9))
- {
- for ($y = $min_y; $y < $max_y; $y += mt_rand(2, 5))
- {
- imagesetpixel($img, $x, $y, $non_font[array_rand($non_font)]);
- }
- }
-
- for ($y = $min_y; $y < $max_y; $y += mt_rand(4, 9))
- {
- for ($x = $min_x; $x < $max_x; $x += mt_rand(2, 5))
- {
- imagesetpixel($img, $x, $y, $non_font[array_rand($non_font)]);
- }
- }
-
- break;
-
- case 'noise_pixel_heavy':
-
- for ($x = $min_x; $x < $max_x; $x += mt_rand(4, 9))
- {
- for ($y = $min_y; $y < $max_y; $y++)
- {
- imagesetpixel($img, $x, $y, $non_font[array_rand($non_font)]);
- }
- }
-
- for ($y = $min_y; $y < $max_y; $y+= mt_rand(4, 9))
- {
- for ($x = $min_x; $x < $max_x; $x++)
- {
- imagesetpixel($img, $x, $y, $non_font[array_rand($non_font)]);
- }
- }
-
- break;
- }
- }
-
- /**
- * Noise line
- */
- function noise_line($img, $min_x, $min_y, $max_x, $max_y, $bg, $font, $non_font)
- {
- imagesetthickness($img, 2);
- $x1 = $min_x;
- $x2 = $max_x;
- $y1 = $min_y;
- $y2 = $min_y;
-
- do
+ else
{
- $line = array_merge(
- array_fill(0, mt_rand(30, 60), $non_font[array_rand($non_font)]),
- array_fill(0, mt_rand(30, 60), $bg)
- );
-
- imagesetstyle($img, $line);
- imageline($img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED);
-
- $y1 += mt_rand(12, 35);
- $y2 += mt_rand(12, 35);
+ $bundled = false;
}
- while ($y1 < $max_y && $y2 < $max_y);
-
- $x1 = $min_x;
- $x2 = $min_x;
- $y1 = $min_y;
- $y2 = $max_y;
- do
+ preg_match('/[\\d.]+/', $stats['GD Version'], $version);
+ if (version_compare($version[0], '2.0.1', '>='))
{
- $line = array_merge(
- array_fill(0, mt_rand(30, 60), $non_font[array_rand($non_font)]),
- array_fill(0, mt_rand(30, 60), $bg)
- );
-
- imagesetstyle($img, $line);
- imageline($img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED);
-
- $x1 += mt_rand(12, 35);
- $x2 += mt_rand(12, 35);
+ $gd_version = 2;
}
- while ($x1 < $max_x && $x2 < $max_x);
- imagesetthickness($img, 1);
- }
-
- /**
- * Randomly determine which char class to use
- * Able to define static one with override
- */
- function captcha_char($override = false)
- {
- static $character_classes = array();
-
- // Some people have GD but no TTF support
- if (sizeof($character_classes) == 0)
+ else
{
- $character_classes = array('char_vector', 'char_hatches', 'char_cube3d', 'char_dots');
-
- if (function_exists('imagettfbbox') && function_exists('imagettftext'))
- {
- $character_classes[] = 'char_ttf';
- }
+ $gd_version = 1;
}
- // Use the module $override, else a random picked one...
- $class = ($override !== false && in_array($override, $character_classes)) ? $override : $character_classes[array_rand($character_classes)];
-
- return $class;
- }
-}
-
-/**
-* @package VC
-*/
-class char_dots
-{
- var $vectors;
- var $space;
- var $radius;
- var $letter;
- var $width_percent;
+ // set dimension of image
+ $lx = 360;
+ $ly = 96;
- /**
- * Constuctor
- */
- function char_dots($letter = '', $args = false)
- {
- $width_percent = false;
- if (is_array($args))
+ // create the image, stay compat with older versions of GD
+ if ($gd_version === 2)
{
- $width_percent = (!empty($args['width_percent'])) ? $args['width_percent'] : false;
+ $func1 = 'imagecreatetruecolor';
+ $func2 = 'imagecolorallocate';
}
-
- $this->vectors = captcha_vectors();
- $this->width_percent = (!empty($width_percent)) ? max(25, min(150, intval($width_percent))) : mt_rand(60, 90);
-
- $this->space = 10;
- $this->radius = 3;
- $this->density = 3;
- $this->letter = $letter;
- }
-
- /**
- * Draw a character
- */
- function drawchar($scale, $xoff, $yoff, $img, $background, $colors)
- {
- $vectorset = $this->vectors[$this->letter];
- $height = $scale;
- $width = (($scale * $this->width_percent) / 100);
- $color = $colors[array_rand($colors)];
-
- if (sizeof($vectorset))
+ else
{
- foreach ($vectorset as $veclist)
- {
- switch ($veclist[0])
- {
- case 'line':
-
- $dx = ($veclist[3] - $veclist[1]) * $width;
- $dy = ($veclist[4] - $veclist[2]) * -$height;
-
- $len = sqrt(($dx * $dx) + ($dy * $dy));
-
- $inv_dx = -($dy / $len);
- $inv_dy = ($dx / $len);
-
- for ($i = 0; $i < $len; ++$i)
- {
- for ($k = 0; $k <= $this->density; ++$k)
- {
- $shift = mt_rand(-$this->radius, $this->radius);
- imagesetpixel($img,
- $xoff + ($veclist[1] * $width) + (($i * $dx) / $len) + ($inv_dx * $shift),
- $yoff + ((1 - $veclist[2]) * $height) + (($i * $dy) / $len) + ($inv_dy * $shift),
- $color);
- }
- }
-
- break;
-
- case 'arc':
-
- $arclengthdeg = $veclist[6] - $veclist[5];
- $arclengthdeg += ( $arclengthdeg < 0 ) ? 360 : 0;
-
- $arclength = ((($veclist[3] * $width) + ($veclist[4] * $height)) * M_PI) / 2;
-
- $arclength = ($arclength * $arclengthdeg) / 360;
-
- $x_c = $veclist[1] * $width;
- $y_c = (1 - $veclist[2]) * $height;
- $increment = ($arclengthdeg / $arclength);
-
- for ($i = 0; $i < $arclengthdeg; $i += $increment)
- {
- $theta = deg2rad(($i + $veclist[5]) % 360);
- $x_o = cos($theta);
- $y_o = sin($theta);
- $pre_width = ($veclist[3] * 0.5 * $width);
- $pre_height = ($veclist[4] * 0.5 * $height);
- for ($k = 0; $k <= $this->density; ++$k)
- {
- $shift = mt_rand(-$this->radius, $this->radius);
- $x_o1 = $x_o * ($pre_width + $shift);
- $y_o1 = $y_o * ($pre_height + $shift);
- imagesetpixel($img,
- $xoff + $x_c + $x_o1,
- $yoff + $y_c + $y_o1,
- $color);
- }
- }
-
- break;
-
- default:
- // Do nothing with bad input
- break;
- }
- }
+ $func1 = 'imagecreate';
+ $func2 = 'imagecolorclosest';
}
- }
- /*
- * return a roughly acceptable range of sizes for rendering with this texttype
- */
- function range()
- {
- return array(60, 80);
- }
+ $image = $func1($lx, $ly);
- /**
- * dimensions
- */
- function dimensions($size)
- {
- return array(-4, -4, (($size * $this->width_percent) / 100) + 4, $size + 4);
- }
-}
-
-/**
-* @package VC
-*/
-class char_vector
-{
- var $vectors;
- var $width_percent;
- var $letter;
-
- /**
- * Constructor
- */
- function char_vector($letter = '', $args = false)
- {
- $width_percent = false;
- if (is_array($args))
+ if ($bundled)
{
- $width_percent = (!empty($args['width_percent'])) ? $args['width_percent'] : false;
+ imageantialias($image, true);
}
- $this->vectors = captcha_vectors();
- $this->width_percent = (!empty($width_percent)) ? max(25, min(150, intval($width_percent))) : mt_rand(60,90);
- $this->letter = $letter;
- }
-
- /**
- * Draw a character
- */
- function drawchar($scale, $xoff, $yoff, $img, $background, $colors)
- {
- $vectorset = $this->vectors[$this->letter];
- $height = $scale;
- $width = (($scale * $this->width_percent) / 100);
- $color = $colors[array_rand($colors)];
+ // set background color
+ $back = imagecolorallocate($image, mt_rand(224, 255), mt_rand(224, 255), mt_rand(224, 255));
+ imagefilledrectangle($image, 0, 0, $lx, $ly, $back);
- if (sizeof($vectorset))
+ // allocates the 216 websafe color palette to the image
+ if ($gd_version === 1)
{
- foreach ($vectorset as $veclist)
+ for ($r = 0; $r <= 255; $r += 51)
{
- for ($i = 0; $i < 9; ++$i)
+ for ($g = 0; $g <= 255; $g += 51)
{
- $xp = $i % 3;
- $yp = ($i - $xp) / 3;
- $xp--;
- $yp--;
-
- switch ($veclist[0])
+ for ($b = 0; $b <= 255; $b += 51)
{
- case 'line':
- imageline($img,
- $xoff + $xp + ($veclist[1] * $width),
- $yoff + $yp + ((1 - $veclist[2]) * $height),
- $xoff + $xp + ($veclist[3] * $width),
- $yoff + $yp + ((1 - $veclist[4]) * $height),
- $color
- );
- break;
-
- case 'arc':
- imagearc($img,
- $xoff + $xp + ($veclist[1] * $width),
- $yoff + $yp + ((1 - $veclist[2]) * $height),
- $veclist[3] * $width,
- $veclist[4] * $height,
- $veclist[5],
- $veclist[6],
- $color
- );
- break;
+ imagecolorallocate($image, $r, $g, $b);
}
}
}
}
- }
-
- /*
- * return a roughly acceptable range of sizes for rendering with this texttype
- */
- function range()
- {
- return array(50, 80);
- }
-
- /**
- * dimensions
- */
- function dimensions($size)
- {
- return array(-2, -2, (($size * $this->width_percent) / 100 ) + 2, $size + 2);
- }
-}
-
-/**
-* @package VC
-*/
-class char_ttf
-{
- var $angle = 0;
- var $fontfile = '';
- var $letter = '';
-
- /**
- * Constructor
- */
- function char_ttf($letter = '', $args = false)
- {
- $font = $angle = false;
-
- if (is_array($args))
- {
- $font = (!empty($args['font'])) ? $args['font'] : false;
- $angle = (isset($args['angle'])) ? $args['angle'] : false;
- }
-
- $fonts = captcha_load_ttf_fonts();
-
- if (empty($font) || !isset($fonts[$font]))
- {
- $font = array_rand($fonts);
- }
-
- $this->fontfile = $fonts[$font];
- $this->angle = ($angle !== false) ? intval($angle) : mt_rand(-40, 40);
- $this->letter = $letter;
- }
-
- /**
- * Draw a character
- */
- function drawchar($scale, $xoff, $yoff, $img, $background, $colors)
- {
- $color = $colors[array_rand($colors)];
- imagettftext($img, $scale, $this->angle, $xoff, $yoff, $color, $this->fontfile, $this->letter);
- }
-
- /*
- * return a roughly acceptable range of sizes for rendering with this texttype
- */
- function range()
- {
- return array(36, 150);
- }
-
- /**
- * Dimensions
- */
- function dimensions($scale)
- {
- $data = imagettfbbox($scale, $this->angle, $this->fontfile, $this->letter);
- return ($this->angle > 0) ? array($data[6], $data[5], $data[2], $data[1]) : array($data[0], $data[7], $data[4], $data[3]);
- }
-}
-
-/**
-* @package VC
-*/
-class char_hatches
-{
- var $vectors;
- var $space;
- var $radius;
- var $letter;
-
- /**
- * Constructor
- */
- function char_hatches($letter = '', $args = false)
- {
- $width_percent = false;
- if (is_array($args))
- {
- $width_percent = (!empty($args['width_percent'])) ? $args['width_percent'] : false;
- }
-
- $this->vectors = captcha_vectors();
- $this->width_percent = (!empty($width_percent)) ? max(25, min(150, intval($width_percent))) : mt_rand(60, 90);
- $this->space = 10;
- $this->radius = 3;
- $this->letter = $letter;
- }
-
- /**
- * Draw a character
- */
- function drawchar($scale, $xoff, $yoff, $img, $background, $colors)
- {
- $vectorset = $this->vectors[$this->letter];
- $height = $scale;
- $width = (($scale * $this->width_percent) / 100);
- $color = $colors[array_rand($colors)];
- if (sizeof($vectorset))
+ // fill with noise or grid
+ if ($config['captcha_gd_noise'])
{
- foreach ($vectorset as $veclist)
+ // random characters in background with random position, angle, color
+ for ($i = 0 ; $i < 72; $i++)
{
- switch ($veclist[0])
- {
- case 'line':
- $dx = ($veclist[3] - $veclist[1]) * $width;
- $dy = ($veclist[4] - $veclist[2]) * -$height;
-
- $idx = -$dy;
- $idy = $dx;
-
- $length = sqrt(pow($dx, 2) + pow($dy, 2));
-
- $hatches = $length / $this->space;
-
- for ($p = 0; $p <= $hatches; ++$p)
- {
- if (!$p && !mt_rand(0, 9) && ($hatches > 3))
- {
- continue;
- }
-
- $xp = 1;
- $yp = -2;
- for ($i = 0; $i < 9; ++$i)
- {
- $xp += !($i % 3) ? -2 : 1;
- $yp += !($i % 3) ? 1 : 0;
-
- $x_o = ((($p * $veclist[1]) + (($hatches - $p) * $veclist[3])) * $width ) / $hatches;
- $y_o = $height - (((($p * $veclist[2]) + (($hatches - $p) * $veclist[4])) * $height ) / $hatches);
- $x_1 = $xoff + $xp + $x_o;
- $y_1 = $yoff + $yp + $y_o;
-
- $x_d1 = (($dx - $idx) * $this->radius) / $length;
- $y_d1 = (($dy - $idy) * $this->radius) / $length;
-
- $x_d2 = (($dx - $idx) * -$this->radius) / $length;
- $y_d2 = (($dy - $idy) * -$this->radius) / $length;
-
- imageline($img, $x_1 + $x_d1, $y_1 + $y_d1, $x_1 + $x_d2, $y_1 + $y_d2, $color);
- }
- }
- break;
-
- case 'arc':
- $arclengthdeg = $veclist[6] - $veclist[5];
- $arclengthdeg += ( $arclengthdeg < 0 ) ? 360 : 0;
-
- $arclength = ((($veclist[3] * $width) + ($veclist[4] * $height)) * M_PI) / 2;
- $arclength = ($arclength * $arclengthdeg) / 360;
-
- $hatches = $arclength / $this->space;
-
- $hatchdeg = ($arclengthdeg * $this->space) / $arclength;
- $shiftdeg = ($arclengthdeg * $this->radius) / $arclength;
-
- $x_c = $veclist[1] * $width;
- $y_c = (1 - $veclist[2]) * $height;
-
- for ($p = 0; $p <= $arclengthdeg; $p += $hatchdeg)
- {
- if (!mt_rand(0, 9) && ($hatches > 3) && !$p)
- {
- continue;
- }
-
- $theta1 = deg2rad(($p + $veclist[5] - $shiftdeg) % 360);
- $theta2 = deg2rad(($p + $veclist[5] + $shiftdeg) % 360);
- $x_o1 = cos($theta1) * (($veclist[3] * 0.5 * $width) - $this->radius);
- $y_o1 = sin($theta1) * (($veclist[4] * 0.5 * $height) - $this->radius);
- $x_o2 = cos($theta2) * (($veclist[3] * 0.5 * $width) + $this->radius);
- $y_o2 = sin($theta2) * (($veclist[4] * 0.5 * $height) + $this->radius);
-
- $xp = 1;
- $yp = -2;
- for ($i = 0; $i < 9; ++$i)
- {
- $xp += !($i % 3) ? -2 : 1;
- $yp += !($i % 3) ? 1 : 0;
-
- imageline($img,
- $xoff + $xp + $x_c + $x_o1,
- $yoff + $yp + $y_c + $y_o1,
- $xoff + $xp + $x_c + $x_o2,
- $yoff + $yp + $y_c + $y_o2,
- $color
- );
- }
- }
- break;
- }
+ $size = mt_rand(8, 23);
+ $angle = mt_rand(0, 360);
+ $x = mt_rand(0, 360);
+ $y = mt_rand(0, (int)($ly - ($size / 5)));
+ $color = $func2($image, mt_rand(160, 224), mt_rand(160, 224), mt_rand(160, 224));
+ $text = chr(mt_rand(45, 250));
+ imagettftext($image, $size, $angle, $x, $y, $color, $this->get_font(), $text);
}
}
- }
-
- /*
- * return a roughly acceptable range of sizes for rendering with this texttype
- */
- function range()
- {
- return array(60, 80);
- }
-
- /**
- * Dimensions
- */
- function dimensions($size)
- {
- return array(-4, -4, (($size * $this->width_percent) / 100) + 4, $size + 4);
- }
-}
-
-/**
-* @package VC
-*/
-class char_cube3d
-{
- // need to abstract out the cube3d from the cubechar
- var $bitmaps;
-
- var $basis_matrix = array(array(1, 0, 0), array(0, 1, 0), array(0, 0, 1));
- var $abs_x = array(1, 0);
- var $abs_y = array(0, 1);
- var $x = 0;
- var $y = 1;
- var $z = 2;
- var $letter = '';
-
- function char_cube3d($letter)
- {
- $this->bitmaps = captcha_bitmaps();
-
- $this->basis_matrix[0][0] = mt_rand(-600, 600);
- $this->basis_matrix[0][1] = mt_rand(-600, 600);
- $this->basis_matrix[0][2] = (mt_rand(0, 1) * 2000) - 1000;
- $this->basis_matrix[1][0] = mt_rand(-1000, 1000);
- $this->basis_matrix[1][1] = mt_rand(-1000, 1000);
- $this->basis_matrix[1][2] = mt_rand(-1000, 1000);
-
- $this->normalize($this->basis_matrix[0]);
- $this->normalize($this->basis_matrix[1]);
- $this->basis_matrix[2] = $this->cross_product($this->basis_matrix[0], $this->basis_matrix[1]);
- $this->normalize($this->basis_matrix[2]);
-
- // $this->basis_matrix[1] might not be (probably isn't) orthogonal to $basis_matrix[0]
- $this->basis_matrix[1] = $this->cross_product($this->basis_matrix[0], $this->basis_matrix[2]);
- $this->normalize($this->basis_matrix[1]);
-
- // Make sure our cube is facing into the canvas (assuming +z == in)
- for ($i = 0; $i < 3; ++$i)
+ else
{
- if ($this->basis_matrix[$i][2] < 0)
+ // generate grid
+ for ($i = 0; $i < $lx; $i += 13)
{
- $this->basis_matrix[$i][0] *= -1;
- $this->basis_matrix[$i][1] *= -1;
- $this->basis_matrix[$i][2] *= -1;
+ $color = $func2($image, mt_rand(160, 224), mt_rand(160, 224), mt_rand(160, 224));
+ imageline($image, $i, 0, $i, $ly, $color);
}
- }
-
- // Force our "z" basis vector to be the one with greatest absolute z value
- $this->x = 0;
- $this->y = 1;
- $this->z = 2;
-
- // Swap "y" with "z"
- if ($this->basis_matrix[1][2] > $this->basis_matrix[2][2])
- {
- $this->z = 1;
- $this->y = 2;
- }
-
- // Swap "x" with "z"
- if ($this->basis_matrix[0][2] > $this->basis_matrix[$this->z][2])
- {
- $this->x = $this->z;
- $this->z = 0;
- }
-
- // Still need to determine which of $x,$y are which.
- // wrong orientation if y's y-component is less than it's x-component
- // likewise if x's x-component is less than it's y-component
- // if they disagree, go with the one with the greater weight difference.
- // rotate if positive
- $weight = (abs($this->basis_matrix[$this->x][1]) - abs($this->basis_matrix[$this->x][0])) +
- (abs($this->basis_matrix[$this->y][0]) - abs($this->basis_matrix[$this->y][1]));
-
- // Swap "x" with "y"
- if ($weight > 0)
- {
- list($this->x, $this->y) = array($this->y, $this->x);
- }
-
- $this->abs_x = array($this->basis_matrix[$this->x][0], $this->basis_matrix[$this->x][1]);
- $this->abs_y = array($this->basis_matrix[$this->y][0], $this->basis_matrix[$this->y][1]);
-
- if ($this->abs_x[0] < 0)
- {
- $this->abs_x[0] *= -1;
- $this->abs_x[1] *= -1;
- }
-
- if ($this->abs_y[1] > 0)
- {
- $this->abs_y[0] *= -1;
- $this->abs_y[1] *= -1;
- }
-
- $this->letter = $letter;
- }
-
- /**
- *
- */
- function draw($im, $scale, $xoff, $yoff, $face, $xshadow, $yshadow)
- {
- $origin = array(0, 0, 0);
- $xvec = $this->scale($this->basis_matrix[$this->x], $scale);
- $yvec = $this->scale($this->basis_matrix[$this->y], $scale);
- $face_corner = $this->sum2($xvec, $yvec);
-
- $zvec = $this->scale($this->basis_matrix[$this->z], $scale);
- $x_corner = $this->sum2($xvec, $zvec);
- $y_corner = $this->sum2($yvec, $zvec);
-
- imagefilledpolygon($im, $this->gen_poly($xoff, $yoff, $origin, $xvec, $x_corner, $zvec), 4, $yshadow);
- imagefilledpolygon($im, $this->gen_poly($xoff, $yoff, $origin, $yvec, $y_corner, $zvec), 4, $xshadow);
- imagefilledpolygon($im, $this->gen_poly($xoff, $yoff, $origin, $xvec, $face_corner, $yvec), 4, $face);
- }
-
- /**
- * Draw a character
- */
- function drawchar($scale, $xoff, $yoff, $img, $background, $colors)
- {
- $width = $this->bitmaps['width'];
- $height = $this->bitmaps['height'];
- $bitmap = $this->bitmaps['data'][$this->letter];
-
- $color1 = $colors[array_rand($colors)];
- $color2 = $colors[array_rand($colors)];
-
- $swapx = ($this->basis_matrix[$this->x][0] > 0);
- $swapy = ($this->basis_matrix[$this->y][1] < 0);
-
- for ($y = 0; $y < $height; ++$y)
- {
- for ($x = 0; $x < $width; ++$x)
+ for ($i = 0; $i < $ly; $i += 11)
{
- $xp = ($swapx) ? ($width - $x - 1) : $x;
- $yp = ($swapy) ? ($height - $y - 1) : $y;
-
- if ($bitmap[$height - $yp - 1][$xp])
- {
- $dx = $this->scale($this->abs_x, ($xp - ($swapx ? ($width / 2) : ($width / 2) - 1)) * $scale);
- $dy = $this->scale($this->abs_y, ($yp - ($swapy ? ($height / 2) : ($height / 2) - 1)) * $scale);
- $xo = $xoff + $dx[0] + $dy[0];
- $yo = $yoff + $dx[1] + $dy[1];
-
- $origin = array(0, 0, 0);
- $xvec = $this->scale($this->basis_matrix[$this->x], $scale);
- $yvec = $this->scale($this->basis_matrix[$this->y], $scale);
- $face_corner = $this->sum2($xvec, $yvec);
-
- $zvec = $this->scale($this->basis_matrix[$this->z], $scale);
- $x_corner = $this->sum2($xvec, $zvec);
- $y_corner = $this->sum2($yvec, $zvec);
-
- imagefilledpolygon($img, $this->gen_poly($xo, $yo, $origin, $xvec, $x_corner,$zvec), 4, $color1);
- imagefilledpolygon($img, $this->gen_poly($xo, $yo, $origin, $yvec, $y_corner,$zvec), 4, $color2);
-
- $face = $this->gen_poly($xo, $yo, $origin, $xvec, $face_corner, $yvec);
-
- imagefilledpolygon($img, $face, 4, $background);
- imagepolygon($img, $face, 4, $color1);
- }
+ $color = $func2($image, mt_rand(160, 224), mt_rand(160, 224), mt_rand(160, 224));
+ imageline($image, 0, $i, $lx, $i, $color);
}
}
- }
-
- /*
- * return a roughly acceptable range of sizes for rendering with this texttype
- */
- function range()
- {
- return array(5, 10);
- }
- /**
- * Vector length
- */
- function vectorlen($vector)
- {
- return sqrt(pow($vector[0], 2) + pow($vector[1], 2) + pow($vector[2], 2));
- }
-
- /**
- * Normalize
- */
- function normalize(&$vector, $length = 1)
- {
- $length = (( $length < 1) ? 1 : $length);
- $length /= $this->vectorlen($vector);
- $vector[0] *= $length;
- $vector[1] *= $length;
- $vector[2] *= $length;
- }
-
- /**
- *
- */
- function cross_product($vector1, $vector2)
- {
- $retval = array(0, 0, 0);
- $retval[0] = (($vector1[1] * $vector2[2]) - ($vector1[2] * $vector2[1]));
- $retval[1] = -(($vector1[0] * $vector2[2]) - ($vector1[2] * $vector2[0]));
- $retval[2] = (($vector1[0] * $vector2[1]) - ($vector1[1] * $vector2[0]));
+ $len = strlen($code);
- return $retval;
- }
-
- /**
- *
- */
- function sum($vector1, $vector2)
- {
- return array($vector1[0] + $vector2[0], $vector1[1] + $vector2[1], $vector1[2] + $vector2[2]);
- }
-
- /**
- *
- */
- function sum2($vector1, $vector2)
- {
- return array($vector1[0] + $vector2[0], $vector1[1] + $vector2[1]);
- }
-
- /**
- *
- */
- function scale($vector, $length)
- {
- if (sizeof($vector) == 2)
+ for ($i = 0, $x = mt_rand(20, 40); $i < $len; $i++)
{
- return array($vector[0] * $length, $vector[1] * $length);
- }
+ $text = strtoupper($code[$i]);
+ $angle = mt_rand(-30, 30);
+ $size = mt_rand(20, 40);
+ $y = mt_rand((int)($size * 1.5), (int)($ly - ($size / 7)));
- return array($vector[0] * $length, $vector[1] * $length, $vector[2] * $length);
- }
+ $color = $func2($image, mt_rand(0, 127), mt_rand(0, 127), mt_rand(0, 127));
+ $shadow = $func2($image, mt_rand(127, 254), mt_rand(127, 254), mt_rand(127, 254));
+ $font = $this->get_font();
- /**
- *
- */
- function gen_poly($xoff, $yoff, &$vec1, &$vec2, &$vec3, &$vec4)
- {
- $poly = array();
- $poly[0] = $xoff + $vec1[0];
- $poly[1] = $yoff + $vec1[1];
- $poly[2] = $xoff + $vec2[0];
- $poly[3] = $yoff + $vec2[1];
- $poly[4] = $xoff + $vec3[0];
- $poly[5] = $yoff + $vec3[1];
- $poly[6] = $xoff + $vec4[0];
- $poly[7] = $yoff + $vec4[1];
+ imagettftext($image, $size, $angle, $x + (int)($size / 15), $y, $shadow, $font, $text);
+ imagettftext($image, $size, $angle, $x, $y - (int)($size / 15), $color, $font, $text);
- return $poly;
- }
-
- /**
- * dimensions
- */
- function dimensions($size)
- {
- $xn = $this->scale($this->basis_matrix[$this->x], -($this->bitmaps['width'] / 2) * $size);
- $xp = $this->scale($this->basis_matrix[$this->x], ($this->bitmaps['width'] / 2) * $size);
- $yn = $this->scale($this->basis_matrix[$this->y], -($this->bitmaps['height'] / 2) * $size);
- $yp = $this->scale($this->basis_matrix[$this->y], ($this->bitmaps['height'] / 2) * $size);
-
- $p = array();
- $p[0] = $this->sum2($xn, $yn);
- $p[1] = $this->sum2($xp, $yn);
- $p[2] = $this->sum2($xp, $yp);
- $p[3] = $this->sum2($xn, $yp);
-
- $min_x = $max_x = $p[0][0];
- $min_y = $max_y = $p[0][1];
-
- for ($i = 1; $i < 4; ++$i)
- {
- $min_x = ($min_x > $p[$i][0]) ? $p[$i][0] : $min_x;
- $min_y = ($min_y > $p[$i][1]) ? $p[$i][1] : $min_y;
- $max_x = ($max_x < $p[$i][0]) ? $p[$i][0] : $max_x;
- $max_y = ($max_y < $p[$i][1]) ? $p[$i][1] : $max_y;
+ $x += $size + 4;
}
- return array($min_x, $min_y, $max_x, $max_y);
- }
-}
-
-/**
-* Return bitmaps
-*/
-function captcha_bitmaps()
-{
- return array(
- 'width' => 9,
- 'height' => 15,
- 'data' => array(
- 'A' => array(
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,1,0,1,0,0,0),
- array(0,0,0,1,0,1,0,0,0),
- array(0,0,0,1,0,1,0,0,0),
- array(0,0,1,0,0,0,1,0,0),
- array(0,0,1,0,0,0,1,0,0),
- array(0,0,1,0,0,0,1,0,0),
- array(0,1,0,0,0,0,0,1,0),
- array(0,1,0,0,0,0,0,1,0),
- array(0,1,1,1,1,1,1,1,0),
- array(0,1,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- ),
- 'B' => array(
- array(1,1,1,1,1,1,1,0,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,1,0),
- array(1,1,1,1,1,1,1,0,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,1,0),
- array(1,1,1,1,1,1,1,0,0),
- ),
- 'C' => array(
- array(0,0,1,1,1,1,1,0,0),
- array(0,1,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,1,1,1,1,1,0,0),
- ),
- 'D' => array(
- array(1,1,1,1,1,1,1,0,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,1,0),
- array(1,1,1,1,1,1,1,0,0),
- ),
- 'E' => array(
- array(1,1,1,1,1,1,1,1,1),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,1,1,1,1,1,1,1,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,1,1,1,1,1,1,1,1),
- ),
- 'F' => array(
- array(1,1,1,1,1,1,1,1,1),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,1,1,1,1,1,1,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- ),
- 'G' => array(
- array(0,0,1,1,1,1,1,0,0),
- array(0,1,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,1,1,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,1,1,1,1,1,0,0),
- ),
- 'H' => array(
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,1,1,1,1,1,1,1,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- ),
- 'I' => array(
- array(1,1,1,1,1,1,1,1,1),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(1,1,1,1,1,1,1,1,1),
- ),
- 'J' => array(
- array(1,1,1,1,1,1,1,1,1),
- array(0,0,0,0,0,1,0,0,0),
- array(0,0,0,0,0,1,0,0,0),
- array(0,0,0,0,0,1,0,0,0),
- array(0,0,0,0,0,1,0,0,0),
- array(0,0,0,0,0,1,0,0,0),
- array(0,0,0,0,0,1,0,0,0),
- array(0,0,0,0,0,1,0,0,0),
- array(0,0,0,0,0,1,0,0,0),
- array(0,0,0,0,0,1,0,0,0),
- array(0,0,0,0,0,1,0,0,0),
- array(1,0,0,0,0,1,0,0,0),
- array(1,0,0,0,0,1,0,0,0),
- array(0,1,0,0,1,0,0,0,0),
- array(0,0,1,1,0,0,0,0,0),
- ),
- 'K' => array( // New 'K', supplied by NeoThermic
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,1,0,0),
- array(1,0,0,0,0,1,0,0,0),
- array(1,0,0,0,1,0,0,0,0),
- array(1,0,0,1,0,0,0,0,0),
- array(1,0,1,0,0,0,0,0,0),
- array(1,1,0,0,0,0,0,0,0),
- array(1,0,1,0,0,0,0,0,0),
- array(1,0,0,1,0,0,0,0,0),
- array(1,0,0,0,1,0,0,0,0),
- array(1,0,0,0,0,1,0,0,0),
- array(1,0,0,0,0,0,1,0,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,0,1),
- ),
- 'L' => array(
- array(0,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,1,1,1,1,1,1,1,1),
- ),
- 'M' => array(
- array(1,1,0,0,0,0,0,1,1),
- array(1,1,0,0,0,0,0,1,1),
- array(1,0,1,0,0,0,1,0,1),
- array(1,0,1,0,0,0,1,0,1),
- array(1,0,1,0,0,0,1,0,1),
- array(1,0,0,1,0,1,0,0,1),
- array(1,0,0,1,0,1,0,0,1),
- array(1,0,0,1,0,1,0,0,1),
- array(1,0,0,0,1,0,0,0,1),
- array(1,0,0,0,1,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- ),
- 'N' => array(
- array(1,1,0,0,0,0,0,0,1),
- array(1,1,0,0,0,0,0,0,1),
- array(1,0,1,0,0,0,0,0,1),
- array(1,0,1,0,0,0,0,0,1),
- array(1,0,0,1,0,0,0,0,1),
- array(1,0,0,1,0,0,0,0,1),
- array(1,0,0,0,1,0,0,0,1),
- array(1,0,0,0,1,0,0,0,1),
- array(1,0,0,0,1,0,0,0,1),
- array(1,0,0,0,0,1,0,0,1),
- array(1,0,0,0,0,1,0,0,1),
- array(1,0,0,0,0,0,1,0,1),
- array(1,0,0,0,0,0,1,0,1),
- array(1,0,0,0,0,0,0,1,1),
- array(1,0,0,0,0,0,0,1,1),
- ),
- 'O' => array(
- array(0,0,1,1,1,1,1,0,0),
- array(0,1,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,1,1,1,1,1,0,0),
- ),
- 'P' => array(
- array(1,1,1,1,1,1,1,0,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,1,0),
- array(1,1,1,1,1,1,1,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- ),
- 'Q' => array(
- array(0,0,1,1,1,1,1,0,0),
- array(0,1,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,1,0,0,1),
- array(1,0,0,0,0,0,1,0,1),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,1,1,1,1,1,0,1),
- ),
- 'R' => array(
- array(1,1,1,1,1,1,1,0,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,1,0),
- array(1,1,1,1,1,1,1,0,0),
- array(1,1,1,0,0,0,0,0,0),
- array(1,0,0,1,0,0,0,0,0),
- array(1,0,0,0,1,0,0,0,0),
- array(1,0,0,0,0,1,0,0,0),
- array(1,0,0,0,0,0,1,0,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,0,1),
- ),
- 'S' => array(
- array(0,0,1,1,1,1,1,0,0),
- array(0,1,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(0,1,0,0,0,0,0,0,0),
- array(0,0,1,1,1,1,1,0,0),
- array(0,0,0,0,0,0,0,1,0),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,1,1,1,1,1,0,0),
- ),
- 'T' => array(
- array(1,1,1,1,1,1,1,1,1),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- ),
- 'U' => array(
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,1,1,1,1,1,0,0),
- ),
- 'V' => array(
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,1,0),
- array(0,1,0,0,0,0,0,1,0),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,1,0,0,0,1,0,0),
- array(0,0,1,0,0,0,1,0,0),
- array(0,0,1,0,0,0,1,0,0),
- array(0,0,1,0,0,0,1,0,0),
- array(0,0,0,1,0,1,0,0,0),
- array(0,0,0,1,0,1,0,0,0),
- array(0,0,0,1,0,1,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- ),
- 'W' => array( // New 'W', supplied by MHobbit
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,1,0,0,0,1),
- array(1,0,0,0,1,0,0,0,1),
- array(1,0,0,1,0,1,0,0,1),
- array(1,0,0,1,0,1,0,0,1),
- array(1,0,0,1,0,1,0,0,1),
- array(1,0,1,0,0,0,1,0,1),
- array(1,0,1,0,0,0,1,0,1),
- array(1,0,1,0,0,0,1,0,1),
- array(1,1,0,0,0,0,0,1,1),
- array(1,1,0,0,0,0,0,1,1),
- ),
- 'X' => array(
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,1,0),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,1,0,0,0,1,0,0),
- array(0,0,0,1,0,1,0,0,0),
- array(0,0,0,1,0,1,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,1,0,1,0,0,0),
- array(0,0,0,1,0,1,0,0,0),
- array(0,0,1,0,0,0,1,0,0),
- array(0,1,0,0,0,0,1,0,0),
- array(0,1,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- ),
- 'Y' => array(
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,1,0),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,1,0,0,0,1,0,0),
- array(0,0,1,0,0,0,1,0,0),
- array(0,0,0,1,0,1,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- ),
- 'Z' => array( // New 'Z' supplied by Anon
- array(1,1,1,1,1,1,1,1,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,1,0),
- array(0,0,0,0,0,0,1,0,0),
- array(0,0,0,0,0,1,0,0,0),
- array(0,0,0,0,0,1,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,1,0,0,0,0,0),
- array(0,0,0,1,0,0,0,0,0),
- array(0,0,1,0,0,0,0,0,0),
- array(0,1,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,1),
- array(1,1,1,1,1,1,1,1,1),
- ),
- '1' => array(
- array(0,0,0,1,1,0,0,0,0),
- array(0,0,1,0,1,0,0,0,0),
- array(0,1,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,1,1,1,1,1,1,1,0),
- ),
- '2' => array( // New '2' supplied by Anon
- array(0,0,0,1,1,1,0,0,0),
- array(0,0,1,0,0,0,1,0,0),
- array(0,1,0,0,0,0,1,1,0),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,1,1),
- array(0,0,0,0,0,0,0,1,0),
- array(0,0,0,0,0,0,1,0,0),
- array(0,0,0,0,0,1,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,1,0,0,0,0,0),
- array(0,0,1,0,0,0,0,0,0),
- array(0,1,0,0,0,0,0,0,0),
- array(1,1,1,1,1,1,1,1,1),
- array(0,0,0,0,0,0,0,0,0),
- ),
- '3' => array(
- array(0,0,1,1,1,1,1,0,0),
- array(0,1,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,1,0),
- array(0,0,0,0,0,1,1,0,0),
- array(0,0,0,0,0,0,0,1,0),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,1,1,1,1,1,0,0),
- ),
- '4' => array(
- array(0,0,0,0,0,0,1,1,0),
- array(0,0,0,0,0,1,0,1,0),
- array(0,0,0,0,1,0,0,1,0),
- array(0,0,0,1,0,0,0,1,0),
- array(0,0,1,0,0,0,0,1,0),
- array(0,1,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,1,1,1,1,1,1,1,1),
- array(0,0,0,0,0,0,0,1,0),
- array(0,0,0,0,0,0,0,1,0),
- array(0,0,0,0,0,0,0,1,0),
- array(0,0,0,0,0,0,0,1,0),
- array(0,0,0,0,0,0,0,1,0),
- array(0,0,0,0,0,0,0,1,0),
- ),
- '5' => array(
- array(1,1,1,1,1,1,1,1,1),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(0,1,0,0,0,0,0,0,0),
- array(0,0,1,1,1,1,1,0,0),
- array(0,0,0,0,0,0,0,1,0),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,1,1,1,1,1,0,0),
- ),
- '6' => array(
- array(0,0,1,1,1,1,1,0,0),
- array(0,1,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,1,1,1,1,0,0),
- array(1,0,1,0,0,0,0,1,0),
- array(1,1,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,1,1,1,1,1,0,0),
- ),
- '7' => array(
- array(1,1,1,1,1,1,1,1,1),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,1,0),
- array(0,0,0,0,0,0,0,1,0),
- array(0,0,0,0,0,0,1,0,0),
- array(0,0,0,0,0,1,0,0,0),
- array(0,0,0,0,0,1,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,1,0,0,0,0,0),
- array(0,0,0,1,0,0,0,0,0),
- array(0,0,1,0,0,0,0,0,0),
- array(0,1,0,0,0,0,0,0,0),
- array(0,1,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- ),
- '8' => array(
- array(0,0,1,1,1,1,1,0,0),
- array(0,1,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,1,1,1,1,1,0,0),
- array(0,1,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,1,1,1,1,1,0,0),
- ),
- '9' => array(
- array(0,0,1,1,1,1,1,0,0),
- array(0,1,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,1,1),
- array(0,1,0,0,0,0,1,0,1),
- array(0,0,1,1,1,1,0,0,1),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,1,1,1,1,1,0,0),
- ),
- )
- );
-}
-
-
-/**
-* Load True Type Fonts
-*/
-function captcha_load_ttf_fonts()
-{
- static $load_files = array();
-
- if (sizeof($load_files) > 0)
- {
- return $load_files;
+ // Output image
+ header('Content-Type: image/png');
+ header('Cache-control: no-cache, no-store');
+ imagepng($image);
+ imagedestroy($image);
}
- global $phpbb_root_path;
-
- $dr = opendir($phpbb_root_path . 'includes/captcha/fonts');
- while (false !== ($entry = readdir($dr)))
+ function get_font()
{
- if (strtolower(pathinfo($entry, PATHINFO_EXTENSION)) == 'ttf')
- {
- $load_files[$entry] = $phpbb_root_path . 'includes/captcha/fonts/' . $entry;
- }
- }
- closedir($dr);
-
- return $load_files;
-}
-
-
-/**
-* Return vectors
-*/
-function captcha_vectors()
-{
- return array(
- 'A' => array(
- array('line', 0.00, 0.00, 0.50, 1.00, 1.10714871779, 1.11803398875),
- array('line', 1.00, 0.00, 0.50, 1.00, 2.0344439358, 1.11803398875),
- array('line', 0.25, 0.50, 0.75, 0.50, 0.00, 0.50),
- ),
- 'B' => array(
- array('line', 0.00, 0.00, 0.00, 1.00, 1.57079632679, 1.00),
- array('line', 0.00, 1.00, 0.70, 1.00, 0.00, 0.70),
- array('line', 0.00, 0.50, 0.70, 0.50, 0.00, 0.70),
- array('line', 0.00, 0.00, 0.70, 0.00, 0.00, 0.70),
- array('arc', 0.70, 0.75, 0.60, 0.50, 270, 90),
- array('arc', 0.70, 0.25, 0.60, 0.50, 270, 90),
- ),
- 'C' => array(
- array('arc', 0.50, 0.50, 1.00, 1.00, 45, 315),
- ),
- 'D' => array(
- array('line', 0.00, 0.00, 0.00, 1.00, 1.57079632679, 1.00),
- array('line', 0.00, 0.00, 0.50, 0.00, 0.00, 0.50),
- array('line', 0.00, 1.00, 0.50, 1.00, 0.00, 0.50),
- array('arc', 0.50, 0.50, 1.00, 1.00, 270, 90),
- ),
- 'E' => array(
- array('line', 0.00, 0.00, 1.00, 0.00, 0.00, 1.00),
- array('line', 0.00, 0.00, 0.00, 1.00, 1.57079632679, 1.00),
- array('line', 0.00, 1.00, 1.00, 1.00, 0.00, 1.00),
- array('line', 0.00, 0.50, 0.50, 0.50, 0.00, 0.50),
- ),
- 'F' => array(
- array('line', 0.00, 0.00, 0.00, 1.00, 1.57079632679, 1.00),
- array('line', 0.00, 1.00, 1.00, 1.00, 0.00, 1.00),
- array('line', 0.00, 0.50, 0.50, 0.50, 0.00, 0.50),
- ),
- 'G' => array(
- array('line', 0.50, 0.50, 1.00, 0.50, 0.00, 0.50),
- array('line', 1.00, 0.00, 1.00, 0.50, 1.57079632679, 0.50),
- array('arc', 0.50, 0.50, 1.00, 1.00, 0, 315),
- ),
- 'H' => array(
- array('line', 0.00, 0.00, 0.00, 1.00, 1.57079632679, 1.00),
- array('line', 1.00, 0.00, 1.00, 1.00, 1.57079632679, 1.00),
- array('line', 0.00, 0.50, 1.00, 0.50, 0.00, 1.00),
- ),
- 'I' => array(
- array('line', 0.00, 0.00, 1.00, 0.00, 0.00, 1.00),
- array('line', 0.00, 1.00, 1.00, 1.00, 0.00, 1.00),
- array('line', 0.50, 0.00, 0.50, 1.00, 1.57079632679, 1.00),
- ),
- 'J' => array(
- array('line', 1.00, 1.00, 1.00, 0.25, -1.57079632679, 0.75),
- array('arc', 0.50, 0.25, 1.00, 0.50, 0, 180),
- ),
- 'K' => array(
- array('line', 0.00, 0.00, 0.00, 1.00, 1.57079632679, 1.00),
- array('line', 0.00, 0.50, 1.00, 1.00, 0.463647609001, 1.11803398875),
- array('line', 0.00, 0.50, 1.00, 0.00, -0.463647609001, 1.11803398875),
- ),
- 'L' => array(
- array('line', 0.00, 0.00, 0.00, 1.00, 1.57079632679, 1.00),
- array('line', 0.00, 0.00, 1.00, 0.00, 0.00, 1.00),
- ),
- 'M' => array(
- array('line', 0.00, 0.00, 0.00, 1.00, 1.57079632679, 1.00),
- array('line', 0.50, 0.50, 0.00, 1.00, 2.35619449019, 0.707106781187),
- array('line', 0.50, 0.50, 1.00, 1.00, 0.785398163397, 0.707106781187),
- array('line', 1.00, 0.00, 1.00, 1.00, 1.57079632679, 1.00),
- ),
- 'N' => array(
- array('line', 0.00, 0.00, 0.00, 1.00, 1.57079632679, 1.00),
- array('line', 0.00, 1.00, 1.00, 0.00, -0.785398163397, 1.41421356237),
- array('line', 1.00, 0.00, 1.00, 1.00, 1.57079632679, 1.00),
- ),
- 'O' => array(
- array('arc', 0.50, 0.50, 1.00, 1.00, 0, 360),
- ),
- 'P' => array(
- array('line', 0.00, 0.00, 0.00, 1.00, 1.57079632679, 1.00),
- array('line', 0.00, 1.00, 0.70, 1.00, 0.00, 0.70),
- array('line', 0.00, 0.50, 0.70, 0.50, 0.00, 0.70),
- array('arc', 0.70, 0.75, 0.60, 0.50, 270, 90),
- ),
- 'Q' => array(
- array('line', 0.70, 0.30, 1.00, 0.00, -0.785398163397, 0.424264068712),
- array('arc', 0.50, 0.50, 1.00, 1.00, 0, 360),
- ),
- 'R' => array(
- array('line', 0.00, 0.00, 0.00, 1.00, 1.57079632679, 1.00),
- array('line', 0.00, 1.00, 0.70, 1.00, 0.00, 0.70),
- array('line', 0.00, 0.50, 0.70, 0.50, 0.00, 0.70),
- array('line', 0.50, 0.50, 1.00, 0.00, -0.785398163397, 0.707106781187),
- array('arc', 0.70, 0.75, 0.60, 0.50, 270, 90),
- ),
- 'S' => array(
- array('arc', 0.50, 0.75, 1.00, 0.50, 90, 360),
- array('arc', 0.50, 0.25, 1.00, 0.50, 270, 180),
- ),
- 'T' => array(
- array('line', 0.00, 1.00, 1.00, 1.00, 0.00, 1.00),
- array('line', 0.50, 0.00, 0.50, 1.00, 1.57079632679, 1.00),
- ),
- 'U' => array(
- array('line', 0.00, 1.00, 0.00, 0.25, -1.57079632679, 0.75),
- array('line', 1.00, 1.00, 1.00, 0.25, -1.57079632679, 0.75),
- array('arc', 0.50, 0.25, 1.00, 0.50, 0, 180),
- ),
- 'V' => array(
- array('line', 0.00, 1.00, 0.50, 0.00, -1.10714871779, 1.11803398875),
- array('line', 1.00, 1.00, 0.50, 0.00, -2.0344439358, 1.11803398875),
- ),
- 'W' => array(
- array('line', 0.00, 1.00, 0.25, 0.00, -1.32581766367, 1.0307764064),
- array('line', 0.50, 0.50, 0.25, 0.00, -2.0344439358, 0.559016994375),
- array('line', 0.50, 0.50, 0.75, 0.00, -1.10714871779, 0.559016994375),
- array('line', 1.00, 1.00, 0.75, 0.00, -1.81577498992, 1.0307764064),
- ),
- 'X' => array(
- array('line', 0.00, 1.00, 1.00, 0.00, -0.785398163397, 1.41421356237),
- array('line', 0.00, 0.00, 1.00, 1.00, 0.785398163397, 1.41421356237),
- ),
- 'Y' => array(
- array('line', 0.00, 1.00, 0.50, 0.50, -0.785398163397, 0.707106781187),
- array('line', 1.00, 1.00, 0.50, 0.50, -2.35619449019, 0.707106781187),
- array('line', 0.50, 0.50, 0.50, 0.00, -1.57079632679, 0.50),
- ),
- 'Z' => array(
- array('line', 0.00, 1.00, 1.00, 1.00, 0.00, 1.00),
- array('line', 0.00, 0.00, 1.00, 1.00, 0.785398163397, 1.41421356237),
- array('line', 0.00, 0.00, 1.00, 0.00, 0.00, 1.00),
- ),
- '1' => array(
- array('line', 0.00, 0.75, 0.50, 1.00, 0.463647609001, 0.559016994375),
- array('line', 0.50, 0.00, 0.50, 1.00, 1.57079632679, 1.00),
- array('line', 0.00, 0.00, 1.00, 0.00, 0.00, 1.00),
- ),
- '2' => array(
- array('line', 0.00, 0.00, 1.00, 0.00, 0.00, 1.00),
- array('arc', 0.50, 0.70, 1.00, 0.60, 180, 360),
- array('arc', 0.50, 0.70, 1.00, 0.70, 0, 90),
- array('arc', 0.50, 0.00, 1.00, 0.70, 180, 270),
- ),
- '3' => array(
- array('arc', 0.50, 0.75, 1.00, 0.50, 180, 90),
- array('arc', 0.50, 0.25, 1.00, 0.50, 270, 180),
- ),
- '4' => array(
- array('line', 0.70, 0.00, 0.70, 1.00, 1.57079632679, 1.00),
- array('line', 0.00, 0.50, 0.70, 1.00, 0.620249485983, 0.860232526704),
- array('line', 0.00, 0.50, 1.00, 0.50, 0.00, 1.00),
- ),
- '5' => array(
- array('line', 0.00, 1.00, 1.00, 1.00, 0.00, 1.00),
- array('line', 0.00, 1.00, 0.00, 0.60, -1.57079632679, 0.4),
- array('line', 0.00, 0.60, 0.50, 0.60, 0.00, 0.50),
- array('arc', 0.50, 0.30, 1.00, 0.60, 270, 180),
- ),
- '6' => array(
- array('arc', 0.50, 0.50, 1.00, 1.00, 90, 315),
- array('arc', 0.50, 0.30, 0.80, 0.60, 0, 360),
- ),
- '7' => array(
- array('line', 0.00, 1.00, 1.00, 1.00, 0.00, 1.00),
- array('line', 0.50, 0.00, 1.00, 1.00, 1.10714871779, 1.11803398875),
- ),
- '8' => array(
- array('arc', 0.50, 0.75, 1.00, 0.50, 0, 360),
- array('arc', 0.50, 0.25, 1.00, 0.50, 0, 360),
- ),
- '9' => array(
- array('arc', 0.50, 0.50, 1.00, 1.00, 270, 135),
- array('arc', 0.50, 0.70, 0.80, 0.60, 0, 360),
- )
- );
-}
-
-class color_manager
-{
- var $img;
- var $mode;
- var $colors;
- var $named_colors;
- var $named_rgb = array(
- 'red' => array(0xff, 0x00, 0x00),
- 'maroon' => array(0x80, 0x00, 0x00),
- 'yellow' => array(0xff, 0xff, 0x00),
- 'olive' => array(0x80, 0x80, 0x00),
- 'lime' => array(0x00, 0xff, 0x00),
- 'green' => array(0x00, 0x80, 0x00),
- 'aqua' => array(0x00, 0xff, 0xff),
- 'teal' => array(0x00, 0x80, 0x80),
- 'blue' => array(0x00, 0x00, 0xff),
- 'navy' => array(0x00, 0x00, 0x80),
- 'fuchsia' => array(0xff, 0x00, 0xff),
- 'purple' => array(0x80, 0x00, 0x80),
- 'white' => array(0xff, 0xff, 0xff),
- 'silver' => array(0xc0, 0xc0, 0xc0),
- 'gray' => array(0x80, 0x80, 0x80),
- 'black' => array(0x00, 0x00, 0x00),
- );
-
- /**
- * Create the color manager, link it to
- * the image resource
- */
- function color_manager($img, $background = false, $mode = 'ahsv')
- {
- $this->img = $img;
- $this->mode = $mode;
- $this->colors = array();
- $this->named_colors = array();
- if ($background !== false)
- {
- $bg = $this->allocate_named('background', $background);
- imagefill($this->img, 0, 0, $bg);
- }
- }
+ static $fonts = array();
- /**
- * Lookup a named color resource
- */
- function r($named_color)
- {
- if (isset($this->named_colors[$named_color]))
- {
- return $this->named_colors[$named_color];
- }
- if (isset($this->named_rgb[$named_color]))
+ if (!sizeof($fonts))
{
- return $this->allocate_named($named_color, $this->named_rgb[$named_color], 'rgb');
- }
- return false;
- }
-
- /**
- * Assign a name to a color resource
- */
- function name_color($name, $resource)
- {
- $this->named_colors[$name] = $resource;
- }
+ global $phpbb_root_path;
- /**
- * random color resource
- */
- function r_rand($colors)
- {
- return $colors[array_rand($colors)];
- }
-
- /**
- * names and allocates a color resource
- */
- function allocate_named($name, $color, $mode = false)
- {
- $resource = $this->allocate($color, $mode);
- if ($resource !== false)
- {
- $this->name_color($name, $resource);
- }
- return $resource;
- }
-
- /**
- * allocates a specified color into the image
- */
- function allocate($color, $mode = false)
- {
- if ($mode === false)
- {
- $mode = $this->mode;
- }
- if (!is_array($color))
- {
- if (isset($this->named_rgb[$color]))
+ $dr = opendir($phpbb_root_path . 'includes/captcha/fonts');
+ while (false !== ($entry = readdir($dr)))
{
- return $this->allocate_named($color, $this->named_rgb[$color], 'rgb');
- }
- if (!is_int($color))
- {
- return false;
- }
- $mode = 'rgb';
- $color = array(
- 255 & ($color >> 16),
- 255 & ($color >> 8),
- 255 & $color,
- );
- }
-
- if (isset($color['mode']))
- {
- $mode = $color['mode'];
- unset($color['mode']);
- }
- if (isset($color['random']))
- {
- unset($color['random']);
- // everything else is params
- return $this->random_color($color, $mode);
- }
-
- $rgb = color_manager::model_convert($color, $mode, 'rgb');
- $store = ($this->mode == 'rgb') ? $rgb : color_manager::model_convert($color, $mode, $this->mode);
- $resource = imagecolorallocate($this->img, $rgb[0], $rgb[1], $rgb[2]);
-
- $this->colors[$resource] = $store;
-
- return $resource;
- }
-
- /**
- * randomly generates a color, with optional params
- */
- function random_color($params = array(), $mode = false)
- {
- if ($mode === false)
- {
- $mode = $this->mode;
- }
- switch ($mode)
- {
- case 'rgb':
-
- // @TODO random rgb generation. do we intend to do this, or is it just too tedious?
-
- break;
-
- case 'ahsv':
- case 'hsv':
- default:
-
- $default_params = array(
- 'hue_bias' => false, // degree / 'r'/'g'/'b'/'c'/'m'/'y' /'o'
- 'hue_range' => false, // if hue bias, then difference range +/- from bias
- 'min_saturation' => 30, // 0 - 100
- 'max_saturation' => 100, // 0 - 100
- 'min_value' => 30, // 0 - 100
- 'max_value' => 100, // 0 - 100
- );
-
- $alt = ($mode == 'ahsv');
-
- $params = array_merge($default_params, $params);
-
- $min_hue = 0;
- $max_hue = 359;
- $min_saturation = max(0, $params['min_saturation']);
- $max_saturation = min(100, $params['max_saturation']);
- $min_value = max(0, $params['min_value']);
- $max_value = min(100, $params['max_value']);
-
- if ($params['hue_bias'] !== false)
- {
- if (is_numeric($params['hue_bias']))
- {
- $h = intval($params['hue_bias']) % 360;
- }
- else
- {
- switch ($params['hue_bias'])
- {
- case 'o':
- $h = $alt ? 60 : 30;
- break;
-
- case 'y':
- $h = $alt ? 120 : 60;
- break;
-
- case 'g':
- $h = $alt ? 180 : 120;
- break;
-
- case 'c':
- $h = $alt ? 210 : 180;
- break;
-
- case 'b':
- $h = 240;
- break;
-
- case 'm':
- $h = 300;
- break;
-
- case 'r':
- default:
- $h = 0;
- break;
- }
- }
-
- $min_hue = $h + 360;
- $max_hue = $h + 360;
-
- if ($params['hue_range'])
- {
- $min_hue -= min(180, $params['hue_range']);
- $max_hue += min(180, $params['hue_range']);
- }
- }
-
- $h = mt_rand($min_hue, $max_hue);
- $s = mt_rand($min_saturation, $max_saturation);
- $v = mt_rand($min_value, $max_value);
-
- return $this->allocate(array($h, $s, $v), $mode);
-
- break;
- }
- }
-
- function color_scheme($resource, $scheme, $include_original = true)
- {
- $mode = (in_array($this->mode, array('hsv', 'ahsv'), true) ? $this->mode : 'hsv');
- if (($pre = $this->r($resource)) !== false)
- {
- $resource = $pre;
- }
- $color = color_manager::model_convert($this->colors[$resource], $this->mode, $mode);
- $results = $include_original ? array($resource) : array();
-
- switch ($scheme)
- {
- case 'complement':
-
- $color2 = $color;
- $color2[0] += 180;
- $results[] = $this->allocate($color2, $mode);
-
- break;
-
- case 'triadic':
-
- $color2 = $color3 = $color;
- $color2[0] += 120;
- $color3[0] += 240;
- $results[] = $this->allocate($color2, $mode);
- $results[] = $this->allocate($color3, $mode);
-
- break;
-
- case 'tetradic':
-
- $color2 = $color3 = $color4 = $color;
- $color2[0] += 30;
- $color3[0] += 180;
- $color4[0] += 210;
- $results[] = $this->allocate($color2, $mode);
- $results[] = $this->allocate($color3, $mode);
- $results[] = $this->allocate($color4, $mode);
-
- break;
-
- case 'analogous':
-
- $color2 = $color3 = $color;
- $color2[0] += 30;
- $color3[0] += 330;
- $results[] = $this->allocate($color2, $mode);
- $results[] = $this->allocate($color3, $mode);
-
- break;
- }
- return $results;
- }
-
- function mono_range($resource, $type = 'both', $count = 5, $include_original = true)
- {
- if (is_array($resource))
- {
- $results = array();
- for ($i = 0, $size = sizeof($resource); $i < $size; ++$i)
- {
- $results = array_merge($results, $this->mono_range($resource[$i], $type, $count, $include_original));
- }
- return $results;
- }
- $mode = (in_array($this->mode, array('hsv', 'ahsv'), true) ? $this->mode : 'ahsv');
- if (($pre = $this->r($resource)) !== false)
- {
- $resource = $pre;
- }
- $color = color_manager::model_convert($this->colors[$resource], $this->mode, $mode);
-
- $results = array();
- if ($include_original)
- {
- $results[] = $resource;
- $count--;
- }
-
- switch ($type)
- {
- case 'saturation':
-
- $pivot = $color[1];
- $num_below = intval(($pivot * $count) / 100);
- $num_above = $count - $num_below;
-
- for ($i = $num_above; $i > 0; --$i)
- {
- $color[1] = (($i * 100) + (($num_above - $i) * $pivot)) / $num_above;
- $results[] = $this->allocate($color, $mode);
- }
-
- ++$num_below;
-
- for ($i = $num_below - 1; $i > 0; --$i)
- {
- $color[1] = ($i * $pivot) / $num_below;;
- $results[] = $this->allocate($color, $mode);
- }
-
- return $results;
-
- break;
-
- case 'value':
-
- $pivot = $color[2];
- $num_below = intval(($pivot * $count) / 100);
- $num_above = $count - $num_below;
-
- for ($i = $num_above; $i > 0; --$i)
- {
- $color[2] = (($i * 100) + (($num_above - $i) * $pivot)) / $num_above;
- $results[] = $this->allocate($color, $mode);
- }
-
- ++$num_below;
-
- for ($i = $num_below - 1; $i > 0; --$i)
- {
- $color[2] = ($i * $pivot) / $num_below;;
- $results[] = $this->allocate($color, $mode);
- }
-
- return $results;
-
- break;
-
- case 'both':
-
- // This is a hard problem. I chicken out and do an even triangle
- // the problem is that it disregards the original saturation and value,
- // and as such a generated result might come arbitrarily close to our original value.
- $length = ceil(sqrt($count * 2));
- for ($i = $length; $i > 0; --$i)
- {
- for ($j = $i; $j > 0; --$j)
- {
- $color[1] = ($i * 100) / $length;
- $color[2] = ($j * 100) / $i;
- $results[] = $this->allocate($color, $mode);
- --$count;
- if (!$count)
- {
- return $results;
- }
- }
- }
-
- return $results;
-
- break;
- }
-
- return false;
- }
-
- function is_dark($resource)
- {
- $color = (($pre = $this->r($resource)) !== false) ? $this->colors[$pre] : $this->colors[$resource];
- switch($this->mode)
- {
- case 'ahsv':
- case 'hsv':
-
- return ($color[2] <= 50);
-
- break;
-
- case 'rgb':
-
- return (max($color[0], $color[1], $color[2]) <= 128);
-
- break;
- }
- return false;
- }
-
- /**
- * Convert from one color model to another
- *
- * note: properly following coding standards here yields unweildly amounts of whitespace, rendering this less than easily readable
- *
- */
- function model_convert($color, $from_model, $to_model)
- {
- if ($from_model == $to_model)
- {
- return $color;
- }
- switch ($to_model)
- {
- case 'hsv':
- switch($from_model)
- {
- case 'ahsv':
- return color_manager::ah2h($color);
- break;
-
- case 'rgb':
- return color_manager::rgb2hsv($color);
- break;
- }
- break;
-
- case 'ahsv':
- switch($from_model)
+ if (strtolower(pathinfo($entry, PATHINFO_EXTENSION)) == 'ttf')
{
- case 'hsv':
- return color_manager::h2ah($color);
- break;
-
- case 'rgb':
- return color_manager::h2ah(color_manager::rgb2hsv($color));
- break;
- }
- break;
-
- case 'rgb':
- switch($from_model)
- {
- case 'hsv':
- return color_manager::hsv2rgb($color);
- break;
-
- case 'ahsv':
- return color_manager::hsv2rgb(color_manager::ah2h($color));
- break;
+ $fonts[] = $phpbb_root_path . 'includes/captcha/fonts/' . $entry;
}
- break;
- }
- return false;
- }
-
- /**
- * Slightly altered from wikipedia's algorithm
- */
- function hsv2rgb($hsv)
- {
- color_manager::normalize_hue($hsv[0]);
- $h = $hsv[0];
- $s = min(1, max(0, $hsv[1] / 100));
- $v = min(1, max(0, $hsv[2] / 100));
-
- $hi = floor($hsv[0] / 60); // calculate hue sector
-
- $p = $v * (1 - $s); // calculate opposite color
- $f = ($h / 60) - $hi; // calculate distance between hex vertices
- if (!($hi & 1)) // coming in or going out?
- {
- $f = 1 - $f;
- }
- $q = $v * (1 - ($f * $s)); // calculate adjacent color
-
- switch ($hi)
- {
- case 0:
- $rgb = array($v, $q, $p);
- break;
-
- case 1:
- $rgb = array($q, $v, $p);
- break;
-
- case 2:
- $rgb = array($p, $v, $q);
- break;
-
- case 3:
- $rgb = array($p, $q, $v);
- break;
-
- case 4:
- $rgb = array($q, $p, $v);
- break;
-
- case 5:
- $rgb = array($v, $p, $q);
- break;
-
- default:
- return array(0, 0, 0);
- break;
- }
- return array(255 * $rgb[0], 255 * $rgb[1], 255 * $rgb[2]);
- }
-
- /**
- * (more than) Slightly altered from wikipedia's algorithm
- */
- function rgb2hsv($rgb)
- {
- $r = min(255, max(0, $rgb[0]));
- $g = min(255, max(0, $rgb[1]));
- $b = min(255, max(0, $rgb[2]));
- $max = max($r, $g, $b);
- $min = min($r, $g, $b);
-
- $v = $max / 255;
- $s = (!$max) ? 0 : 1 - ($min / $max);
- $h = $max - $min; // if max - min is 0, we want hue to be 0 anyway.
- if ($h)
- {
- switch ($max)
- {
- case $g:
- $h = 120 + (60 * ($b - $r) / $h);
- break;
-
- case $b:
- $h = 240 + (60 * ($r - $g) / $h);
- break;
-
- case $r:
- $h = 360 + (60 * ($g - $b) / $h);
- break;
}
+ closedir($dr);
}
- color_manager::normalize_hue($h);
- return array($h, $s * 100, $v * 100);
- }
-
- /**
- * Bleh
- */
- function normalize_hue(&$hue)
- {
- $hue %= 360;
- if ($hue < 0)
- {
- $hue += 360;
- }
- }
-
- /**
- * Alternate hue to hue
- */
- function ah2h($ahue)
- {
- if (is_array($ahue))
- {
- $ahue[0] = color_manager::ah2h($ahue[0]);
- return $ahue;
- }
- color_manager::normalize_hue($ahue);
- if ($ahue >= 240) // blue through red is already ok
- {
- return $ahue;
- }
- if ($ahue >= 180) // ahue green is at 180
- {
- // return (240 - (2 * (240 - $ahue)));
- return (2 * $ahue) - 240; // equivalent
- }
- if ($ahue >= 120) // ahue yellow is at 120 (RYB rather than RGB)
- {
- return $ahue - 60;
- }
- return $ahue / 2;
- }
- /**
- * hue to Alternate hue
- */
- function h2ah($hue)
- {
- if (is_array($hue))
- {
- $hue[0] = color_manager::h2ah($hue[0]);
- return $hue;
- }
- color_manager::normalize_hue($hue);
- if ($hue >= 240) // blue through red is already ok
- {
- return $hue;
- }
- else if ($hue <= 60)
- {
- return $hue * 2;
- }
- else if ($hue <= 120)
- {
- return $hue + 60;
- }
- else
- {
- return ($hue + 240) / 2;
- }
+ return $fonts[array_rand($fonts)];
}
}
-function vector_distance(&$char, $x, $y, $range = 0.1)
-{
- $distance = $range + 1;
- foreach ($char AS $vector)
- {
- $d = $range + 1;
- switch ($vector[0])
- {
- case 'arc':
-
- $dx = $x - $vector[1];
- $dy = -($y - $vector[2]); //because our arcs are upside-down....
- if (abs($dx) > abs($dy))
- {
- $phi = rad2deg(atan(($dy * $vector[3])/($dx * $vector[4])));
- $phi += ($dx < 0) ? 180 : 360;
- $phi %= 360;
- }
- else
- {
- $phi = 90 - rad2deg(atan(($dx * $vector[4])/($dy * $vector[3])));
- $phi += ($dy < 0) ? 180 : 360;
- $phi %= 360;
- }
-
- $internal = $vector[6] > $vector[5]; //external wraps over the 360 point
- $low = $phi >= $vector[5]; //phi is above our low range
- $high = $phi <= $vector[6]; //phi is below our high range.
- if ($internal ? ($low && $high) : ($low || $high)) //if it wraps, it can only be one or the other
- {
- $radphi = deg2rad($phi); // i'm awesome. or not.
- $px = cos($radphi) * 0.5 * $vector[3];
- $py = sin($radphi) * 0.5 * $vector[4];
- $d = sqrt(pow($px - $dx, 2) + pow($py - $dy, 2));
- }
-
- break;
-
- case 'line':
-
- $bx = $x - $vector[1];
- $by = $y - $vector[2];
- $dx = cos($vector[5]);
- $dy = sin($vector[5]);
- $r = ($by * $dx) - ($bx * $dy);
- if ($r < $range && $r > -$range)
- {
- if (abs($dx) > abs($dy))
- {
- $s = (($bx + ($dy * $r)) / $dx);
- }
- else
- {
- $s = (($by + ($dx * $r)) / $dy);
- }
- if ($s > -$range)
- {
- if ($s < 0)
- {
- $d = sqrt(pow($s, 2) + pow($r, 2));
- }
- elseif ($s < $vector[6])
- {
- $d = $r;
- }
- elseif ($s < $vector[6] + $range)
- {
- $d = sqrt(pow($s - $vector[6], 2) + pow($r, 2));
- }
- }
- }
-
- break;
- }
- $distance = min($distance, abs($d));
- }
- return $distance;
-}
?> \ No newline at end of file
diff --git a/phpBB/includes/captcha/captcha_non_gd.php b/phpBB/includes/captcha/captcha_non_gd.php
index e247823a5e..e4ab36f30b 100644
--- a/phpBB/includes/captcha/captcha_non_gd.php
+++ b/phpBB/includes/captcha/captcha_non_gd.php
@@ -11,6 +11,7 @@
/**
* Main non-gd captcha class
+* @ignore
* @package VC
*/
class captcha
diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php
index 61016b5b31..652bda40a6 100644
--- a/phpBB/includes/constants.php
+++ b/phpBB/includes/constants.php
@@ -27,8 +27,11 @@ define('USER_NORMAL', 0);
define('USER_INACTIVE', 1);
define('USER_IGNORE', 2);
define('USER_FOUNDER', 3);
-//define('USER_BOT', 2);
-//define('USER_GUEST', 4);
+
+define('INACTIVE_REGISTER', 1);
+define('INACTIVE_PROFILE', 2);
+define('INACTIVE_MANUAL', 3);
+define('INACTIVE_REMIND', 4);
// ACL
define('ACL_NEVER', 0);
@@ -61,6 +64,19 @@ define('ITEM_UNLOCKED', 0);
define('ITEM_LOCKED', 1);
define('ITEM_MOVED', 2);
+// Forum Flags
+define('FORUM_FLAG_LINK_TRACK', 1);
+define('FORUM_FLAG_PRUNE_POLL', 2);
+define('FORUM_FLAG_PRUNE_ANNOUNCE', 4);
+define('FORUM_FLAG_PRUNE_STICKY', 8);
+define('FORUM_FLAG_ACTIVE_TOPICS', 16);
+define('FORUM_FLAG_POST_REVIEW', 32);
+
+// Optional text flags
+define('OPTION_FLAG_BBCODE', 1);
+define('OPTION_FLAG_SMILIES', 2);
+define('OPTION_FLAG_LINKS', 4);
+
// Topic types
define('POST_NORMAL', 0);
define('POST_STICKY', 1);
@@ -114,7 +130,8 @@ define('ATTACHMENT_CATEGORY_IMAGE', 1); // Inline Images
define('ATTACHMENT_CATEGORY_WM', 2); // Windows Media Files - Streaming
define('ATTACHMENT_CATEGORY_RM', 3); // Real Media Files - Streaming
define('ATTACHMENT_CATEGORY_THUMB', 4); // Not used within the database, only while displaying posts
-//define('SWF_CAT', 5); // Replaced by [flash]? or an additional possibility?
+define('ATTACHMENT_CATEGORY_FLASH', 5); // Flash/SWF files
+define('ATTACHMENT_CATEGORY_QUICKTIME', 6); // Quicktime/Mov files
// BBCode UID length
define('BBCODE_UID_LEN', 5);
@@ -130,6 +147,7 @@ define('FIELD_BOOL', 4);
define('FIELD_DROPDOWN', 5);
define('FIELD_DATE', 6);
+
// Additional constants
@@ -172,7 +190,6 @@ define('PROFILE_FIELDS_DATA_TABLE', $table_prefix . 'profile_fields_data');
define('PROFILE_FIELDS_LANG_TABLE', $table_prefix . 'profile_fields_lang');
define('PROFILE_LANG_TABLE', $table_prefix . 'profile_lang');
define('RANKS_TABLE', $table_prefix . 'ranks');
-define('RATINGS_TABLE', $table_prefix . 'ratings');
define('REPORTS_TABLE', $table_prefix . 'reports');
define('REPORTS_REASONS_TABLE', $table_prefix . 'reports_reasons');
define('SEARCH_RESULTS_TABLE', $table_prefix . 'search_results');
@@ -193,7 +210,6 @@ define('TOPICS_TRACK_TABLE', $table_prefix . 'topics_track');
define('TOPICS_WATCH_TABLE', $table_prefix . 'topics_watch');
define('USER_GROUP_TABLE', $table_prefix . 'user_group');
define('USERS_TABLE', $table_prefix . 'users');
-define('USERS_NOTES_TABLE', $table_prefix . 'users_notes');
define('WARNINGS_TABLE', $table_prefix . 'warnings');
define('WORDS_TABLE', $table_prefix . 'words');
define('ZEBRA_TABLE', $table_prefix . 'zebra');
diff --git a/phpBB/includes/db/dbal.php b/phpBB/includes/db/dbal.php
index f774b5dcc3..d2d3efedaa 100644
--- a/phpBB/includes/db/dbal.php
+++ b/phpBB/includes/db/dbal.php
@@ -39,6 +39,11 @@ class dbal
var $sql_error_sql = '';
/**
+ * Current sql layer
+ */
+ var $sql_layer = '';
+
+ /**
* Constructor
*/
function dbal()
@@ -48,6 +53,10 @@ class dbal
'normal' => 0,
'total' => 0,
);
+
+ // Fill default sql layer based on the class being called.
+ // This can be changed by the specified layer itself later if needed.
+ $this->sql_layer = substr(get_class($this), 5);
}
/**
@@ -110,12 +119,12 @@ class dbal
*/
function sql_fetchrowset($query_id = false)
{
- if (!$query_id)
+ if ($query_id === false)
{
$query_id = $this->query_result;
}
- if ($query_id)
+ if ($query_id !== false)
{
$result = array();
while ($row = $this->sql_fetchrow($query_id))
@@ -130,8 +139,40 @@ class dbal
}
/**
+ * Fetch field
+ * if rownum is false, the current row is used, else it is pointing to the row (zero-based)
+ */
+ function sql_fetchfield($field, $rownum = false, $query_id = false)
+ {
+ global $cache;
+
+ if ($query_id === false)
+ {
+ $query_id = $this->query_result;
+ }
+
+ if ($query_id !== false)
+ {
+ if ($rownum !== false)
+ {
+ $this->sql_rowseek($rownum, $query_id);
+ }
+
+ if (!is_object($query_id) && isset($cache->sql_rowset[$query_id]))
+ {
+ return $cache->sql_fetchfield($query_id, $field);
+ }
+
+ $row = $this->sql_fetchrow($query_id);
+ return (isset($row[$field])) ? $row[$field] : false;
+ }
+
+ return false;
+ }
+
+ /**
* SQL Transaction
- * @access: private
+ * @access private
*/
function sql_transaction($status = 'begin')
{
@@ -211,6 +252,12 @@ class dbal
$ary = array();
foreach ($assoc_ary as $id => $sql_ary)
{
+ // If by accident the sql array is only one-dimensional we build a normal insert statement
+ if (!is_array($sql_ary))
+ {
+ return $this->sql_build_array('INSERT', $assoc_ary);
+ }
+
$values = array();
foreach ($sql_ary as $key => $var)
{
@@ -234,27 +281,75 @@ class dbal
return $query;
}
+ /**
+ * Build IN, NOT IN, = and <> sql comparison string.
+ * @access public
+ */
function sql_in_set($field, $array, $negate = false)
{
if (!sizeof($array))
{
- trigger_error('No values specified for SQL IN comparison', E_USER_ERROR);
+ // Not optimal, but at least the backtrace should help in identifying where the problem lies.
+ $this->sql_error('No values specified for SQL IN comparison');
}
- $values = array();
- foreach ($array as $var)
+ if (!is_array($array))
{
- $values[] = $this->_sql_validate_value($var);
+ $array = array($array);
}
- if (sizeof($values) == 1)
+ if (sizeof($array) == 1)
{
- return $field . ($negate ? ' <> ' : ' = ') . $values[0];
+ @reset($array);
+ $var = current($array);
+
+ return $field . ($negate ? ' <> ' : ' = ') . $this->_sql_validate_value($var);
}
else
{
- return $field . ($negate ? ' NOT IN ' : ' IN ' ) . '(' . implode(', ', $values) . ')';
+ return $field . ($negate ? ' NOT IN ' : ' IN ' ) . '(' . implode(', ', array_map(array($this, '_sql_validate_value'), $array)) . ')';
+ }
+ }
+
+ /**
+ * Run more than one insert statement.
+ *
+ * @param $sql_ary array multi-dimensional array holding the statement data.
+ * @param $table string table name to run the statements on
+ *
+ * @return bool false if no statements were executed.
+ * @access public
+ */
+ function sql_multi_insert($table, &$sql_ary)
+ {
+ if (!sizeof($sql_ary))
+ {
+ return false;
}
+
+ switch ($this->sql_layer)
+ {
+ case 'mysql':
+ case 'mysql4':
+ case 'mysqli':
+ case 'sqlite':
+ $this->sql_query('INSERT INTO ' . $table . ' ' . $this->sql_build_array('MULTI_INSERT', $sql_ary));
+ break;
+
+ default:
+ foreach ($sql_ary as $ary)
+ {
+ if (!is_array($ary))
+ {
+ return false;
+ }
+
+ $this->sql_query('INSERT INTO ' . $table . ' ' . $this->sql_build_array('INSERT', $ary));
+ }
+ break;
+ }
+
+ return true;
}
/**
@@ -354,7 +449,7 @@ class dbal
if (!$this->return_on_error)
{
- $message = '<u>SQL ERROR</u> [ ' . SQL_LAYER . ' ]<br /><br />' . $error['message'] . ' [' . $error['code'] . ']';
+ $message = '<u>SQL ERROR</u> [ ' . $this->sql_layer . ' ]<br /><br />' . $error['message'] . ' [' . $error['code'] . ']';
// Show complete SQL error and path to administrators only
// Additionally show complete error on installation or if extended debug mode is enabled
@@ -364,7 +459,7 @@ class dbal
// Print out a nice backtrace...
$backtrace = get_backtrace();
- $message .= ($sql) ? '<br /><br /><u>SQL</u><br /><br />' . $sql : '';
+ $message .= ($sql) ? '<br /><br /><u>SQL</u><br /><br />' . htmlspecialchars($sql) : '';
$message .= ($backtrace) ? '<br /><br /><u>BACKTRACE</u><br />' . $backtrace : '';
$message .= '<br />';
}
@@ -409,7 +504,7 @@ class dbal
{
global $cache, $starttime, $phpbb_root_path, $user;
- if (empty($_GET['explain']))
+ if (empty($_REQUEST['explain']))
{
return false;
}
@@ -453,7 +548,7 @@ class dbal
<br />
<p><b>Page generated in ' . round($totaltime, 4) . " seconds with {$this->num_queries['normal']} queries" . (($this->num_queries['cached']) ? " + {$this->num_queries['cached']} " . (($this->num_queries['cached'] == 1) ? 'query' : 'queries') . ' returning data from cache' : '') . '</b></p>
- <p>Time spent on ' . SQL_LAYER . ' queries: <b>' . round($this->sql_time, 5) . 's</b> | Time spent on PHP: <b>' . round($totaltime - $this->sql_time, 5) . 's</b></p>
+ <p>Time spent on ' . $this->sql_layer . ' queries: <b>' . round($this->sql_time, 5) . 's</b> | Time spent on PHP: <b>' . round($totaltime - $this->sql_time, 5) . 's</b></p>
<br /><br />
' . $this->sql_report . '
@@ -504,7 +599,7 @@ class dbal
else
{
$error = $this->sql_error();
- $this->sql_report .= '<b style="color: red">FAILED</b> - ' . SQL_LAYER . ' Error ' . $error['code'] . ': ' . htmlspecialchars($error['message']);
+ $this->sql_report .= '<b style="color: red">FAILED</b> - ' . $this->sql_layer . ' Error ' . $error['code'] . ': ' . htmlspecialchars($error['message']);
}
$this->sql_report .= '</p><br /><br />';
diff --git a/phpBB/includes/db/firebird.php b/phpBB/includes/db/firebird.php
index 7ea5dd3612..7fd034c7dc 100644
--- a/phpBB/includes/db/firebird.php
+++ b/phpBB/includes/db/firebird.php
@@ -9,24 +9,18 @@
*/
/**
+* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
-/**
-* @ignore
-*/
-if (!defined('SQL_LAYER'))
-{
-
- define('SQL_LAYER', 'firebird');
- include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
+include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
/**
* Firebird/Interbase Database Abstraction Layer
-* Minimum Requirement is Firebird 1.5+/Interbase 7.1+
+* Minimum Requirement is Firebird 2.0
* @package dbal
*/
class dbal_firebird extends dbal
@@ -66,7 +60,7 @@ class dbal_firebird extends dbal
/**
* SQL Transaction
- * @access: private
+ * @access private
*/
function _sql_transaction($status = 'begin')
{
@@ -107,7 +101,7 @@ class dbal_firebird extends dbal
$this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result);
- if (!$this->query_result)
+ if ($this->query_result === false)
{
if (($this->query_result = @ibase_query($this->db_connect_id, $query)) === false)
{
@@ -122,7 +116,8 @@ class dbal_firebird extends dbal
}
else
{
- @ibase_commit();
+ // way cooler than ibase_commit_ret :D
+ @ibase_query('COMMIT RETAIN;');
}
}
@@ -165,27 +160,6 @@ class dbal_firebird extends dbal
}
/**
- * Return number of rows
- * Not used within core code
- */
- function sql_numrows($query_id = false)
- {
- global $cache;
-
- if (!$query_id)
- {
- $query_id = $this->query_result;
- }
-
- if (isset($cache->sql_rowset[$query_id]))
- {
- return $cache->sql_numrows($query_id);
- }
-
- return false;
- }
-
- /**
* Return number of affected rows
*/
function sql_affectedrows()
@@ -208,7 +182,7 @@ class dbal_firebird extends dbal
{
global $cache;
- if (!$query_id)
+ if ($query_id === false)
{
$query_id = $this->query_result;
}
@@ -218,6 +192,11 @@ class dbal_firebird extends dbal
return $cache->sql_fetchrow($query_id);
}
+ if ($query_id === false)
+ {
+ return false;
+ }
+
$row = array();
$cur_row = @ibase_fetch_object($query_id, IBASE_TEXT);
@@ -228,60 +207,41 @@ class dbal_firebird extends dbal
foreach (get_object_vars($cur_row) as $key => $value)
{
- $row[strtolower($key)] = trim(str_replace("\\0", "\0", str_replace("\\n", "\n", $value)));
+ $row[strtolower($key)] = trim(str_replace(array("\\0", "\\n"), array("\0", "\n"), $value));
}
return (sizeof($row)) ? $row : false;
}
/**
- * Fetch field
- * if rownum is false, the current row is used, else it is pointing to the row (zero-based)
+ * Seek to given row number
+ * rownum is zero-based
*/
- function sql_fetchfield($field, $rownum = false, $query_id = false)
+ function sql_rowseek($rownum, $query_id = false)
{
global $cache;
- if (!$query_id)
+ if ($query_id === false)
{
$query_id = $this->query_result;
}
- if ($query_id)
+ if (isset($cache->sql_rowset[$query_id]))
{
- if ($rownum !== false)
- {
- $this->sql_rowseek($rownum, $query_id);
- }
-
- if (isset($cache->sql_rowset[$query_id]))
- {
- return $cache->sql_fetchfield($query_id, $field);
- }
-
- $row = $this->sql_fetchrow($query_id);
- return isset($row[$field]) ? $row[$field] : false;
+ return $cache->sql_rowseek($rownum, $query_id);
}
- return false;
- }
-
- /**
- * Seek to given row number
- * rownum is zero-based
- */
- function sql_rowseek($rownum, $query_id = false)
- {
- global $cache;
-
- if (!$query_id)
+ if ($query_id === false)
{
- $query_id = $this->query_result;
+ return;
}
- if (isset($cache->sql_rowset[$query_id]))
+ $this->sql_freeresult($query_id);
+ $query_id = $this->sql_query($this->last_query_text);
+
+ if ($query_id === false)
{
- return $cache->sql_rowseek($query_id, $rownum);
+ return false;
}
// We do not fetch the row for rownum == 0 because then the next resultset would be the second row
@@ -303,7 +263,7 @@ class dbal_firebird extends dbal
{
$query_id = $this->query_result;
- if ($query_id && $this->last_query_text != '')
+ if ($query_id !== false && $this->last_query_text != '')
{
if ($this->query_result && preg_match('#^INSERT[\t\n ]+INTO[\t\n ]+([a-z0-9\_\-]+)#is', $this->last_query_text, $tablename))
{
@@ -331,7 +291,7 @@ class dbal_firebird extends dbal
{
global $cache;
- if (!$query_id)
+ if ($query_id === false)
{
$query_id = $this->query_result;
}
@@ -355,12 +315,12 @@ class dbal_firebird extends dbal
*/
function sql_escape($msg)
{
- return (@ini_get('magic_quotes_sybase') || strtolower(@ini_get('magic_quotes_sybase')) == 'on') ? str_replace('\\\'', '\'', addslashes($msg)) : str_replace('\'', '\'\'', stripslashes($msg));
+ return (@ini_get('magic_quotes_sybase') == 1 || strtolower(@ini_get('magic_quotes_sybase')) == 'on') ? str_replace('\\\'', '\'', addslashes($msg)) : str_replace('\'', '\'\'', stripslashes($msg));
}
/**
* Build db-specific query data
- * @access: private
+ * @access private
*/
function _sql_custom_build($stage, $data)
{
@@ -369,7 +329,7 @@ class dbal_firebird extends dbal
/**
* return sql error array
- * @access: private
+ * @access private
*/
function _sql_error()
{
@@ -381,7 +341,7 @@ class dbal_firebird extends dbal
/**
* Close sql connection
- * @access: private
+ * @access private
*/
function _sql_close()
{
@@ -395,7 +355,7 @@ class dbal_firebird extends dbal
/**
* Build db-specific report
- * @access: private
+ * @access private
*/
function _sql_report($mode, $query = '')
{
@@ -423,9 +383,6 @@ class dbal_firebird extends dbal
break;
}
}
-
}
-} // if ... define
-
?> \ No newline at end of file
diff --git a/phpBB/includes/db/mssql.php b/phpBB/includes/db/mssql.php
index fe6cf75b12..f95f99969c 100644
--- a/phpBB/includes/db/mssql.php
+++ b/phpBB/includes/db/mssql.php
@@ -9,20 +9,14 @@
*/
/**
+* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
-/**
-* @ignore
-*/
-if (!defined('SQL_LAYER'))
-{
-
- define('SQL_LAYER', 'mssql');
- include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
+include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
/**
* MSSQL Database Abstraction Layer
@@ -79,7 +73,7 @@ class dbal_mssql extends dbal
/**
* SQL Transaction
- * @access: private
+ * @access private
*/
function _sql_transaction($status = 'begin')
{
@@ -122,10 +116,13 @@ class dbal_mssql extends dbal
$this->sql_report('start', $query);
}
+ // For now, MSSQL has no real UTF-8 support
+ $query = utf8_decode($query);
+
$this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result);
- if (!$this->query_result)
+ if ($this->query_result === false)
{
if (($this->query_result = @mssql_query($query, $this->db_connect_id)) === false)
{
@@ -169,30 +166,26 @@ class dbal_mssql extends dbal
{
$this->query_result = false;
- // if $total is set to 0 we do not want to limit the number of rows
- if ($total == 0)
+ // Since TOP is only returning a set number of rows we won't need it if total is set to 0 (return all rows)
+ if ($total)
{
- $total = -1;
- }
-
- $row_offset = ($total) ? $offset : '';
- $num_rows = ($total) ? $total : $offset;
-
- if (strpos($query, 'SELECT DISTINCT') === 0)
- {
- $query = 'SELECT DISTINCT TOP ' . ($row_offset + $num_rows) . ' ' . substr($query, 15);
- }
- else
- {
- $query = 'SELECT TOP ' . ($row_offset + $num_rows) . ' ' . substr($query, 6);
+ // We need to grab the total number of rows + the offset number of rows to get the correct result
+ if (strpos($query, 'SELECT DISTINCT') === 0)
+ {
+ $query = 'SELECT DISTINCT TOP ' . ($total + $offset) . ' ' . substr($query, 15);
+ }
+ else
+ {
+ $query = 'SELECT TOP ' . ($total + $offset) . ' ' . substr($query, 6);
+ }
}
$result = $this->sql_query($query, $cache_ttl);
- // Seek by $row_offset rows
- if ($row_offset)
+ // Seek by $offset rows
+ if ($offset)
{
- $this->sql_rowseek($result, $row_offset);
+ $this->sql_rowseek($offset, $result);
}
return $result;
@@ -204,27 +197,6 @@ class dbal_mssql extends dbal
}
/**
- * Return number of rows
- * Not used within core code
- */
- function sql_numrows($query_id = false)
- {
- global $cache;
-
- if (!$query_id)
- {
- $query_id = $this->query_result;
- }
-
- if (isset($cache->sql_rowset[$query_id]))
- {
- return $cache->sql_numrows($query_id);
- }
-
- return ($query_id) ? @mssql_num_rows($query_id) : false;
- }
-
- /**
* Return number of affected rows
*/
function sql_affectedrows()
@@ -239,7 +211,7 @@ class dbal_mssql extends dbal
{
global $cache;
- if (!$query_id)
+ if ($query_id === false)
{
$query_id = $this->query_result;
}
@@ -249,6 +221,11 @@ class dbal_mssql extends dbal
return $cache->sql_fetchrow($query_id);
}
+ if ($query_id === false)
+ {
+ return false;
+ }
+
$row = @mssql_fetch_assoc($query_id);
// I hope i am able to remove this later... hopefully only a PHP or MSSQL bug
@@ -264,38 +241,6 @@ class dbal_mssql extends dbal
}
/**
- * Fetch field
- * if rownum is false, the current row is used, else it is pointing to the row (zero-based)
- */
- function sql_fetchfield($field, $rownum = false, $query_id = false)
- {
- global $cache;
-
- if (!$query_id)
- {
- $query_id = $this->query_result;
- }
-
- if ($query_id)
- {
- if ($rownum !== false)
- {
- $this->sql_rowseek($rownum, $query_id);
- }
-
- if (isset($cache->sql_rowset[$query_id]))
- {
- return $cache->sql_fetchfield($query_id, $field);
- }
-
- $row = $this->sql_fetchrow($query_id);
- return isset($row[$field]) ? $row[$field] : false;
- }
-
- return false;
- }
-
- /**
* Seek to given row number
* rownum is zero-based
*/
@@ -303,17 +248,17 @@ class dbal_mssql extends dbal
{
global $cache;
- if (!$query_id)
+ if ($query_id === false)
{
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
{
- return $cache->sql_rowseek($query_id, $rownum);
+ return $cache->sql_rowseek($rownum, $query_id);
}
- return ($query_id) ? @mssql_data_seek($query_id, $rownum) : false;
+ return ($query_id !== false) ? @mssql_data_seek($query_id, $rownum) : false;
}
/**
@@ -342,7 +287,7 @@ class dbal_mssql extends dbal
{
global $cache;
- if (!$query_id)
+ if ($query_id === false)
{
$query_id = $this->query_result;
}
@@ -371,7 +316,7 @@ class dbal_mssql extends dbal
/**
* return sql error array
- * @access: private
+ * @access private
*/
function _sql_error()
{
@@ -410,7 +355,7 @@ class dbal_mssql extends dbal
/**
* Build db-specific query data
- * @access: private
+ * @access private
*/
function _sql_custom_build($stage, $data)
{
@@ -419,7 +364,7 @@ class dbal_mssql extends dbal
/**
* Close sql connection
- * @access: private
+ * @access private
*/
function _sql_close()
{
@@ -428,7 +373,7 @@ class dbal_mssql extends dbal
/**
* Build db-specific report
- * @access: private
+ * @access private
*/
function _sql_report($mode, $query = '')
{
@@ -486,9 +431,6 @@ class dbal_mssql extends dbal
break;
}
}
-
}
-} // if ... define
-
?> \ No newline at end of file
diff --git a/phpBB/includes/db/mssql_odbc.php b/phpBB/includes/db/mssql_odbc.php
index e1b2675a23..12e3ca686e 100644
--- a/phpBB/includes/db/mssql_odbc.php
+++ b/phpBB/includes/db/mssql_odbc.php
@@ -9,20 +9,14 @@
*/
/**
+* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
-/**
-* @ignore
-*/
-if (!defined('SQL_LAYER'))
-{
-
- define('SQL_LAYER', 'mssql_odbc');
- include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
+include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
/**
* Unified ODBC functions
@@ -73,7 +67,7 @@ class dbal_mssql_odbc extends dbal
/**
* SQL Transaction
- * @access: private
+ * @access private
*/
function _sql_transaction($status = 'begin')
{
@@ -120,11 +114,14 @@ class dbal_mssql_odbc extends dbal
$this->sql_report('start', $query);
}
+ // For now, MSSQL has no real UTF-8 support
+ $query = utf8_decode($query);
+
$this->last_query_text = $query;
$this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result);
- if (!$this->query_result)
+ if ($this->query_result === false)
{
if (($this->query_result = @odbc_exec($this->db_connect_id, $query)) === false)
{
@@ -168,33 +165,26 @@ class dbal_mssql_odbc extends dbal
{
$this->query_result = false;
- // if $total is set to 0 we do not want to limit the number of rows
- if ($total == 0)
- {
- $total = -1;
- }
-
- $row_offset = ($total) ? $offset : 0;
- $num_rows = ($total) ? $total : $offset;
-
- if (strpos($query, 'SELECT DISTINCT') === 0)
- {
- $query = 'SELECT DISTINCT TOP ' . ($row_offset + $num_rows) . ' ' . substr($query, 15);
- }
- else
+ // Since TOP is only returning a set number of rows we won't need it if total is set to 0 (return all rows)
+ if ($total)
{
- $query = 'SELECT TOP ' . ($row_offset + $num_rows) . ' ' . substr($query, 6);
+ // We need to grab the total number of rows + the offset number of rows to get the correct result
+ if (strpos($query, 'SELECT DISTINCT') === 0)
+ {
+ $query = 'SELECT DISTINCT TOP ' . ($total + $offset) . ' ' . substr($query, 15);
+ }
+ else
+ {
+ $query = 'SELECT TOP ' . ($total + $offset) . ' ' . substr($query, 6);
+ }
}
$result = $this->sql_query($query, $cache_ttl);
- // Seek by $row_offset rows
- if ($row_offset)
+ // Seek by $offset rows
+ if ($offset)
{
- for ($i = 0; $i < $row_offset; $i++)
- {
- $this->sql_fetchrow($result);
- }
+ $this->sql_rowseek($offset, $result);
}
return $result;
@@ -206,27 +196,6 @@ class dbal_mssql_odbc extends dbal
}
/**
- * Return number of rows
- * Not used within core code
- */
- function sql_numrows($query_id = false)
- {
- global $cache;
-
- if (!$query_id)
- {
- $query_id = $this->query_result;
- }
-
- if (isset($cache->sql_rowset[$query_id]))
- {
- return $cache->sql_numrows($query_id);
- }
-
- return ($query_id) ? @odbc_num_rows($query_id) : false;
- }
-
- /**
* Return number of affected rows
*/
function sql_affectedrows()
@@ -241,7 +210,7 @@ class dbal_mssql_odbc extends dbal
{
global $cache;
- if (!$query_id)
+ if ($query_id === false)
{
$query_id = $this->query_result;
}
@@ -251,39 +220,7 @@ class dbal_mssql_odbc extends dbal
return $cache->sql_fetchrow($query_id);
}
- return ($query_id) ? @odbc_fetch_array($query_id) : false;
- }
-
- /**
- * Fetch field
- * if rownum is false, the current row is used, else it is pointing to the row (zero-based)
- */
- function sql_fetchfield($field, $rownum = false, $query_id = false)
- {
- global $cache;
-
- if (!$query_id)
- {
- $query_id = $this->query_result;
- }
-
- if ($query_id)
- {
- if ($rownum !== false)
- {
- $this->sql_rowseek($rownum, $query_id);
- }
-
- if (isset($cache->sql_rowset[$query_id]))
- {
- return $cache->sql_fetchfield($query_id, $field);
- }
-
- $row = $this->sql_fetchrow($query_id);
- return isset($row[$field]) ? $row[$field] : false;
- }
-
- return false;
+ return ($query_id !== false) ? @odbc_fetch_array($query_id) : false;
}
/**
@@ -294,20 +231,25 @@ class dbal_mssql_odbc extends dbal
{
global $cache;
- if (!$query_id)
+ if ($query_id === false)
{
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
{
- return $cache->sql_rowseek($query_id, $rownum);
+ return $cache->sql_rowseek($rownum, $query_id);
+ }
+
+ if ($query_id === false)
+ {
+ return false;
}
$this->sql_freeresult($query_id);
$query_id = $this->sql_query($this->last_query_text);
- if (!$query_id)
+ if ($query_id === false)
{
return false;
}
@@ -352,7 +294,7 @@ class dbal_mssql_odbc extends dbal
{
global $cache;
- if (!$query_id)
+ if ($query_id === false)
{
$query_id = $this->query_result;
}
@@ -381,7 +323,7 @@ class dbal_mssql_odbc extends dbal
/**
* Build db-specific query data
- * @access: private
+ * @access private
*/
function _sql_custom_build($stage, $data)
{
@@ -390,7 +332,7 @@ class dbal_mssql_odbc extends dbal
/**
* return sql error array
- * @access: private
+ * @access private
*/
function _sql_error()
{
@@ -402,7 +344,7 @@ class dbal_mssql_odbc extends dbal
/**
* Close sql connection
- * @access: private
+ * @access private
*/
function _sql_close()
{
@@ -411,7 +353,7 @@ class dbal_mssql_odbc extends dbal
/**
* Build db-specific report
- * @access: private
+ * @access private
*/
function _sql_report($mode, $query = '')
{
@@ -469,9 +411,6 @@ class dbal_mssql_odbc extends dbal
break;
}
}
-
}
-} // if ... define
-
?> \ No newline at end of file
diff --git a/phpBB/includes/db/mysql.php b/phpBB/includes/db/mysql.php
index 7e363721a9..89a6e21d70 100644
--- a/phpBB/includes/db/mysql.php
+++ b/phpBB/includes/db/mysql.php
@@ -9,31 +9,31 @@
*/
/**
+* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
-/**
-* @ignore
-*/
-if (!defined('SQL_LAYER'))
-{
-
- define('SQL_LAYER', 'mysql');
- include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
+include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
/**
-* MySQL Database Abstraction Layer
-* Minimum Requirement is 3.23+/4.0+/4.1+
+* MySQL4 Database Abstraction Layer
+* Compatible with:
+* MySQL 3.23+
+* MySQL 4.0+
+* MySQL 4.1+
+* MySQL 5.0+
* @package dbal
*/
class dbal_mysql extends dbal
{
+ var $mysql_version;
+
/**
* Connect to server
- * @access: public
+ * @access public
*/
function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false)
{
@@ -42,12 +42,26 @@ class dbal_mysql extends dbal
$this->server = $sqlserver . (($port) ? ':' . $port : '');
$this->dbname = $database;
+ $this->sql_layer = 'mysql4';
+
$this->db_connect_id = ($this->persistency) ? @mysql_pconnect($this->server, $this->user, $sqlpassword) : @mysql_connect($this->server, $this->user, $sqlpassword);
if ($this->db_connect_id && $this->dbname != '')
{
if (@mysql_select_db($this->dbname))
{
+ // Determine what version we are using and if it natively supports UNICODE
+ $this->mysql_version = mysql_get_server_info($this->db_connect_id);
+
+ if (version_compare($this->mysql_version, '4.1.3', '>='))
+ {
+ @mysql_query("SET NAMES 'utf8'", $this->db_connect_id);
+ }
+ else if (version_compare($this->mysql_version, '4.0.0', '<'))
+ {
+ $this->sql_layer = 'mysql';
+ }
+
return $this->db_connect_id;
}
}
@@ -60,12 +74,12 @@ class dbal_mysql extends dbal
*/
function sql_server_info()
{
- return 'MySQL ' . @mysql_get_server_info($this->db_connect_id);
+ return 'MySQL ' . $this->mysql_version;
}
/**
* SQL Transaction
- * @access: private
+ * @access private
*/
function _sql_transaction($status = 'begin')
{
@@ -111,7 +125,7 @@ class dbal_mysql extends dbal
$this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result);
- if (!$this->query_result)
+ if ($this->query_result === false)
{
if (($this->query_result = @mysql_query($query, $this->db_connect_id)) === false)
{
@@ -158,7 +172,8 @@ class dbal_mysql extends dbal
// if $total is set to 0 we do not want to limit the number of rows
if ($total == 0)
{
- $total = -1;
+ // Having a value of -1 was always a bug
+ $total = '18446744073709551615';
}
$query .= "\n LIMIT " . ((!empty($offset)) ? $offset . ', ' . $total : $total);
@@ -172,27 +187,6 @@ class dbal_mysql extends dbal
}
/**
- * Return number of rows
- * Not used within core code
- */
- function sql_numrows($query_id = false)
- {
- global $cache;
-
- if (!$query_id)
- {
- $query_id = $this->query_result;
- }
-
- if (isset($cache->sql_rowset[$query_id]))
- {
- return $cache->sql_numrows($query_id);
- }
-
- return ($query_id) ? @mysql_num_rows($query_id) : false;
- }
-
- /**
* Return number of affected rows
*/
function sql_affectedrows()
@@ -207,7 +201,7 @@ class dbal_mysql extends dbal
{
global $cache;
- if (!$query_id)
+ if ($query_id === false)
{
$query_id = $this->query_result;
}
@@ -217,47 +211,7 @@ class dbal_mysql extends dbal
return $cache->sql_fetchrow($query_id);
}
- return ($query_id) ? @mysql_fetch_assoc($query_id) : false;
- }
-
- /**
- * Fetch field
- * if rownum is false, the current row is used, else it is pointing to the row (zero-based)
- */
- function sql_fetchfield($field, $rownum = false, $query_id = false)
- {
- global $cache;
-
- if (!$query_id)
- {
- $query_id = $this->query_result;
- }
-
- if ($query_id)
- {
- if ($rownum === false)
- {
- if (isset($cache->sql_rowset[$query_id]))
- {
- return $cache->sql_fetchfield($query_id, $field);
- }
-
- $row = $this->sql_fetchrow($query_id);
- return isset($row[$field]) ? $row[$field] : false;
- }
- else
- {
- if (isset($cache->sql_rowset[$query_id]))
- {
- $cache->sql_rowseek($query_id, $rownum);
- return $cache->sql_fetchfield($query_id, $field);
- }
-
- return @mysql_result($query_id, $rownum, $field);
- }
- }
-
- return false;
+ return ($query_id !== false) ? @mysql_fetch_assoc($query_id) : false;
}
/**
@@ -268,17 +222,17 @@ class dbal_mysql extends dbal
{
global $cache;
- if (!$query_id)
+ if ($query_id === false)
{
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
{
- return $cache->sql_rowseek($query_id, $rownum);
+ return $cache->sql_rowseek($rownum, $query_id);
}
- return ($query_id) ? @mysql_data_seek($query_id, $rownum) : false;
+ return ($query_id !== false) ? @mysql_data_seek($query_id, $rownum) : false;
}
/**
@@ -296,7 +250,7 @@ class dbal_mysql extends dbal
{
global $cache;
- if (!$query_id)
+ if ($query_id === false)
{
$query_id = $this->query_result;
}
@@ -324,13 +278,13 @@ class dbal_mysql extends dbal
{
return @mysql_real_escape_string($msg);
}
-
+
return @mysql_real_escape_string($msg, $this->db_connect_id);
}
/**
* Build db-specific query data
- * @access: private
+ * @access private
*/
function _sql_custom_build($stage, $data)
{
@@ -343,10 +297,10 @@ class dbal_mysql extends dbal
return $data;
}
-
+
/**
* return sql error array
- * @access: private
+ * @access private
*/
function _sql_error()
{
@@ -366,7 +320,7 @@ class dbal_mysql extends dbal
/**
* Close sql connection
- * @access: private
+ * @access private
*/
function _sql_close()
{
@@ -375,7 +329,7 @@ class dbal_mysql extends dbal
/**
* Build db-specific report
- * @access: private
+ * @access private
*/
function _sql_report($mode, $query = '')
{
@@ -433,9 +387,6 @@ class dbal_mysql extends dbal
break;
}
}
-
}
-} // if ... define
-
?> \ No newline at end of file
diff --git a/phpBB/includes/db/mysql4.php b/phpBB/includes/db/mysql4.php
deleted file mode 100644
index 071f4c4b55..0000000000
--- a/phpBB/includes/db/mysql4.php
+++ /dev/null
@@ -1,443 +0,0 @@
-<?php
-/**
-*
-* @package dbal
-* @version $Id$
-* @copyright (c) 2005 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License
-*
-*/
-
-/**
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* @ignore
-*/
-if (!defined('SQL_LAYER'))
-{
-
- define('SQL_LAYER', 'mysql4');
- include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
-
-/**
-* MySQL4 Database Abstraction Layer
-* Compatible with:
-* MySQL 4.0+
-* MySQL 4.1+
-* MySQL 5.0+
-* @package dbal
-*/
-class dbal_mysql4 extends dbal
-{
- /**
- * Connect to server
- */
- function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false)
- {
- $this->persistency = $persistency;
- $this->user = $sqluser;
- $this->server = $sqlserver . (($port) ? ':' . $port : '');
- $this->dbname = $database;
-
- $this->db_connect_id = ($this->persistency) ? @mysql_pconnect($this->server, $this->user, $sqlpassword) : @mysql_connect($this->server, $this->user, $sqlpassword);
-
- if ($this->db_connect_id && $this->dbname != '')
- {
- if (@mysql_select_db($this->dbname))
- {
- return $this->db_connect_id;
- }
- }
-
- return $this->sql_error('');
- }
-
- /**
- * Version information about used database
- */
- function sql_server_info()
- {
- return 'MySQL ' . @mysql_get_server_info($this->db_connect_id);
- }
-
- /**
- * SQL Transaction
- * @access: private
- */
- function _sql_transaction($status = 'begin')
- {
- switch ($status)
- {
- case 'begin':
- return @mysql_query('BEGIN', $this->db_connect_id);
- break;
-
- case 'commit':
- return @mysql_query('COMMIT', $this->db_connect_id);
- break;
-
- case 'rollback':
- return @mysql_query('ROLLBACK', $this->db_connect_id);
- break;
- }
-
- return true;
- }
-
- /**
- * Base query method
- *
- * @param string $query Contains the SQL query which shall be executed
- * @param int $cache_ttl Either 0 to avoid caching or the time in seconds which the result shall be kept in cache
- * @return mixed When casted to bool the returned value returns true on success and false on failure
- *
- * @access public
- */
- function sql_query($query = '', $cache_ttl = 0)
- {
- if ($query != '')
- {
- global $cache;
-
- // EXPLAIN only in extra debug mode
- if (defined('DEBUG_EXTRA'))
- {
- $this->sql_report('start', $query);
- }
-
- $this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false;
- $this->sql_add_num_queries($this->query_result);
-
- if (!$this->query_result)
- {
- if (($this->query_result = @mysql_query($query, $this->db_connect_id)) === false)
- {
- $this->sql_error($query);
- }
-
- if (defined('DEBUG_EXTRA'))
- {
- $this->sql_report('stop', $query);
- }
-
- if ($cache_ttl && method_exists($cache, 'sql_save'))
- {
- $this->open_queries[(int) $this->query_result] = $this->query_result;
- $cache->sql_save($query, $this->query_result, $cache_ttl);
- }
- else if (strpos($query, 'SELECT') === 0 && $this->query_result)
- {
- $this->open_queries[(int) $this->query_result] = $this->query_result;
- }
- }
- else if (defined('DEBUG_EXTRA'))
- {
- $this->sql_report('fromcache', $query);
- }
- }
- else
- {
- return false;
- }
-
- return ($this->query_result) ? $this->query_result : false;
- }
-
- /**
- * Build LIMIT query
- */
- function sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0)
- {
- if ($query != '')
- {
- $this->query_result = false;
-
- // if $total is set to 0 we do not want to limit the number of rows
- if ($total == 0)
- {
- // Because MySQL 4.1+ no longer supports -1 in LIMIT queries we set it to the maximum value
- $total = '18446744073709551615';
- }
-
- $query .= "\n LIMIT " . ((!empty($offset)) ? $offset . ', ' . $total : $total);
-
- return $this->sql_query($query, $cache_ttl);
- }
- else
- {
- return false;
- }
- }
-
- /**
- * Return number of rows
- * Not used within core code
- */
- function sql_numrows($query_id = false)
- {
- global $cache;
-
- if (!$query_id)
- {
- $query_id = $this->query_result;
- }
-
- if (isset($cache->sql_rowset[$query_id]))
- {
- return $cache->sql_numrows($query_id);
- }
-
- return ($query_id) ? @mysql_num_rows($query_id) : false;
- }
-
- /**
- * Return number of affected rows
- */
- function sql_affectedrows()
- {
- return ($this->db_connect_id) ? @mysql_affected_rows($this->db_connect_id) : false;
- }
-
- /**
- * Fetch current row
- */
- function sql_fetchrow($query_id = false)
- {
- global $cache;
-
- if (!$query_id)
- {
- $query_id = $this->query_result;
- }
-
- if (isset($cache->sql_rowset[$query_id]))
- {
- return $cache->sql_fetchrow($query_id);
- }
-
- return ($query_id) ? @mysql_fetch_assoc($query_id) : false;
- }
-
- /**
- * Fetch field
- * if rownum is false, the current row is used, else it is pointing to the row (zero-based)
- */
- function sql_fetchfield($field, $rownum = false, $query_id = false)
- {
- global $cache;
-
- if (!$query_id)
- {
- $query_id = $this->query_result;
- }
-
- if ($query_id)
- {
- if ($rownum === false)
- {
- if (isset($cache->sql_rowset[$query_id]))
- {
- return $cache->sql_fetchfield($query_id, $field);
- }
-
- $row = $this->sql_fetchrow($query_id);
- return isset($row[$field]) ? $row[$field] : false;
- }
- else
- {
- if (isset($cache->sql_rowset[$query_id]))
- {
- $cache->sql_rowseek($query_id, $rownum);
- return $cache->sql_fetchfield($query_id, $field);
- }
-
- return @mysql_result($query_id, $rownum, $field);
- }
- }
-
- return false;
- }
-
- /**
- * Seek to given row number
- * rownum is zero-based
- */
- function sql_rowseek($rownum, $query_id = false)
- {
- global $cache;
-
- if (!$query_id)
- {
- $query_id = $this->query_result;
- }
-
- if (isset($cache->sql_rowset[$query_id]))
- {
- return $cache->sql_rowseek($query_id, $rownum);
- }
-
- return ($query_id) ? @mysql_data_seek($query_id, $rownum) : false;
- }
-
- /**
- * Get last inserted id after insert statement
- */
- function sql_nextid()
- {
- return ($this->db_connect_id) ? @mysql_insert_id($this->db_connect_id) : false;
- }
-
- /**
- * Free sql result
- */
- function sql_freeresult($query_id = false)
- {
- global $cache;
-
- if (!$query_id)
- {
- $query_id = $this->query_result;
- }
-
- if (isset($cache->sql_rowset[$query_id]))
- {
- return $cache->sql_freeresult($query_id);
- }
-
- if (isset($this->open_queries[(int) $query_id]))
- {
- unset($this->open_queries[(int) $query_id]);
- return @mysql_free_result($query_id);
- }
-
- return false;
- }
-
- /**
- * Escape string used in sql query
- */
- function sql_escape($msg)
- {
- if (!$this->db_connect_id)
- {
- return @mysql_real_escape_string($msg);
- }
-
- return @mysql_real_escape_string($msg, $this->db_connect_id);
- }
-
- /**
- * Build db-specific query data
- * @access: private
- */
- function _sql_custom_build($stage, $data)
- {
- switch ($stage)
- {
- case 'FROM':
- $data = '(' . $data . ')';
- break;
- }
-
- return $data;
- }
-
- /**
- * return sql error array
- * @access: private
- */
- function _sql_error()
- {
- if (!$this->db_connect_id)
- {
- return array(
- 'message' => @mysql_error(),
- 'code' => @mysql_errno()
- );
- }
-
- return array(
- 'message' => @mysql_error($this->db_connect_id),
- 'code' => @mysql_errno($this->db_connect_id)
- );
- }
-
- /**
- * Close sql connection
- * @access: private
- */
- function _sql_close()
- {
- return @mysql_close($this->db_connect_id);
- }
-
- /**
- * Build db-specific report
- * @access: private
- */
- function _sql_report($mode, $query = '')
- {
- switch ($mode)
- {
- case 'start':
-
- $explain_query = $query;
- if (preg_match('/UPDATE ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m))
- {
- $explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2];
- }
- else if (preg_match('/DELETE FROM ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m))
- {
- $explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2];
- }
-
- if (preg_match('/^SELECT/', $explain_query))
- {
- $html_table = false;
-
- if ($result = @mysql_query("EXPLAIN $explain_query", $this->db_connect_id))
- {
- while ($row = @mysql_fetch_assoc($result))
- {
- $html_table = $this->sql_report('add_select_row', $query, $html_table, $row);
- }
- }
- @mysql_free_result($result);
-
- if ($html_table)
- {
- $this->html_hold .= '</table>';
- }
- }
-
- break;
-
- case 'fromcache':
- $endtime = explode(' ', microtime());
- $endtime = $endtime[0] + $endtime[1];
-
- $result = @mysql_query($query, $this->db_connect_id);
- while ($void = @mysql_fetch_assoc($result))
- {
- // Take the time spent on parsing rows into account
- }
- @mysql_free_result($result);
-
- $splittime = explode(' ', microtime());
- $splittime = $splittime[0] + $splittime[1];
-
- $this->sql_report('record_fromcache', $query, $endtime, $splittime);
-
- break;
- }
- }
-}
-
-} // if ... define
-
-?> \ No newline at end of file
diff --git a/phpBB/includes/db/mysqli.php b/phpBB/includes/db/mysqli.php
index fa4d3ffdc7..86700744fb 100644
--- a/phpBB/includes/db/mysqli.php
+++ b/phpBB/includes/db/mysqli.php
@@ -9,20 +9,14 @@
*/
/**
+* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
-/**
-* @ignore
-*/
-if (!defined('SQL_LAYER'))
-{
-
- define('SQL_LAYER', 'mysqli');
- include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
+include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
/**
* MySQLi Database Abstraction Layer
@@ -48,10 +42,8 @@ class dbal_mysqli extends dbal
if ($this->db_connect_id && $this->dbname != '')
{
- if (@mysqli_select_db($this->db_connect_id, $this->dbname))
- {
- return $this->db_connect_id;
- }
+ @mysqli_query($this->db_connect_id, "SET NAMES 'utf8'");
+ return $this->db_connect_id;
}
return $this->sql_error('');
@@ -67,7 +59,7 @@ class dbal_mysqli extends dbal
/**
* SQL Transaction
- * @access: private
+ * @access private
*/
function _sql_transaction($status = 'begin')
{
@@ -117,7 +109,7 @@ class dbal_mysqli extends dbal
$this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result);
- if (!$this->query_result)
+ if ($this->query_result === false)
{
if (($this->query_result = @mysqli_query($this->db_connect_id, $query)) === false)
{
@@ -174,27 +166,6 @@ class dbal_mysqli extends dbal
}
/**
- * Return number of rows
- * Not used within core code
- */
- function sql_numrows($query_id = false)
- {
- global $cache;
-
- if (!$query_id)
- {
- $query_id = $this->query_result;
- }
-
- if (!is_object($query_id) && isset($cache->sql_rowset[$query_id]))
- {
- return $cache->sql_numrows($query_id);
- }
-
- return ($query_id) ? @mysqli_num_rows($query_id) : false;
- }
-
- /**
* Return number of affected rows
*/
function sql_affectedrows()
@@ -209,7 +180,7 @@ class dbal_mysqli extends dbal
{
global $cache;
- if (!$query_id)
+ if ($query_id === false)
{
$query_id = $this->query_result;
}
@@ -219,39 +190,7 @@ class dbal_mysqli extends dbal
return $cache->sql_fetchrow($query_id);
}
- return ($query_id) ? @mysqli_fetch_assoc($query_id) : false;
- }
-
- /**
- * Fetch field
- * if rownum is false, the current row is used, else it is pointing to the row (zero-based)
- */
- function sql_fetchfield($field, $rownum = false, $query_id = false)
- {
- global $cache;
-
- if (!$query_id)
- {
- $query_id = $this->query_result;
- }
-
- if ($query_id)
- {
- if ($rownum !== false)
- {
- $this->sql_rowseek($rownum, $query_id);
- }
-
- if (!is_object($query_id) && isset($cache->sql_rowset[$query_id]))
- {
- return $cache->sql_fetchfield($query_id, $field);
- }
-
- $row = $this->sql_fetchrow($query_id);
- return isset($row[$field]) ? $row[$field] : false;
- }
-
- return false;
+ return ($query_id !== false) ? @mysqli_fetch_assoc($query_id) : false;
}
/**
@@ -262,17 +201,17 @@ class dbal_mysqli extends dbal
{
global $cache;
- if (!$query_id)
+ if ($query_id === false)
{
$query_id = $this->query_result;
}
if (!is_object($query_id) && isset($cache->sql_rowset[$query_id]))
{
- return $cache->sql_rowseek($query_id, $rownum);
+ return $cache->sql_rowseek($rownum, $query_id);
}
- return ($query_id) ? @mysqli_data_seek($query_id, $rownum) : false;
+ return ($query_id !== false) ? @mysqli_data_seek($query_id, $rownum) : false;
}
/**
@@ -290,7 +229,7 @@ class dbal_mysqli extends dbal
{
global $cache;
- if (!$query_id)
+ if ($query_id === false)
{
$query_id = $this->query_result;
}
@@ -313,7 +252,7 @@ class dbal_mysqli extends dbal
/**
* Build db-specific query data
- * @access: private
+ * @access private
*/
function _sql_custom_build($stage, $data)
{
@@ -329,7 +268,7 @@ class dbal_mysqli extends dbal
/**
* return sql error array
- * @access: private
+ * @access private
*/
function _sql_error()
{
@@ -349,7 +288,7 @@ class dbal_mysqli extends dbal
/**
* Close sql connection
- * @access: private
+ * @access private
*/
function _sql_close()
{
@@ -358,7 +297,7 @@ class dbal_mysqli extends dbal
/**
* Build db-specific report
- * @access: private
+ * @access private
*/
function _sql_report($mode, $query = '')
{
@@ -418,6 +357,4 @@ class dbal_mysqli extends dbal
}
}
-} // if ... define
-
?> \ No newline at end of file
diff --git a/phpBB/includes/db/oracle.php b/phpBB/includes/db/oracle.php
index fc5bf6f78e..e8a0ce3605 100644
--- a/phpBB/includes/db/oracle.php
+++ b/phpBB/includes/db/oracle.php
@@ -9,20 +9,14 @@
*/
/**
+* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
-/**
-* @ignore
-*/
-if(!defined('SQL_LAYER'))
-{
-
- define('SQL_LAYER', 'oracle');
- include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
+include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
/**
* Oracle Database Abstraction Layer
@@ -42,7 +36,7 @@ class dbal_oracle extends dbal
$this->server = $sqlserver . (($port) ? ':' . $port : '');
$this->dbname = $database;
- $this->db_connect_id = ($this->persistency) ? @ociplogon($this->user, $sqlpassword, $this->server) : @ocinlogon($this->user, $sqlpassword, $this->server);
+ $this->db_connect_id = ($this->persistency) ? @ociplogon($this->user, $sqlpassword, $this->server, 'UTF8') : @ocinlogon($this->user, $sqlpassword, $this->server, 'UTF8');
return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error('');
}
@@ -57,7 +51,7 @@ class dbal_oracle extends dbal
/**
* SQL Transaction
- * @access: private
+ * @access private
*/
function _sql_transaction($status = 'begin')
{
@@ -104,7 +98,7 @@ class dbal_oracle extends dbal
$this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result);
- if (!$this->query_result)
+ if ($this->query_result === false)
{
$in_transaction = false;
if (!$this->transaction)
@@ -116,7 +110,63 @@ class dbal_oracle extends dbal
$in_transaction = true;
}
+ $array = array();
+
+ // We overcome Oracle's 4000 char limit by binding vars
+ if (preg_match('/^(INSERT INTO[^(]+)\\(([^()]+)\\) VALUES[^(]+\\(([^()]+)\\)$/', $query, $regs))
+ {
+ if (strlen($regs[3]) > 4000)
+ {
+ $cols = explode(', ', $regs[2]);
+ $vals = explode(', ', $regs[3]);
+ foreach ($vals as $key => $value)
+ {
+ if (strlen($value) > 4002) // check to see if this thing is greater than the max + 'x2
+ {
+ $vals[$key] = ':' . strtoupper($cols[$key]);
+ $array[$vals[$key]] = substr($value, 1, -1);
+ }
+ }
+ $query = $regs[1] . '(' . implode(', ', $cols) . ') VALUES (' . implode(', ', $vals) . ')';
+ }
+ }
+ else if (preg_match('/^(UPDATE.*?)SET (.*)(\\sWHERE.*)$/s', $query, $regs))
+ {
+ if (strlen($regs[2]) > 4000)
+ {
+ $args = explode(', ', $regs[2]);
+ $cols = array();
+ foreach ($args as $value)
+ {
+ $temp_array = explode('=', $value);
+ $cols[$temp_array[0]] = $temp_array[1];
+ }
+
+ foreach ($cols as $col => $val)
+ {
+ if (strlen($val) > 4003) // check to see if this thing is greater than the max + 'x2 + a space
+ {
+ $cols[$col] = ' :' . strtoupper(rtrim($col));
+ $array[ltrim($cols[$col])] = substr(trim($val), 2, -1);
+ }
+ }
+
+ $art = array();
+ foreach ($cols as $col => $val)
+ {
+ $art[] = $col . '=' . $val;
+ }
+ $query = $regs[1] . 'SET ' . implode(', ', $art) . $regs[3];
+ }
+ }
+
$this->query_result = @ociparse($this->db_connect_id, $query);
+
+ foreach ($array as $key => $value)
+ {
+ @ocibindbyname($this->query_result, $key, $array[$key], -1);
+ }
+
$success = @ociexecute($this->query_result, OCI_DEFAULT);
if (!$success)
@@ -226,33 +276,6 @@ class dbal_oracle extends dbal
}
/**
- * Return number of rows
- * Not used within core code
- */
- function sql_numrows($query_id = false)
- {
- global $cache;
-
- if (!$query_id)
- {
- $query_id = $this->query_result;
- }
-
- if (isset($cache->sql_rowset[$query_id]))
- {
- return $cache->sql_numrows($query_id);
- }
-
- $result = @ocifetchstatement($query_id, $this->rowset);
-
- // OCIFetchStatment kills our query result so we have to execute the statment again
- // if we ever want to use the query_id again.
- @ociexecute($query_id, OCI_DEFAULT);
-
- return $result;
- }
-
- /**
* Return number of affected rows
*/
function sql_affectedrows()
@@ -267,7 +290,7 @@ class dbal_oracle extends dbal
{
global $cache;
- if (!$query_id)
+ if ($query_id === false)
{
$query_id = $this->query_result;
}
@@ -277,56 +300,29 @@ class dbal_oracle extends dbal
return $cache->sql_fetchrow($query_id);
}
- $row = array();
- $result = @ocifetchinto($query_id, $row, OCI_ASSOC + OCI_RETURN_NULLS);
-
- if (!$result || !$row)
- {
- return false;
- }
-
- $result_row = array();
- foreach ($row as $key => $value)
- {
- // OCI->CLOB?
- if (is_object($value))
- {
- $value = $value->load();
- }
-
- $result_row[strtolower($key)] = $value;
- }
-
- return ($query_id) ? $result_row : false;
- }
-
- /**
- * Fetch field
- * if rownum is false, the current row is used, else it is pointing to the row (zero-based)
- */
- function sql_fetchfield($field, $rownum = false, $query_id = false)
- {
- global $cache;
-
- if (!$query_id)
+ if ($query_id !== false)
{
- $query_id = $this->query_result;
- }
+ $row = array();
+ $result = @ocifetchinto($query_id, $row, OCI_ASSOC + OCI_RETURN_NULLS);
- if ($query_id)
- {
- if ($rownum !== false)
+ if (!$result || !$row)
{
- $this->sql_rowseek($rownum, $query_id);
+ return false;
}
- if (isset($cache->sql_rowset[$query_id]))
+ $result_row = array();
+ foreach ($row as $key => $value)
{
- return $cache->sql_fetchfield($query_id, $field);
+ // OCI->CLOB?
+ if (is_object($value))
+ {
+ $value = $value->load();
+ }
+
+ $result_row[strtolower($key)] = $value;
}
- $row = $this->sql_fetchrow($query_id);
- return isset($row[$field]) ? $row[$field] : false;
+ return $result_row;
}
return false;
@@ -340,17 +336,17 @@ class dbal_oracle extends dbal
{
global $cache;
- if (!$query_id)
+ if ($query_id === false)
{
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
{
- return $cache->sql_rowseek($query_id, $rownum);
+ return $cache->sql_rowseek($rownum, $query_id);
}
- if (!$query_id)
+ if ($query_id === false)
{
return false;
}
@@ -377,13 +373,13 @@ class dbal_oracle extends dbal
{
$query_id = $this->query_result;
- if ($query_id && $this->last_query_text != '')
+ if ($query_id !== false && $this->last_query_text != '')
{
if (preg_match('#^INSERT[\t\n ]+INTO[\t\n ]+([a-z0-9\_\-]+)#is', $this->last_query_text, $tablename))
{
$query = 'SELECT ' . $tablename[1] . '_seq.currval FROM DUAL';
$stmt = @ociparse($this->db_connect_id, $query);
- @ociexecute($stmt, OCI_DEFAULT );
+ @ociexecute($stmt, OCI_DEFAULT);
$temp_result = @ocifetchinto($stmt, $temp_array, OCI_ASSOC + OCI_RETURN_NULLS);
@ocifreestatement($stmt);
@@ -409,7 +405,7 @@ class dbal_oracle extends dbal
{
global $cache;
- if (!$query_id)
+ if ($query_id === false)
{
$query_id = $this->query_result;
}
@@ -443,7 +439,7 @@ class dbal_oracle extends dbal
/**
* return sql error array
- * @access: private
+ * @access private
*/
function _sql_error()
{
@@ -465,7 +461,7 @@ class dbal_oracle extends dbal
/**
* Close sql connection
- * @access: private
+ * @access private
*/
function _sql_close()
{
@@ -474,7 +470,7 @@ class dbal_oracle extends dbal
/**
* Build db-specific report
- * @access: private
+ * @access private
*/
function _sql_report($mode, $query = '')
{
@@ -505,10 +501,6 @@ class dbal_oracle extends dbal
break;
}
}
-
-
}
-} // if ... define
-
?> \ No newline at end of file
diff --git a/phpBB/includes/db/postgres.php b/phpBB/includes/db/postgres.php
index 1836952346..c06786a795 100644
--- a/phpBB/includes/db/postgres.php
+++ b/phpBB/includes/db/postgres.php
@@ -9,20 +9,14 @@
*/
/**
+* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
-/**
-* @ignore
-*/
-if (!defined('SQL_LAYER'))
-{
-
- define('SQL_LAYER', 'postgres');
- include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
+include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
/**
* PostgreSQL Database Abstraction Layer
@@ -38,48 +32,45 @@ class dbal_postgres extends dbal
*/
function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false)
{
- $this->connect_string = '';
+ $connect_string = '';
if ($sqluser)
{
- $this->connect_string .= "user=$sqluser ";
+ $connect_string .= "user=$sqluser ";
}
if ($sqlpassword)
{
- $this->connect_string .= "password=$sqlpassword ";
+ $connect_string .= "password=$sqlpassword ";
}
if ($sqlserver)
{
if (strpos($sqlserver, ':') !== false)
{
- list($sqlserver, $sqlport) = explode(':', $sqlserver);
- $this->connect_string .= "host=$sqlserver port=$sqlport ";
+ list($sqlserver, $port) = explode(':', $sqlserver);
}
- else
+
+ if ($sqlserver !== 'localhost')
{
- if ($sqlserver != "localhost")
- {
- $this->connect_string .= "host=$sqlserver ";
- }
-
- if ($port)
- {
- $this->connect_string .= "port=$port ";
- }
+ $connect_string .= "host=$sqlserver ";
+ }
+
+ if ($port)
+ {
+ $connect_string .= "port=$port ";
}
}
if ($database)
{
$this->dbname = $database;
- $this->connect_string .= "dbname=$database";
+ $connect_string .= "dbname=$database";
}
$this->persistency = $persistency;
- $this->db_connect_id = ($this->persistency) ? @pg_pconnect($this->connect_string) : @pg_connect($this->connect_string);
+ $this->db_connect_id = ($this->persistency) ? @pg_pconnect($connect_string) : @pg_connect($connect_string);
return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error('');
}
@@ -98,6 +89,8 @@ class dbal_postgres extends dbal
{
$query_id = @pg_query($this->db_connect_id, 'select version()');
$row = @pg_fetch_assoc($query_id, null);
+ @pg_free_result($query_id);
+
$version = $row['version'];
return ((!empty($version)) ? ' ' . $version : '');
}
@@ -105,7 +98,7 @@ class dbal_postgres extends dbal
/**
* SQL Transaction
- * @access: private
+ * @access private
*/
function _sql_transaction($status = 'begin')
{
@@ -152,7 +145,7 @@ class dbal_postgres extends dbal
$this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result);
- if (!$this->query_result)
+ if ($this->query_result === false)
{
if (($this->query_result = @pg_query($this->db_connect_id, $query)) === false)
{
@@ -189,7 +182,7 @@ class dbal_postgres extends dbal
/**
* Build db-specific query data
- * @access: private
+ * @access private
*/
function _sql_custom_build($stage, $data)
{
@@ -222,27 +215,6 @@ class dbal_postgres extends dbal
}
/**
- * Return number of rows
- * Not used within core code
- */
- function sql_numrows($query_id = false)
- {
- global $cache;
-
- if (!$query_id)
- {
- $query_id = $this->query_result;
- }
-
- if (isset($cache->sql_rowset[$query_id]))
- {
- return $cache->sql_numrows($query_id);
- }
-
- return ($query_id) ? @pg_num_rows($query_id) : false;
- }
-
- /**
* Return number of affected rows
*/
function sql_affectedrows()
@@ -257,7 +229,7 @@ class dbal_postgres extends dbal
{
global $cache;
- if (!$query_id)
+ if ($query_id === false)
{
$query_id = $this->query_result;
}
@@ -267,48 +239,7 @@ class dbal_postgres extends dbal
return $cache->sql_fetchrow($query_id);
}
- $row = @pg_fetch_assoc($query_id, null);
- if ($row)
- {
- foreach ($row as $key => $value)
- {
- $row[$key] = (strpos($key, 'bitfield') === false) ? $value : pg_unescape_bytea($value);
- }
- }
-
- return ($query_id) ? $row : false;
- }
-
- /**
- * Fetch field
- * if rownum is false, the current row is used, else it is pointing to the row (zero-based)
- */
- function sql_fetchfield($field, $rownum = false, $query_id = false)
- {
- global $cache;
-
- if (!$query_id)
- {
- $query_id = $this->query_result;
- }
-
- if ($query_id)
- {
- if ($rownum !== false)
- {
- $this->sql_rowseek($rownum, $query_id);
- }
-
- if (isset($cache->sql_rowset[$query_id]))
- {
- return $cache->sql_fetchfield($query_id, $field);
- }
-
- $row = $this->sql_fetchrow($query_id);
- return isset($row[$field]) ? $row[$field] : false;
- }
-
- return false;
+ return ($query_id !== false) ? @pg_fetch_assoc($query_id, null) : false;
}
/**
@@ -319,17 +250,17 @@ class dbal_postgres extends dbal
{
global $cache;
- if (!$query_id)
+ if ($query_id === false)
{
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
{
- return $cache->sql_rowseek($query_id, $rownum);
+ return $cache->sql_rowseek($rownum, $query_id);
}
- return ($query_id) ? @pg_result_seek($query_id, $rownum) : false;
+ return ($query_id !== false) ? @pg_result_seek($query_id, $rownum) : false;
}
/**
@@ -339,7 +270,7 @@ class dbal_postgres extends dbal
{
$query_id = $this->query_result;
- if ($query_id && $this->last_query_text != '')
+ if ($query_id !== false && $this->last_query_text != '')
{
if (preg_match("/^INSERT[\t\n ]+INTO[\t\n ]+([a-z0-9\_\-]+)/is", $this->last_query_text, $tablename))
{
@@ -368,7 +299,7 @@ class dbal_postgres extends dbal
{
global $cache;
- if (!$query_id)
+ if ($query_id === false)
{
$query_id = $this->query_result;
}
@@ -398,7 +329,7 @@ class dbal_postgres extends dbal
/**
* return sql error array
- * @access: private
+ * @access private
*/
function _sql_error()
{
@@ -410,7 +341,7 @@ class dbal_postgres extends dbal
/**
* Close sql connection
- * @access: private
+ * @access private
*/
function _sql_close()
{
@@ -419,7 +350,7 @@ class dbal_postgres extends dbal
/**
* Build db-specific report
- * @access: private
+ * @access private
*/
function _sql_report($mode, $query = '')
{
@@ -477,9 +408,6 @@ class dbal_postgres extends dbal
break;
}
}
-
}
-} // if ... defined
-
?> \ No newline at end of file
diff --git a/phpBB/includes/db/sqlite.php b/phpBB/includes/db/sqlite.php
index cd6d40e3c7..708376881c 100644
--- a/phpBB/includes/db/sqlite.php
+++ b/phpBB/includes/db/sqlite.php
@@ -9,20 +9,14 @@
*/
/**
+* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
-/**
-* @ignore
-*/
-if (!defined('SQL_LAYER'))
-{
-
- define('SQL_LAYER', 'sqlite');
- include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
+include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
/**
* Sqlite Database Abstraction Layer
@@ -63,7 +57,7 @@ class dbal_sqlite extends dbal
/**
* SQL Transaction
- * @access: private
+ * @access private
*/
function _sql_transaction($status = 'begin')
{
@@ -109,7 +103,7 @@ class dbal_sqlite extends dbal
$this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result);
- if (!$this->query_result)
+ if ($this->query_result === false)
{
if (($this->query_result = @sqlite_query($query, $this->db_connect_id)) === false)
{
@@ -170,27 +164,6 @@ class dbal_sqlite extends dbal
}
/**
- * Return number of rows
- * Not used within core code
- */
- function sql_numrows($query_id = false)
- {
- global $cache;
-
- if (!$query_id)
- {
- $query_id = $this->query_result;
- }
-
- if (isset($cache->sql_rowset[$query_id]))
- {
- return $cache->sql_numrows($query_id);
- }
-
- return ($query_id) ? @sqlite_num_rows($query_id) : false;
- }
-
- /**
* Return number of affected rows
*/
function sql_affectedrows()
@@ -205,7 +178,7 @@ class dbal_sqlite extends dbal
{
global $cache;
- if (!$query_id)
+ if ($query_id === false)
{
$query_id = $this->query_result;
}
@@ -215,40 +188,7 @@ class dbal_sqlite extends dbal
return $cache->sql_fetchrow($query_id);
}
- $row = @sqlite_fetch_array($query_id, SQLITE_ASSOC);
-
- return $row;
- }
-
- /**
- * Fetch field
- * if rownum is false, the current row is used, else it is pointing to the row (zero-based)
- */
- function sql_fetchfield($field, $rownum = false, $query_id = false)
- {
- global $cache;
-
- if (!$query_id)
- {
- $query_id = $this->query_result;
- }
-
- if ($query_id)
- {
- if ($rownum !== false)
- {
- $this->sql_rowseek($rownum, $query_id);
- }
-
- if (isset($cache->sql_rowset[$query_id]))
- {
- return $cache->sql_fetchfield($query_id, $field);
- }
-
- return @sqlite_column($query_id, $field);
- }
-
- return false;
+ return ($query_id !== false) ? @sqlite_fetch_array($query_id, SQLITE_ASSOC) : false;
}
/**
@@ -259,17 +199,17 @@ class dbal_sqlite extends dbal
{
global $cache;
- if (!$query_id)
+ if ($query_id === false)
{
$query_id = $this->query_result;
}
if (isset($cache->sql_rowset[$query_id]))
{
- return $cache->sql_rowseek($query_id, $rownum);
+ return $cache->sql_rowseek($rownum, $query_id);
}
- return ($query_id) ? @sqlite_seek($query_id, $rownum) : false;
+ return ($query_id !== false) ? @sqlite_seek($query_id, $rownum) : false;
}
/**
@@ -287,7 +227,7 @@ class dbal_sqlite extends dbal
{
global $cache;
- if (!$query_id)
+ if ($query_id === false)
{
$query_id = $this->query_result;
}
@@ -310,7 +250,7 @@ class dbal_sqlite extends dbal
/**
* return sql error array
- * @access: private
+ * @access private
*/
function _sql_error()
{
@@ -322,7 +262,7 @@ class dbal_sqlite extends dbal
/**
* Build db-specific query data
- * @access: private
+ * @access private
*/
function _sql_custom_build($stage, $data)
{
@@ -331,7 +271,7 @@ class dbal_sqlite extends dbal
/**
* Close sql connection
- * @access: private
+ * @access private
*/
function _sql_close()
{
@@ -340,7 +280,7 @@ class dbal_sqlite extends dbal
/**
* Build db-specific report
- * @access: private
+ * @access private
*/
function _sql_report($mode, $query = '')
{
@@ -367,9 +307,6 @@ class dbal_sqlite extends dbal
break;
}
}
-
}
-} // if ... define
-
?> \ No newline at end of file
diff --git a/phpBB/includes/diff/diff.php b/phpBB/includes/diff/diff.php
new file mode 100644
index 0000000000..fd2d557a19
--- /dev/null
+++ b/phpBB/includes/diff/diff.php
@@ -0,0 +1,781 @@
+<?php
+/**
+*
+* @package phpBB3
+* @version $Id$
+* @copyright (c) 2006 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+/**
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+// Include renderer and engine
+include_once($phpbb_root_path . 'includes/diff/engine.' . $phpEx);
+include_once($phpbb_root_path . 'includes/diff/renderer.' . $phpEx);
+
+/**
+* Code from pear.php.net, Text_Diff-0.2.1 (beta) package
+* http://pear.php.net/package/Text_Diff/
+*
+* Modified by Acyd Burn to meet our coding standards
+* and being able to integrate into phpBB
+*/
+
+/**
+* General API for generating and formatting diffs - the differences between
+* two sequences of strings.
+*
+* The PHP diff code used in this package was originally written by Geoffrey
+* T. Dairiki and is used with his permission.
+*
+* @package phpBB3
+* @author Geoffrey T. Dairiki <dairiki@dairiki.org>
+*/
+class diff
+{
+ /**
+ * Array of changes.
+ * @var array
+ */
+ var $_edits;
+
+ /**
+ * Computes diffs between sequences of strings.
+ *
+ * @param array $from_lines An array of strings. Typically these are lines from a file.
+ * @param array $to_lines An array of strings.
+ */
+ function diff($from_lines, $to_lines)
+ {
+ $diff_engine = &new diff_engine();
+ $this->_edits = call_user_func_array(array($diff_engine, 'diff'), array($from_lines, $to_lines));
+ }
+
+ /**
+ * Returns the array of differences.
+ */
+ function get_diff()
+ {
+ return $this->_edits;
+ }
+
+ /**
+ * Computes a reversed diff.
+ *
+ * Example:
+ * <code>
+ * $diff = &new diff($lines1, $lines2);
+ * $rev = $diff->reverse();
+ * </code>
+ *
+ * @return diff A Diff object representing the inverse of the original diff.
+ * Note that we purposely don't return a reference here, since
+ * this essentially is a clone() method.
+ */
+ function reverse()
+ {
+ if (version_compare(zend_version(), '2', '>'))
+ {
+ $rev = clone($this);
+ }
+ else
+ {
+ $rev = $this;
+ }
+
+ $rev->_edits = array();
+
+ foreach ($this->_edits as $edit)
+ {
+ $rev->_edits[] = $edit->reverse();
+ }
+
+ return $rev;
+ }
+
+ /**
+ * Checks for an empty diff.
+ *
+ * @return boolean True if two sequences were identical.
+ */
+ function is_empty()
+ {
+ foreach ($this->_edits as $edit)
+ {
+ if (!is_a($edit, 'diff_op_copy'))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Computes the length of the Longest Common Subsequence (LCS).
+ *
+ * This is mostly for diagnostic purposes.
+ *
+ * @return integer The length of the LCS.
+ */
+ function lcs()
+ {
+ $lcs = 0;
+
+ foreach ($this->_edits as $edit)
+ {
+ if (is_a($edit, 'diff_op_copy'))
+ {
+ $lcs += sizeof($edit->orig);
+ }
+ }
+ return $lcs;
+ }
+
+ /**
+ * Gets the original set of lines.
+ *
+ * This reconstructs the $from_lines parameter passed to the constructor.
+ *
+ * @return array The original sequence of strings.
+ */
+ function get_original()
+ {
+ $lines = array();
+
+ foreach ($this->_edits as $edit)
+ {
+ if ($edit->orig)
+ {
+ array_splice($lines, sizeof($lines), 0, $edit->orig);
+ }
+ }
+ return $lines;
+ }
+
+ /**
+ * Gets the final set of lines.
+ *
+ * This reconstructs the $to_lines parameter passed to the constructor.
+ *
+ * @return array The sequence of strings.
+ */
+ function get_final()
+ {
+ $lines = array();
+
+ foreach ($this->_edits as $edit)
+ {
+ if ($edit->final)
+ {
+ array_splice($lines, sizeof($lines), 0, $edit->final);
+ }
+ }
+ return $lines;
+ }
+
+ /**
+ * Removes trailing newlines from a line of text. This is meant to be used with array_walk().
+ *
+ * @param string $line The line to trim.
+ * @param integer $key The index of the line in the array. Not used.
+ */
+ function trim_newlines(&$line, $key)
+ {
+ $line = str_replace(array("\n", "\r"), '', $line);
+ }
+
+ /**
+ * Checks a diff for validity.
+ *
+ * This is here only for debugging purposes.
+ */
+ function _check($from_lines, $to_lines)
+ {
+ if (serialize($from_lines) != serialize($this->get_original()))
+ {
+ trigger_error("[diff] Reconstructed original doesn't match", E_USER_ERROR);
+ }
+
+ if (serialize($to_lines) != serialize($this->get_final()))
+ {
+ trigger_error("[diff] Reconstructed final doesn't match", E_USER_ERROR);
+ }
+
+ $rev = $this->reverse();
+
+ if (serialize($to_lines) != serialize($rev->get_original()))
+ {
+ trigger_error("[diff] Reversed original doesn't match", E_USER_ERROR);
+ }
+
+ if (serialize($from_lines) != serialize($rev->get_final()))
+ {
+ trigger_error("[diff] Reversed final doesn't match", E_USER_ERROR);
+ }
+
+ $prevtype = null;
+
+ foreach ($this->_edits as $edit)
+ {
+ if ($prevtype == get_class($edit))
+ {
+ trigger_error("[diff] Edit sequence is non-optimal", E_USER_ERROR);
+ }
+ $prevtype = get_class($edit);
+ }
+
+ return true;
+ }
+}
+
+/**
+* @package phpBB3
+* @author Geoffrey T. Dairiki <dairiki@dairiki.org>
+*/
+class mapped_diff extends diff
+{
+ /**
+ * Computes a diff between sequences of strings.
+ *
+ * This can be used to compute things like case-insensitve diffs, or diffs
+ * which ignore changes in white-space.
+ *
+ * @param array $from_lines An array of strings.
+ * @param array $to_lines An array of strings.
+ * @param array $mapped_from_lines This array should have the same size number of elements as $from_lines.
+ * The elements in $mapped_from_lines and $mapped_to_lines are what is actually
+ * compared when computing the diff.
+ * @param array $mapped_to_lines This array should have the same number of elements as $to_lines.
+ */
+ function mapped_diff($from_lines, $to_lines, $mapped_from_lines, $mapped_to_lines)
+ {
+ if (sizeof($from_lines) != sizeof($mapped_from_lines) || sizeof($to_lines) != sizeof($mapped_to_lines))
+ {
+ return false;
+ }
+
+ parent::diff($mapped_from_lines, $mapped_to_lines);
+
+ $xi = $yi = 0;
+ for ($i = 0; $i < sizeof($this->_edits); $i++)
+ {
+ $orig = &$this->_edits[$i]->orig;
+ if (is_array($orig))
+ {
+ $orig = array_slice($from_lines, $xi, sizeof($orig));
+ $xi += sizeof($orig);
+ }
+
+ $final = &$this->_edits[$i]->final;
+ if (is_array($final))
+ {
+ $final = array_slice($to_lines, $yi, sizeof($final));
+ $yi += sizeof($final);
+ }
+ }
+ }
+}
+
+/**
+* @package phpBB3
+* @author Geoffrey T. Dairiki <dairiki@dairiki.org>
+*
+* @access private
+*/
+class diff_op
+{
+ var $orig;
+ var $final;
+
+ function reverse()
+ {
+ trigger_error('[diff] Abstract method', E_USER_ERROR);
+ }
+
+ function norig()
+ {
+ return ($this->orig) ? sizeof($this->orig) : 0;
+ }
+
+ function nfinal()
+ {
+ return ($this->final) ? sizeof($this->final) : 0;
+ }
+}
+
+/**
+* @package phpBB3
+* @author Geoffrey T. Dairiki <dairiki@dairiki.org>
+*
+* @access private
+*/
+class diff_op_copy extends diff_op
+{
+ function diff_op_copy($orig, $final = false)
+ {
+ if (!is_array($final))
+ {
+ $final = $orig;
+ }
+ $this->orig = $orig;
+ $this->final = $final;
+ }
+
+ function &reverse()
+ {
+ $reverse = &new diff_op_copy($this->final, $this->orig);
+ return $reverse;
+ }
+}
+
+/**
+* @package phpBB3
+* @author Geoffrey T. Dairiki <dairiki@dairiki.org>
+*
+* @access private
+*/
+class diff_op_delete extends diff_op
+{
+ function diff_op_delete($lines)
+ {
+ $this->orig = $lines;
+ $this->final = false;
+ }
+
+ function &reverse()
+ {
+ $reverse = &new diff_op_add($this->orig);
+ return $reverse;
+ }
+}
+
+/**
+* @package phpBB3
+* @author Geoffrey T. Dairiki <dairiki@dairiki.org>
+*
+* @access private
+*/
+class diff_op_add extends diff_op
+{
+ function diff_op_add($lines)
+ {
+ $this->final = $lines;
+ $this->orig = false;
+ }
+
+ function &reverse()
+ {
+ $reverse = &new diff_op_delete($this->final);
+ return $reverse;
+ }
+}
+
+/**
+* @package phpBB3
+* @author Geoffrey T. Dairiki <dairiki@dairiki.org>
+*
+* @access private
+*/
+class diff_op_change extends diff_op
+{
+ function diff_op_change($orig, $final)
+ {
+ $this->orig = $orig;
+ $this->final = $final;
+ }
+
+ function &reverse()
+ {
+ $reverse = &new diff_op_change($this->final, $this->orig);
+ return $reverse;
+ }
+}
+
+
+/**
+* A class for computing three way diffs.
+*
+* @package phpBB3
+* @author Geoffrey T. Dairiki <dairiki@dairiki.org>
+*/
+class diff3 extends diff
+{
+ /**
+ * Conflict counter.
+ * @var integer
+ */
+ var $_conflicting_blocks = 0;
+
+ /**
+ * Computes diff between 3 sequences of strings.
+ *
+ * @param array $orig The original lines to use.
+ * @param array $final1 The first version to compare to.
+ * @param array $final2 The second version to compare to.
+ */
+ function diff3($orig, $final1, $final2)
+ {
+ $engine = new diff_engine();
+ $this->_edits = $this->_diff3($engine->diff($orig, $final1), $engine->diff($orig, $final2));
+ }
+
+ /**
+ * Return merged output
+ *
+ * @param string $label1 the cvs file version/label from the original set of lines
+ * @param string $label2 the cvs file version/label from the new set of lines
+ * @param string $label_sep the explanation between label1 and label2 - more of a helper for the user
+ * @param bool $get_conflicts if set to true only the number of conflicts is returned
+ * @param bool $merge_new if set to true the merged output will have the new file contents on a conflicting merge
+ *
+ * @return mixed the merged output
+ */
+ function merged_output($label1 = 'CURRENT_FILE', $label2 = 'NEW_FILE', $label_sep = 'DIFF_SEP_EXPLAIN', $get_conflicts = false, $merge_new = false)
+ {
+ global $user;
+
+ if ($get_conflicts)
+ {
+ foreach ($this->_edits as $edit)
+ {
+ if ($edit->is_conflict())
+ {
+ $this->_conflicting_blocks++;
+ }
+ }
+
+ return $this->_conflicting_blocks;
+ }
+
+ $label1 = (!empty($user->lang[$label1])) ? $user->lang[$label1] : $label1;
+ $label2 = (!empty($user->lang[$label2])) ? $user->lang[$label2] : $label2;
+ $label_sep = (!empty($user->lang[$label_sep])) ? $user->lang[$label_sep] : $label_sep;
+
+ $lines = array();
+
+ foreach ($this->_edits as $edit)
+ {
+ if ($edit->is_conflict())
+ {
+ if (!$merge_new)
+ {
+ $lines = array_merge($lines, array('<<<<<<<' . ($label1 ? ' ' . $label1 : '')), $edit->final1, array('=======' . ($label_sep ? ' ' . $label_sep : '')), $edit->final2, array('>>>>>>>' . ($label2 ? ' ' . $label2 : '')));
+ }
+ else
+ {
+ $lines = array_merge($lines, $edit->final1);
+ }
+ $this->_conflicting_blocks++;
+ }
+ else
+ {
+ $lines = array_merge($lines, $edit->merged());
+ }
+ }
+
+ return $lines;
+ }
+
+ /**
+ * Merge the output and use the new file code for conflicts
+ */
+ function merged_new_output()
+ {
+ $lines = array();
+
+ foreach ($this->_edits as $edit)
+ {
+ if ($edit->is_conflict())
+ {
+ $lines = array_merge($lines, $edit->final2);
+ }
+ else
+ {
+ $lines = array_merge($lines, $edit->merged());
+ }
+ }
+
+ return $lines;
+ }
+
+ /**
+ * Merge the output and use the original file code for conflicts
+ */
+ function merged_orig_output()
+ {
+ $lines = array();
+
+ foreach ($this->_edits as $edit)
+ {
+ if ($edit->is_conflict())
+ {
+ $lines = array_merge($lines, $edit->final1);
+ }
+ else
+ {
+ $lines = array_merge($lines, $edit->merged());
+ }
+ }
+
+ return $lines;
+ }
+
+ /**
+ * Get conflicting block(s)
+ */
+ function get_conflicts()
+ {
+ $conflicts = array();
+
+ foreach ($this->_edits as $edit)
+ {
+ if ($edit->is_conflict())
+ {
+ $conflicts[] = array($edit->final1, $edit->final2);
+ }
+ }
+
+ return $conflicts;
+ }
+
+ /**
+ * @access private
+ */
+ function _diff3($edits1, $edits2)
+ {
+ $edits = array();
+ $bb = &new diff3_block_builder();
+
+ $e1 = current($edits1);
+ $e2 = current($edits2);
+
+ while ($e1 || $e2)
+ {
+ if ($e1 && $e2 && is_a($e1, 'diff_op_copy') && is_a($e2, 'diff_op_copy'))
+ {
+ // We have copy blocks from both diffs. This is the (only) time we want to emit a diff3 copy block.
+ // Flush current diff3 diff block, if any.
+ if ($edit = $bb->finish())
+ {
+ $edits[] = $edit;
+ }
+
+ $ncopy = min($e1->norig(), $e2->norig());
+ $edits[] = &new diff3_op_copy(array_slice($e1->orig, 0, $ncopy));
+
+ if ($e1->norig() > $ncopy)
+ {
+ array_splice($e1->orig, 0, $ncopy);
+ array_splice($e1->final, 0, $ncopy);
+ }
+ else
+ {
+ $e1 = next($edits1);
+ }
+
+ if ($e2->norig() > $ncopy)
+ {
+ array_splice($e2->orig, 0, $ncopy);
+ array_splice($e2->final, 0, $ncopy);
+ }
+ else
+ {
+ $e2 = next($edits2);
+ }
+ }
+ else
+ {
+ if ($e1 && $e2)
+ {
+ if ($e1->orig && $e2->orig)
+ {
+ $norig = min($e1->norig(), $e2->norig());
+ $orig = array_splice($e1->orig, 0, $norig);
+ array_splice($e2->orig, 0, $norig);
+ $bb->input($orig);
+ }
+ else
+ {
+ $norig = 0;
+ }
+
+ if (is_a($e1, 'diff_op_copy'))
+ {
+ $bb->out1(array_splice($e1->final, 0, $norig));
+ }
+
+ if (is_a($e2, 'diff_op_copy'))
+ {
+ $bb->out2(array_splice($e2->final, 0, $norig));
+ }
+ }
+
+ if ($e1 && ! $e1->orig)
+ {
+ $bb->out1($e1->final);
+ $e1 = next($edits1);
+ }
+
+ if ($e2 && ! $e2->orig)
+ {
+ $bb->out2($e2->final);
+ $e2 = next($edits2);
+ }
+ }
+ }
+
+ if ($edit = $bb->finish())
+ {
+ $edits[] = $edit;
+ }
+
+ return $edits;
+ }
+}
+
+/**
+* @package phpBB3
+* @author Geoffrey T. Dairiki <dairiki@dairiki.org>
+*
+* @access private
+*/
+class diff3_op
+{
+ function diff3_op($orig = false, $final1 = false, $final2 = false)
+ {
+ $this->orig = $orig ? $orig : array();
+ $this->final1 = $final1 ? $final1 : array();
+ $this->final2 = $final2 ? $final2 : array();
+ }
+
+ function merged()
+ {
+ if (!isset($this->_merged))
+ {
+ if ($this->final1 === $this->final2)
+ {
+ $this->_merged = &$this->final1;
+ }
+ else if ($this->final1 === $this->orig)
+ {
+ $this->_merged = &$this->final2;
+ }
+ else if ($this->final2 === $this->orig)
+ {
+ $this->_merged = &$this->final1;
+ }
+ else
+ {
+ $this->_merged = false;
+ }
+ }
+
+ return $this->_merged;
+ }
+
+ function is_conflict()
+ {
+ return ($this->merged() === false) ? true : false;
+ }
+}
+
+/**
+* @package phpBB3
+* @author Geoffrey T. Dairiki <dairiki@dairiki.org>
+*
+* @access private
+*/
+class diff3_op_copy extends diff3_op
+{
+ function diff3_op_copy($lines = false)
+ {
+ $this->orig = $lines ? $lines : array();
+ $this->final1 = &$this->orig;
+ $this->final2 = &$this->orig;
+ }
+
+ function merged()
+ {
+ return $this->orig;
+ }
+
+ function is_conflict()
+ {
+ return false;
+ }
+}
+
+/**
+* @package phpBB3
+* @author Geoffrey T. Dairiki <dairiki@dairiki.org>
+*
+* @access private
+*/
+class diff3_block_builder
+{
+ function diff3_block_builder()
+ {
+ $this->_init();
+ }
+
+ function input($lines)
+ {
+ if ($lines)
+ {
+ $this->_append($this->orig, $lines);
+ }
+ }
+
+ function out1($lines)
+ {
+ if ($lines)
+ {
+ $this->_append($this->final1, $lines);
+ }
+ }
+
+ function out2($lines)
+ {
+ if ($lines)
+ {
+ $this->_append($this->final2, $lines);
+ }
+ }
+
+ function is_empty()
+ {
+ return !$this->orig && !$this->final1 && !$this->final2;
+ }
+
+ function finish()
+ {
+ if ($this->is_empty())
+ {
+ return false;
+ }
+ else
+ {
+ $edit = &new diff3_op($this->orig, $this->final1, $this->final2);
+ $this->_init();
+ return $edit;
+ }
+ }
+
+ function _init()
+ {
+ $this->orig = $this->final1 = $this->final2 = array();
+ }
+
+ function _append(&$array, $lines)
+ {
+ array_splice($array, sizeof($array), 0, $lines);
+ }
+}
+
+?> \ No newline at end of file
diff --git a/phpBB/includes/diff/engine.php b/phpBB/includes/diff/engine.php
new file mode 100644
index 0000000000..c230d865cd
--- /dev/null
+++ b/phpBB/includes/diff/engine.php
@@ -0,0 +1,512 @@
+<?php
+/**
+*
+* @package phpBB3
+* @version $Id$
+* @copyright (c) 2006 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+/**
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Code from pear.php.net, Text_Diff-0.2.1 (beta) package
+* http://pear.php.net/package/Text_Diff/
+*
+* Modified by Acyd Burn to meet our coding standards
+* and being able to integrate into phpBB
+*/
+
+/**
+* Class used internally by Diff to actually compute the diffs. This class is
+* implemented using native PHP code.
+*
+* The algorithm used here is mostly lifted from the perl module
+* Algorithm::Diff (version 1.06) by Ned Konz, which is available at:
+* http://www.perl.com/CPAN/authors/id/N/NE/NEDKONZ/Algorithm-Diff-1.06.zip
+*
+* More ideas are taken from:
+* http://www.ics.uci.edu/~eppstein/161/960229.html
+*
+* Some ideas (and a bit of code) are taken from analyze.c, of GNU
+* diffutils-2.7, which can be found at:
+* ftp://gnudist.gnu.org/pub/gnu/diffutils/diffutils-2.7.tar.gz
+*
+* Some ideas (subdivision by NCHUNKS > 2, and some optimizations) are from
+* Geoffrey T. Dairiki <dairiki@dairiki.org>. The original PHP version of this
+* code was written by him, and is used/adapted with his permission.
+*
+* @author Geoffrey T. Dairiki <dairiki@dairiki.org>
+* @package phpBB3
+*
+* @access private
+*/
+class diff_engine
+{
+ function diff($from_lines, $to_lines)
+ {
+ array_walk($from_lines, array('diff', 'trim_newlines'));
+ array_walk($to_lines, array('diff', 'trim_newlines'));
+
+ $n_from = sizeof($from_lines);
+ $n_to = sizeof($to_lines);
+
+ $this->xchanged = $this->ychanged = $this->xv = $this->yv = $this->xind = $this->yind = array();
+ unset($this->seq, $this->in_seq, $this->lcs);
+
+ // Skip leading common lines.
+ for ($skip = 0; $skip < $n_from && $skip < $n_to; $skip++)
+ {
+ if ($from_lines[$skip] !== $to_lines[$skip])
+ {
+ break;
+ }
+ $this->xchanged[$skip] = $this->ychanged[$skip] = false;
+ }
+
+ // Skip trailing common lines.
+ $xi = $n_from;
+ $yi = $n_to;
+
+ for ($endskip = 0; --$xi > $skip && --$yi > $skip; $endskip++)
+ {
+ if ($from_lines[$xi] !== $to_lines[$yi])
+ {
+ break;
+ }
+ $this->xchanged[$xi] = $this->ychanged[$yi] = false;
+ }
+
+ // Ignore lines which do not exist in both files.
+ for ($xi = $skip; $xi < $n_from - $endskip; $xi++)
+ {
+ $xhash[$from_lines[$xi]] = 1;
+ }
+
+ for ($yi = $skip; $yi < $n_to - $endskip; $yi++)
+ {
+ $line = $to_lines[$yi];
+
+ if (($this->ychanged[$yi] = empty($xhash[$line])))
+ {
+ continue;
+ }
+ $yhash[$line] = 1;
+ $this->yv[] = $line;
+ $this->yind[] = $yi;
+ }
+
+ for ($xi = $skip; $xi < $n_from - $endskip; $xi++)
+ {
+ $line = $from_lines[$xi];
+
+ if (($this->xchanged[$xi] = empty($yhash[$line])))
+ {
+ continue;
+ }
+ $this->xv[] = $line;
+ $this->xind[] = $xi;
+ }
+
+ // Find the LCS.
+ $this->_compareseq(0, sizeof($this->xv), 0, sizeof($this->yv));
+
+ // Merge edits when possible.
+ $this->_shift_boundaries($from_lines, $this->xchanged, $this->ychanged);
+ $this->_shift_boundaries($to_lines, $this->ychanged, $this->xchanged);
+
+ // Compute the edit operations.
+ $edits = array();
+ $xi = $yi = 0;
+
+ while ($xi < $n_from || $yi < $n_to)
+ {
+ // Skip matching "snake".
+ $copy = array();
+
+ while ($xi < $n_from && $yi < $n_to && !$this->xchanged[$xi] && !$this->ychanged[$yi])
+ {
+ $copy[] = $from_lines[$xi++];
+ $yi++;
+ }
+
+ if ($copy)
+ {
+ $edits[] = &new diff_op_copy($copy);
+ }
+
+ // Find deletes & adds.
+ $delete = array();
+ while ($xi < $n_from && $this->xchanged[$xi])
+ {
+ $delete[] = $from_lines[$xi++];
+ }
+
+ $add = array();
+ while ($yi < $n_to && $this->ychanged[$yi])
+ {
+ $add[] = $to_lines[$yi++];
+ }
+
+ if ($delete && $add)
+ {
+ $edits[] = &new diff_op_change($delete, $add);
+ }
+ else if ($delete)
+ {
+ $edits[] = &new diff_op_delete($delete);
+ }
+ else if ($add)
+ {
+ $edits[] = &new diff_op_add($add);
+ }
+ }
+
+ return $edits;
+ }
+
+ /**
+ * Divides the Largest Common Subsequence (LCS) of the sequences (XOFF,
+ * XLIM) and (YOFF, YLIM) into NCHUNKS approximately equally sized segments.
+ *
+ * Returns (LCS, PTS). LCS is the length of the LCS. PTS is an array of
+ * NCHUNKS+1 (X, Y) indexes giving the diving points between sub
+ * sequences. The first sub-sequence is contained in (X0, X1), (Y0, Y1),
+ * the second in (X1, X2), (Y1, Y2) and so on. Note that (X0, Y0) ==
+ * (XOFF, YOFF) and (X[NCHUNKS], Y[NCHUNKS]) == (XLIM, YLIM).
+ *
+ * This function assumes that the first lines of the specified portions of
+ * the two files do not match, and likewise that the last lines do not
+ * match. The caller must trim matching lines from the beginning and end
+ * of the portions it is going to specify.
+ */
+ function _diag($xoff, $xlim, $yoff, $ylim, $nchunks)
+ {
+ $flip = false;
+
+ if ($xlim - $xoff > $ylim - $yoff)
+ {
+ // Things seems faster (I'm not sure I understand why) when the shortest sequence is in X.
+ $flip = true;
+ list($xoff, $xlim, $yoff, $ylim) = array($yoff, $ylim, $xoff, $xlim);
+ }
+
+ if ($flip)
+ {
+ for ($i = $ylim - 1; $i >= $yoff; $i--)
+ {
+ $ymatches[$this->xv[$i]][] = $i;
+ }
+ }
+ else
+ {
+ for ($i = $ylim - 1; $i >= $yoff; $i--)
+ {
+ $ymatches[$this->yv[$i]][] = $i;
+ }
+ }
+
+ $this->lcs = 0;
+ $this->seq[0]= $yoff - 1;
+ $this->in_seq = array();
+ $ymids[0] = array();
+
+ $numer = $xlim - $xoff + $nchunks - 1;
+ $x = $xoff;
+
+ for ($chunk = 0; $chunk < $nchunks; $chunk++)
+ {
+ if ($chunk > 0)
+ {
+ for ($i = 0; $i <= $this->lcs; $i++)
+ {
+ $ymids[$i][$chunk - 1] = $this->seq[$i];
+ }
+ }
+
+ $x1 = $xoff + (int)(($numer + ($xlim-$xoff)*$chunk) / $nchunks);
+
+ for (; $x < $x1; $x++)
+ {
+ $line = $flip ? $this->yv[$x] : $this->xv[$x];
+ if (empty($ymatches[$line]))
+ {
+ continue;
+ }
+ $matches = $ymatches[$line];
+
+ foreach ($matches as $y)
+ {
+ if (empty($this->in_seq[$y]))
+ {
+ $k = $this->_lcs_pos($y);
+ $ymids[$k] = $ymids[$k - 1];
+ break;
+ }
+ }
+
+ while (list($junk, $y) = each($matches))
+ {
+ if ($y > $this->seq[$k - 1])
+ {
+ // Optimization: this is a common case: next match is just replacing previous match.
+ $this->in_seq[$this->seq[$k]] = false;
+ $this->seq[$k] = $y;
+ $this->in_seq[$y] = 1;
+ }
+ else if (empty($this->in_seq[$y]))
+ {
+ $k = $this->_lcs_pos($y);
+ $ymids[$k] = $ymids[$k - 1];
+ }
+ }
+ }
+ }
+
+ $seps[] = $flip ? array($yoff, $xoff) : array($xoff, $yoff);
+ $ymid = $ymids[$this->lcs];
+
+ for ($n = 0; $n < $nchunks - 1; $n++)
+ {
+ $x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $n) / $nchunks);
+ $y1 = $ymid[$n] + 1;
+ $seps[] = $flip ? array($y1, $x1) : array($x1, $y1);
+ }
+ $seps[] = $flip ? array($ylim, $xlim) : array($xlim, $ylim);
+
+ return array($this->lcs, $seps);
+ }
+
+ function _lcs_pos($ypos)
+ {
+ $end = $this->lcs;
+
+ if ($end == 0 || $ypos > $this->seq[$end])
+ {
+ $this->seq[++$this->lcs] = $ypos;
+ $this->in_seq[$ypos] = 1;
+ return $this->lcs;
+ }
+
+ $beg = 1;
+ while ($beg < $end)
+ {
+ $mid = (int)(($beg + $end) / 2);
+ if ($ypos > $this->seq[$mid])
+ {
+ $beg = $mid + 1;
+ }
+ else
+ {
+ $end = $mid;
+ }
+ }
+
+ $this->in_seq[$this->seq[$end]] = false;
+ $this->seq[$end] = $ypos;
+ $this->in_seq[$ypos] = 1;
+
+ return $end;
+ }
+
+ /**
+ * Finds LCS of two sequences.
+ *
+ * The results are recorded in the vectors $this->{x,y}changed[], by
+ * storing a 1 in the element for each line that is an insertion or
+ * deletion (ie. is not in the LCS).
+ *
+ * The subsequence of file 0 is (XOFF, XLIM) and likewise for file 1.
+ *
+ * Note that XLIM, YLIM are exclusive bounds. All line numbers are
+ * origin-0 and discarded lines are not counted.
+ */
+ function _compareseq($xoff, $xlim, $yoff, $ylim)
+ {
+ // Slide down the bottom initial diagonal.
+ while ($xoff < $xlim && $yoff < $ylim && $this->xv[$xoff] == $this->yv[$yoff])
+ {
+ ++$xoff;
+ ++$yoff;
+ }
+
+ // Slide up the top initial diagonal.
+ while ($xlim > $xoff && $ylim > $yoff && $this->xv[$xlim - 1] == $this->yv[$ylim - 1])
+ {
+ --$xlim;
+ --$ylim;
+ }
+
+ if ($xoff == $xlim || $yoff == $ylim)
+ {
+ $lcs = 0;
+ }
+ else
+ {
+ // This is ad hoc but seems to work well.
+ // $nchunks = sqrt(min($xlim - $xoff, $ylim - $yoff) / 2.5);
+ // $nchunks = max(2,min(8,(int)$nchunks));
+ $nchunks = min(7, $xlim - $xoff, $ylim - $yoff) + 1;
+ list($lcs, $seps) = $this->_diag($xoff, $xlim, $yoff, $ylim, $nchunks);
+ }
+
+ if ($lcs == 0)
+ {
+ // X and Y sequences have no common subsequence: mark all changed.
+ while ($yoff < $ylim)
+ {
+ $this->ychanged[$this->yind[$yoff++]] = 1;
+ }
+
+ while ($xoff < $xlim)
+ {
+ $this->xchanged[$this->xind[$xoff++]] = 1;
+ }
+ }
+ else
+ {
+ // Use the partitions to split this problem into subproblems.
+ reset($seps);
+ $pt1 = $seps[0];
+
+ while ($pt2 = next($seps))
+ {
+ $this->_compareseq($pt1[0], $pt2[0], $pt1[1], $pt2[1]);
+ $pt1 = $pt2;
+ }
+ }
+ }
+
+ /**
+ * Adjusts inserts/deletes of identical lines to join changes as much as possible.
+ *
+ * We do something when a run of changed lines include a line at one end
+ * and has an excluded, identical line at the other. We are free to
+ * choose which identical line is included. 'compareseq' usually chooses
+ * the one at the beginning, but usually it is cleaner to consider the
+ * following identical line to be the "change".
+ *
+ * This is extracted verbatim from analyze.c (GNU diffutils-2.7).
+ */
+ function _shift_boundaries($lines, &$changed, $other_changed)
+ {
+ $i = 0;
+ $j = 0;
+
+ $len = sizeof($lines);
+ $other_len = sizeof($other_changed);
+
+ while (1)
+ {
+ // Scan forward to find the beginning of another run of
+ // changes. Also keep track of the corresponding point in the other file.
+ //
+ // Throughout this code, $i and $j are adjusted together so that
+ // the first $i elements of $changed and the first $j elements of
+ // $other_changed both contain the same number of zeros (unchanged lines).
+ //
+ // Furthermore, $j is always kept so that $j == $other_len or $other_changed[$j] == false.
+ while ($j < $other_len && $other_changed[$j])
+ {
+ $j++;
+ }
+
+ while ($i < $len && ! $changed[$i])
+ {
+ $i++;
+ $j++;
+
+ while ($j < $other_len && $other_changed[$j])
+ {
+ $j++;
+ }
+ }
+
+ if ($i == $len)
+ {
+ break;
+ }
+
+ $start = $i;
+
+ // Find the end of this run of changes.
+ while (++$i < $len && $changed[$i])
+ {
+ continue;
+ }
+
+ do
+ {
+ // Record the length of this run of changes, so that we can later determine whether the run has grown.
+ $runlength = $i - $start;
+
+ // Move the changed region back, so long as the previous unchanged line matches the last changed one.
+ // This merges with previous changed regions.
+ while ($start > 0 && $lines[$start - 1] == $lines[$i - 1])
+ {
+ $changed[--$start] = 1;
+ $changed[--$i] = false;
+
+ while ($start > 0 && $changed[$start - 1])
+ {
+ $start--;
+ }
+
+ while ($other_changed[--$j])
+ {
+ continue;
+ }
+ }
+
+ // Set CORRESPONDING to the end of the changed run, at the last point where it corresponds to a changed run in the
+ // other file. CORRESPONDING == LEN means no such point has been found.
+ $corresponding = $j < $other_len ? $i : $len;
+
+ // Move the changed region forward, so long as the first changed line matches the following unchanged one.
+ // This merges with following changed regions.
+ // Do this second, so that if there are no merges, the changed region is moved forward as far as possible.
+ while ($i < $len && $lines[$start] == $lines[$i])
+ {
+ $changed[$start++] = false;
+ $changed[$i++] = 1;
+
+ while ($i < $len && $changed[$i])
+ {
+ $i++;
+ }
+
+ $j++;
+ if ($j < $other_len && $other_changed[$j])
+ {
+ $corresponding = $i;
+ while ($j < $other_len && $other_changed[$j])
+ {
+ $j++;
+ }
+ }
+ }
+ }
+ while ($runlength != $i - $start);
+
+ // If possible, move the fully-merged run of changes back to a corresponding run in the other file.
+ while ($corresponding < $i)
+ {
+ $changed[--$start] = 1;
+ $changed[--$i] = 0;
+
+ while ($other_changed[--$j])
+ {
+ continue;
+ }
+ }
+ }
+ }
+}
+
+?> \ No newline at end of file
diff --git a/phpBB/includes/diff/renderer.php b/phpBB/includes/diff/renderer.php
new file mode 100644
index 0000000000..408addb858
--- /dev/null
+++ b/phpBB/includes/diff/renderer.php
@@ -0,0 +1,832 @@
+<?php
+/**
+*
+* @package phpBB3
+* @version $Id$
+* @copyright (c) 2006 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+/**
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Code from pear.php.net, Text_Diff-0.2.1 (beta) package
+* http://pear.php.net/package/Text_Diff/
+*
+* Modified by Acyd Burn to meet our coding standards
+* and being able to integrate into phpBB
+*/
+
+/**
+* A class to render Diffs in different formats.
+*
+* This class renders the diff in classic diff format. It is intended that
+* this class be customized via inheritance, to obtain fancier outputs.
+*
+* @package phpBB3
+*/
+class diff_renderer
+{
+ /**
+ * Number of leading context "lines" to preserve.
+ *
+ * This should be left at zero for this class, but subclasses may want to
+ * set this to other values.
+ */
+ var $_leading_context_lines = 0;
+
+ /**
+ * Number of trailing context "lines" to preserve.
+ *
+ * This should be left at zero for this class, but subclasses may want to
+ * set this to other values.
+ */
+ var $_trailing_context_lines = 0;
+
+ /**
+ * Constructor.
+ */
+ function diff_renderer($params = array())
+ {
+ foreach ($params as $param => $value)
+ {
+ $v = '_' . $param;
+ if (isset($this->$v))
+ {
+ $this->$v = $value;
+ }
+ }
+ }
+
+ /**
+ * Get any renderer parameters.
+ *
+ * @return array All parameters of this renderer object.
+ */
+ function get_params()
+ {
+ $params = array();
+ foreach (get_object_vars($this) as $k => $v)
+ {
+ if ($k[0] == '_')
+ {
+ $params[substr($k, 1)] = $v;
+ }
+ }
+
+ return $params;
+ }
+
+ /**
+ * Renders a diff.
+ *
+ * @param diff $diff A diff object.
+ *
+ * @return string The formatted output.
+ */
+ function render(&$diff)
+ {
+ $xi = $yi = 1;
+ $block = false;
+ $context = array();
+
+ // Create a new diff object if it is a 3-way diff
+ if (is_a($diff, 'diff3'))
+ {
+ $diff3 = &$diff;
+ $diff = &new diff($diff3->get_original(), $diff3->merged_output());
+ unset($diff3);
+ }
+
+ $nlead = $this->_leading_context_lines;
+ $ntrail = $this->_trailing_context_lines;
+
+ $output = $this->_start_diff();
+ $diffs = $diff->get_diff();
+
+ foreach ($diffs as $i => $edit)
+ {
+ if (is_a($edit, 'diff_op_copy'))
+ {
+ if (is_array($block))
+ {
+ $keep = ($i == sizeof($diffs) - 1) ? $ntrail : $nlead + $ntrail;
+ if (sizeof($edit->orig) <= $keep)
+ {
+ $block[] = $edit;
+ }
+ else
+ {
+ if ($ntrail)
+ {
+ $context = array_slice($edit->orig, 0, $ntrail);
+ $block[] = &new diff_op_copy($context);
+ }
+
+ $output .= $this->_block($x0, $ntrail + $xi - $x0, $y0, $ntrail + $yi - $y0, $block);
+ $block = false;
+ }
+ }
+ $context = $edit->orig;
+ }
+ else
+ {
+ if (!is_array($block))
+ {
+ $context = array_slice($context, sizeof($context) - $nlead);
+ $x0 = $xi - sizeof($context);
+ $y0 = $yi - sizeof($context);
+ $block = array();
+
+ if ($context)
+ {
+ $block[] = &new diff_op_copy($context);
+ }
+ }
+ $block[] = $edit;
+ }
+
+ $xi += ($edit->orig) ? sizeof($edit->orig) : 0;
+ $yi += ($edit->final) ? sizeof($edit->final) : 0;
+ }
+
+ if (is_array($block))
+ {
+ $output .= $this->_block($x0, $xi - $x0, $y0, $yi - $y0, $block);
+ }
+
+ return $output . $this->_end_diff();
+ }
+
+ function _block($xbeg, $xlen, $ybeg, $ylen, &$edits)
+ {
+ $output = $this->_start_block($this->_block_header($xbeg, $xlen, $ybeg, $ylen));
+
+ foreach ($edits as $edit)
+ {
+ switch (get_class($edit))
+ {
+ case 'diff_op_copy':
+ $output .= $this->_context($edit->orig);
+ break;
+
+ case 'diff_op_add':
+ $output .= $this->_added($edit->final);
+ break;
+
+ case 'diff_op_delete':
+ $output .= $this->_deleted($edit->orig);
+ break;
+
+ case 'diff_op_change':
+ $output .= $this->_changed($edit->orig, $edit->final);
+ break;
+ }
+ }
+
+ return $output . $this->_end_block();
+ }
+
+ function _start_diff()
+ {
+ return '';
+ }
+
+ function _end_diff()
+ {
+ return '';
+ }
+
+ function _block_header($xbeg, $xlen, $ybeg, $ylen)
+ {
+ if ($xlen > 1)
+ {
+ $xbeg .= ',' . ($xbeg + $xlen - 1);
+ }
+
+ if ($ylen > 1)
+ {
+ $ybeg .= ',' . ($ybeg + $ylen - 1);
+ }
+
+ return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg;
+ }
+
+ function _start_block($header)
+ {
+ return $header . "\n";
+ }
+
+ function _end_block()
+ {
+ return '';
+ }
+
+ function _lines($lines, $prefix = ' ')
+ {
+ return $prefix . implode("\n$prefix", $lines) . "\n";
+ }
+
+ function _context($lines)
+ {
+ return $this->_lines($lines, ' ');
+ }
+
+ function _added($lines)
+ {
+ return $this->_lines($lines, '> ');
+ }
+
+ function _deleted($lines)
+ {
+ return $this->_lines($lines, '< ');
+ }
+
+ function _changed($orig, $final)
+ {
+ return $this->_deleted($orig) . "---\n" . $this->_added($final);
+ }
+
+ /**
+ * Our function to get the diff
+ */
+ function get_diff_content($diff)
+ {
+ return $this->render($diff);
+ }
+}
+
+/**
+* Renders a unified diff
+* @package phpBB3
+*/
+class diff_renderer_unified extends diff_renderer
+{
+ var $_leading_context_lines = 4;
+ var $_trailing_context_lines = 4;
+
+ /**
+ * Our function to get the diff
+ */
+ function get_diff_content($diff)
+ {
+ return nl2br($this->render($diff));
+ }
+
+ function _block_header($xbeg, $xlen, $ybeg, $ylen)
+ {
+ if ($xlen != 1)
+ {
+ $xbeg .= ',' . $xlen;
+ }
+
+ if ($ylen != 1)
+ {
+ $ybeg .= ',' . $ylen;
+ }
+ return '<div class="diff"><big class="info">@@ -' . $xbeg . ' +' . $ybeg . ' @@</big></div>';
+ }
+
+ function _context($lines)
+ {
+ return '<pre class="diff context">' . htmlspecialchars($this->_lines($lines, ' ')) . '</pre>';
+ }
+
+ function _added($lines)
+ {
+ return '<pre class="diff added">' . htmlspecialchars($this->_lines($lines, '+')) . '</pre>';
+ }
+
+ function _deleted($lines)
+ {
+ return '<pre class="diff removed">' . htmlspecialchars($this->_lines($lines, '-')) . '</pre>';
+ }
+
+ function _changed($orig, $final)
+ {
+ return $this->_deleted($orig) . $this->_added($final);
+ }
+
+ function _start_diff()
+ {
+ $start = '<div class="file">';
+
+ return $start;
+ }
+
+ function _end_diff()
+ {
+ return '</div>';
+ }
+
+ function _end_block()
+ {
+ return '';
+ }
+}
+
+/**
+* "Inline" diff renderer.
+*
+* This class renders diffs in the Wiki-style "inline" format.
+*
+* @author Ciprian Popovici
+* @package phpBB3
+*/
+class diff_renderer_inline extends diff_renderer
+{
+ var $_leading_context_lines = 10000;
+ var $_trailing_context_lines = 10000;
+
+ // Prefix and suffix for inserted text
+ var $_ins_prefix = '<span class="ins">';
+ var $_ins_suffix = '</span>';
+
+ // Prefix and suffix for deleted text
+ var $_del_prefix = '<span class="del">';
+ var $_del_suffix = '</span>';
+
+ var $_block_head = '';
+
+ // What are we currently splitting on? Used to recurse to show word-level
+ var $_split_level = 'lines';
+
+ /**
+ * Our function to get the diff
+ */
+ function get_diff_content($diff)
+ {
+ return '<pre>' . nl2br($this->render($diff)) . '</pre>';
+ }
+
+ function _start_diff()
+ {
+ return '';
+ }
+
+ function _end_diff()
+ {
+ return '';
+ }
+
+ function _block_header($xbeg, $xlen, $ybeg, $ylen)
+ {
+ return $this->_block_head;
+ }
+
+ function _start_block($header)
+ {
+ return $header;
+ }
+
+ function _lines($lines, $prefix = ' ', $encode = true)
+ {
+ if ($encode)
+ {
+ array_walk($lines, array(&$this, '_encode'));
+ }
+
+ if ($this->_split_level == 'words')
+ {
+ return implode('', $lines);
+ }
+ else
+ {
+ return implode("\n", $lines) . "\n";
+ }
+ }
+
+ function _added($lines)
+ {
+ array_walk($lines, array(&$this, '_encode'));
+ $lines[0] = $this->_ins_prefix . $lines[0];
+ $lines[sizeof($lines) - 1] .= $this->_ins_suffix;
+ return $this->_lines($lines, ' ', false);
+ }
+
+ function _deleted($lines, $words = false)
+ {
+ array_walk($lines, array(&$this, '_encode'));
+ $lines[0] = $this->_del_prefix . $lines[0];
+ $lines[sizeof($lines) - 1] .= $this->_del_suffix;
+ return $this->_lines($lines, ' ', false);
+ }
+
+ function _changed($orig, $final)
+ {
+ // If we've already split on words, don't try to do so again - just display.
+ if ($this->_split_level == 'words')
+ {
+ $prefix = '';
+ while ($orig[0] !== false && $final[0] !== false && substr($orig[0], 0, 1) == ' ' && substr($final[0], 0, 1) == ' ')
+ {
+ $prefix .= substr($orig[0], 0, 1);
+ $orig[0] = substr($orig[0], 1);
+ $final[0] = substr($final[0], 1);
+ }
+
+ return $prefix . $this->_deleted($orig) . $this->_added($final);
+ }
+
+ $text1 = implode("\n", $orig);
+ $text2 = implode("\n", $final);
+
+ // Non-printing newline marker.
+ $nl = "\0";
+
+ // We want to split on word boundaries, but we need to preserve whitespace as well.
+ // Therefore we split on words, but include all blocks of whitespace in the wordlist.
+ $diff = &new diff($this->_split_on_words($text1, $nl), $this->_split_on_words($text2, $nl));
+
+ // Get the diff in inline format.
+ $renderer = &new diff_renderer_inline(array_merge($this->get_params(), array('split_level' => 'words')));
+
+ // Run the diff and get the output.
+ return str_replace($nl, "\n", $renderer->render($diff)) . "\n";
+ }
+
+ function _split_on_words($string, $newline_escape = "\n")
+ {
+ // Ignore \0; otherwise the while loop will never finish.
+ $string = str_replace("\0", '', $string);
+
+ $words = array();
+ $length = strlen($string);
+ $pos = 0;
+
+ $tab_there = true;
+ while ($pos < $length)
+ {
+ // Check for tabs... do not include them
+ if ($tab_there && substr($string, $pos, 1) === "\t")
+ {
+ $words[] = "\t";
+ $pos++;
+
+ continue;
+ }
+ else
+ {
+ $tab_there = false;
+ }
+
+ // Eat a word with any preceding whitespace.
+ $spaces = strspn(substr($string, $pos), " \n");
+ $nextpos = strcspn(substr($string, $pos + $spaces), " \n");
+ $words[] = str_replace("\n", $newline_escape, substr($string, $pos, $spaces + $nextpos));
+ $pos += $spaces + $nextpos;
+ }
+
+ return $words;
+ }
+
+ function _encode(&$string)
+ {
+ $string = htmlspecialchars($string);
+ }
+}
+
+/**
+* "raw" diff renderer.
+* This class could be used to output a raw unified patch file
+*
+* @package phpBB3
+*/
+class diff_renderer_raw extends diff_renderer
+{
+ var $_leading_context_lines = 4;
+ var $_trailing_context_lines = 4;
+
+ /**
+ * Our function to get the diff
+ */
+ function get_diff_content($diff)
+ {
+ return '<textarea style="height: 400px;" class="full">' . htmlspecialchars($this->render($diff)) . '</textarea>';
+ }
+
+ function _block_header($xbeg, $xlen, $ybeg, $ylen)
+ {
+ if ($xlen != 1)
+ {
+ $xbeg .= ',' . $xlen;
+ }
+
+ if ($ylen != 1)
+ {
+ $ybeg .= ',' . $ylen;
+ }
+ return '@@ -' . $xbeg . ' +' . $ybeg . ' @@';
+ }
+
+ function _context($lines)
+ {
+ return $this->_lines($lines, ' ');
+ }
+
+ function _added($lines)
+ {
+ return $this->_lines($lines, '+');
+ }
+
+ function _deleted($lines)
+ {
+ return $this->_lines($lines, '-');
+ }
+
+ function _changed($orig, $final)
+ {
+ return $this->_deleted($orig) . $this->_added($final);
+ }
+}
+
+/**
+* "chora (Horde)" diff renderer - similar style.
+* This renderer class is a modified human_readable function from the Horde Framework.
+*
+* @package phpBB3
+*/
+class diff_renderer_side_by_side extends diff_renderer
+{
+ var $_leading_context_lines = 3;
+ var $_trailing_context_lines = 3;
+
+ var $lines = array();
+
+ // Hold the left and right columns of lines for change blocks.
+ var $cols;
+ var $state;
+
+ var $data = false;
+
+ /**
+ * Our function to get the diff
+ */
+ function get_diff_content($diff)
+ {
+ global $user;
+
+ $output = '';
+ $output .= '<table cellspacing="0" class="hrdiff">
+<caption>
+ <span class="unmodified">&nbsp;</span> ' . $user->lang['LINE_UNMODIFIED'] . '
+ <span class="added">&nbsp;</span> ' . $user->lang['LINE_ADDED'] . '
+ <span class="modified">&nbsp;</span> ' . $user->lang['LINE_MODIFIED'] . '
+ <span class="removed">&nbsp;</span> ' . $user->lang['LINE_REMOVED'] . '
+</caption>
+<tbody>
+';
+
+ $this->render($diff);
+
+ // Is the diff empty?
+ if (!sizeof($this->lines))
+ {
+ $output .= '<tr><th colspan="2">' . $user->lang['NO_VISIBLE_CHANGES'] . '</th></tr>';
+ }
+ else
+ {
+ // Iterate through every header block of changes
+ foreach ($this->lines as $header)
+ {
+ $output .= '<tr><th>Line ' . $header['oldline'] . '</th><th>' . $user->lang['LINE'] . ' ' . $header['newline'] . '</th></tr>';
+
+ // Each header block consists of a number of changes (add, remove, change).
+ $current_context = '';
+
+ foreach ($header['contents'] as $change)
+ {
+ if (!empty($current_context) && $change['type'] != 'empty')
+ {
+ $line = $current_context;
+ $current_context = '';
+
+ $output .= '<tr class="unmodified"><td><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '</pre></td>
+ <td><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '</pre></td></tr>';
+ }
+
+ switch ($change['type'])
+ {
+ case 'add':
+ $line = '';
+
+ foreach ($change['lines'] as $_line)
+ {
+ $line .= htmlspecialchars($_line) . '<br />';
+ }
+
+ $output .= '<tr><td class="added_empty">&nbsp;</td><td class="added"><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '</pre></td></tr>';
+ break;
+
+ case 'remove':
+ $line = '';
+
+ foreach ($change['lines'] as $_line)
+ {
+ $line .= htmlspecialchars($_line) . '<br />';
+ }
+
+ $output .= '<tr><td class="removed"><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '</pre></td><td class="removed_empty">&nbsp;</td></tr>';
+ break;
+
+ case 'empty':
+ $current_context .= htmlspecialchars($change['line']) . '<br />';
+ break;
+
+ case 'change':
+ // Pop the old/new stacks one by one, until both are empty.
+ $oldsize = sizeof($change['old']);
+ $newsize = sizeof($change['new']);
+ $left = $right = '';
+
+ for ($row = 0, $row_max = max($oldsize, $newsize); $row < $row_max; ++$row)
+ {
+ $left .= isset($change['old'][$row]) ? htmlspecialchars($change['old'][$row]) : '';
+ $left .= '<br />';
+ $right .= isset($change['new'][$row]) ? htmlspecialchars($change['new'][$row]) : '';
+ $right .= '<br />';
+ }
+
+ $output .= '<tr>';
+
+ if (!empty($left))
+ {
+ $output .= '<td class="modified"><pre>' . $left . '</pre></td>';
+ }
+ else if ($row < $oldsize)
+ {
+ $output .= '<td class="modified">&nbsp;</td>';
+ }
+ else
+ {
+ $output .= '<td class="unmodified">&nbsp;</td>';
+ }
+
+ if (!empty($right))
+ {
+ $output .= '<td class="modified"><pre>' . $right . '</pre></td>';
+ }
+ else if ($row < $newsize)
+ {
+ $output .= '<td class="modified">&nbsp;</td>';
+ }
+ else
+ {
+ $output .= '<td class="unmodified">&nbsp;</td>';
+ }
+
+ $output .= '</tr>';
+ break;
+ }
+ }
+
+ if (!empty($current_context))
+ {
+ $line = $current_context;
+ $current_context = '';
+
+ $output .= '<tr class="unmodified"><td><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '</pre></td>';
+ $output .= '<td><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '</pre></td></tr>';
+ }
+ }
+ }
+
+ $output .= '</tbody></table>';
+
+ return $output;
+ }
+
+ function _start_diff()
+ {
+ $this->lines = array();
+
+ $this->data = false;
+ $this->cols = array(array(), array());
+ $this->state = 'empty';
+
+ return '';
+ }
+
+ function _end_diff()
+ {
+ // Just flush any remaining entries in the columns stack.
+ switch ($this->state)
+ {
+ case 'add':
+ $this->data['contents'][] = array('type' => 'add', 'lines' => $this->cols[0]);
+ break;
+
+ case 'remove':
+ // We have some removal lines pending in our stack, so flush them.
+ $this->data['contents'][] = array('type' => 'remove', 'lines' => $this->cols[0]);
+ break;
+
+ case 'change':
+ // We have both remove and addition lines, so this is a change block.
+ $this->data['contents'][] = array('type' => 'change', 'old' => $this->cols[0], 'new' => $this->cols[1]);
+ break;
+ }
+
+ if ($this->data !== false)
+ {
+ $this->lines[] = $this->data;
+ }
+
+ return '';
+ }
+
+ function _block_header($xbeg, $xlen, $ybeg, $ylen)
+ {
+ // Push any previous header information to the return stack.
+ if ($this->data !== false)
+ {
+ $this->lines[] = $this->data;
+ }
+
+ $this->data = array('type' => 'header', 'oldline' => $xbeg, 'newline' => $ybeg, 'contents' => array());
+ $this->state = 'dump';
+ }
+
+ function _added($lines)
+ {
+ array_walk($lines, array(&$this, '_perform_add'));
+ }
+
+ function _perform_add($line)
+ {
+ if ($this->state == 'empty')
+ {
+ return '';
+ }
+
+ // This is just an addition line.
+ if ($this->state == 'dump' || $this->state == 'add')
+ {
+ // Start adding to the addition stack.
+ $this->cols[0][] = $line;
+ $this->state = 'add';
+ }
+ else
+ {
+ // This is inside a change block, so start accumulating lines.
+ $this->state = 'change';
+ $this->cols[1][] = $line;
+ }
+ }
+
+ function _deleted($lines)
+ {
+ array_walk($lines, array(&$this, '_perform_delete'));
+ }
+
+ function _perform_delete($line)
+ {
+ // This is a removal line.
+ $this->state = 'remove';
+ $this->cols[0][] = $line;
+ }
+
+ function _context($lines)
+ {
+ array_walk($lines, array(&$this, '_perform_context'));
+ }
+
+ function _perform_context($line)
+ {
+ // An empty block with no action.
+ switch ($this->state)
+ {
+ case 'add':
+ $this->data['contents'][] = array('type' => 'add', 'lines' => $this->cols[0]);
+ break;
+
+ case 'remove':
+ // We have some removal lines pending in our stack, so flush them.
+ $this->data['contents'][] = array('type' => 'remove', 'lines' => $this->cols[0]);
+ break;
+
+ case 'change':
+ // We have both remove and addition lines, so this is a change block.
+ $this->data['contents'][] = array('type' => 'change', 'old' => $this->cols[0], 'new' => $this->cols[1]);
+ break;
+ }
+
+ $this->cols = array(array(), array());
+ $this->data['contents'][] = array('type' => 'empty', 'line' => $line);
+ $this->state = 'dump';
+ }
+
+ function _changed($orig, $final)
+ {
+ return $this->_deleted($orig) . $this->_added($final);
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php
index 48fec2d795..91a818d454 100644
--- a/phpBB/includes/functions.php
+++ b/phpBB/includes/functions.php
@@ -15,7 +15,7 @@
*
* Set variable, used by {@link request_var the request_var function}
*
-* @access: private
+* @access private
*/
function set_var(&$result, $var, $type, $multibyte = false)
{
@@ -24,14 +24,26 @@ function set_var(&$result, $var, $type, $multibyte = false)
if ($type == 'string')
{
- $result = trim(htmlspecialchars(str_replace(array("\r\n", "\r"), array("\n", "\n"), $result)));
- $result = (STRIP) ? stripslashes($result) : $result;
+ $result = trim(htmlspecialchars(str_replace(array("\r\n", "\r"), array("\n", "\n"), $result), ENT_COMPAT, 'UTF-8'));
- // Check for possible multibyte characters to save a preg_replace call if nothing is in there...
- if ($multibyte && strpos($result, '&amp;#') !== false)
+ if (!empty($result))
{
- $result = preg_replace('#&amp;(\#[0-9]+;)#', '&\1', $result);
+ // Make sure multibyte characters are wellformed
+ if ($multibyte)
+ {
+ if (!preg_match('/^./u', $result))
+ {
+ $result = '';
+ }
+ }
+ else
+ {
+ // no multibyte, allow only ASCII (0-127)
+ $result = preg_replace('/[\x80-\xFF]/', '?', $result);
+ }
}
+
+ $result = (STRIP) ? stripslashes($result) : $result;
}
}
@@ -40,8 +52,17 @@ function set_var(&$result, $var, $type, $multibyte = false)
*
* Used to get passed variable
*/
-function request_var($var_name, $default, $multibyte = false)
+function request_var($var_name, $default, $multibyte = false, $cookie = false)
{
+ if (!$cookie && isset($_COOKIE[$var_name]))
+ {
+ if (!isset($_GET[$var_name]) && !isset($_POST[$var_name]))
+ {
+ return (is_array($default)) ? array() : $default;
+ }
+ $_REQUEST[$var_name] = isset($_POST[$var_name]) ? $_POST[$var_name] : $_GET[$var_name];
+ }
+
if (!isset($_REQUEST[$var_name]) || (is_array($_REQUEST[$var_name]) && !is_array($default)) || (is_array($default) && !is_array($_REQUEST[$var_name])))
{
return (is_array($default)) ? array() : $default;
@@ -136,16 +157,17 @@ function gen_rand_string($num_chars = 8)
*/
function unique_id($extra = 'c')
{
+ static $dss_seeded = false;
global $config;
- static $dss_seeded;
$val = $config['rand_seed'] . microtime();
$val = md5($val);
$config['rand_seed'] = md5($config['rand_seed'] . $val . $extra);
- if ($dss_seeded !== true)
+ if ($dss_seeded !== true && ($config['rand_seed_last_update'] < time() - rand(1,10)))
{
set_config('rand_seed', $config['rand_seed'], true);
+ set_config('rand_seed_last_update', time(), true);
$dss_seeded = true;
}
@@ -161,6 +183,26 @@ function gen_sort_selects(&$limit_days, &$sort_by_text, &$sort_days, &$sort_key,
$sort_dir_text = array('a' => $user->lang['ASCENDING'], 'd' => $user->lang['DESCENDING']);
+ // Check if the key is selectable. If not, we reset to the first key found.
+ // This ensures the values are always valid.
+ if (!isset($limit_days[$sort_days]))
+ {
+ @reset($limit_days);
+ $sort_days = key($limit_days);
+ }
+
+ if (!isset($sort_by_text[$sort_key]))
+ {
+ @reset($sort_by_text);
+ $sort_key = key($sort_by_text);
+ }
+
+ if (!isset($sort_dir_text[$sort_dir]))
+ {
+ @reset($sort_dir_text);
+ $sort_dir = key($sort_dir_text);
+ }
+
$s_limit_days = '<select name="st">';
foreach ($limit_days as $day => $text)
{
@@ -378,62 +420,191 @@ if (!function_exists('stripos'))
if (!function_exists('realpath'))
{
- /**
- * Replacement for realpath if it is disabled
- * This function is from the php manual by nospam at savvior dot com
- */
- function phpbb_realpath($path)
+ if (substr(PHP_OS, 0, 3) != 'WIN' && !(bool) ini_get('safe_mode') && function_exists('shell_exec') && trim(`realpath .`))
+ {
+ /**
+ * @author Chris Smith <chris@project-minerva.org>
+ * @copyright 2006 Project Minerva Team
+ * @param string $path The path which we should attempt to resolve.
+ * @return mixed
+ * @ignore
+ */
+ function phpbb_realpath($path)
+ {
+ $arg = escapeshellarg($path);
+ return trim(`realpath '$arg'`);
+ }
+ }
+ else
{
- $translated_path = getenv('PATH_TRANSLATED');
+ /**
+ * Checks if a path ($path) is absolute or relative
+ *
+ * @param string $path Path to check absoluteness of
+ * @return boolean
+ */
+ function is_absolute($path)
+ {
+ return ($path[0] == '/' || (substr(PHP_OS, 0, 3) == 'WIN' && preg_match('#^[a-z]:/#i', $path))) ? true : false;
+ }
- $translated_path = str_replace('\\', '/', $translated_path);
- $translated_path = str_replace(basename(getenv('PATH_INFO')), '', $translated_path);
+ /**
+ * @author Chris Smith <chris@project-minerva.org>
+ * @copyright 2006 Project Minerva Team
+ * @param string $path The path which we should attempt to resolve.
+ * @return mixed
+ */
+ function phpbb_realpath($path)
+ {
+ // Now to perform funky shizzle
- $translated_path .= '/';
+ // Switch to use UNIX slashes
+ $path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
+ $path_prefix = '';
- if ($path == '.' || $path == './')
- {
- return $translated_path;
- }
+ // Determine what sort of path we have
+ if (is_absolute($path))
+ {
+ $absolute = true;
+
+ if ($path[0] == '/')
+ {
+ // Absolute path, *NIX style
+ $path_prefix = '';
+ }
+ else
+ {
+ // Absolute path, Windows style
+ // Remove the drive letter and colon
+ $path_prefix = $path[0] . ':';
+ $path = substr($path, 2);
+ }
+ }
+ else
+ {
+ // Relative Path
+ // Prepend the current working directory
+ if (function_exists('getcwd'))
+ {
+ // This is the best method, hopefully it is enabled!
+ $path = str_replace(DIRECTORY_SEPARATOR, '/', getcwd()) . '/' . $path;
+ $absolute = true;
+ if (preg_match('#^[a-z]:#i', $path))
+ {
+ $path_prefix = $path[0] . ':';
+ $path = substr($path, 2);
+ }
+ else
+ {
+ $path_prefix = '';
+ }
+ }
+ else if (isset($_SERVER['SCRIPT_FILENAME']) && !empty($_SERVER['SCRIPT_FILENAME']))
+ {
+ // Warning: If chdir() has been used this will lie!
+ // @todo This has some problems sometime (CLI can create them easily)
+ $path = str_replace(DIRECTORY_SEPARATOR, '/', dirname($_SERVER['SCRIPT_FILENAME'])) . '/' . $path;
+ $absolute = true;
+ $path_prefix = '';
+ }
+ else
+ {
+ // We have no way of getting the absolute path, just run on using relative ones.
+ $absolute = false;
+ $path_prefix = '.';
+ }
+ }
- // now check for back directory
- $translated_path .= $path;
+ // Remove any repeated slashes
+ $path = preg_replace('#/{2,}#', '/', $path);
- $dirs = explode('/', $translated_path);
+ // Remove the slashes from the start and end of the path
+ $path = trim($path, '/');
- foreach ($dirs as $key => $value)
- {
- if ($value == '..')
+ // Break the string into little bits for us to nibble on
+ $bits = explode('/', $path);
+
+ // Remove any . in the path
+ $bits = array_diff($bits, array('.'));
+
+ // Lets get looping, run over and resolve any .. (up directory)
+ for ($i = 0, $max = sizeof($bits); $i < $max; $i++)
{
- $dirs[$key] = '';
- $dirs[$key - 2] = '';
+ // @todo Optimise
+ if ($bits[$i] == '..' )
+ {
+ if (isset($bits[$i - 1]))
+ {
+ if ($bits[$i - 1] != '..')
+ {
+ // We found a .. and we are able to traverse upwards, lets do it!
+ unset($bits[$i]);
+ unset($bits[$i - 1]);
+ $i -= 2;
+ $max -= 2;
+ $bits = array_values($bits);
+ }
+ }
+ else if ($absolute) // ie. !isset($bits[$i - 1]) && $absolute
+ {
+ // We have an absolute path trying to descend above the root of the filesystem
+ // ... Error!
+ return false;
+ }
+ }
}
- }
- $translated_path = '';
+ // Prepend the path prefix
+ array_unshift($bits, $path_prefix);
- foreach ($dirs as $key => $value)
- {
- if (strlen($value) > 0)
+ $resolved = '';
+
+ $max = sizeof($bits) - 1;
+
+ // Check if we are able to resolve symlinks, Windows cannot.
+ $symlink_resolve = (function_exists('readlink')) ? true : false;
+
+ foreach ($bits as $i => $bit)
+ {
+ if (@is_dir("$resolved/$bit") || ($i == $max && @is_file("$resolved/$bit")))
+ {
+ // Path Exists
+ if ($symlink_resolve && is_link("$resolved/$bit") && ($link = readlink("$resolved/$bit")))
+ {
+ // Resolved a symlink.
+ $resolved = $link . (($i == $max) ? '' : '/');
+ continue;
+ }
+ }
+ else
+ {
+ // Something doesn't exist here!
+ // This is correct realpath() behaviour but sadly open_basedir and safe_mode make this problematic
+ // return false;
+ }
+ $resolved .= $bit . (($i == $max) ? '' : '/');
+ }
+
+ // @todo If the file exists fine and open_basedir only has one path we should be able to prepend it
+ // because we must be inside that basedir, the question is where...
+ // @internal The slash in is_dir() gets around an open_basedir restriction
+ if (!@file_exists($resolved) || (!is_dir($resolved . '/') && !is_file($resolved)))
{
- $translated_path .= $value . '/';
+ return false;
}
- }
- $translated_path = substr($translated_path, 0, strlen($translated_path) - 1);
+ // Put the slashes back to the native operating systems slashes
+ $resolved = str_replace('/', DIRECTORY_SEPARATOR, $resolved);
- if (is_dir($translated_path) || is_file($translated_path))
- {
- return $translated_path;
+ return $resolved; // We got here, in the end!
}
-
- return false;
}
}
else
{
/**
* A wrapper for realpath
+ * @ignore
*/
function phpbb_realpath($path)
{
@@ -441,6 +612,14 @@ else
}
}
+if (!function_exists('htmlspecialchars_decode'))
+{
+ function htmlspecialchars_decode($string, $quote_style = ENT_COMPAT)
+ {
+ return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
+ }
+}
+
// functions used for building option fields
/**
@@ -503,7 +682,7 @@ function tz_select($default = '', $truncate = false)
{
if ($truncate)
{
- $zone = (strlen($zone) > 70) ? substr($zone, 0, 70) . '...' : $zone;
+ $zone = (utf8_strlen($zone) > 70) ? utf8_substr($zone, 0, 70) . '...' : $zone;
}
if (is_numeric($offset))
@@ -613,24 +792,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $
);
}
- if (sizeof($sql_ary))
- {
- switch (SQL_LAYER)
- {
- case 'mysql':
- case 'mysql4':
- case 'mysqli':
- $db->sql_query('INSERT INTO ' . FORUMS_TRACK_TABLE . ' ' . $db->sql_build_array('MULTI_INSERT', $sql_ary));
- break;
-
- default:
- foreach ($sql_ary as $ary)
- {
- $db->sql_query('INSERT INTO ' . FORUMS_TRACK_TABLE . ' ' . $db->sql_build_array('INSERT', $ary));
- }
- break;
- }
- }
+ $db->sql_multi_insert(FORUMS_TRACK_TABLE, $sql_ary);
}
}
else if ($config['load_anon_lastread'] || $user->data['is_registered'])
@@ -1004,6 +1166,7 @@ function get_complete_topic_tracking($forum_id, $topic_ids, $global_announce_lis
* @param int $f_mark_time the forums last mark time if user is registered and load_db_lastread enabled
* @param int $mark_time_forum false if the mark time needs to be obtained, else the last users forum mark time
*
+* @return true if complete forum got marked read, else false.
*/
function update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_time = false, $mark_time_forum = false)
{
@@ -1098,7 +1261,10 @@ function update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_ti
if (!$row)
{
markread('topics', $forum_id);
+ return true;
}
+
+ return false;
}
// Pagination functions
@@ -1304,16 +1470,19 @@ function generate_board_url($without_script_path = false)
/**
* Redirects the user to another page then exits the script nicely
*/
-function redirect($url)
+function redirect($url, $return = false)
{
- global $db, $cache, $config, $user;
+ global $db, $cache, $config, $user, $phpbb_root_path;
if (empty($user->lang))
{
$user->add_lang('common');
}
- garbage_collection();
+ if (!$return)
+ {
+ garbage_collection();
+ }
// Make sure no &amp;'s are in, this will break the redirect
$url = str_replace('&amp;', '&', $url);
@@ -1336,7 +1505,7 @@ function redirect($url)
{
// Full URL
}
- else if ($url{0} == '/')
+ else if ($url[0] == '/')
{
// Absolute uri, prepend direct url...
$url = generate_board_url(true) . $url;
@@ -1360,8 +1529,8 @@ function redirect($url)
}
else
{
- // Get the realpath of dirname
- $root_dirs = explode('/', str_replace('\\', '/', phpbb_realpath('./')));
+ // Used ./ before, but $phpbb_root_path is working better with urls within another root path
+ $root_dirs = explode('/', str_replace('\\', '/', phpbb_realpath($phpbb_root_path)));
$page_dirs = explode('/', str_replace('\\', '/', phpbb_realpath($pathinfo['dirname'])));
$intersection = array_intersect_assoc($root_dirs, $page_dirs);
@@ -1380,6 +1549,17 @@ function redirect($url)
}
}
+ // Make sure no linebreaks are there... to prevent http response splitting for PHP < 4.4.2
+ if (strpos(urldecode($url), "\n") !== false || strpos(urldecode($url), "\r") !== false || strpos($url, ';') !== false)
+ {
+ trigger_error('Tried to redirect to potentially insecure url.', E_USER_ERROR);
+ }
+
+ if ($return)
+ {
+ return $url;
+ }
+
// Redirect via an HTML form for PITA webservers
if (@preg_match('#Microsoft|WebSTAR|Xitami#', getenv('SERVER_SOFTWARE')))
{
@@ -1453,9 +1633,20 @@ function build_url($strip_vars = false)
}
$query = $_query = array();
- parse_str(substr($redirect, strpos($redirect, '?') + 1), $query);
+
+ $args = substr($redirect, strpos($redirect, '?') + 1);
+ $args = ($args) ? explode('&', $args) : array();
$redirect = substr($redirect, 0, strpos($redirect, '?'));
+ foreach ($args as $argument)
+ {
+ $arguments = explode('=', $argument);
+ $key = $arguments[0];
+ unset($arguments[0]);
+
+ $query[$key] = implode('=', $arguments);
+ }
+
// Strip the vars off
foreach ($strip_vars as $strip)
{
@@ -1465,7 +1656,7 @@ function build_url($strip_vars = false)
}
}
- //
+ // Glue the remaining parts together... already urlencoded
foreach ($query as $key => $value)
{
$_query[] = $key . '=' . $value;
@@ -1485,6 +1676,8 @@ function meta_refresh($time, $url)
{
global $template;
+ $url = redirect($url, true);
+
$template->assign_vars(array(
'META' => '<meta http-equiv="refresh" content="' . $time . ';url=' . $url . '" />')
);
@@ -1632,14 +1825,14 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
if (isset($_POST['login']))
{
- $username = request_var('username', '');
- $password = request_var('password', '');
+ $username = request_var('username', '', true);
+ $password = request_var('password', '', true);
$autologin = (!empty($_POST['autologin'])) ? true : false;
$viewonline = (!empty($_POST['viewonline'])) ? 0 : 1;
$admin = ($admin) ? 1 : 0;
// Check if the supplied username is equal to the one stored within the database if re-authenticating
- if ($admin && strtolower($username) != strtolower($user->data['username']))
+ if ($admin && utf8_clean_string($username) != utf8_clean_string($user->data['username']))
{
// We log the attempt to use a different username...
add_log('admin', 'LOG_ADMIN_AUTH_FAIL');
@@ -1715,7 +1908,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
'S_CONFIRM_CODE' => true,
'CONFIRM_ID' => $confirm_id,
'CONFIRM_IMAGE' => '<img src="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=confirm&amp;id=' . $confirm_id . '&amp;type=' . CONFIRM_LOGIN) . '" alt="" title="" />',
- 'L_LOGIN_CONFIRM_EXPLAIN' => sprintf($user->lang['LOGIN_CONFIRM_EXPLAIN'], '<a href="mailto:' . htmlentities($config['board_contact']) . '">', '</a>'),
+ 'L_LOGIN_CONFIRM_EXPLAIN' => sprintf($user->lang['LOGIN_CONFIRM_EXPLAIN'], '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>'),
));
$err = $user->lang[$result['error_msg']];
@@ -1729,7 +1922,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
// Assign admin contact to some error messages
if ($result['error_msg'] == 'LOGIN_ERROR_USERNAME' || $result['error_msg'] == 'LOGIN_ERROR_PASSWORD')
{
- $err = (!$config['board_contact']) ? sprintf($user->lang[$result['error_msg']], '', '') : sprintf($user->lang[$result['error_msg']], '<a href="mailto:' . htmlentities($config['board_contact']) . '">', '</a>');
+ $err = (!$config['board_contact']) ? sprintf($user->lang[$result['error_msg']], '', '') : sprintf($user->lang[$result['error_msg']], '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>');
}
break;
}
@@ -1738,7 +1931,15 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
if (!$redirect)
{
// We just use what the session code determined...
- $redirect = $user->page['page_name'] . (($user->page['query_string']) ? '?' . $user->page['query_string'] : '');
+ // If we are not within the admin directory we use the page dir...
+ $redirect = '';
+
+ if (!$admin)
+ {
+ $redirect .= ($user->page['page_dir']) ? $user->page['page_dir'] . '/' : '';
+ }
+
+ $redirect .= $user->page['page_name'] . (($user->page['query_string']) ? '?' . $user->page['query_string'] : '');
}
$s_hidden_fields = build_hidden_fields(array('redirect' => $redirect, 'sid' => $user->session_id));
@@ -1753,7 +1954,8 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
'U_PRIVACY' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=privacy'),
'S_DISPLAY_FULL_LOGIN' => ($s_display) ? true : false,
- 'S_LOGIN_ACTION' => (!$admin) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login') : append_sid("index.$phpEx"), // Needs to stay index.$phpEx because we are within the admin directory
+ 'S_AUTOLOGIN_ENABLED' => ($config['allow_autologin']) ? true : false,
+ 'S_LOGIN_ACTION' => (!$admin) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login') : append_sid("index.$phpEx", false, true, $user->session_id), // Needs to stay index.$phpEx because we are within the admin directory
'S_HIDDEN_FIELDS' => $s_hidden_fields,
'S_ADMIN_AUTH' => $admin,
@@ -1777,7 +1979,7 @@ function login_forum_box($forum_data)
{
global $db, $config, $user, $template, $phpEx;
- $password = request_var('password', '');
+ $password = request_var('password', '', true);
$sql = 'SELECT forum_id
FROM ' . FORUMS_ACCESS_TABLE . '
@@ -1832,7 +2034,11 @@ function login_forum_box($forum_data)
$template->assign_var('LOGIN_ERROR', $user->lang['WRONG_PASSWORD']);
}
- page_header();
+ page_header($user->lang['LOGIN']);
+
+ $template->assign_vars(array(
+ 'S_HIDDEN_FIELDS' => build_hidden_fields(array('f' => $forum_data['forum_id'])))
+ );
$template->set_filenames(array(
'body' => 'login_forum.html')
@@ -1876,6 +2082,117 @@ function bump_topic_allowed($forum_id, $topic_bumped, $last_post_time, $topic_po
}
/**
+* Generates a text with approx. the specified length which contains the specified words and their context
+*
+* @param string $text The full text from which context shall be extracted
+* @param string $words An array of words which should be contained in the result, has to be a valid part of a PCRE pattern (escape with preg_quote!)
+* @param int $length The desired length of the resulting text, however the result might be shorter or longer than this value
+*
+* @return string Context of the specified words seperated by "..."
+*/
+function get_context($text, $words, $length = 400)
+{
+ // first replace all whitespaces with single spaces
+ $text = preg_replace('/\s+/', ' ', $text);
+
+ $word_indizes = array();
+ if (sizeof($words))
+ {
+ $match = '';
+ // find the starting indizes of all words
+ foreach ($words as $word)
+ {
+ if (preg_match('#(?:[^\w]|^)(' . $word . ')(?:[^\w]|$)#i', $text, $match))
+ {
+ $pos = strpos($text, $match[1]);
+ if ($pos !== false)
+ {
+ $word_indizes[] = $pos;
+ }
+ }
+ }
+ unset($match);
+
+ if (sizeof($word_indizes))
+ {
+ $word_indizes = array_unique($word_indizes);
+ sort($word_indizes);
+
+ $wordnum = sizeof($word_indizes);
+ // number of characters on the right and left side of each word
+ $sequence_length = (int) ($length / (2 * $wordnum)) - 2;
+ $final_text = '';
+ $word = $j = 0;
+ $final_text_index = -1;
+
+ // cycle through every character in the original text
+ for ($i = $word_indizes[$word], $n = strlen($text); $i < $n; $i++)
+ {
+ // if the current position is the start of one of the words then append $sequence_length characters to the final text
+ if (isset($word_indizes[$word]) && ($i == $word_indizes[$word]))
+ {
+ if ($final_text_index < $i - $sequence_length - 1)
+ {
+ $final_text .= '... ' . preg_replace('#^([^ ]*)#', '', substr($text, $i - $sequence_length, $sequence_length));
+ }
+ else
+ {
+ // if the final text is already nearer to the current word than $sequence_length we only append the text
+ // from its current index on and distribute the unused length to all other sequenes
+ $sequence_length += (int) (($final_text_index - $i + $sequence_length + 1) / (2 * $wordnum));
+ $final_text .= substr($text, $final_text_index + 1, $i - $final_text_index - 1);
+ }
+ $final_text_index = $i - 1;
+
+ // add the following characters to the final text (see below)
+ $word++;
+ $j = 1;
+ }
+
+ if ($j > 0)
+ {
+ // add the character to the final text and increment the sequence counter
+ $final_text .= $text[$i];
+ $final_text_index++;
+ $j++;
+
+ // if this is a whitespace then check whether we are done with this sequence
+ if ($text[$i] == ' ')
+ {
+ // only check whether we have to exit the context generation completely if we haven't already reached the end anyway
+ if ($i + 4 < $n)
+ {
+ if (($j > $sequence_length && $word >= $wordnum) || strlen($final_text) > $length)
+ {
+ $final_text .= ' ...';
+ break;
+ }
+ }
+ else
+ {
+ // make sure the text really reaches the end
+ $j -= 4;
+ }
+
+ // stop context generation and wait for the next word
+ if ($j > $sequence_length)
+ {
+ $j = 0;
+ }
+ }
+ }
+ }
+ return $final_text;
+ }
+ }
+
+ if (!sizeof($words) || !sizeof($word_indizes))
+ {
+ return (strlen($text) >= $length + 3) ? substr($text, 0, $length) . '...' : $text;
+ }
+}
+
+/**
* Decode text whereby text is coming from the db and expected to be pre-parsed content
* We are placing this outside of the message parser because we are often in need of it...
*/
@@ -1896,21 +2213,28 @@ function decode_message(&$message, $bbcode_uid = '')
$message = str_replace($match, $replace, $message);
- $match = array(
- '#<!\-\- e \-\-><a href="mailto:(.*?)">.*?</a><!\-\- e \-\->#',
- '#<!\-\- m \-\-><a href="(.*?)" target="_blank">.*?</a><!\-\- m \-\->#',
- '#<!\-\- w \-\-><a href="http:\/\/(.*?)" target="_blank">.*?</a><!\-\- w \-\->#',
- '#<!\-\- l \-\-><a href="(.*?)">.*?</a><!\-\- l \-\->#',
- '#<!\-\- s(.*?) \-\-><img src="\{SMILIES_PATH\}\/.*? \/><!\-\- s\1 \-\->#',
- '#<!\-\- .*? \-\->#s',
- '#<.*?>#s'
- );
-
- $replace = array('\1', '\1', '\1', '\1', '\1', '', '');
-
+ $match = get_preg_expression('bbcode_htm');
+ $replace = array('\1', '\2', '\1', '', '');
+
$message = preg_replace($match, $replace, $message);
+}
- return;
+/**
+* Strips all bbcode from a text and returns the plain content
+*/
+function strip_bbcode(&$text, $uid = '')
+{
+ if (!$uid)
+ {
+ $uid = '[0-9a-z]{5,}';
+ }
+
+ $text = preg_replace("#\[\/?[a-z0-9\*\+\-]+(?:=.*?)?(?::[a-z])?(\:?$uid)\]#", ' ', $text);
+
+ $match = get_preg_expression('bbcode_htm');
+ $replace = array('\1', '\2', '\1', '', '');
+
+ $text = preg_replace($match, $replace, $text);
}
/**
@@ -1919,36 +2243,37 @@ function decode_message(&$message, $bbcode_uid = '')
*/
function generate_text_for_display($text, $uid, $bitfield, $flags)
{
- global $__bbcode;
+ static $bbcode;
if (!$text)
{
return '';
}
+ $text = str_replace("\n", '<br />', censor_text($text));
+
// Parse bbcode if bbcode uid stored and bbcode enabled
- if ($uid && ($flags & 1))
+ if ($uid && ($flags & OPTION_FLAG_BBCODE))
{
if (!class_exists('bbcode'))
{
global $phpbb_root_path, $phpEx;
- include_once($phpbb_root_path . 'includes/bbcode.' . $phpEx);
+ include($phpbb_root_path . 'includes/bbcode.' . $phpEx);
}
- if (empty($__bbcode))
+ if (empty($bbcode))
{
- $__bbcode = new bbcode($bitfield);
+ $bbcode = new bbcode($bitfield);
}
else
{
- $__bbcode->bbcode($bitfield);
+ $bbcode->bbcode($bitfield);
}
- $__bbcode->bbcode_second_pass($text, $uid);
+ $bbcode->bbcode_second_pass($text, $uid);
}
- $text = smiley_text($text, !($flags & 2));
- $text = str_replace("\n", '<br />', censor_text($text));
+ $text = smiley_text($text, !($flags & OPTION_FLAG_SMILIES));
return $text;
}
@@ -1962,8 +2287,7 @@ function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bb
{
global $phpbb_root_path, $phpEx;
- $uid = '';
- $bitfield = '';
+ $uid = $bitfield = '';
if (!$text)
{
@@ -1972,7 +2296,7 @@ function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bb
if (!class_exists('parse_message'))
{
- include_once($phpbb_root_path . 'includes/message_parser.' . $phpEx);
+ include($phpbb_root_path . 'includes/message_parser.' . $phpEx);
}
$message_parser = new parse_message($text);
@@ -2004,9 +2328,9 @@ function generate_text_for_edit($text, $uid, $flags)
decode_message($text, $uid);
return array(
- 'allow_bbcode' => ($flags & 1) ? 1 : 0,
- 'allow_smilies' => ($flags & 2) ? 1 : 0,
- 'allow_urls' => ($flags & 4) ? 1 : 0,
+ 'allow_bbcode' => ($flags & OPTION_FLAG_BBCODE) ? 1 : 0,
+ 'allow_smilies' => ($flags & OPTION_FLAG_SMILIES) ? 1 : 0,
+ 'allow_urls' => ($flags & OPTION_FLAG_LINKS) ? 1 : 0,
'text' => $text
);
}
@@ -2039,11 +2363,11 @@ function make_clickable($text, $server_url = false)
// matches a xxxx://aaaaa.bbb.cccc. ...
$magic_url_match[] = '#(^|[\n ]|\()([\w]+:/{2}.*?([^[ \t\n\r<"\'\)&]+|&(?!lt;|quot;))*)#ie';
- $magic_url_replace[] = "'\$1<!-- m --><a href=\"\$2\" target=\"_blank\">' . ((strlen('\$2') > 55) ? substr(str_replace('&amp;', '&', '\$2'), 0, 39) . ' ... ' . substr(str_replace('&amp;', '&', '\$2'), -10) : '\$2') . '</a><!-- m -->'";
+ $magic_url_replace[] = "'\$1<!-- m --><a href=\"\$2\">' . ((strlen('\$2') > 55) ? substr(str_replace('&amp;', '&', '\$2'), 0, 39) . ' ... ' . substr(str_replace('&amp;', '&', '\$2'), -10) : '\$2') . '</a><!-- m -->'";
// matches a "www.xxxx.yyyy[/zzzz]" kinda lazy URL thing
$magic_url_match[] = '#(^|[\n ]|\()(w{3}\.[\w\-]+\.[\w\-.\~]+(?:[^[ \t\n\r<"\'\)&]+|&(?!lt;|quot;))*)#ie';
- $magic_url_replace[] = "'\$1<!-- w --><a href=\"http://\$2\" target=\"_blank\">' . ((strlen('\$2') > 55) ? substr(str_replace('&amp;', '&', '\$2'), 0, 39) . ' ... ' . substr(str_replace('&amp;', '&', '\$2'), -10) : '\$2') . '</a><!-- w -->'";
+ $magic_url_replace[] = "'\$1<!-- w --><a href=\"http://\$2\">' . ((strlen('\$2') > 55) ? substr(str_replace('&amp;', '&', '\$2'), 0, 39) . ' ... ' . substr(str_replace('&amp;', '&', '\$2'), -10) : '\$2') . '</a><!-- w -->'";
// matches an email@domain type address at the start of a line, or after a space or after what might be a BBCode.
$magic_url_match[] = '/(^|[\n ]|\()(' . get_preg_expression('email') . ')/ie';
@@ -2058,19 +2382,16 @@ function make_clickable($text, $server_url = false)
*/
function censor_text($text)
{
- global $censors, $user, $cache;
+ static $censors;
+ global $cache;
- if (!isset($censors))
+ if (!isset($censors) || !is_array($censors))
{
- $censors = array();
-
- if ($user->optionget('viewcensors'))
- {
- $cache->obtain_word_list($censors);
- }
+ // obtain_word_list is taking care of the users censor option and the board-wide option
+ $censors = $cache->obtain_word_list();
}
- if (sizeof($censors) && $user->optionget('viewcensors'))
+ if (sizeof($censors))
{
return preg_replace($censors['match'], $censors['replace'], $text);
}
@@ -2102,6 +2423,12 @@ function parse_inline_attachments(&$text, &$attachments, &$update_count, $forum_
{
global $config, $user;
+ if (!function_exists('display_attachments'))
+ {
+ global $phpbb_root_path, $phpEx;
+ include("{$phpbb_root_path}includes/functions_display.$phpEx");
+ }
+
$attachments = display_attachments($forum_id, NULL, $attachments, $update_count, false, true);
$tpl_size = sizeof($attachments);
@@ -2137,9 +2464,7 @@ function extension_allowed($forum_id, $extension, &$extensions)
if (!sizeof($extensions))
{
global $cache;
-
- $extensions = array();
- $cache->obtain_attach_extensions($extensions);
+ $extensions = $cache->obtain_attach_extensions();
}
if (!isset($extensions['_allowed_'][$extension]))
@@ -2221,7 +2546,7 @@ function parse_cfg_file($filename, $lines = false)
{
$line = trim($line);
- if (!$line || $line{0} == '#' || ($delim_pos = strpos($line, '=')) === false)
+ if (!$line || $line[0] == '#' || ($delim_pos = strpos($line, '=')) === false)
{
continue;
}
@@ -2242,7 +2567,7 @@ function parse_cfg_file($filename, $lines = false)
{
$value = '';
}
- else if (($value{0} == "'" && $value{sizeof($value)-1} == "'") || ($value{0} == '"' && $value{sizeof($value)-1} == '"'))
+ else if (($value[0] == "'" && $value[sizeof($value) - 1] == "'") || ($value[0] == '"' && $value[sizeof($value) - 1] == '"'))
{
$value = substr($value, 1, sizeof($value)-2);
}
@@ -2367,15 +2692,25 @@ function get_backtrace()
/**
* This function returns a regular expression pattern for commonly used expressions
-* Use with / as delimiter
-* mode can be: email|
+* Use with / as delimiter for email mode
+* mode can be: email|bbcode_htm
*/
function get_preg_expression($mode)
{
switch ($mode)
{
case 'email':
- return '[a-z0-9&\'\.\-_\+]+@[a-z0-9\-]+\.([a-z0-9\-]+\.)*?[a-z]+';
+ return '[a-z0-9&\'\.\-_\+]+@[a-z0-9\-]+\.([a-z0-9\-]+\.)*[a-z]+';
+ break;
+
+ case 'bbcode_htm':
+ return array(
+ '#<!\-\- e \-\-><a href="mailto:(.*?)">.*?</a><!\-\- e \-\->#',
+ '#<!\-\- (l|m|w) \-\-><a href="(.*?)">.*?</a><!\-\- \1 \-\->#',
+ '#<!\-\- s(.*?) \-\-><img src="\{SMILIES_PATH\}\/.*? \/><!\-\- s\1 \-\->#',
+ '#<!\-\- .*? \-\->#s',
+ '#<.*?>#s',
+ );
break;
}
@@ -2386,35 +2721,80 @@ function get_preg_expression($mode)
* Truncates string while retaining special characters if going over the max length
* The default max length is 60 at the moment
*/
-function truncate_string($string, $max_length = 60)
+function truncate_string($string, $max_length = 60, $allow_reply = true)
{
$chars = array();
- // split the multibyte characters first
- $string_ary = preg_split('#(&\#[0-9]+;)#', $string, -1, PREG_SPLIT_DELIM_CAPTURE);
+ $strip_reply = false;
+ if ($allow_reply && strpos($string, 'Re: ') === 0)
+ {
+ $strip_reply = true;
+ $string = substr($string, 4);
+ }
+
+ $_chars = utf8_str_split(htmlspecialchars_decode($string));
+ $chars = array_map('htmlspecialchars', $_chars);
- // Now go through the array and split the other characters
- foreach ($string_ary as $key => $value)
+ // Now check the length ;)
+ if (sizeof($chars) > $max_length)
+ {
+ // Cut off the last elements from the array
+ $string = implode('', array_slice($chars, 0, $max_length));
+ }
+
+ if ($strip_reply)
+ {
+ $string = 'Re: ' . $string;
+ }
+
+ return $string;
+}
+
+
+/**
+* Wrapper for php's checkdnsrr function.
+*
+* The windows failover is from the php manual
+* Please make sure to check the return value for === true and === false, since NULL could
+* be returned too.
+*
+* @return true if entry found, false if not, NULL if this function is not supported by this environment
+*/
+function phpbb_checkdnsrr($host, $type = '')
+{
+ $type = (!$type) ? 'MX' : $type;
+
+ if (strpos(PHP_OS, 'WIN') !== false)
{
- if (strpos($value, '&#') === 0)
+ if (!function_exists('exec'))
{
- $chars[] = $value;
- continue;
+ return NULL;
}
- // decode html entities and put them back later
- $_chars = str_split(html_entity_decode($value));
- $chars = array_merge($chars, array_map('htmlspecialchars', $_chars));
- }
+ @exec('nslookup -type=' . escapeshellarg($type) . ' ' . escapeshellarg($host), $output);
- // Now check the length ;)
- if (sizeof($chars) <= $max_length)
+ foreach ($output as $line)
+ {
+ if (!trim($line))
+ {
+ continue;
+ }
+
+ // Valid records begin with host name:
+ if (strpos($line, $host) === 0)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ else if (function_exists('checkdnsrr'))
{
- return $string;
+ return (checkdnsrr($host, $type)) ? true : false;
}
- // Cut off the last elements from the array
- return implode('', array_slice($chars, 0, $max_length));
+ return NULL;
}
// Handler, header and footer
@@ -2489,7 +2869,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
if (!empty($config['board_contact']))
{
- echo ' <p>Please notify the board administrator or webmaster : <a href="mailto:' . $config['board_contact'] . '">' . $config['board_contact'] . '</a></p>';
+ echo ' <p>Please notify the board administrator or webmaster: <a href="mailto:' . $config['board_contact'] . '">' . $config['board_contact'] . '</a></p>';
}
echo ' </div>';
@@ -2510,7 +2890,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
case E_USER_NOTICE:
define('IN_ERROR_HANDLER', true);
-
+
if (empty($user->data))
{
$user->session_begin();
@@ -2544,8 +2924,10 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
);
$template->assign_vars(array(
- 'MESSAGE_TITLE' => $msg_title,
- 'MESSAGE_TEXT' => $msg_text)
+ 'MESSAGE_TITLE' => $msg_title,
+ 'MESSAGE_TEXT' => $msg_text,
+ 'S_USER_WARNING' => ($errno == E_USER_WARNING) ? true : false,
+ 'S_USER_NOTICE' => ($errno == E_USER_NOTICE) ? true : false)
);
// We do not want the cron script to be called on error messages
@@ -2620,7 +3002,7 @@ function page_header($page_title = '', $display_online_list = true)
$reading_sql = " AND s.session_page LIKE '%\_f\_={$f}x%'";
// Specify escape character for MSSQL
- if (SQL_LAYER == 'mssql' || SQL_LAYER == 'mssql_odbc')
+ if ($db->sql_layer == 'mssql' || $db->sql_layer == 'mssql_odbc')
{
$reading_sql .= " ESCAPE '\\'";
}
@@ -2629,11 +3011,25 @@ function page_header($page_title = '', $display_online_list = true)
// Get number of online guests
if (!$config['load_online_guests'])
{
- $sql = 'SELECT COUNT(DISTINCT s.session_ip) as num_guests
- FROM ' . SESSIONS_TABLE . ' s
- WHERE s.session_user_id = ' . ANONYMOUS . '
- AND s.session_time >= ' . (time() - ($config['load_online_time'] * 60)) .
- $reading_sql;
+ if ($db->sql_layer === 'sqlite')
+ {
+ $sql = 'SELECT COUNT(session_ip) as num_guests
+ FROM (
+ SELECT DISTINCT s.session_ip
+ FROM ' . SESSIONS_TABLE . ' s
+ WHERE s.session_user_id = ' . ANONYMOUS . '
+ AND s.session_time >= ' . (time() - ($config['load_online_time'] * 60)) .
+ $reading_sql .
+ ')';
+ }
+ else
+ {
+ $sql = 'SELECT COUNT(DISTINCT s.session_ip) as num_guests
+ FROM ' . SESSIONS_TABLE . ' s
+ WHERE s.session_user_id = ' . ANONYMOUS . '
+ AND s.session_time >= ' . (time() - ($config['load_online_time'] * 60)) .
+ $reading_sql;
+ }
$result = $db->sql_query($sql);
$guests_online = (int) $db->sql_fetchfield('num_guests');
$db->sql_freeresult($result);
@@ -2658,7 +3054,12 @@ function page_header($page_title = '', $display_online_list = true)
{
if ($row['user_colour'])
{
- $row['username'] = '<b style="color:#' . $row['user_colour'] . '">' . $row['username'] . '</b>';
+ $user_colour = ' style="color:#' . $row['user_colour'] . '"';
+ $row['username'] = '<strong>' . $row['username'] . '</strong>';
+ }
+ else
+ {
+ $user_colour = '';
}
if ($row['user_allow_viewonline'] && $row['session_viewonline'])
@@ -2668,13 +3069,21 @@ function page_header($page_title = '', $display_online_list = true)
}
else
{
- $user_online_link = '<i>' . $row['username'] . '</i>';
+ $user_online_link = '<em>' . $row['username'] . '</em>';
$logged_hidden_online++;
}
if (($row['user_allow_viewonline'] && $row['session_viewonline']) || $auth->acl_get('u_viewonline'))
{
- $user_online_link = ($row['user_type'] <> USER_IGNORE) ? '<a href="' . append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&amp;u=' . $row['user_id']) . '">' . $user_online_link . '</a>' : $user_online_link;
+ if ($row['user_type'] <> USER_IGNORE)
+ {
+ $user_online_link = '<a href="' . append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&amp;u=' . $row['user_id']) . '"' . $user_colour . '>' . $user_online_link . '</a>';
+ }
+ else
+ {
+ $user_online_link = ($user_colour) ? '<span' . $user_colour . '>' . $user_online_link . '</span>' : $user_online_link;
+ }
+
$online_userlist .= ($online_userlist != '') ? ', ' . $user_online_link : $user_online_link;
}
}
@@ -2849,18 +3258,19 @@ function page_header($page_title = '', $display_online_list = true)
'U_RESTORE_PERMISSIONS' => ($user->data['user_perm_from'] && $auth->acl_get('a_switchperm')) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=restore_perm') : '',
'S_USER_LOGGED_IN' => ($user->data['user_id'] != ANONYMOUS) ? true : false,
- 'S_BOARD_DISABLED' => ($config['board_disable'] && !defined('IN_LOGIN') && $auth->acl_gets('a_', 'm_')) ? true : false,
+ 'S_BOARD_DISABLED' => ($config['board_disable'] && !defined('IN_LOGIN') && !$auth->acl_gets('a_', 'm_')) ? true : false,
'S_REGISTERED_USER' => $user->data['is_registered'],
'S_IS_BOT' => $user->data['is_bot'],
'S_USER_PM_POPUP' => $user->optionget('popuppm'),
- 'S_USER_LANG' => $user->data['user_lang'],
+ 'S_USER_LANG' => $user->lang['USER_LANG'],
'S_USER_BROWSER' => (isset($user->data['session_browser'])) ? $user->data['session_browser'] : $user->lang['UNKNOWN_BROWSER'],
+ 'S_USERNAME' => $user->data['username'],
'S_CONTENT_DIRECTION' => $user->lang['DIRECTION'],
- 'S_CONTENT_ENCODING' => $user->lang['ENCODING'],
+ 'S_CONTENT_ENCODING' => 'UTF-8',
'S_CONTENT_DIR_LEFT' => $user->lang['LEFT'],
'S_CONTENT_DIR_RIGHT' => $user->lang['RIGHT'],
'S_TIMEZONE' => ($user->data['user_dst'] || ($user->data['user_id'] == ANONYMOUS && $config['board_dst'])) ? sprintf($user->lang['ALL_TIMES'], $user->lang['tz'][$tz], $user->lang['tz']['dst']) : sprintf($user->lang['ALL_TIMES'], $user->lang['tz'][$tz], ''),
- 'S_DISPLAY_ONLINE_LIST' => ($config['load_online']) ? 1 : 0,
+ 'S_DISPLAY_ONLINE_LIST' => ($l_online_time) ? 1 : 0,
'S_DISPLAY_SEARCH' => (!$config['load_search']) ? 0 : (isset($auth) ? ($auth->acl_get('u_search') && $auth->acl_getf_global('f_search')) : 1),
'S_DISPLAY_PM' => ($config['allow_privmsg'] && $user->data['is_registered']) ? 1 : 0,
'S_DISPLAY_MEMBERLIST' => (isset($auth)) ? $auth->acl_get('u_viewprofile') : 0,
@@ -2877,7 +3287,7 @@ function page_header($page_title = '', $display_online_list = true)
'T_ICONS_PATH' => "{$phpbb_root_path}{$config['icons_path']}/",
'T_RANKS_PATH' => "{$phpbb_root_path}{$config['ranks_path']}/",
'T_UPLOAD_PATH' => "{$phpbb_root_path}{$config['upload_path']}/",
- 'T_STYLESHEET_LINK' => (!$user->theme['theme_storedb']) ? "{$phpbb_root_path}styles/" . $user->theme['theme_path'] . '/theme/stylesheet.css' : "{$phpbb_root_path}style.$phpEx?sid=$user->session_id&amp;id=" . $user->theme['style_id'],
+ 'T_STYLESHEET_LINK' => (!$user->theme['theme_storedb']) ? "{$phpbb_root_path}styles/" . $user->theme['theme_path'] . '/theme/stylesheet.css' : "{$phpbb_root_path}style.$phpEx?sid=$user->session_id&amp;id=" . $user->theme['style_id'] . '&amp;lang=' . $user->data['user_lang'],
'T_STYLESHEET_NAME' => $user->theme['theme_name'],
'T_THEME_DATA' => (!$user->theme['theme_storedb']) ? '' : $user->theme['theme_data'],
@@ -2886,7 +3296,7 @@ function page_header($page_title = '', $display_online_list = true)
if ($config['send_encoding'])
{
- header('Content-type: text/html; charset=' . $user->lang['ENCODING']);
+ header('Content-type: text/html; charset=UTF-8');
}
header('Cache-Control: private, no-cache="set-cookie"');
header('Expires: 0');
@@ -2898,7 +3308,7 @@ function page_header($page_title = '', $display_online_list = true)
/**
* Generate page footer
*/
-function page_footer()
+function page_footer($run_cron = true)
{
global $db, $config, $template, $user, $auth, $cache, $messenger, $starttime, $phpbb_root_path, $phpEx;
@@ -2936,11 +3346,11 @@ function page_footer()
$template->assign_vars(array(
'DEBUG_OUTPUT' => (defined('DEBUG')) ? $debug_output : '',
- 'U_ACP' => ($auth->acl_get('a_') && $user->data['is_registered']) ? "{$phpbb_root_path}adm/index.$phpEx?sid=" . $user->session_id : '')
+ 'U_ACP' => ($auth->acl_get('a_') && $user->data['is_registered']) ? append_sid("{$phpbb_root_path}adm/index.$phpEx", '', true, $user->session_id) : '')
);
// Call cron-type script
- if (!defined('IN_CRON'))
+ if (!defined('IN_CRON') && $run_cron)
{
$cron_type = '';
@@ -2975,7 +3385,7 @@ function page_footer()
if ($cron_type)
{
- $template->assign_var('RUN_CRON_TASK', '<img src="' . $phpbb_root_path . 'cron.' . $phpEx . '?cron_type=' . $cron_type . '" width="1" height="1" />');
+ $template->assign_var('RUN_CRON_TASK', '<img src="' . $phpbb_root_path . 'cron.' . $phpEx . '?cron_type=' . $cron_type . '" width="1" height="1" alt="cron" />');
}
}
@@ -3001,10 +3411,14 @@ function garbage_collection()
}
// Close our DB connection.
- $db->sql_close();
+ if (!empty($db))
+ {
+ $db->sql_close();
+ }
}
/**
+* @package phpBB3
*/
class bitfield
{
diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php
index 307044b9a0..c85802dafb 100644
--- a/phpBB/includes/functions_admin.php
+++ b/phpBB/includes/functions_admin.php
@@ -207,7 +207,7 @@ function group_select_options($group_id, $exclude_ids = false)
global $db, $user, $config;
$exclude_sql = ($exclude_ids !== false && sizeof($exclude_ids)) ? 'WHERE ' . $db->sql_in_set('group_id', array_map('intval', $exclude_ids), true) : '';
- $sql_and = (!$config['coppa_enable']) ? (($exclude_sql) ? ' AND ' : ' WHERE ') . "group_name NOT IN ('INACTIVE_COPPA', 'REGISTERED_COPPA')" : '';
+ $sql_and = (!$config['coppa_enable']) ? (($exclude_sql) ? ' AND ' : ' WHERE ') . "group_name <> 'REGISTERED_COPPA'" : '';
$sql = 'SELECT group_id, group_name, group_type
FROM ' . GROUPS_TABLE . "
@@ -245,6 +245,7 @@ function get_forum_list($acl_list = 'f_list', $id_only = true, $postable_only =
ORDER BY left_id ASC';
$result = $db->sql_query($sql, $expire_time);
+ $forum_rows = array();
while ($row = $db->sql_fetchrow($result))
{
$forum_rows[] = $row;
@@ -346,7 +347,7 @@ function filelist($rootdir, $dir = '', $type = 'gif|jpg|jpeg|png')
$matches[$dir][] = $fname;
}
}
- else if ($fname{0} != '.' && is_dir("$rootdir$dir$fname"))
+ else if ($fname[0] != '.' && is_dir("$rootdir$dir$fname"))
{
$matches += filelist($rootdir, "$dir$fname", $type);
}
@@ -511,7 +512,7 @@ function delete_topics($where_type, $where_ids, $auto_sync = true)
$forum_ids[] = $row['forum_id'];
$topic_ids[] = $row['topic_id'];
}
- $db->sql_freeresult();
+ $db->sql_freeresult($result);
$return['topics'] = sizeof($topic_ids);
@@ -628,7 +629,7 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync =
trigger_error('NO_SUCH_SEARCH_MODULE');
}
- require("{$phpbb_root_path}includes/search/$search_type.$phpEx");
+ include_once("{$phpbb_root_path}includes/search/$search_type.$phpEx");
$error = false;
$search = new $search_type($error);
@@ -879,7 +880,7 @@ function delete_topic_shadows($max_age, $forum_id = '', $auto_sync = true)
{
$where = (is_array($forum_id)) ? 'AND ' . $db->sql_in_set('t.forum_id', array_map('intval', $forum_id)) : (($forum_id) ? 'AND t.forum_id = ' . (int) $forum_id : '');
- switch (SQL_LAYER)
+ switch ($db->sql_layer)
{
case 'mysql4':
case 'mysqli':
@@ -970,24 +971,7 @@ function update_posted_info(&$topic_ids)
}
unset($posted);
- if (sizeof($sql_ary))
- {
- switch (SQL_LAYER)
- {
- case 'mysql':
- case 'mysql4':
- case 'mysqli':
- $db->sql_query('INSERT INTO ' . TOPICS_POSTED_TABLE . ' ' . $db->sql_build_array('MULTI_INSERT', $sql_ary));
- break;
-
- default:
- foreach ($sql_ary as $ary)
- {
- $db->sql_query('INSERT INTO ' . TOPICS_POSTED_TABLE . ' ' . $db->sql_build_array('INSERT', $ary));
- }
- break;
- }
- }
+ $db->sql_multi_insert(TOPICS_POSTED_TABLE, $sql_ary);
}
/**
@@ -1036,7 +1020,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
$where_ids = ($where_ids) ? array((int) $where_ids) : array();
}
- if ($mode == 'forum' || $mode == 'topic')
+ if ($mode == 'forum' || $mode == 'topic' || $mode == 'topic_approved')
{
if (!$where_type)
{
@@ -1046,7 +1030,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
else if ($where_type == 'range')
{
// Only check a range of topics/forums. For instance: 'topic_id BETWEEN 1 AND 60'
- $where_sql = 'WHERE (' . $mode{0} . ".$where_ids)";
+ $where_sql = 'WHERE (' . $mode[0] . ".$where_ids)";
$where_sql_and = $where_sql . "\n\tAND";
}
else
@@ -1062,7 +1046,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
// Limit the topics/forums we are syncing, use specific topic/forum IDs.
// $where_type contains the field for the where clause (forum_id, topic_id)
- $where_sql = 'WHERE ' . $db->sql_in_set($mode{0} . '.' . $where_type, $where_ids);
+ $where_sql = 'WHERE ' . $db->sql_in_set($mode[0] . '.' . $where_type, $where_ids);
$where_sql_and = $where_sql . "\n\tAND";
}
}
@@ -1074,14 +1058,14 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
}
// $where_type contains the field for the where clause (forum_id, topic_id)
- $where_sql = 'WHERE ' . $db->sql_in_set($mode{0} . '.' . $where_type, $where_ids);
+ $where_sql = 'WHERE ' . $db->sql_in_set($mode[0] . '.' . $where_type, $where_ids);
$where_sql_and = $where_sql . "\n\tAND";
}
switch ($mode)
{
case 'topic_moved':
- switch (SQL_LAYER)
+ switch ($db->sql_layer)
{
case 'mysql4':
case 'mysqli':
@@ -1120,7 +1104,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
break;
case 'topic_approved':
- switch (SQL_LAYER)
+ switch ($db->sql_layer)
{
case 'mysql4':
case 'mysqli':
@@ -1129,7 +1113,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
$where_sql_and t.topic_first_post_id = p.post_id";
$db->sql_query($sql);
break;
-
+
default:
$sql = 'SELECT t.topic_id, p.post_approved
FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p
@@ -1142,7 +1126,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
{
$topic_ids[] = $row['topic_id'];
}
- $db->sql_freeresult();
+ $db->sql_freeresult($result);
if (!sizeof($topic_ids))
{
@@ -1375,9 +1359,11 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
$forum_data[$forum_id]['topics'] = 0;
$forum_data[$forum_id]['topics_real'] = 0;
$forum_data[$forum_id]['last_post_id'] = 0;
+ $forum_data[$forum_id]['last_post_subject'] = '';
$forum_data[$forum_id]['last_post_time'] = 0;
$forum_data[$forum_id]['last_poster_id'] = 0;
$forum_data[$forum_id]['last_poster_name'] = '';
+ $forum_data[$forum_id]['last_poster_colour'] = '';
}
$db->sql_freeresult($result);
@@ -1386,6 +1372,8 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
break;
}
+ $forum_ids = array_values($forum_ids);
+
// 2: Get topic counts for each forum
$sql = 'SELECT forum_id, topic_approved, COUNT(topic_id) AS forum_topics
FROM ' . TOPICS_TABLE . '
@@ -1406,16 +1394,27 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
$db->sql_freeresult($result);
// 3: Get post count and last_post_id for each forum
- $sql = 'SELECT forum_id, COUNT(post_id) AS forum_posts, MAX(post_id) AS last_post_id
- FROM ' . POSTS_TABLE . '
- WHERE ' . $db->sql_in_set('forum_id', $forum_ids) . '
- AND post_approved = 1
- GROUP BY forum_id';
+ if (sizeof($forum_ids) == 1)
+ {
+ $sql = 'SELECT COUNT(post_id) AS forum_posts, MAX(post_id) AS last_post_id
+ FROM ' . POSTS_TABLE . '
+ WHERE ' . $db->sql_in_set('forum_id', $forum_ids) . '
+ AND post_approved = 1';
+ }
+ else
+ {
+ $sql = 'SELECT forum_id, COUNT(post_id) AS forum_posts, MAX(post_id) AS last_post_id
+ FROM ' . POSTS_TABLE . '
+ WHERE ' . $db->sql_in_set('forum_id', $forum_ids) . '
+ AND post_approved = 1
+ GROUP BY forum_id';
+ }
+
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
- $forum_id = (int) $row['forum_id'];
+ $forum_id = (sizeof($forum_ids) == 1) ? (int) $forum_ids[0] : (int) $row['forum_id'];
$forum_data[$forum_id]['posts'] = (int) $row['forum_posts'];
$forum_data[$forum_id]['last_post_id'] = (int) $row['last_post_id'];
@@ -1427,7 +1426,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
// 4: Retrieve last_post infos
if (sizeof($post_ids))
{
- $sql = 'SELECT p.post_id, p.poster_id, p.post_time, p.post_username, u.username
+ $sql = 'SELECT p.post_id, p.poster_id, p.post_subject, p.post_time, p.post_username, u.username, u.user_colour
FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u
WHERE ' . $db->sql_in_set('p.post_id', $post_ids) . '
AND p.poster_id = u.user_id';
@@ -1445,17 +1444,21 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
{
if (isset($post_info[$data['last_post_id']]))
{
+ $forum_data[$forum_id]['last_post_subject'] = $post_info[$data['last_post_id']]['post_subject'];
$forum_data[$forum_id]['last_post_time'] = $post_info[$data['last_post_id']]['post_time'];
$forum_data[$forum_id]['last_poster_id'] = $post_info[$data['last_post_id']]['poster_id'];
$forum_data[$forum_id]['last_poster_name'] = ($post_info[$data['last_post_id']]['poster_id'] != ANONYMOUS) ? $post_info[$data['last_post_id']]['username'] : $post_info[$data['last_post_id']]['post_username'];
+ $forum_data[$forum_id]['last_poster_colour'] = $post_info[$data['last_post_id']]['user_colour'];
}
else
{
// For some reason we did not find the post in the db
$forum_data[$forum_id]['last_post_id'] = 0;
+ $forum_data[$forum_id]['last_post_subject'] = '';
$forum_data[$forum_id]['last_post_time'] = 0;
$forum_data[$forum_id]['last_poster_id'] = 0;
$forum_data[$forum_id]['last_poster_name'] = '';
+ $forum_data[$forum_id]['last_poster_colour'] = '';
}
}
}
@@ -1463,7 +1466,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
}
// 5: Now do that thing
- $fieldnames = array('posts', 'topics', 'topics_real', 'last_post_id', 'last_post_time', 'last_poster_id', 'last_poster_name');
+ $fieldnames = array('posts', 'topics', 'topics_real', 'last_post_id', 'last_post_subject', 'last_post_time', 'last_poster_id', 'last_poster_name', 'last_poster_colour');
foreach ($forum_data as $forum_id => $row)
{
@@ -1473,7 +1476,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
{
if ($row['forum_' . $fieldname] != $row[$fieldname])
{
- if (preg_match('#name$#', $fieldname))
+ if (preg_match('#(name|colour|subject)$#', $fieldname))
{
$sql_ary['forum_' . $fieldname] = (string) $row[$fieldname];
}
@@ -1497,7 +1500,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
case 'topic':
$topic_data = $post_ids = $approved_unapproved_ids = $resync_forums = $delete_topics = $delete_posts = $moved_topics = array();
- $sql = 'SELECT t.topic_id, t.forum_id, t.topic_moved_id, t.topic_approved, ' . (($sync_extra) ? 't.topic_attachment, t.topic_reported, ' : '') . 't.topic_poster, t.topic_time, t.topic_replies, t.topic_replies_real, t.topic_first_post_id, t.topic_first_poster_name, t.topic_last_post_id, t.topic_last_poster_id, t.topic_last_poster_name, t.topic_last_post_time
+ $sql = 'SELECT t.topic_id, t.forum_id, t.topic_moved_id, t.topic_approved, ' . (($sync_extra) ? 't.topic_attachment, t.topic_reported, ' : '') . 't.topic_poster, t.topic_time, t.topic_replies, t.topic_replies_real, t.topic_first_post_id, t.topic_first_poster_name, t.topic_first_poster_colour, t.topic_last_post_id, t.topic_last_post_subject, t.topic_last_poster_id, t.topic_last_poster_name, t.topic_last_poster_colour, t.topic_last_post_time
FROM ' . TOPICS_TABLE . " t
$where_sql";
$result = $db->sql_query($sql);
@@ -1513,6 +1516,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
$topic_id = (int) $row['topic_id'];
$topic_data[$topic_id] = $row;
$topic_data[$topic_id]['replies_real'] = -1;
+ $topic_data[$topic_id]['replies'] = 0;
$topic_data[$topic_id]['first_post_id'] = 0;
$topic_data[$topic_id]['last_post_id'] = 0;
unset($topic_data[$topic_id]['topic_id']);
@@ -1532,19 +1536,8 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
// NOTE: 't.post_approved' in the GROUP BY is causing a major slowdown.
$sql = 'SELECT t.topic_id, t.post_approved, COUNT(t.post_id) AS total_posts, MIN(t.post_id) AS first_post_id, MAX(t.post_id) AS last_post_id
FROM ' . POSTS_TABLE . " t
- $where_sql";
-
- switch (SQL_LAYER)
- {
- case 'mssql':
- case 'mssql_odbc':
- $sql .= ' GROUP BY t.topic_id, t.post_approved';
- break;
-
- default:
- $sql .= ' GROUP BY t.topic_id';
- break;
- }
+ $where_sql
+ GROUP BY t.topic_id, t.post_approved";
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
@@ -1638,7 +1631,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
unset($delete_topics);
}
- $sql = 'SELECT p.post_id, p.topic_id, p.post_approved, p.poster_id, p.post_username, p.post_time, u.username
+ $sql = 'SELECT p.post_id, p.topic_id, p.post_approved, p.poster_id, p.post_subject, p.post_username, p.post_time, u.username, u.user_colour
FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u
WHERE ' . $db->sql_in_set('p.post_id', $post_ids) . '
AND u.user_id = p.poster_id';
@@ -1658,13 +1651,16 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
$topic_data[$topic_id]['time'] = $row['post_time'];
$topic_data[$topic_id]['poster'] = $row['poster_id'];
$topic_data[$topic_id]['first_poster_name'] = ($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username'];
+ $topic_data[$topic_id]['first_poster_colour'] = $row['user_colour'];
}
if ($row['post_id'] == $topic_data[$topic_id]['last_post_id'])
{
$topic_data[$topic_id]['last_poster_id'] = $row['poster_id'];
+ $topic_data[$topic_id]['last_post_subject'] = $row['post_subject'];
$topic_data[$topic_id]['last_post_time'] = $row['post_time'];
$topic_data[$topic_id]['last_poster_name'] = ($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username'];
+ $topic_data[$topic_id]['last_poster_colour'] = $row['user_colour'];
}
}
$db->sql_freeresult($result);
@@ -1680,7 +1676,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
unset($approved_unapproved_ids);
// These are fields that will be synchronised
- $fieldnames = array('time', 'replies', 'replies_real', 'poster', 'first_post_id', 'first_poster_name', 'last_post_id', 'last_post_time', 'last_poster_id', 'last_poster_name');
+ $fieldnames = array('time', 'replies', 'replies_real', 'poster', 'first_post_id', 'first_poster_name', 'first_poster_colour', 'last_post_id', 'last_post_subject', 'last_post_time', 'last_poster_id', 'last_poster_name', 'last_poster_colour');
if ($sync_extra)
{
@@ -1723,7 +1719,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
foreach ($fieldnames as $fieldname)
{
- if ($row['topic_' . $fieldname] != $row[$fieldname])
+ if (isset($row[$fieldname]) && isset($row['topic_' . $fieldname]) && $row['topic_' . $fieldname] != $row[$fieldname])
{
$sql_ary['topic_' . $fieldname] = $row[$fieldname];
}
@@ -1746,7 +1742,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false,
// batch processing.
if ($resync_parents && sizeof($resync_forums) && $where_type != 'range')
{
- sync('forum', 'forum_id', $resync_forums, true);
+ sync('forum', 'forum_id', array_values($resync_forums), true);
}
break;
}
@@ -1773,12 +1769,12 @@ function prune($forum_id, $prune_mode, $prune_date, $prune_flags = 0, $auto_sync
$sql_and = '';
- if (!($prune_flags & 4))
+ if (!($prune_flags & FORUM_FLAG_PRUNE_ANNOUNCE))
{
$sql_and .= ' AND topic_type <> ' . POST_ANNOUNCE;
}
- if (!($prune_flags & 8))
+ if (!($prune_flags & FORUM_FLAG_PRUNE_STICKY))
{
$sql_and .= ' AND topic_type <> ' . POST_STICKY;
}
@@ -1807,7 +1803,7 @@ function prune($forum_id, $prune_mode, $prune_date, $prune_flags = 0, $auto_sync
}
$db->sql_freeresult($result);
- if ($prune_flags & 2)
+ if ($prune_flags & FORUM_FLAG_PRUNE_POLL)
{
$sql = 'SELECT topic_id
FROM ' . TOPICS_TABLE . '
@@ -1943,7 +1939,7 @@ function cache_moderators()
$cache->destroy('sql', MODERATOR_CACHE_TABLE);
// Clear table
- $db->sql_query(((SQL_LAYER != 'sqlite') ? 'TRUNCATE TABLE ' : 'DELETE FROM ') . MODERATOR_CACHE_TABLE);
+ $db->sql_query((($db->sql_layer != 'sqlite') ? 'TRUNCATE TABLE ' : 'DELETE FROM ') . MODERATOR_CACHE_TABLE);
// We add moderators who have forum moderator permissions without an explicit ACL_NEVER setting
$hold_ary = $ug_id_ary = $sql_ary = array();
@@ -1981,7 +1977,7 @@ function cache_moderators()
AND ' . $db->sql_in_set('ug.user_id', $ug_id_ary) . "
AND ug.user_pending = 0
AND o.auth_option LIKE 'm\_%'" .
- ((SQL_LAYER == 'mssql' || SQL_LAYER == 'mssql_odbc') ? " ESCAPE '\\'" : ''),
+ (($db->sql_layer == 'mssql' || $db->sql_layer == 'mssql_odbc') ? " ESCAPE '\\'" : ''),
));
$result = $db->sql_query($sql);
@@ -2010,6 +2006,12 @@ function cache_moderators()
foreach ($hold_ary as $user_id => $forum_id_ary)
{
+ // Do not continue if user does not exist
+ if (!isset($usernames_ary[$user_id]))
+ {
+ continue;
+ }
+
foreach ($forum_id_ary as $forum_id => $auth_ary)
{
$sql_ary[] = array(
@@ -2051,6 +2053,12 @@ function cache_moderators()
foreach ($hold_ary as $group_id => $forum_id_ary)
{
+ // If there is no group, we do not assign it...
+ if (!isset($groupnames_ary[$group_id]))
+ {
+ continue;
+ }
+
foreach ($forum_id_ary as $forum_id => $auth_ary)
{
$flag = false;
@@ -2080,24 +2088,7 @@ function cache_moderators()
}
}
- if (sizeof($sql_ary))
- {
- switch (SQL_LAYER)
- {
- case 'mysql':
- case 'mysql4':
- case 'mysqli':
- $db->sql_query('INSERT INTO ' . MODERATOR_CACHE_TABLE . ' ' . $db->sql_build_array('MULTI_INSERT', $sql_ary));
- break;
-
- default:
- foreach ($sql_ary as $ary)
- {
- $db->sql_query('INSERT INTO ' . MODERATOR_CACHE_TABLE . ' ' . $db->sql_build_array('INSERT', $ary));
- }
- break;
- }
- }
+ $db->sql_multi_insert(MODERATOR_CACHE_TABLE, $sql_ary);
}
/**
@@ -2296,6 +2287,82 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id
}
/**
+* Update foes - remove moderators and administrators from foe lists...
+*/
+function update_foes()
+{
+ global $db, $auth;
+
+ $perms = array();
+ foreach ($auth->acl_get_list(false, array('a_', 'm_'), false) as $forum_id => $forum_ary)
+ {
+ foreach ($forum_ary as $auth_option => $user_ary)
+ {
+ $perms = array_merge($perms, $user_ary);
+ }
+ }
+
+ if (sizeof($perms))
+ {
+ $sql = 'DELETE FROM ' . ZEBRA_TABLE . '
+ WHERE ' . $db->sql_in_set('zebra_id', array_unique($perms)) . '
+ AND foe = 1';
+ $db->sql_query($sql);
+ }
+ unset($perms);
+}
+
+/**
+* Lists inactive users
+*/
+function view_inactive_users(&$users, &$user_count, $limit = 0, $offset = 0, $limit_days = 0, $sort_by = 'user_inactive_time DESC')
+{
+ global $db, $user;
+
+ $sql = 'SELECT user_id, username, user_regdate, user_lastvisit, user_inactive_time, user_inactive_reason
+ FROM ' . USERS_TABLE . '
+ WHERE user_type = ' . USER_INACTIVE .
+ (($limit_days) ? " AND user_inactive_time >= $limit_days" : '') . "
+ ORDER BY $sort_by";
+ $result = $db->sql_query_limit($sql, $limit, $offset);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $row['inactive_reason'] = $user->lang['INACTIVE_REASON_UNKNOWN'];
+ switch ($row['user_inactive_reason'])
+ {
+ case INACTIVE_REGISTER:
+ $row['inactive_reason'] = $user->lang['INACTIVE_REASON_REGISTER'];
+ break;
+
+ case INACTIVE_PROFILE:
+ $row['inactive_reason'] = $user->lang['INACTIVE_REASON_PROFILE'];
+ break;
+
+ case INACTIVE_MANUAL:
+ $row['inactive_reason'] = $user->lang['INACTIVE_REASON_MANUAL'];
+ break;
+
+ case INACTIVE_REMIND:
+ $row['inactive_reason'] = $user->lang['INACTIVE_REASON_REMIND'];
+ break;
+ }
+
+ $users[] = $row;
+ }
+
+ $sql = 'SELECT COUNT(user_id) AS user_count
+ FROM ' . USERS_TABLE . '
+ WHERE user_type = ' . USER_INACTIVE .
+ (($limit_days) ? " AND user_inactive_time >= $limit_days" : '');
+ $result = $db->sql_query($sql);
+ $user_count = (int) $db->sql_fetchfield('user_count');
+ $db->sql_freeresult($result);
+
+ return;
+}
+
+/**
* Lists warned users
*/
function view_warned_users(&$users, &$user_count, $limit = 0, $offset = 0, $limit_days = 0, $sort_by = 'user_warnings DESC')
@@ -2333,7 +2400,7 @@ function get_database_size()
$database_size = false;
// This code is heavily influenced by a similar routine in phpMyAdmin 2.2.0
- switch (SQL_LAYER)
+ switch ($db->sql_layer)
{
case 'mysql':
case 'mysql4':
@@ -2363,7 +2430,7 @@ function get_database_size()
{
if ($table_prefix != '')
{
- if (strstr($row['Name'], $table_prefix))
+ if (strpos($row['Name'], $table_prefix) !== false)
{
$database_size += $row['Data_length'] + $row['Index_length'];
}
@@ -2465,7 +2532,7 @@ function get_remote_file($host, $directory, $filename, &$errstr, &$errno, $port
}
else if (strpos($line, '404 Not Found') !== false)
{
- $errstr = $user->lang['FILE_NOT_FOUND'];
+ $errstr = $user->lang['FILE_NOT_FOUND'] . ': ' . $filename;
return false;
}
}
@@ -2509,7 +2576,7 @@ function tidy_warnings()
while ($row = $db->sql_fetchrow($result))
{
$warning_list[] = $row['warning_id'];
- $user_list[$row['user_id']] = isset($user_list[$row['user_id']]) ? $user_list[$row['user_id']]++ : 0;
+ $user_list[$row['user_id']] = isset($user_list[$row['user_id']]) ? $user_list[$row['user_id']]++ : 1;
}
$db->sql_freeresult($result);
@@ -2541,9 +2608,46 @@ function tidy_database()
{
global $db;
+ set_config('database_last_gc', time(), true);
+}
+
+/**
+* Add permission language - this will make sure custom files will be included
+*/
+function add_permission_language()
+{
+ global $user, $phpEx;
+ // First of all, our own file.
+ $user->add_lang('acp/permissions_phpbb');
- set_config('database_last_gc', time(), true);
+ $files_to_add = array();
+
+ // Now search in acp and mods folder for permissions_ files.
+ foreach (array('acp/', 'mods/') as $path)
+ {
+ $dh = opendir($user->lang_path . $path);
+
+ if ($dh !== false)
+ {
+ while (($file = readdir($dh)) !== false)
+ {
+ if (strpos($file, 'permissions_') === 0 && strpos($file, 'permissions_phpbb') === false && substr($file, -(strlen($phpEx) + 1)) === '.' . $phpEx)
+ {
+ $files_to_add[] = $path . substr($file, 0, -(strlen($phpEx) + 1));
+ }
+ }
+ closedir($dh);
+ }
+ }
+
+ if (!sizeof($files_to_add))
+ {
+ return false;
+ }
+
+ $user->add_lang($files_to_add);
+ return true;
}
?> \ No newline at end of file
diff --git a/phpBB/includes/functions_compress.php b/phpBB/includes/functions_compress.php
index 09ad1f4e8f..93a3547e21 100644
--- a/phpBB/includes/functions_compress.php
+++ b/phpBB/includes/functions_compress.php
@@ -322,8 +322,7 @@ class compress_zip extends compress
{
$name = str_replace('\\', '/', $name);
- $dtime = dechex($this->unix_to_dos_time($stat[9]));
- $hexdtime = pack('H8', $dtime[6] . $dtime[7] . $dtime[4] . $dtime[5] . $dtime[2] . $dtime[3] . $dtime[0] . $dtime[1]);
+ $hexdtime = pack('V', $this->unix_to_dos_time($stat[9]));
if ($is_dir)
{
@@ -479,17 +478,17 @@ class compress_tar extends compress
// Run through the file and grab directory entries
while ($buffer = $fzread($this->fp, 512))
{
- $tmp = unpack("A6magic", substr($buffer, 257, 6));
+ $tmp = unpack('A6magic', substr($buffer, 257, 6));
if (trim($tmp['magic']) == 'ustar')
{
- $tmp = unpack("A100name", $buffer);
+ $tmp = unpack('A100name', $buffer);
$filename = trim($tmp['name']);
- $tmp = unpack("Atype", substr($buffer, 156, 1));
+ $tmp = unpack('Atype', substr($buffer, 156, 1));
$filetype = (int) trim($tmp['type']);
- $tmp = unpack("A12size", substr($buffer, 124, 12));
+ $tmp = unpack('A12size', substr($buffer, 124, 12));
$filesize = octdec((int) trim($tmp['size']));
if ($filetype == 5)
@@ -509,12 +508,12 @@ class compress_tar extends compress
{
trigger_error("Could not create directory $folder");
}
- @chmod("$str", 0777);
+ @chmod($str, 0777);
}
}
}
}
- else if($filesize != 0 && ($filetype == 0 || $filetype == "\0"))
+ else if ($filesize != 0 && ($filetype == 0 || $filetype == "\0"))
{
// Write out the files
if (!($fp = fopen("$dst$filename", 'wb')))
@@ -524,7 +523,7 @@ class compress_tar extends compress
@chmod("$dst$filename", 0777);
// Grab the file contents
- fwrite($fp, $fzread($this->fp, $filesize + 512 - $filesize % 512), $filesize);
+ fwrite($fp, $fzread($this->fp, ($filesize + 511) &~ 511), $filesize);
fclose($fp);
}
}
@@ -543,7 +542,7 @@ class compress_tar extends compress
$fzwrite = ($this->isbz && function_exists('bzwrite')) ? 'bzwrite' : (($this->isgz && @extension_loaded('zlib')) ? 'gzwrite' : 'fwrite');
// Symbolizes that there are no more files
- $fzwrite($this->fp, pack("a512", ""));
+ $fzwrite($this->fp, str_repeat("\0", 512));
}
$fzclose($this->fp);
@@ -561,37 +560,37 @@ class compress_tar extends compress
// This is the header data, it contains all the info we know about the file or folder that we are about to archive
$header = '';
- $header .= pack("a100", $name); // file name
- $header .= pack("a8", sprintf("%07o", $stat[2])); // file mode
- $header .= pack("a8", sprintf("%07o", $stat[4])); // owner id
- $header .= pack("a8", sprintf("%07o", $stat[5])); // group id
- $header .= pack("a12", sprintf("%011o", $stat[7])); // file size
- $header .= pack("a12", sprintf("%011o", $stat[9])); // last mod time
+ $header .= pack('a100', $name); // file name
+ $header .= pack('a8', sprintf("%07o", $stat[2])); // file mode
+ $header .= pack('a8', sprintf("%07o", $stat[4])); // owner id
+ $header .= pack('a8', sprintf("%07o", $stat[5])); // group id
+ $header .= pack('a12', sprintf("%011o", $stat[7])); // file size
+ $header .= pack('a12', sprintf("%011o", $stat[9])); // last mod time
// Checksum
$checksum = 0;
for ($i = 0; $i < 148; $i++)
{
- $checksum += ord(substr($header, $i, 1));
+ $checksum += ord($header[$i]);
}
// We precompute the rest of the hash, this saves us time in the loop and allows us to insert our hash without resorting to string functions
$checksum += 2415 + (($is_dir) ? 53 : 0);
- $header .= pack("a8", sprintf("%07o", $checksum)); // checksum
- $header .= pack("a1", $typeflag); // link indicator
- $header .= pack("a100", ''); // name of linked file
- $header .= pack("a6", 'ustar'); // ustar indicator
- $header .= pack("a2", '00'); // ustar version
- $header .= pack("a32", 'Unknown'); // owner name
- $header .= pack("a32", 'Unknown'); // group name
- $header .= pack("a8", ''); // device major number
- $header .= pack("a8", ''); // device minor number
- $header .= pack("a155", ''); // filename prefix
- $header .= pack("a12", ''); // end
+ $header .= pack('a8', sprintf("%07o", $checksum)); // checksum
+ $header .= pack('a1', $typeflag); // link indicator
+ $header .= pack('a100', ''); // name of linked file
+ $header .= pack('a6', 'ustar'); // ustar indicator
+ $header .= pack('a2', '00'); // ustar version
+ $header .= pack('a32', 'Unknown'); // owner name
+ $header .= pack('a32', 'Unknown'); // group name
+ $header .= pack('a8', ''); // device major number
+ $header .= pack('a8', ''); // device minor number
+ $header .= pack('a155', ''); // filename prefix
+ $header .= pack('a12', ''); // end
// This writes the entire file in one shot. Header, followed by data and then null padded to a multiple of 512
- $fzwrite($this->fp, $header . (($stat[7] !== 0 && !$is_dir) ? $data . (($stat[7] % 512 > 0) ? str_repeat("\0", 512 - $stat[7] % 512) : '') : ''));
+ $fzwrite($this->fp, $header . (($stat[7] !== 0 && !$is_dir) ? $data . str_repeat("\0", (($stat[7] + 511) &~ 511) - $stat[7]) : ''));
unset($data);
}
diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php
index f6b73afa0e..cb8f963528 100644
--- a/phpBB/includes/functions_display.php
+++ b/phpBB/includes/functions_display.php
@@ -44,7 +44,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
}
// Display list of active topics for this category?
- $show_active = (isset($root_data['forum_flags']) && $root_data['forum_flags'] & 16) ? true : false;
+ $show_active = (isset($root_data['forum_flags']) && ($root_data['forum_flags'] & FORUM_FLAG_ACTIVE_TOPICS)) ? true : false;
$sql_from = FORUMS_TABLE . ' f ';
$lastread_select = $sql_lastread = '';
@@ -126,7 +126,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
}
// Display active topics from this forum?
- if ($show_active && $row['forum_type'] == FORUM_POST && $auth->acl_get('f_read', $forum_id) && ($row['forum_flags'] & 16))
+ if ($show_active && $row['forum_type'] == FORUM_POST && $auth->acl_get('f_read', $forum_id) && ($row['forum_flags'] & FORUM_FLAG_ACTIVE_TOPICS))
{
if (!isset($active_forum_ary['forum_topics']))
{
@@ -180,9 +180,11 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
if ($row['forum_last_post_time'] > $forum_rows[$parent_id]['forum_last_post_time'])
{
$forum_rows[$parent_id]['forum_last_post_id'] = $row['forum_last_post_id'];
+ $forum_rows[$parent_id]['forum_last_post_subject'] = $row['forum_last_post_subject'];
$forum_rows[$parent_id]['forum_last_post_time'] = $row['forum_last_post_time'];
$forum_rows[$parent_id]['forum_last_poster_id'] = $row['forum_last_poster_id'];
$forum_rows[$parent_id]['forum_last_poster_name'] = $row['forum_last_poster_name'];
+ $forum_rows[$parent_id]['forum_last_poster_colour'] = $row['forum_last_poster_colour'];
$forum_rows[$parent_id]['forum_id_last_post'] = $forum_id;
}
else
@@ -235,8 +237,10 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
'FORUM_ID' => $row['forum_id'],
'FORUM_NAME' => $row['forum_name'],
'FORUM_DESC' => generate_text_for_display($row['forum_desc'], $row['forum_desc_uid'], $row['forum_desc_bitfield'], $row['forum_desc_options']),
- 'FORUM_FOLDER_IMG' => ($row['forum_image']) ? '<img src="' . $phpbb_root_path . $row['forum_image'] . '" alt="' . $user->lang['FORUM_CAT'] . '" />' : '',
- 'FORUM_FOLDER_IMG_SRC' => ($row['forum_image']) ? $phpbb_root_path . $row['forum_image'] : '',
+ 'FORUM_FOLDER_IMG' => '',
+ 'FORUM_FOLDER_IMG_SRC' => '',
+ 'FORUM_IMAGE' => ($row['forum_image']) ? '<img src="' . $phpbb_root_path . $row['forum_image'] . '" alt="' . $user->lang['FORUM_CAT'] . '" />' : '',
+ 'FORUM_IMAGE_SRC' => ($row['forum_image']) ? $phpbb_root_path . $row['forum_image'] : '',
'U_VIEWFORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $row['forum_id']))
);
@@ -303,16 +307,18 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
// Create last post link information, if appropriate
if ($row['forum_last_post_id'])
{
+ $last_post_subject = $row['forum_last_post_subject'];
$last_post_time = $user->format_date($row['forum_last_post_time']);
$last_poster = ($row['forum_last_poster_name'] != '') ? $row['forum_last_poster_name'] : $user->lang['GUEST'];
+ $last_poster_colour = ($row['forum_last_poster_colour']) ? '#' . $row['forum_last_poster_colour'] : '';
$last_poster_url = ($row['forum_last_poster_id'] == ANONYMOUS) ? '' : append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&amp;u=' . $row['forum_last_poster_id']);
$last_post_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $row['forum_id_last_post'] . '&amp;p=' . $row['forum_last_post_id']) . '#p' . $row['forum_last_post_id'];
}
else
{
- $last_post_time = $last_poster = $last_poster_url = $last_post_url = '';
+ $last_post_subject = $last_post_time = $last_poster = $last_poster_colour = $last_poster_url = $last_post_url = '';
}
// Output moderator listing ... if applicable
@@ -324,7 +330,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
}
$l_post_click_count = ($row['forum_type'] == FORUM_LINK) ? 'CLICKS' : 'POSTS';
- $post_click_count = ($row['forum_type'] != FORUM_LINK || $row['forum_flags'] & 1) ? $row['forum_posts'] : '';
+ $post_click_count = ($row['forum_type'] != FORUM_LINK || $row['forum_flags'] & FORUM_FLAG_LINK_TRACK) ? $row['forum_posts'] : '';
$template->assign_block_vars('forumrow', array(
'S_IS_CAT' => false,
@@ -337,18 +343,22 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
'FORUM_DESC' => generate_text_for_display($row['forum_desc'], $row['forum_desc_uid'], $row['forum_desc_bitfield'], $row['forum_desc_options']),
'TOPICS' => $row['forum_topics'],
$l_post_click_count => $post_click_count,
- 'FORUM_FOLDER_IMG' => ($row['forum_image']) ? '<img src="' . $phpbb_root_path . $row['forum_image'] . '" alt="' . $user->lang[$folder_alt] . '" />' : $user->img($folder_image, $folder_alt),
- 'FORUM_FOLDER_IMG_SRC' => ($row['forum_image']) ? $phpbb_root_path . $row['forum_image'] : $user->img($folder_image, $folder_alt, false, '', 'src'),
+ 'FORUM_FOLDER_IMG' => $user->img($folder_image, $folder_alt),
+ 'FORUM_FOLDER_IMG_SRC' => $user->img($folder_image, $folder_alt, false, '', 'src'),
+ 'FORUM_IMAGE' => ($row['forum_image']) ? '<img src="' . $phpbb_root_path . $row['forum_image'] . '" alt="' . $user->lang[$folder_alt] . '" />' : '',
+ 'FORUM_IMAGE_SRC' => ($row['forum_image']) ? $phpbb_root_path . $row['forum_image'] : '',
'SUBFORUMS' => $subforums_list,
+ 'LAST_POST_SUBJECT' => censor_text($last_post_subject),
'LAST_POST_TIME' => $last_post_time,
'LAST_POSTER' => $last_poster,
+ 'LAST_POSTER_COLOUR' => $last_poster_colour,
'MODERATORS' => $moderators_list,
'L_SUBFORUM_STR' => $l_subforums,
'L_FORUM_FOLDER_ALT' => $folder_alt,
'L_MODERATOR_STR' => $l_moderator,
- 'U_VIEWFORUM' => ($row['forum_type'] != FORUM_LINK || $row['forum_flags'] & 1) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $row['forum_id']) : $row['forum_link'],
+ 'U_VIEWFORUM' => ($row['forum_type'] != FORUM_LINK || ($row['forum_flags'] & FORUM_FLAG_LINK_TRACK)) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $row['forum_id']) : $row['forum_link'],
'U_LAST_POSTER' => $last_poster_url,
'U_LAST_POST' => $last_post_url)
);
@@ -492,20 +502,6 @@ function get_forum_parents(&$forum_data)
}
/**
-* Get topic author
-*/
-function topic_topic_author(&$topic_row)
-{
- global $phpEx, $phpbb_root_path, $user;
-
- $topic_author = ($topic_row['topic_poster'] != ANONYMOUS) ? '<a href="' . append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&amp;u=' . $topic_row['topic_poster']) . '">' : '';
- $topic_author .= ($topic_row['topic_poster'] != ANONYMOUS) ? $topic_row['topic_first_poster_name'] : (($topic_row['topic_first_poster_name'] != '') ? $topic_row['topic_first_poster_name'] : $user->lang['GUEST']);
- $topic_author .= ($topic_row['topic_poster'] != ANONYMOUS) ? '</a>' : '';
-
- return $topic_author;
-}
-
-/**
* Generate topic pagination
*/
function topic_generate_pagination($replies, $url)
@@ -660,7 +656,7 @@ function topic_status(&$topic_row, $replies, $unread_topic, &$folder_img, &$fold
$folder = 'topic_read';
$folder_new = 'topic_unread';
- if ($config['hot_threshold'] && $replies >= $config['hot_threshold'])
+ if ($config['hot_threshold'] && $replies >= $config['hot_threshold'] && $topic_row['topic_status'] != ITEM_LOCKED)
{
$folder .= '_hot';
$folder_new .= '_hot';
@@ -706,14 +702,59 @@ function display_attachments($forum_id, $blockname, &$attachment_data, &$update_
'attachment_tpl' => 'attachment.html')
);
+ if (!sizeof($attachment_data))
+ {
+ return array();
+ }
+
if (empty($extensions) || !is_array($extensions))
{
- $extensions = array();
- $cache->obtain_attach_extensions($extensions);
+ $extensions = $cache->obtain_attach_extensions();
+ }
+
+ // Look for missing attachment informations...
+ $attach_ids = array();
+ foreach ($attachment_data as $pos => $attachment)
+ {
+ // If is_orphan is set, we need to retrieve the attachments again...
+ if (!isset($attachment['extension']) && !isset($attachment['physical_filename']))
+ {
+ $attach_ids[(int) $attachment['attach_id']] = $pos;
+ }
+ }
+
+ if (sizeof($attach_ids))
+ {
+ global $db;
+
+ $attachment_data = array();
+
+ $sql = 'SELECT *
+ FROM ' . ATTACHMENTS_TABLE . '
+ WHERE ' . $db->sql_in_set('attach_id', array_keys($attach_ids));
+ $result = $db->sql_query($sql);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ if (!isset($attach_ids[$row['attach_id']]))
+ {
+ continue;
+ }
+
+ $attachment_data[$attach_ids[$row['attach_id']]] = $row;
+ }
+ $db->sql_freeresult($result);
+
+ ksort($attachment_data);
}
foreach ($attachment_data as $attachment)
{
+ if (!sizeof($attachment))
+ {
+ continue;
+ }
+
// We need to reset/empty the _file block var, because this function might be called more than once
$template->destroy_block_vars('_file');
@@ -795,6 +836,8 @@ function display_attachments($forum_id, $blockname, &$attachment_data, &$update_
$download_link = (!$force_physical && $attachment['attach_id']) ? append_sid("{$phpbb_root_path}download.$phpEx", 'id=' . $attachment['attach_id'] . '&amp;f=' . $forum_id) : $filename;
+ $download_link_full = (!$force_physical && $attachment['attach_id']) ? generate_board_url() . append_sid("/download.$phpEx", 'id=' . $attachment['attach_id'] . '&amp;f=' . $forum_id) : generate_board_url() . $filename;
+
switch ($display_cat)
{
// Images
@@ -823,53 +866,51 @@ function display_attachments($forum_id, $blockname, &$attachment_data, &$update_
case ATTACHMENT_CATEGORY_WM:
$l_downloaded_viewed = $user->lang['VIEWED'];
- // The download link is slightly different, because somehow phpBB is not able to get the correct results if called
- // within the wmp object (cookies are not present).
- // $download_link = (!$force_physical && $attachment['attach_id']) ? generate_board_url() . append_sid("/download.$phpEx", 'id=' . $attachment['attach_id'] . '&f=' . $forum_id, false, $user->session_id) : $filename;
-
// Giving the filename directly because within the wm object all variables are in local context making it impossible
// to validate against a valid session (all params can differ)
$download_link = $filename;
$block_array += array(
+ 'U_FORUM' => generate_board_url(),
'S_WM_FILE' => true,
);
- // Viewed/Heared File ... update the download count (download.php is not called here)
+ // Viewed/Heared File ... update the download count
$update_count[] = $attachment['attach_id'];
break;
// Real Media Streams
case ATTACHMENT_CATEGORY_RM:
+ case ATTACHMENT_CATEGORY_QUICKTIME:
$l_downloaded_viewed = $user->lang['VIEWED'];
$block_array += array(
- 'S_RM_FILE' => true,
- 'U_FORUM' => generate_board_url(),
- 'ATTACH_ID' => $attachment['attach_id'],
+ 'S_RM_FILE' => ($display_cat == ATTACHMENT_CATEGORY_RM) ? true : false,
+ 'S_QUICKTIME_FILE' => ($display_cat == ATTACHMENT_CATEGORY_QUICKTIME) ? true : false,
+ 'U_FORUM' => generate_board_url(),
+ 'ATTACH_ID' => $attachment['attach_id'],
);
- // Viewed/Heared File ... update the download count (download.php is not called here)
+ // Viewed/Heared File ... update the download count
$update_count[] = $attachment['attach_id'];
break;
-/* // Macromedia Flash Files
- case SWF_CAT:
- list($width, $height) = swf_getdimension($filename);
+ // Macromedia Flash Files
+ case ATTACHMENT_CATEGORY_FLASH:
+ list($width, $height) = @getimagesize($filename);
$l_downloaded_viewed = $user->lang['VIEWED'];
- $download_link = $filename;
$block_array += array(
- 'S_SWF_FILE' => true,
+ 'S_FLASH_FILE' => true,
'WIDTH' => $width,
'HEIGHT' => $height,
);
- // Viewed/Heared File ... update the download count (download.php is not called here)
+ // Viewed/Heared File ... update the download count
$update_count[] = $attachment['attach_id'];
break;
-*/
+
default:
$l_downloaded_viewed = $user->lang['DOWNLOADED'];
@@ -933,7 +974,7 @@ function display_custom_bbcodes()
'BBCODE_NAME' => "'[{$row['bbcode_tag']}]', '[/" . str_replace('=', '', $row['bbcode_tag']) . "]'",
'BBCODE_ID' => $num_predefined_bbcodes + ($i * 2),
'BBCODE_TAG' => $row['bbcode_tag'],
- 'BBCODE_HELPLINE' => $row['bbcode_helpline'])
+ 'BBCODE_HELPLINE' => str_replace(array('&amp;', '&quot;', '&#039;', '&lt;', '&gt;'), array('\&', '\"', '\\\'', '<', '>'), $row['bbcode_helpline']))
);
$i++;
@@ -980,24 +1021,17 @@ function display_user_activity(&$userdata)
global $auth, $template, $db, $user;
global $phpbb_root_path, $phpEx;
- // Init new auth class if user is different
- if ($user->data['user_id'] != $userdata['user_id'])
- {
- $auth2 = new auth();
- $auth2->acl($userdata);
-
- $post_count_ary = $auth2->acl_getf('!f_postcount');
- }
- else
+ // Do not display user activity for users having more than 5000 posts...
+ if ($userdata['user_posts'] > 5000)
{
- $post_count_ary = $auth->acl_getf('!f_postcount');
+ return;
}
- $forum_read_ary = $auth->acl_getf('!f_read');
-
$forum_ary = array();
// Do not include those forums the user is not having read access to...
+ $forum_read_ary = $auth->acl_getf('!f_read');
+
foreach ($forum_read_ary as $forum_id => $not_allowed)
{
if ($not_allowed['f_read'])
@@ -1006,44 +1040,18 @@ function display_user_activity(&$userdata)
}
}
- // Now do not include those forums where the posts do not count...
- foreach ($post_count_ary as $forum_id => $not_counted)
- {
- if ($not_counted['f_postcount'])
- {
- $forum_ary[] = (int) $forum_id;
- }
- }
-
$forum_ary = array_unique($forum_ary);
- $post_count_sql = (sizeof($forum_ary)) ? 'AND ' . $db->sql_in_set('f.forum_id', $forum_ary, true) : '';
-
- // Firebird does not support ORDER BY on aliased columns
- // MySQL does not support ORDER BY on functions
- switch (SQL_LAYER)
- {
- case 'firebird':
- $sql = 'SELECT f.forum_id, COUNT(p.post_id) AS num_posts
- FROM ' . POSTS_TABLE . ' p, ' . FORUMS_TABLE . ' f
- WHERE p.poster_id = ' . $userdata['user_id'] . "
- AND f.forum_id = p.forum_id
- $post_count_sql
- GROUP BY f.forum_id
- ORDER BY COUNT(p.post_id) DESC";
- break;
-
- default:
- $sql = 'SELECT f.forum_id, COUNT(p.post_id) AS num_posts
- FROM ' . POSTS_TABLE . ' p, ' . FORUMS_TABLE . ' f
- WHERE p.poster_id = ' . $userdata['user_id'] . "
- AND f.forum_id = p.forum_id
- $post_count_sql
- GROUP BY f.forum_id
- ORDER BY num_posts DESC";
- break;
- }
-
- $result = $db->sql_query_limit($sql, 1);
+ $forum_sql = (sizeof($forum_ary)) ? 'AND ' . $db->sql_in_set('forum_id', $forum_ary, true) : '';
+
+ // Obtain active forum
+ $sql = 'SELECT forum_id, COUNT(post_id) AS num_posts
+ FROM ' . POSTS_TABLE . '
+ WHERE poster_id = ' . $userdata['user_id'] . "
+ AND post_postcount = 1
+ $forum_sql
+ GROUP BY forum_id
+ ORDER BY num_posts DESC";
+ $result = $db->sql_query_limit($sql, 1, 0, 3600);
$active_f_row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
@@ -1057,34 +1065,15 @@ function display_user_activity(&$userdata)
$db->sql_freeresult($result);
}
- // Firebird does not support ORDER BY on aliased columns
- // MySQL does not support ORDER BY on functions
- switch (SQL_LAYER)
- {
- case 'firebird':
- $sql = 'SELECT t.topic_id, COUNT(p.post_id) AS num_posts
- FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t, ' . FORUMS_TABLE . ' f
- WHERE p.poster_id = ' . $userdata['user_id'] . "
- AND t.topic_id = p.topic_id
- AND f.forum_id = t.forum_id
- $post_count_sql
- GROUP BY t.topic_id
- ORDER BY COUNT(p.post_id) DESC";
- break;
-
- default:
- $sql = 'SELECT t.topic_id, COUNT(p.post_id) AS num_posts
- FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t, ' . FORUMS_TABLE . ' f
- WHERE p.poster_id = ' . $userdata['user_id'] . "
- AND t.topic_id = p.topic_id
- AND f.forum_id = t.forum_id
- $post_count_sql
- GROUP BY t.topic_id
- ORDER BY num_posts DESC";
- break;
- }
-
- $result = $db->sql_query_limit($sql, 1);
+ // Obtain active topic
+ $sql = 'SELECT topic_id, COUNT(post_id) AS num_posts
+ FROM ' . POSTS_TABLE . '
+ WHERE poster_id = ' . $userdata['user_id'] . "
+ AND post_postcount = 1
+ $forum_sql
+ GROUP BY topic_id
+ ORDER BY num_posts DESC";
+ $result = $db->sql_query_limit($sql, 1, 0, 3600);
$active_t_row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
@@ -1127,7 +1116,8 @@ function display_user_activity(&$userdata)
'ACTIVE_TOPIC_POSTS' => ($active_t_count == 1) ? sprintf($user->lang['USER_POST'], 1) : sprintf($user->lang['USER_POSTS'], $active_t_count),
'ACTIVE_TOPIC_PCT' => sprintf($user->lang['POST_PCT_ACTIVE'], $active_t_pct),
'U_ACTIVE_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $active_f_id),
- 'U_ACTIVE_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=' . $active_t_id))
+ 'U_ACTIVE_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=' . $active_t_id),
+ 'S_SHOW_ACTIVITY' => true)
);
}
diff --git a/phpBB/includes/functions_jabber.php b/phpBB/includes/functions_jabber.php
index d98293dd0f..726985e631 100644
--- a/phpBB/includes/functions_jabber.php
+++ b/phpBB/includes/functions_jabber.php
@@ -3,29 +3,29 @@
*
* @package phpBB3
* @version $Id$
-* @copyright (c) 2005 phpBB Group
+* @copyright (c) 2006 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
/**
*
-* Class.Jabber.PHP v0.4
-* (c) 2002 Carlo "Gossip" Zottmann
-* http://phpjabber.g-blog.net *** gossip@jabber.g-blog.net
+* Class.Jabber.PHP v0.4.2
+* (c) 2004 Nathan "Fritzy" Fritz
+* http://cjphp.netflint.net *** fritzy@netflint.net
*
-* The FULL documentation and examples for this software can be found at
-* http://phpjabber.g-blog.net (not many doc comments in here, sorry)
+* This is a bugfix version, specifically for those who can't get
+* 0.4 to work on Jabberd2 servers.
*
-* last modified: 27.04.2003 13:01:53 CET
-*
-* Modified by members of the phpBB Group
+* last modified: 24.03.2004 13:01:53
+*
+* Modified by phpBB Development Team
+* version: v0.4.3a
*
* @package phpBB3
*/
class jabber
{
- var $encoding;
var $server;
var $port;
var $username;
@@ -37,13 +37,14 @@ class jabber
var $delay_disconnect;
var $stream_id;
- var $roster;
+
+ var $enable_logging;
+ var $log_array;
var $iq_sleep_timer;
var $last_ping_time;
var $packet_queue;
- var $subscription_queue;
var $iq_version_name;
var $iq_version_os;
@@ -61,19 +62,24 @@ class jabber
/**
* Constructor
*/
- function jabber()
+ function jabber($server, $port, $username, $password, $resource)
{
- $this->port = '5222';
- $this->resource = NULL;
- $this->packet_queue = $this->subscription_queue = array();
- $this->iq_sleep_timer = $this->delay_disconnect = 1;
+ $this->server = ($server) ? $server : 'localhost';
+ $this->port = ($port) ? $port : '5222';
+ $this->username = $username;
+ $this->password = $password;
+ $this->resource = ($resource) ? $resource : NULL;
- $this->encoding = 'UTF-8';
+ $this->enable_logging = true;
+ $this->log_array = array();
+
+ $this->packet_queue = array();
+ $this->iq_sleep_timer = $this->delay_disconnect = 1;
$this->returned_keep_alive = true;
$this->txnid = 0;
- $this->iq_version_name = "Class.Jabber.PHP -- http://phpjabber.g-blog.net -- by Carlo 'Gossip' Zottmann, gossip@jabber.g-blog.net";
+ $this->iq_version_name = "Class.Jabber.PHP -- http://cjphp.netflint.net -- by Nathan 'Fritzy' Fritz, fritz@netflint.net";
$this->iq_version_version = '0.4';
$this->iq_version_os = $_SERVER['SERVER_SOFTWARE'];
@@ -107,7 +113,7 @@ class jabber
if ($this->connector->open_socket($this->server, $this->port))
{
$this->send_packet("<?xml version='1.0' encoding='UTF-8' ?" . ">\n");
- $this->send_packet("<stream:stream to='{$this->server}' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>\n");
+ $this->send_packet("<stream:stream to='{$this->server}' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>\n");
sleep(2);
@@ -118,11 +124,13 @@ class jabber
}
else
{
+ $this->add_to_log('ERROR: connect() #1');
return false;
}
}
else
{
+ $this->add_to_log('ERROR: connect() #2');
return false;
}
}
@@ -142,55 +150,12 @@ class jabber
}
/**
- * Cruise Control
- */
- function cruise_control($seconds = -1)
- {
- $count = 0;
-
- while ($count != $seconds)
- {
- $this->listen();
-
- do
- {
- $packet = $this->get_first_from_queue();
-
- if ($packet)
- {
- $this->call_handler($packet);
- }
- }
- while (sizeof($this->packet_queue) > 1);
-
- $count += 0.25;
- usleep(250000);
-
- if ($this->last_ping_time != date('H:i'))
- {
- // Modified by Nathan Fritz
- if ($this->returned_keep_alive == false)
- {
- $this->connected = false;
- //EVENT: Disconnected
- }
-
- $this->returned_keep_alive = false;
- $this->keep_alive_id = 'keep_alive_' . time();
- $this->send_packet("<iq id='{$this->keep_alive_id}'/>", 'cruise_control');
- $this->last_ping_time = date('H:i');
- }
- }
-
- return true;
- }
-
- /**
* Send authentication request
*/
function send_auth()
{
$this->auth_id = 'auth_' . md5(time() . $_SERVER['REMOTE_ADDR']);
+ $this->resource = ($this->resource != NULL) ? $this->resource : ('Class.Jabber.PHP ' . md5($this->auth_id));
$this->jid = "{$this->username}@{$this->server}/{$this->resource}";
// request available authentication methods
@@ -200,6 +165,7 @@ class jabber
// was a result returned?
if ($this->get_info_from_iq_type($packet) == 'result' && $this->get_info_from_iq_id($packet) == $this->auth_id)
{
+ // yes, now check for auth method availability in descending order (best to worst)
if (isset($packet['iq']['#']['query'][0]['#']['sequence'][0]['#']) && isset($packet['iq']['#']['query'][0]['#']['token'][0]['#']))
{
// auth_0k
@@ -215,10 +181,16 @@ class jabber
// plain text
return $this->_sendauth_plaintext();
}
+ else
+ {
+ $this->add_to_log('ERROR: send_auth() #2 - No auth method available!');
+ return false;
+ }
}
else
{
// no result returned
+ $this->add_to_log('ERROR: send_auth() #1');
return false;
}
}
@@ -322,86 +294,15 @@ class jabber
{
$xml = trim($xml);
- return ($this->connector->write_to_socket($xml)) ? true : false;
- }
-
- /**
- * get the transport registration fields
- * method written by Steve Blinch, http://www.blitzaffe.com
- */
- function transport_registration_details($transport)
- {
- $this->txnid++;
- $packet = $this->send_iq($transport, 'get', "reg_{$this->txnid}", "jabber:iq:register", NULL, $this->jid);
-
- if ($packet)
+ if ($this->connector->write_to_socket($xml))
{
- $res = array();
-
- foreach ($packet['iq']['#']['query'][0]['#'] as $element => $data)
- {
- if ($element != 'instructions' && $element != 'key')
- {
- $res[] = $element;
- }
- }
-
- return $res;
- }
- else
- {
- return 3;
- }
- }
-
- /**
- * register with the transport
- * method written by Steve Blinch, http://www.blitzaffe.com
- */
- function transport_registration($transport, $details)
- {
- $this->txnid++;
- $packet = $this->send_iq($transport, 'get', "reg_{$this->txnid}", "jabber:iq:register", NULL, $this->jid);
-
- if ($packet)
- {
- // just in case a key was passed back from the server
- $key = $this->get_info_from_iq_key($packet);
- unset($packet);
-
- $payload = ($key) ? "<key>$key</key>\n" : '';
- foreach ($details as $element => $value)
- {
- $payload .= "<$element>$value</$element>\n";
- }
-
- $packet = $this->send_iq($transport, 'set', "reg_{$this->txnid}", "jabber:iq:register", $payload);
-
- if ($this->get_info_from_iq_type($packet) == 'result')
- {
- if (isset($packet['iq']['#']['query'][0]['#']['registered'][0]['#']))
- {
- $return_code = 1;
- }
- else
- {
- $return_code = 2;
- }
- }
- else if ($this->get_info_from_iq_type($packet) == 'error')
- {
- if (isset($packet['iq']['#']['error'][0]['#']))
- {
- $return_code = "Error " . $packet['iq']['#']['error'][0]['@']['code'] . ": " . $packet['iq']['#']['error'][0]['#'];
- // ERROR: TransportRegistration()
- }
- }
-
- return $return_code;
+ $this->add_to_log('SEND: ' . $xml);
+ return true;
}
else
{
- return 3;
+ $this->add_to_log('ERROR: send_packet() #1');
+ return false;
}
}
@@ -421,11 +322,12 @@ class jabber
if ($incoming != '')
{
+ $this->add_to_log('RECV: ' . $incoming);
$temp = $this->_split_incoming($incoming);
- for ($a = 0, $size = sizeof($temp); $a < $size; $a++)
+ for ($i = 0, $size = sizeof($temp); $i < $size; $i++)
{
- $this->packet_queue[] = $this->xmlize($temp[$a]);
+ $this->packet_queue[] = $this->xmlize($temp[$i]);
}
}
@@ -454,16 +356,15 @@ class jabber
}
$this->_array_xmlspecialchars($content);
- $this->_array_conv_utf8($content);
$xml = "<message to='$to' type='$type' id='$id'>\n";
- if (isset($content['subject']) && $content['subject'])
+ if (!empty($content['subject']))
{
$xml .= '<subject>' . $content['subject'] . "</subject>\n";
}
- if (isset($content['thread']) && $content['thread'])
+ if (!empty($content['thread']))
{
$xml .= '<thread>' . $content['thread'] . "</thread>\n";
}
@@ -472,10 +373,18 @@ class jabber
$xml .= $payload;
$xml .= "</message>\n";
- return ($this->send_packet($xml)) ? true : false;
+ if ($this->send_packet($xml))
+ {
+ return true;
+ }
+ else
+ {
+ $this->add_to_log('ERROR: send_message() #1');
+ }
}
else
{
+ $this->add_to_log('ERROR: send_message() #2');
return false;
}
}
@@ -496,7 +405,15 @@ class jabber
$xml .= ($status || $show || $priority) ? "</presence>\n" : '';
- return ($this->send_packet($xml)) ? true : false;
+ if ($this->send_packet($xml))
+ {
+ return true;
+ }
+ else
+ {
+ $this->add_to_log('ERROR: send_presence() #1');
+ return false;
+ }
}
/**
@@ -583,11 +500,63 @@ class jabber
else
{
$this->handler_not_implemented($packet);
+ $this->add_to_log("ERROR: call_handler() #1 - neither method nor function $funcmeth() available");
}
}
}
/**
+ * Cruise Control
+ */
+ function cruise_control($seconds = -1)
+ {
+ $count = 0;
+
+ while ($count != $seconds)
+ {
+ $this->listen();
+
+ do
+ {
+ $packet = $this->get_first_from_queue();
+
+ if ($packet)
+ {
+ $this->call_handler($packet);
+ }
+ }
+ while (sizeof($this->packet_queue) > 1);
+
+ $count += 0.25;
+ usleep(250000);
+
+ if (($this->last_ping_time + 180) < time())
+ {
+ // Modified by Nathan Fritz
+ if ($this->returned_keep_alive == false)
+ {
+ $this->connected = false;
+ $this->add_to_log('EVENT: Disconnected');
+ }
+
+ if ($this->returned_keep_alive == true)
+ {
+ $this->connected = true;
+ }
+
+ $this->returned_keep_alive = false;
+
+ $this->keep_alive_id = 'keep_alive_' . time();
+ // $this->send_packet("<iq id='{$this->keep_alive_id}'/>", 'cruise_control');
+ $this->send_packet("<iq type='get' from='{$this->username}@{$this->server}/{$this->resource}' to='{$this->server}' id='{$this->keep_alive_id}'><query xmlns='jabber:iq:time' /></iq>");
+ $this->last_ping_time = time();
+ }
+ }
+
+ return true;
+ }
+
+ /**
* Send iq
*/
function send_iq($to = NULL, $type = 'get', $id = NULL, $xmlns = NULL, $payload = NULL, $from = NULL)
@@ -596,12 +565,13 @@ class jabber
{
unset($type);
+ $this->add_to_log("ERROR: send_iq() #2 - type must be 'get', 'set', 'result' or 'error'");
return false;
}
else if ($id && $xmlns)
{
$xml = "<iq type='$type' id='$id'";
- $xml .= ($to) ? " to='$to'" : '';
+ $xml .= ($to) ? " to='" . htmlspecialchars($to) . "'" : '';
$xml .= ($from) ? " from='$from'" : '';
$xml .= ">
<query xmlns='$xmlns'>
@@ -617,17 +587,116 @@ class jabber
}
else
{
+ $this->add_to_log('ERROR: send_iq() #1 - to, id and xmlns are mandatory');
return false;
}
}
+ /**
+ * get the transport registration fields
+ * method written by Steve Blinch, http://www.blitzaffe.com
+ */
+ function transport_registration_details($transport)
+ {
+ $this->txnid++;
+ $packet = $this->send_iq($transport, 'get', "reg_{$this->txnid}", 'jabber:iq:register', NULL, $this->jid);
+
+ if ($packet)
+ {
+ $res = array();
+
+ foreach ($packet['iq']['#']['query'][0]['#'] as $element => $data)
+ {
+ if ($element != 'instructions' && $element != 'key')
+ {
+ $res[] = $element;
+ }
+ }
+
+ return $res;
+ }
+ else
+ {
+ return 3;
+ }
+ }
+
+ /**
+ * register with the transport
+ * method written by Steve Blinch, http://www.blitzaffe.com
+ */
+ function transport_registration($transport, $details)
+ {
+ $this->txnid++;
+ $packet = $this->send_iq($transport, 'get', "reg_{$this->txnid}", 'jabber:iq:register', NULL, $this->jid);
+
+ if ($packet)
+ {
+ // just in case a key was passed back from the server
+ $key = $this->get_info_from_iq_key($packet);
+ unset($packet);
+
+ $payload = ($key) ? "<key>$key</key>\n" : '';
+ foreach ($details as $element => $value)
+ {
+ $payload .= "<$element>$value</$element>\n";
+ }
+
+ $packet = $this->send_iq($transport, 'set', "reg_{$this->txnid}", 'jabber:iq:register', $payload);
+
+ if ($this->get_info_from_iq_type($packet) == 'result')
+ {
+ $return_code = (isset($packet['iq']['#']['query'][0]['#']['registered'][0]['#'])) ? 1 : 2;
+ }
+ else if ($this->get_info_from_iq_type($packet) == 'error')
+ {
+ if (isset($packet['iq']['#']['error'][0]['#']))
+ {
+ $return_code = 'Error ' . $packet['iq']['#']['error'][0]['@']['code'] . ': ' . $packet['iq']['#']['error'][0]['#'];
+ $this->add_to_log('ERROR: transport_registration()');
+ }
+ }
+
+ return $return_code;
+ }
+ else
+ {
+ return 3;
+ }
+ }
+
+ /**
+ * Return log
+ */
+ function get_log()
+ {
+ if ($this->enable_logging && sizeof($this->log_array))
+ {
+ return implode("\n\n", $this->log_array);
+ }
+
+ return '';
+ }
+
+ /**
+ * Add information to log
+ */
+ function add_to_log($string)
+ {
+ if ($this->enable_logging)
+ {
+ $this->log_array[] = htmlspecialchars($string);
+ }
+ }
+
+
// ======================================================================
// private methods
// ======================================================================
/**
* Send auth
- * @access: private
+ * @access private
*/
function _sendauth_ok($zerok_token, $zerok_sequence)
{
@@ -638,7 +707,7 @@ class jabber
$zerok_hash = sha1($zerok_hash . $zerok_token);
// repeat as often as needed
- for ($a = 0; $a < $zerok_sequence; $a++)
+ for ($i = 0; $i < $zerok_sequence; $i++)
{
$zerok_hash = sha1($zerok_hash);
}
@@ -650,12 +719,20 @@ class jabber
$packet = $this->send_iq(NULL, 'set', $this->auth_id, 'jabber:iq:auth', $payload);
// was a result returned?
- return ($this->get_info_from_iq_type($packet) == 'result' && $this->get_info_from_iq_id($packet) == $this->auth_id) ? true : false;
+ if ($this->get_info_from_iq_type($packet) == 'result' && $this->get_info_from_iq_id($packet) == $this->auth_id)
+ {
+ return true;
+ }
+ else
+ {
+ $this->add_to_log('ERROR: _sendauth_ok() #1');
+ return false;
+ }
}
/**
* Send auth digest
- * @access: private
+ * @access private
*/
function _sendauth_digest()
{
@@ -666,12 +743,20 @@ class jabber
$packet = $this->send_iq(NULL, 'set', $this->auth_id, 'jabber:iq:auth', $payload);
// was a result returned?
- return ($this->get_info_from_iq_type($packet) == 'result' && $this->get_info_from_iq_id($packet) == $this->auth_id) ? true : false;
+ if ($this->get_info_from_iq_type($packet) == 'result' && $this->get_info_from_iq_id($packet) == $this->auth_id)
+ {
+ return true;
+ }
+ else
+ {
+ $this->add_to_log('ERROR: _sendauth_digest() #1');
+ return false;
+ }
}
/**
* Send auth plain
- * @access: private
+ * @access private
*/
function _sendauth_plaintext()
{
@@ -682,12 +767,20 @@ class jabber
$packet = $this->send_iq(NULL, 'set', $this->auth_id, 'jabber:iq:auth', $payload);
// was a result returned?
- return ($this->get_info_from_iq_type($packet) == 'result' && $this->get_info_from_iq_id($packet) == $this->auth_id) ? true : false;
+ if ($this->get_info_from_iq_type($packet) == 'result' && $this->get_info_from_iq_id($packet) == $this->auth_id)
+ {
+ return true;
+ }
+ else
+ {
+ $this->add_to_log('ERROR: _sendauth_plaintext() #1');
+ return false;
+ }
}
/**
* Listen on socket
- * @access: private
+ * @access private
*/
function _listen_incoming()
{
@@ -699,12 +792,18 @@ class jabber
}
$incoming = trim($incoming);
+
+ if ($incoming != '')
+ {
+ $this->add_to_log('RECV: ' . $incoming);
+ }
+
return $this->xmlize($incoming);
}
/**
* Check if connected
- * @access: private
+ * @access private
*/
function _check_connected()
{
@@ -712,45 +811,87 @@ class jabber
if (is_array($incoming_array))
{
- if ($incoming_array['stream:stream']['@']['from'] == $this->server
- && $incoming_array['stream:stream']['@']['xmlns'] == 'jabber:client'
- && $incoming_array['stream:stream']['@']['xmlns:stream'] == 'http://etherx.jabber.org/streams')
+ if ($incoming_array['stream:stream']['@']['from'] == $this->server && $incoming_array['stream:stream']['@']['xmlns'] == 'jabber:client' && $incoming_array['stream:stream']['@']['xmlns:stream'] == 'http://etherx.jabber.org/streams')
{
$this->stream_id = $incoming_array['stream:stream']['@']['id'];
- return true;
+ if (!empty($incoming_array['stream:stream']['#']['stream:features'][0]['#']['starttls'][0]['@']['xmlns']) && $incoming_array['stream:stream']['#']['stream:features'][0]['#']['starttls'][0]['@']['xmlns'] == 'urn:ietf:params:xml:ns:xmpp-tls')
+ {
+ return $this->_starttls();
+ }
+ else
+ {
+ return true;
+ }
}
else
{
+ $this->add_to_log('ERROR: _check_connected() #1');
return false;
}
}
else
{
+ $this->add_to_log('ERROR: _check_connected() #2');
return false;
}
}
/**
- * Split incoming packet
- * @access: private
+ * Start TLS/SSL session if supported (PHP5.1)
+ * @access private
*/
- function _split_incoming($incoming)
+ function _starttls()
{
- $temp = preg_split('#<(message|iq|presence|stream)#', $incoming, -1, PREG_SPLIT_DELIM_CAPTURE);
- $array = array();
+ if (!function_exists('stream_socket_enable_crypto') || !function_exists('stream_get_meta_data') || !function_exists('socket_set_blocking'))
+ {
+ $this->add_to_log('WARNING: TLS is not available');
+ return true;
+ }
- for ($a = 1; $a < sizeof($temp); $a = $a + 2)
+ $this->send_packet("<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>\n");
+ sleep(2);
+ $incoming_array = $this->_listen_incoming();
+
+ if (!is_array($incoming_array))
{
- $array[] = '<' . $temp[$a] . $temp[($a + 1)];
+ $this->add_to_log('ERROR: _starttls() #1');
+ return false;
}
- return $array;
+ if ($incoming_array['proceed']['@']['xmlns'] != 'urn:ietf:params:xml:ns:xmpp-tls')
+ {
+ $this->add_to_log('ERROR: _starttls() #2');
+ return false;
+ }
+
+ $meta = stream_get_meta_data($this->connector->active_socket);
+ socket_set_blocking($this->connector->active_socket, 1);
+
+ if (!stream_socket_enable_crypto($this->connector->active_socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT))
+ {
+ socket_set_blocking($this->connector->active_socket, $meta['blocked']);
+ $this->add_to_log('ERROR: _starttls() #3');
+ return false;
+ }
+ socket_set_blocking($this->connector->active_socket, $meta['blocked']);
+
+ $this->send_packet("<?xml version='1.0' encoding='UTF-8' ?" . ">\n");
+ $this->send_packet("<stream:stream to='{$this->server}' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>\n");
+ sleep(2);
+
+ if (!$this->_check_connected())
+ {
+ $this->add_to_log('ERROR: _starttls() #4');
+ return false;
+ }
+
+ return true;
}
/**
* Get packet type
- * @access: private
+ * @access private
*/
function _get_packet_type($packet = NULL)
{
@@ -764,98 +905,52 @@ class jabber
}
/**
- * Recursively prepares the strings in an array to be used in XML data.
- * @access: private
+ * Split incoming packet
+ * @access private
*/
- function _array_xmlspecialchars(&$array)
+ function _split_incoming($incoming)
{
- if (is_array($array))
+ $temp = preg_split('#<(message|iq|presence|stream)#', $incoming, -1, PREG_SPLIT_DELIM_CAPTURE);
+ $array = array();
+
+ for ($i = 1, $size = sizeof($temp); $i < $size; $i += 2)
{
- foreach ($array as $k => $v)
- {
- if (is_array($v))
- {
- $this->_array_xmlspecialchars($array[$k]);
- }
- else
- {
- $this->_xmlspecialchars($array[$k]);
- }
- }
+ $array[] = '<' . $temp[$i] . $temp[($i + 1)];
}
- }
- /**
- * Prepares a string for usage in XML data.
- * @access: private
- */
- function _xmlspecialchars(&$string)
- {
- // we only have a few entities in xml
- $string = str_replace(array('&', '>', '<', '"', '\''), array('&amp;', '&gt;', '&lt;', '&quot;', '&apos;'), $string);
+ return $array;
}
/**
- * Recursively converts all elements in an array to UTF-8 from the encoding stored in {@link encoding the encoding attribute}.
- * @access: private
+ * Recursively prepares the strings in an array to be used in XML data.
+ * @access private
*/
- function _array_conv_utf8(&$array)
+ function _array_xmlspecialchars(&$array)
{
- // no need to do anything if the encoding already is UTF-8
- if (strtoupper($this->encoding) == 'UTF-8')
- {
- return true;
- }
-
if (is_array($array))
{
foreach ($array as $k => $v)
{
if (is_array($v))
{
- $this->_array_conv_utf8($array[$k]);
+ $this->_array_xmlspecialchars($array[$k]);
}
else
{
- $this->_conv_utf8($array[$k]);
+ $this->_xmlspecialchars($array[$k]);
}
}
}
}
/**
- * Converts a string to utf8 encoding.
- *
- * @param string $string has to have the same encoding as {@link encoding the encoding attribute} is set to.
- *
- * @return boolean True on success, false on failure.
- *
- * @access: private
+ * Prepares a string for usage in XML data.
+ * @access private
*/
- function _conv_utf8(&$string)
+ function _xmlspecialchars(&$string)
{
- // no need to do anything if the encoding already is UTF-8
- if (strtoupper($this->encoding) == 'UTF-8')
- {
- return true;
- }
-
- // first try iconv then mb_convert_encoding and as a last fall back try recode_string
- if (function_exists('iconv') && (($string = iconv($this->encoding, 'UTF-8', $string)) !== false))
- {
- return true;
- }
- elseif (function_exists('mb_convert_encoding') && (($string = mb_convert_encoding($string, 'UTF-8', $this->encoding)) !== false))
- {
- return true;
- }
- elseif (function_exists('recode_string') && (($string = recode_string($this->encoding . '..UTF-8', $string)) !== false))
- {
- return true;
- }
-
- // if everything fails we will just have to live with what we have, good luck!
- return false;
+ // we only have a few entities in xml
+ $string = str_replace(array('&', '>', '<', '"', '\''), array('&amp;', '&gt;', '&lt;', '&quot;', '&apos;'), $string);
}
// ======================================================================
@@ -911,6 +1006,14 @@ class jabber
}
/**
+ * Get info from message (xmlns)
+ */
+ function get_info_from_message_xmlns($packet = NULL)
+ {
+ return (is_array($packet)) ? $packet['message']['#']['x'] : false;
+ }
+
+ /**
* Get info from message (error)
*/
function get_info_from_message_error($packet = NULL)
@@ -969,19 +1072,48 @@ class jabber
// ======================================================================
/**
- * return message (from)
+ * Message type normal
*/
function handler_message_normal($packet)
{
$from = $packet['message']['@']['from'];
+ $this->add_to_log("EVENT: Message (type normal) from $from");
+ }
+
+ /**
+ * Message type chat
+ */
+ function handler_message_chat($packet)
+ {
+ $from = $packet['message']['@']['from'];
+ $this->add_to_log("EVENT: Message (type chat) from $from");
+ }
+
+ /**
+ * Message type groupchat
+ */
+ function handler_message_groupchat($packet)
+ {
+ $from = $packet['message']['@']['from'];
+ $this->add_to_log("EVENT: Message (type groupchat) from $from");
+ }
+
+ /**
+ * Message type headline
+ */
+ function handler_message_headline($packet)
+ {
+ $from = $packet['message']['@']['from'];
+ $this->add_to_log("EVENT: Message (type headline) from $from");
}
/**
- * return error (from)
+ * Message type error
*/
function handler_message_error($packet)
{
$from = $packet['message']['@']['from'];
+ $this->add_to_log("EVENT: Message (type error) from $from");
}
// ======================================================================
@@ -989,6 +1121,42 @@ class jabber
// ======================================================================
/**
+ * application version updates
+ */
+ function handler_iq_jabber_iq_autoupdate($packet)
+ {
+ $from = $this->get_info_from_iq_from($packet);
+ $id = $this->get_info_from_iq_id($packet);
+
+ $this->send_error($from, $id, 501);
+ $this->add_to_log("EVENT: jabber:iq:autoupdate from $from");
+ }
+
+ /**
+ * interactive server component properties
+ */
+ function handler_iq_jabber_iq_agent($packet)
+ {
+ $from = $this->get_info_from_iq_from($packet);
+ $id = $this->get_info_from_iq_id($packet);
+
+ $this->send_error($from, $id, 501);
+ $this->add_to_log("EVENT: jabber:iq:agent from $from");
+ }
+
+ /**
+ * method to query interactive server components
+ */
+ function handler_iq_jabber_iq_agents($packet)
+ {
+ $from = $this->get_info_from_iq_from($packet);
+ $id = $this->get_info_from_iq_id($packet);
+
+ $this->send_error($from, $id, 501);
+ $this->add_to_log("EVENT: jabber:iq:agents from $from");
+ }
+
+ /**
* simple client authentication
*/
function handler_iq_jabber_iq_auth($packet)
@@ -997,6 +1165,31 @@ class jabber
$id = $this->get_info_from_iq_id($packet);
$this->send_error($from, $id, 501);
+ $this->add_to_log("EVENT: jabber:iq:auth from $from");
+ }
+
+ /**
+ * out of band data
+ */
+ function handler_iq_jabber_iq_oob($packet)
+ {
+ $from = $this->get_info_from_iq_from($packet);
+ $id = $this->get_info_from_iq_id($packet);
+
+ $this->send_error($from, $id, 501);
+ $this->add_to_log("EVENT: jabber:iq:oob from $from");
+ }
+
+ /**
+ * method to store private data on the server
+ */
+ function handler_iq_jabber_iq_private($packet)
+ {
+ $from = $this->get_info_from_iq_from($packet);
+ $id = $this->get_info_from_iq_id($packet);
+
+ $this->send_error($from, $id, 501);
+ $this->add_to_log("EVENT: jabber:iq:private from $from");
}
/**
@@ -1008,19 +1201,89 @@ class jabber
$id = $this->get_info_from_iq_id($packet);
$this->send_error($from, $id, 501);
+ $this->add_to_log("EVENT: jabber:iq:register from $from");
+ }
+
+ /**
+ * client roster management
+ */
+ function handler_iq_jabber_iq_roster($packet)
+ {
+ $from = $this->get_info_from_iq_from($packet);
+ $id = $this->get_info_from_iq_id($packet);
+
+ $this->send_error($from, $id, 501);
+ $this->add_to_log("EVENT: jabber:iq:roster from $from");
+ }
+
+ /**
+ * method for searching a user database
+ */
+ function handler_iq_jabber_iq_search($packet)
+ {
+ $from = $this->get_info_from_iq_from($packet);
+ $id = $this->get_info_from_iq_id($packet);
+
+ $this->send_error($from, $id, 501);
+ $this->add_to_log("EVENT: jabber:iq:search from $from");
}
/**
- * keepalive method, added by Nathan Fritz
+ * method for requesting the current time
*/
- function handler_iq_($packet)
+ function handler_iq_jabber_iq_time($packet)
{
if ($this->keep_alive_id == $this->get_info_from_iq_id($packet))
{
$this->returned_keep_alive = true;
+ $this->connected = true;
+
+ $this->add_to_log('EVENT: Keep-Alive returned, connection alive.');
+ }
+
+ $type = $this->get_info_from_iq_type($packet);
+ $from = $this->get_info_from_iq_from($packet);
+ $id = $this->get_info_from_iq_id($packet);
+ $id = ($id != '') ? $id : 'time_' . time();
+
+ if ($type == 'get')
+ {
+ $payload = '<utc>' . gmdate("Ydm\TH:i:s") . '</utc><tz>' . date('T') . '</tz><display>' . date("Y/d/m h:i:s A") . '</display>';
+ $this->send_iq($from, 'result', $id, 'jabber:iq:time', $payload);
}
+
+ $this->add_to_log("EVENT: jabber:iq:time (type $type) from $from");
+ }
+
+ /**
+ */
+ function handler_iq_error($packet)
+ {
+ // We'll do something with these later. This is a placeholder so that errors don't bounce back and forth.
+ }
+
+ /**
+ * method for requesting version
+ */
+ function handler_iq_jabber_iq_version($packet)
+ {
+ $type = $this->get_info_from_iq_type($packet);
+ $from = $this->get_info_from_iq_from($packet);
+ $id = $this->get_info_from_iq_id($packet);
+ $id = ($id != '') ? $id : 'version_' . time();
+
+ if ($type == 'get')
+ {
+ $payload = "<name>{$this->iq_version_name}</name>
+ <os>{$this->iq_version_os}</os>
+ <version>{$this->iq_version_version}</version>";
+
+ //$this->SendIq($from, 'result', $id, "jabber:iq:version", $payload);
+ }
+
+ $this->add_to_log("EVENT: jabber:iq:version (type $type) from $from -- DISABLED");
}
-
+
// ======================================================================
// Generic handlers
// ======================================================================
@@ -1035,28 +1298,34 @@ class jabber
$id = call_user_func(array(&$this, 'get_info_from_' . strtolower($packet_type) . '_id'), $packet);
$this->send_error($from, $id, 501);
+ $this->add_to_log("EVENT: Unrecognized <$packet_type/> from $from");
}
+ // ======================================================================
// Third party code
// m@d pr0ps to the coders ;)
+ // ======================================================================
/**
* xmlize()
- * (c) Hans Anderson / http://www.hansanderson.com/php/xml/
+ * @author Hans Anderson
+ * @copyright Hans Anderson / http://www.hansanderson.com/php/xml/
*/
- function xmlize($data)
+ function xmlize($data, $skip_white = 1, $encoding = 'UTF-8')
{
+ $data = trim($data);
+
$vals = $index = $array = array();
- $parser = @xml_parser_create();
- @xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
- @xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
- @xml_parse_into_struct($parser, $data, $vals, $index);
- @xml_parser_free($parser);
+ $parser = xml_parser_create($encoding);
+ xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
+ xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, $skip_white);
+ xml_parse_into_struct($parser, $data, $vals, $index);
+ xml_parser_free($parser);
$i = 0;
-
$tagname = $vals[$i]['tag'];
- $array[$tagname]['@'] = $vals[$i]['attributes'];
+
+ $array[$tagname]['@'] = (isset($vals[$i]['attributes'])) ? $vals[$i]['attributes'] : array();
$array[$tagname]['#'] = $this->_xml_depth($vals, $i);
return $array;
@@ -1064,47 +1333,51 @@ class jabber
/**
* _xml_depth()
- * (c) Hans Anderson / http://www.hansanderson.com/php/xml/
+ * @author Hans Anderson
+ * @copyright Hans Anderson / http://www.hansanderson.com/php/xml/
*/
function _xml_depth($vals, &$i)
{
$children = array();
- if (isset($vals[$i]['value']) && $vals[$i]['value'])
+ if (isset($vals[$i]['value']))
{
- array_push($children, trim($vals[$i]['value']));
+ array_push($children, $vals[$i]['value']);
}
while (++$i < sizeof($vals))
{
switch ($vals[$i]['type'])
{
- case 'cdata':
- array_push($children, trim($vals[$i]['value']));
- break;
+ case 'open':
- case 'complete':
- $tagname = $vals[$i]['tag'];
+ $tagname = (isset($vals[$i]['tag'])) ? $vals[$i]['tag'] : '';
$size = (isset($children[$tagname])) ? sizeof($children[$tagname]) : 0;
- $children[$tagname][$size]['#'] = (isset($vals[$i]['value'])) ? trim($vals[$i]['value']) : '';
- if (isset($vals[$i]['attributes']) && $vals[$i]['attributes'])
+
+ if (isset($vals[$i]['attributes']))
{
$children[$tagname][$size]['@'] = $vals[$i]['attributes'];
}
+
+ $children[$tagname][$size]['#'] = $this->_xml_depth($vals, $i);
+
break;
- case 'open':
+ case 'cdata':
+ array_push($children, $vals[$i]['value']);
+ break;
+
+ case 'complete':
+
$tagname = $vals[$i]['tag'];
$size = (isset($children[$tagname])) ? sizeof($children[$tagname]) : 0;
- if ($vals[$i]['attributes'])
+ $children[$tagname][$size]['#'] = (isset($vals[$i]['value'])) ? $vals[$i]['value'] : array();
+
+ if (isset($vals[$i]['attributes']))
{
$children[$tagname][$size]['@'] = $vals[$i]['attributes'];
- $children[$tagname][$size]['#'] = $this->_xml_depth($vals, $i);
- }
- else
- {
- $children[$tagname][$size]['#'] = $this->_xml_depth($vals, $i);
}
+
break;
case 'close':
@@ -1117,8 +1390,9 @@ class jabber
}
/**
- * traverse_xmlize()
- * (c) acebone@f2s.com, a HUGE help!
+ * TraverseXMLize()
+ * @author acebone@f2s.com
+ * @copyright acebone@f2s.com, a HUGE help!
*/
function traverse_xmlize($array, $arr_name = 'array', $level = 0)
{
@@ -1127,7 +1401,7 @@ class jabber
echo '<pre>';
}
- while (list($key, $val) = @each($array))
+ foreach ($array as $key => $val)
{
if (is_array($val))
{
@@ -1135,7 +1409,7 @@ class jabber
}
else
{
- echo '$' . $arr_name . '[' . $key . '] = "' . $val . "\"\n";
+ $GLOBALS['traverse_array'][] = '$' . $arr_name . '[' . $key . '] = "' . $val . "\"\n";
}
}
@@ -1143,117 +1417,13 @@ class jabber
{
echo '</pre>';
}
- }
-}
-
-/**
-* make_xml
-* Currently not in use
-* @package phpBB3
-class make_xml extends jabber
-{
- var $nodes;
-
- function make_xml()
- {
- $nodes = array();
- }
-
- function add_packet_details($string, $value = NULL)
- {
- if (preg_match('#\(([0-9]*)\)$#i', $string))
- {
- $string .= '/["#"]';
- }
-
- $temp = @explode('/', $string);
-
- for ($a = 0, $size = sizeof($temp); $a < $size; $a++)
- {
- $temp[$a] = preg_replace('#^[@]{1}([a-z0-9_]*)$#i', '["@"]["\1"]', $temp[$a]);
- $temp[$a] = preg_replace('#^([a-z0-9_]*)\(([0-9]*)\)$/i', '["\1"][\2]', $temp[$a]);
- $temp[$a] = preg_replace('#^([a-z0-9_]*)$#i', '["\1"]', $temp[$a]);
- }
-
- $node = implode('', $temp);
-
- // Yeahyeahyeah, I know it's ugly... get over it. ;)
- echo '$this->nodes' . $node . ' = "' . htmlspecialchars($value) . '";<br/>';
- eval('$this->nodes' . $node . ' = "' . htmlspecialchars($value) . '";');
- }
-
- function build_packet($array = NULL)
- {
- if (!$array)
- {
- $array = $this->nodes;
- }
-
- if (is_array($array))
- {
- array_multisort($array, SORT_ASC, SORT_STRING);
-
- foreach ($array as $key => $value)
- {
- if (is_array($value) && $key == '@')
- {
- foreach ($value as $subkey => $subvalue)
- {
- $subvalue = htmlspecialchars($subvalue);
- $text .= " $subkey='$subvalue'";
- }
-
- $text .= ">\n";
-
- }
- else if ($key == '#')
- {
- $text .= htmlspecialchars($value);
- }
- else if (is_array($value))
- {
- for ($a = 0, $size = sizeof($value); $a < $size; $a++)
- {
- $text .= "<$key";
-
- if (!$this->_preg_grep_keys('#^@#', $value[$a]))
- {
- $text .= '>';
- }
-
- $text .= $this->build_packet($value[$a]);
- $text .= "</$key>\n";
- }
- }
- else
- {
- $value = htmlspecialchars($value);
- $text .= "<$key>$value</$key>\n";
- }
- }
-
- return $text;
- }
-
- return false;
- }
- function _preg_grep_keys($pattern, $array)
- {
- foreach ($array as $key => $val)
- {
- if (preg_match($pattern, $key))
- {
- $newarray[$key] = $val;
- }
- }
- return (is_array($newarray)) ? $newarray : false;
+ return 1;
}
}
-*/
/**
-* connector
+* Jabber Connector
* @package phpBB3
*/
class cjp_standard_connector
@@ -1265,7 +1435,21 @@ class cjp_standard_connector
*/
function open_socket($server, $port)
{
- if ($this->active_socket = @fsockopen($server, $port, $err, $err2, 5))
+ if (function_exists('dns_get_record'))
+ {
+ $record = dns_get_record("_xmpp-client._tcp.$server", DNS_SRV);
+
+ if (!empty($record))
+ {
+ $server = $record[0]['target'];
+ $port = $record[0]['port'];
+ }
+ }
+
+ $errno = 0;
+ $errstr = '';
+
+ if ($this->active_socket = @fsockopen($server, $port, $errno, $errstr, 5))
{
@socket_set_blocking($this->active_socket, 0);
@socket_set_timeout($this->active_socket, 31536000);
@@ -1300,9 +1484,7 @@ class cjp_standard_connector
function read_from_socket($chunksize)
{
$buffer = @fread($this->active_socket, $chunksize);
-
- //$buffer = (STRIP) ? stripslashes($buffer) : $buffer;
- //@set_magic_quotes_runtime(get_magic_quotes_gpc());
+ $buffer = (STRIP) ? stripslashes($buffer) : $buffer;
return $buffer;
}
diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php
index 052f372443..75eda9b10c 100644
--- a/phpBB/includes/functions_messenger.php
+++ b/phpBB/includes/functions_messenger.php
@@ -14,7 +14,7 @@
*/
class messenger
{
- var $vars, $msg, $extra_headers, $replyto, $from, $subject, $encoding;
+ var $vars, $msg, $extra_headers, $replyto, $from, $subject;
var $addresses = array();
var $mail_priority = MAIL_NORMAL_PRIORITY;
@@ -44,8 +44,8 @@ class messenger
*/
function reset()
{
- $this->addresses = array();
- $this->vars = $this->msg = $this->extra_headers = $this->replyto = $this->from = $this->encoding = '';
+ $this->addresses = $this->extra_headers = array();
+ $this->vars = $this->msg = $this->replyto = $this->from = '';
$this->mail_priority = MAIL_NORMAL_PRIORITY;
}
@@ -118,7 +118,7 @@ class messenger
*/
function headers($headers)
{
- $this->extra_headers .= trim($headers) . "\n";
+ $this->extra_headers[] = trim($headers);
}
/**
@@ -189,24 +189,17 @@ class messenger
{
global $config, $user;
+ // We add some standard variables we always use, no need to specify them always
+ $this->vars['U_BOARD'] = (!isset($this->vars['U_BOARD'])) ? generate_board_url() : $this->vars['U_BOARD'];
+ $this->vars['EMAIL_SIG'] = (!isset($this->vars['EMAIL_SIG'])) ? str_replace('<br />', "\n", "-- \n" . htmlspecialchars_decode($config['board_email_sig'])) : $this->vars['EMAIL_SIG'];
+ $this->vars['SITENAME'] = (!isset($this->vars['SITENAME'])) ? htmlspecialchars_decode($config['sitename']) : $this->vars['SITENAME'];
+
// Escape all quotes, else the eval will fail.
$this->msg = str_replace ("'", "\'", $this->msg);
- $this->msg = preg_replace('#\{([a-z0-9\-_]*?)\}#is', "' . $\\1 . '", $this->msg);
-
- // Set vars
- foreach ($this->vars as $key => $val)
- {
- $$key = $val;
- }
+ $this->msg = preg_replace('#\{([a-z0-9\-_]*?)\}#is', "' . ((isset(\$this->vars['\\1'])) ? \$this->vars['\\1'] : '') . '", $this->msg);
eval("\$this->msg = '$this->msg';");
- // Clear vars
- foreach ($this->vars as $key => $val)
- {
- unset($$key);
- }
-
// We now try and pull a subject from the email body ... if it exists,
// do this here because the subject may contain a variable
$drop_header = '';
@@ -221,16 +214,6 @@ class messenger
$this->subject = (($this->subject != '') ? $this->subject : $user->lang['NO_SUBJECT']);
}
- if (preg_match('#^(Charset:(.*?))$#m', $this->msg, $match))
- {
- $this->encoding = (trim($match[2]) != '') ? trim($match[2]) : trim($user->lang['ENCODING']);
- $drop_header .= '[\r\n]*?' . preg_quote($match[1], '#');
- }
- else
- {
- $this->encoding = trim($user->lang['ENCODING']);
- }
-
if ($drop_header)
{
$this->msg = trim(preg_replace('#' . $drop_header . '#s', '', $this->msg));
@@ -291,6 +274,53 @@ class messenger
}
/**
+ * Return email header
+ */
+ function build_header($to, $cc, $bcc)
+ {
+ global $config;
+
+ $headers = array();
+
+ $headers[] = 'From: ' . $this->from;
+
+ if ($cc)
+ {
+ $headers[] = 'Cc: ' . $cc;
+ }
+
+ if ($bcc)
+ {
+ $headers[] = 'Bcc: ' . $bcc;
+ }
+
+ $headers[] = 'Reply-To: ' . $this->replyto;
+ $headers[] = 'Return-Path: <' . $config['board_email'] . '>';
+ $headers[] = 'Sender: <' . $config['board_email'] . '>';
+ $headers[] = 'MIME-Version: 1.0';
+ $headers[] = 'Message-ID: <' . md5(unique_id(time())) . '@' . $config['server_name'] . '>';
+ $headers[] = 'Date: ' . gmdate('D, d M Y H:i:s T', time());
+ $headers[] = 'Content-Type: text/plain; charset=UTF-8'; // format=flowed
+ $headers[] = 'Content-Transfer-Encoding: 8bit'; // 7bit
+
+ $headers[] = 'X-Priority: ' . $this->mail_priority;
+ $headers[] = 'X-MSMail-Priority: ' . (($this->mail_priority == MAIL_LOW_PRIORITY) ? 'Low' : (($this->mail_priority == MAIL_NORMAL_PRIORITY) ? 'Normal' : 'High'));
+ $headers[] = 'X-Mailer: PhpBB3';
+ $headers[] = 'X-MimeOLE: phpBB3';
+ $headers[] = 'X-phpBB-Origin: phpbb://' . str_replace(array('http://', 'https://'), array('', ''), generate_board_url());
+
+ // We use \n here instead of \r\n because our smtp mailer is adjusting it to \r\n automatically, whereby the php mail function only works
+ // if using \n.
+
+ if (sizeof($this->extra_headers))
+ {
+ $headers[] = implode("\n", $this->extra_headers);
+ }
+
+ return implode("\n", $headers);
+ }
+
+ /**
* Send out emails
*/
function msg_email()
@@ -313,8 +343,18 @@ class messenger
$use_queue = true;
}
- $to = $cc = $bcc = '';
+ if (empty($this->replyto))
+ {
+ $this->replyto = '<' . $config['board_email'] . '>';
+ }
+
+ if (empty($this->from))
+ {
+ $this->from = '<' . $config['board_email'] . '>';
+ }
+
// Build to, cc and bcc strings
+ $to = $cc = $bcc = '';
foreach ($this->addresses as $type => $address_ary)
{
if ($type == 'im')
@@ -324,40 +364,14 @@ class messenger
foreach ($address_ary as $which_ary)
{
- $$type .= (($$type != '') ? ', ' : '') . (($which_ary['name'] != '') ? '"' . mail_encode($which_ary['name'], $this->encoding) . '" <' . $which_ary['email'] . '>' : $which_ary['email']);
+ $$type .= (($$type != '') ? ', ' : '') . (($which_ary['name'] != '') ? '"' . mail_encode($which_ary['name']) . '" <' . $which_ary['email'] . '>' : $which_ary['email']);
}
}
- if (empty($this->replyto))
- {
- $this->replyto = '<' . $config['board_email'] . '>';
- }
-
- if (empty($this->from))
- {
- $this->from = '<' . $config['board_email'] . '>';
- }
-
// Build header
- $headers = 'From: ' . $this->from . "\n";
- $headers .= ($cc != '') ? "Cc: $cc\n" : '';
- $headers .= ($bcc != '') ? "Bcc: $bcc\n" : '';
- $headers .= 'Reply-to: ' . $this->replyto . "\n";
- $headers .= 'Return-Path: <' . $config['board_email'] . ">\n";
- $headers .= 'Sender: <' . $config['board_email'] . ">\n";
- $headers .= "MIME-Version: 1.0\n";
- $headers .= 'Message-ID: <' . md5(unique_id(time())) . "@" . $config['server_name'] . ">\n";
- $headers .= 'Date: ' . gmdate('D, d M Y H:i:s T', time()) . "\n";
- $headers .= "Content-type: text/plain; charset={$this->encoding}\n";
- $headers .= "Content-transfer-encoding: 8bit\n";
- $headers .= "X-Priority: {$this->mail_priority}\n";
- $headers .= 'X-MSMail-Priority: ' . (($this->mail_priority == MAIL_LOW_PRIORITY) ? 'Low' : (($this->mail_priority == MAIL_NORMAL_PRIORITY) ? 'Normal' : 'High')) . "\n";
- $headers .= "X-Mailer: PhpBB3\n";
- $headers .= "X-MimeOLE: phpBB3\n";
- $headers .= "X-phpBB-Origin: phpbb://" . str_replace(array('http://', 'https://'), array('', ''), generate_board_url()) . "\n";
- $headers .= ($this->extra_headers != '') ? $this->extra_headers : '';
-
- // Send message ... removed $this->encode() from subject for time being
+ $headers = $this->build_header($to, $cc, $bcc);
+
+ // Send message ...
if (!$use_queue)
{
$mail_to = ($to == '') ? 'Undisclosed-Recipient:;' : $to;
@@ -365,11 +379,11 @@ class messenger
if ($config['smtp_delivery'])
{
- $result = smtpmail($this->addresses, $this->subject, wordwrap($this->msg), $err_msg, $this->encoding, $headers);
+ $result = smtpmail($this->addresses, mail_encode($this->subject), wordwrap($this->msg), $err_msg, $headers);
}
else
{
- $result = @$config['email_function_name']($mail_to, $this->subject, implode("\n", preg_split("/\r?\n/", wordwrap($this->msg))), $headers);
+ $result = @$config['email_function_name']($mail_to, mail_encode($this->subject), implode("\n", preg_split("/\r?\n/", wordwrap($this->msg))), $headers);
}
if (!$result)
@@ -387,7 +401,6 @@ class messenger
'addresses' => $this->addresses,
'subject' => $this->subject,
'msg' => $this->msg,
- 'encoding' => $this->encoding,
'headers' => $headers)
);
}
@@ -428,14 +441,7 @@ class messenger
if (!$use_queue)
{
include_once($phpbb_root_path . 'includes/functions_jabber.'.$phpEx);
- $this->jabber = new jabber;
-
- $this->jabber->server = $config['jab_host'];
- $this->jabber->port = ($config['jab_port']) ? $config['jab_port'] : 5222;
- $this->jabber->username = $config['jab_username'];
- $this->jabber->password = $config['jab_password'];
- $this->jabber->resource = ($config['jab_resource']) ? $config['jab_resource'] : '';
- $this->jabber->encoding = $this->encoding;
+ $this->jabber = new jabber($config['jab_host'], $config['jab_port'], $config['jab_username'], $config['jab_password'], $config['jab_resource']);
if (!$this->jabber->connect())
{
@@ -548,7 +554,7 @@ class queue
}
$package_size = $data_ary['package_size'];
- $num_items = (sizeof($data_ary['data']) < $package_size) ? sizeof($data_ary['data']) : $package_size;
+ $num_items = (!$package_size || sizeof($data_ary['data']) < $package_size) ? sizeof($data_ary['data']) : $package_size;
switch ($object)
{
@@ -569,13 +575,7 @@ class queue
}
include_once($phpbb_root_path . 'includes/functions_jabber.'.$phpEx);
- $this->jabber = new jabber;
-
- $this->jabber->server = $config['jab_host'];
- $this->jabber->port = ($config['jab_port']) ? $config['jab_port'] : 5222;
- $this->jabber->username = $config['jab_username'];
- $this->jabber->password = $config['jab_password'];
- $this->jabber->resource = ($config['jab_resource']) ? $config['jab_resource'] : '';
+ $this->jabber = new jabber($config['jab_host'], $config['jab_port'], $config['jab_username'], $config['jab_password'], $config['jab_resource']);
if (!$this->jabber->connect())
{
@@ -607,7 +607,7 @@ class queue
$err_msg = '';
$to = (!$to) ? 'Undisclosed-Recipient:;' : $to;
- $result = ($config['smtp_delivery']) ? smtpmail($addresses, $subject, wordwrap($msg), $err_msg, $encoding, $headers) : @$config['email_function_name']($to, $subject, implode("\n", preg_split("/\r?\n/", wordwrap($msg))), $headers);
+ $result = ($config['smtp_delivery']) ? smtpmail($addresses, mail_encode($subject), wordwrap($msg), $err_msg, $headers) : @$config['email_function_name']($to, mail_encode($subject), implode("\n", preg_split("/\r?\n/", wordwrap($msg))), $headers);
if (!$result)
{
@@ -615,14 +615,19 @@ class queue
$message = 'Method: [ ' . (($config['smtp_delivery']) ? 'SMTP' : 'PHP') . ' ]<br /><br />' . $err_msg . '<br /><br /><u>CALLING PAGE</u><br /><br />' . ((!empty($_SERVER['PHP_SELF'])) ? $_SERVER['PHP_SELF'] : $_ENV['PHP_SELF']);
messenger::error('EMAIL', $message);
- continue 3;
+ continue 2;
}
break;
case 'jabber':
foreach ($addresses as $address)
{
- $this->jabber->send_message($address, 'normal', NULL, array('body' => $msg));
+ if ($this->jabber->send_message($address, 'normal', NULL, array('body' => $msg)) === false)
+ {
+ $message = 'Method: [ JABBER ]<br /><br />' . $this->jabber->get_log() . '<br /><br /><u>CALLING PAGE</u><br /><br />' . ((!empty($_SERVER['PHP_SELF'])) ? $_SERVER['PHP_SELF'] : $_ENV['PHP_SELF']);
+ messenger::error('JABBER', $message);
+ continue 3;
+ }
}
break;
}
@@ -706,7 +711,7 @@ class queue
/**
* Format array
- * @access: private
+ * @access private
*/
function format_array($array)
{
@@ -739,7 +744,7 @@ class queue
/**
* Replacement or substitute for PHP's mail command
*/
-function smtpmail($addresses, $subject, $message, &$err_msg, $encoding, $headers = '')
+function smtpmail($addresses, $subject, $message, &$err_msg, $headers = '')
{
global $config, $user;
@@ -790,10 +795,13 @@ function smtpmail($addresses, $subject, $message, &$err_msg, $encoding, $headers
$mail_rcpt = $mail_to = $mail_cc = array();
// Build correct addresses for RCPT TO command and the client side display (TO, CC)
- foreach ($addresses['to'] as $which_ary)
+ if (isset($addresses['to']) && sizeof($addresses['to']))
{
- $mail_to[] = ($which_ary['name'] != '') ? mail_encode(trim($which_ary['name']), $encoding) . ' <' . trim($which_ary['email']) . '>' : '<' . trim($which_ary['email']) . '>';
- $mail_rcpt['to'][] = '<' . trim($which_ary['email']) . '>';
+ foreach ($addresses['to'] as $which_ary)
+ {
+ $mail_to[] = ($which_ary['name'] != '') ? mail_encode(trim($which_ary['name'])) . ' <' . trim($which_ary['email']) . '>' : '<' . trim($which_ary['email']) . '>';
+ $mail_rcpt['to'][] = '<' . trim($which_ary['email']) . '>';
+ }
}
if (isset($addresses['bcc']) && sizeof($addresses['bcc']))
@@ -808,16 +816,18 @@ function smtpmail($addresses, $subject, $message, &$err_msg, $encoding, $headers
{
foreach ($addresses['cc'] as $which_ary)
{
- $mail_cc[] = ($which_ary['name'] != '') ? mail_encode(trim($which_ary['name']), $encoding) . ' <' . trim($which_ary['email']) . '>' : '<' . trim($which_ary['email']) . '>';
+ $mail_cc[] = ($which_ary['name'] != '') ? mail_encode(trim($which_ary['name'])) . ' <' . trim($which_ary['email']) . '>' : '<' . trim($which_ary['email']) . '>';
$mail_rcpt['cc'][] = '<' . trim($which_ary['email']) . '>';
}
}
- $smtp = new smtp_class;
+ $smtp = new smtp_class();
$errno = 0;
$errstr = '';
+ $smtp->add_backtrace('Connecting to ' . $config['smtp_host'] . ':' . $config['smtp_port']);
+
// Ok we have error checked as much as we can to this point let's get on it already.
if (!$smtp->socket = @fsockopen($config['smtp_host'], $config['smtp_port'], $errno, $errstr, 20))
{
@@ -828,14 +838,14 @@ function smtpmail($addresses, $subject, $message, &$err_msg, $encoding, $headers
// Wait for reply
if ($err_msg = $smtp->server_parse('220', __LINE__))
{
- $smtp->close_session();
+ $smtp->close_session($err_msg);
return false;
}
// Let me in. This function handles the complete authentication process
if ($err_msg = $smtp->log_into_server($config['smtp_host'], $config['smtp_username'], $config['smtp_password'], $config['smtp_auth_method']))
{
- $smtp->close_session();
+ $smtp->close_session($err_msg);
return false;
}
@@ -844,7 +854,7 @@ function smtpmail($addresses, $subject, $message, &$err_msg, $encoding, $headers
$smtp->server_send('MAIL FROM:<' . $config['board_email'] . '>');
if ($err_msg = $smtp->server_parse('250', __LINE__))
{
- $smtp->close_session();
+ $smtp->close_session($err_msg);
return false;
}
@@ -867,7 +877,7 @@ function smtpmail($addresses, $subject, $message, &$err_msg, $encoding, $headers
// We continue... if users are not resolved we do not care
if ($smtp->numeric_response_code != 550)
{
- $smtp->close_session();
+ $smtp->close_session($err_msg);
return false;
}
}
@@ -885,7 +895,7 @@ function smtpmail($addresses, $subject, $message, &$err_msg, $encoding, $headers
$user->session_begin();
$err_msg .= '<br /><br />';
$err_msg .= (isset($user->lang['INVALID_EMAIL_LOG'])) ? sprintf($user->lang['INVALID_EMAIL_LOG'], htmlspecialchars($mail_to_address)) : '<strong>' . htmlspecialchars($mail_to_address) . '</strong> possibly an invalid email address?';
- $smtp->close_session();
+ $smtp->close_session($err_msg);
return false;
}
@@ -895,7 +905,7 @@ function smtpmail($addresses, $subject, $message, &$err_msg, $encoding, $headers
// This is the last response code we look for until the end of the message.
if ($err_msg = $smtp->server_parse('354', __LINE__))
{
- $smtp->close_session();
+ $smtp->close_session($err_msg);
return false;
}
@@ -922,13 +932,13 @@ function smtpmail($addresses, $subject, $message, &$err_msg, $encoding, $headers
$smtp->server_send('.');
if ($err_msg = $smtp->server_parse('250', __LINE__))
{
- $smtp->close_session();
+ $smtp->close_session($err_msg);
return false;
}
// Now tell the server we are done and close the socket...
$smtp->server_send('QUIT');
- $smtp->close_session();
+ $smtp->close_session($err_msg);
return true;
}
@@ -947,16 +957,41 @@ class smtp_class
var $commands = array();
var $numeric_response_code = 0;
+ var $backtrace = false;
+ var $backtrace_log = array();
+
+ function smtp_class()
+ {
+ if (defined('DEBUG_EXTRA'))
+ {
+ $this->backtrace = true;
+ $this->backtrace_log = array();
+ }
+ }
+
+ /**
+ * Add backtrace message for debugging
+ */
+ function add_backtrace($message)
+ {
+ if ($this->backtrace)
+ {
+ $this->backtrace_log[] = $message;
+ }
+ }
+
/**
* Send command to smtp server
*/
- function server_send($command)
+ function server_send($command, $private_info = false)
{
fputs($this->socket, $command . "\r\n");
+ (!$private_info) ? $this->add_backtrace("# $command") : $this->add_backtrace('# Ommitting sensitive Informations');
+
// We could put additional code here
}
-
+
/**
* We use the line to give the support people an indication at which command the error occurred
*/
@@ -976,6 +1011,8 @@ class smtp_class
}
$this->responses[] = substr(rtrim($this->server_response), 4);
$this->numeric_response_code = (int) substr($this->server_response, 0, 3);
+
+ $this->add_backtrace("LINE: $line <- {$this->server_response}");
}
if (!(substr($this->server_response, 0, 3) == $response))
@@ -990,9 +1027,15 @@ class smtp_class
/**
* Close session
*/
- function close_session()
+ function close_session(&$err_msg)
{
fclose($this->socket);
+
+ if ($this->backtrace)
+ {
+ $message = '<h1>Backtrace</h1><p>' . implode('<br />', array_map('htmlspecialchars', $this->backtrace_log)) . '</p>';
+ $err_msg .= $message;
+ }
}
/**
@@ -1008,10 +1051,37 @@ class smtp_class
// If we are authenticating through pop-before-smtp, we
// have to login ones before we get authenticated
+ // NOTE: on some configurations the time between an update of the auth database takes so
+ // long that the first email send does not work. This is not a biggie on a live board (only
+ // the install mail will most likely fail) - but on a dynamic ip connection this might produce
+ // severe problems and is not fixable!
if ($default_auth_method == 'POP-BEFORE-SMTP' && $username && $password)
{
+ global $config;
+
+ $errno = 0;
+ $errstr = '';
+
+ $this->server_send("QUIT");
+ fclose($this->socket);
+
$result = $this->pop_before_smtp($hostname, $username, $password);
$username = $password = $default_auth_method = '';
+
+ // We need to close the previous session, else the server is not
+ // able to get our ip for matching...
+ if (!$this->socket = @fsockopen($config['smtp_host'], $config['smtp_port'], $errno, $errstr, 10))
+ {
+ $err_msg = (isset($user->lang['NO_CONNECT_TO_SMTP_HOST'])) ? sprintf($user->lang['NO_CONNECT_TO_SMTP_HOST'], $errno, $errstr) : "Could not connect to smtp host : $errno : $errstr";
+ return $err_msg;
+ }
+
+ // Wait for reply
+ if ($err_msg = $this->server_parse('220', __LINE__))
+ {
+ $this->close_session($err_msg);
+ return $err_msg;
+ }
}
// Try EHLO first
@@ -1090,32 +1160,26 @@ class smtp_class
{
global $user;
- $old_socket = $this->socket;
-
- if (!$this->socket = fsockopen($hostname, 110, $errno, $errstr, 20))
+ if (!$this->socket = @fsockopen($hostname, 110, $errno, $errstr, 10))
{
- $this->socket = $old_socket;
return (isset($user->lang['NO_CONNECT_TO_SMTP_HOST'])) ? sprintf($user->lang['NO_CONNECT_TO_SMTP_HOST'], $errno, $errstr) : "Could not connect to smtp host : $errno : $errstr";
}
- $this->server_parse('0', __LINE__);
- if (substr($this->server_response, 0, 3) == '+OK')
+ $this->server_send("USER $username", true);
+ if ($err_msg = $this->server_parse('+OK', __LINE__))
{
- fputs($this->socket, "USER $username\r\n");
- fputs($this->socket, "PASS $password\r\n");
+ return $err_msg;
}
- else
+
+ $this->server_send("PASS $password", true);
+ if ($err_msg = $this->server_parse('+OK', __LINE__))
{
- $this->socket = $old_socket;
- return $this->responses[0];
+ return $err_msg;
}
$this->server_send('QUIT');
- $this->server_parse('0', __LINE__);
fclose($this->socket);
- $this->socket = $old_socket;
-
return false;
}
@@ -1131,7 +1195,7 @@ class smtp_class
}
$base64_method_plain = base64_encode("\0" . $username . "\0" . $password);
- $this->server_send($base64_method_plain);
+ $this->server_send($base64_method_plain, true);
if ($err_msg = $this->server_parse('235', __LINE__))
{
return $err_msg;
@@ -1151,13 +1215,13 @@ class smtp_class
return ($this->numeric_response_code == 503) ? false : $err_msg;
}
- $this->server_send(base64_encode($username));
+ $this->server_send(base64_encode($username), true);
if ($err_msg = $this->server_parse('334', __LINE__))
{
return $err_msg;
}
- $this->server_send(base64_encode($password));
+ $this->server_send(base64_encode($password), true);
if ($err_msg = $this->server_parse('235', __LINE__))
{
return $err_msg;
@@ -1183,7 +1247,7 @@ class smtp_class
$base64_method_cram_md5 = base64_encode($username . ' ' . $md5_digest);
- $this->server_send($base64_method_cram_md5);
+ $this->server_send($base64_method_cram_md5, true);
if ($err_msg = $this->server_parse('235', __LINE__))
{
return $err_msg;
@@ -1287,7 +1351,7 @@ class smtp_class
}
$base64_method_digest_md5 = base64_encode($input_string);
- $this->server_send($base64_method_digest_md5);
+ $this->server_send($base64_method_digest_md5, true);
if ($err_msg = $this->server_parse('334', __LINE__))
{
return $err_msg;
@@ -1304,25 +1368,24 @@ class smtp_class
}
/**
-* Encodes the given string for proper display for this encoding ... nabbed
+* Encodes the given string for proper display in UTF-8 ... nabbed
* from php.net and modified. There is an alternative encoding method which
* may produce less output but it's questionable as to its worth in this
-* scenario IMO
+* scenario.
+*
+* This version is using base64 encoded data. The downside of this
+* is if the mail client does not understand this encoding the user
+* is basically doomed with an unreadable subject.
*/
-function mail_encode($str, $encoding)
+function mail_encode($str)
{
- if ($encoding == '')
- {
- return $str;
- }
-
// define start delimimter, end delimiter and spacer
- $end = "?=";
- $start = "=?$encoding?B?";
- $spacer = "$end\r\n $start";
+ $end = '?=';
+ $start = '=?UTF-8?B?';
+ $spacer = "$end $start";
// determine length of encoded text within chunks and ensure length is even
- $length = 75 - strlen($start) - strlen($end);
+ $length = 76 - strlen($start) - strlen($end);
$length = floor($length / 2) * 2;
// encode the string and split it into chunks with spacers after each chunk
diff --git a/phpBB/includes/functions_module.php b/phpBB/includes/functions_module.php
index 9541c9f4cf..89dda74700 100644
--- a/phpBB/includes/functions_module.php
+++ b/phpBB/includes/functions_module.php
@@ -256,9 +256,9 @@ class p_master
// If no category or module selected, go active for first module in first category
if (
(($item_ary['name'] === $id || $item_ary['id'] === (int) $id) && (($item_ary['mode'] == $mode && !$item_ary['cat']) || ($icat && $item_ary['cat']))) ||
- ($item_ary['parent'] === $category && !$item_ary['cat'] && !$icat) ||
+ ($item_ary['parent'] === $category && !$item_ary['cat'] && !$icat && $item_ary['display']) ||
(($item_ary['name'] === $id || $item_ary['id'] === (int) $id) && !$mode && !$item_ary['cat']) ||
- (!$id && !$mode && !$item_ary['cat'])
+ (!$id && !$mode && !$item_ary['cat'] && $item_ary['display'])
)
{
if ($item_ary['cat'])
@@ -309,14 +309,14 @@ class p_master
{
if (!file_exists("$module_path/{$this->p_class}_$this->p_name.$phpEx"))
{
- trigger_error('Cannot find module', E_USER_ERROR);
+ trigger_error("Cannot find module $module_path/{$this->p_class}_$this->p_name.$phpEx", E_USER_ERROR);
}
include("$module_path/{$this->p_class}_$this->p_name.$phpEx");
if (!class_exists("{$this->p_class}_$this->p_name"))
{
- trigger_error('Module does not contain correct class', E_USER_ERROR);
+ trigger_error("Module file $module_path/{$this->p_class}_$this->p_name.$phpEx does not contain correct class [{$this->p_class}_$this->p_name]", E_USER_ERROR);
}
if (!empty($mode))
diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php
index b40fdb369c..b15466b487 100644
--- a/phpBB/includes/functions_posting.php
+++ b/phpBB/includes/functions_posting.php
@@ -111,21 +111,41 @@ function update_post_information($type, $ids, $return_update_sql = false)
$ids = array($ids);
}
- $update_sql = $empty_forums = array();
+ $update_sql = $empty_forums = $not_empty_forums = array();
- $sql = 'SELECT ' . $type . '_id, MAX(post_id) as last_post_id
- FROM ' . POSTS_TABLE . '
- WHERE post_approved = 1
- AND ' . $db->sql_in_set($type . '_id', $ids) . "
- GROUP BY {$type}_id";
+ if (sizeof($ids) == 1)
+ {
+ $sql = 'SELECT MAX(post_id) as last_post_id
+ FROM ' . POSTS_TABLE . '
+ WHERE ' . $db->sql_in_set($type . '_id', $ids) . '
+ AND post_approved = 1';
+ }
+ else
+ {
+ $sql = 'SELECT ' . $type . '_id, MAX(post_id) as last_post_id
+ FROM ' . POSTS_TABLE . '
+ WHERE ' . $db->sql_in_set($type . '_id', $ids) . "
+ AND post_approved = 1
+ GROUP BY {$type}_id";
+ }
$result = $db->sql_query($sql);
$last_post_ids = array();
while ($row = $db->sql_fetchrow($result))
{
+ if (sizeof($ids) == 1)
+ {
+ $row[$type . '_id'] = $ids[0];
+ }
+
if ($type == 'forum')
{
- $empty_forums[] = $row['forum_id'];
+ $not_empty_forums[] = $row['forum_id'];
+
+ if (empty($row['last_post_id']))
+ {
+ $empty_forums[] = $row['forum_id'];
+ }
}
$last_post_ids[] = $row['last_post_id'];
@@ -134,20 +154,22 @@ function update_post_information($type, $ids, $return_update_sql = false)
if ($type == 'forum')
{
- $empty_forums = array_diff($ids, $empty_forums);
+ $empty_forums = array_merge($empty_forums, array_diff($ids, $not_empty_forums));
foreach ($empty_forums as $void => $forum_id)
{
$update_sql[$forum_id][] = 'forum_last_post_id = 0';
- $update_sql[$forum_id][] = 'forum_last_post_time = 0';
+ $update_sql[$forum_id][] = "forum_last_post_subject = ''";
+ $update_sql[$forum_id][] = 'forum_last_post_time = 0';
$update_sql[$forum_id][] = 'forum_last_poster_id = 0';
$update_sql[$forum_id][] = "forum_last_poster_name = ''";
+ $update_sql[$forum_id][] = "forum_last_poster_colour = ''";
}
}
if (sizeof($last_post_ids))
{
- $sql = 'SELECT p.' . $type . '_id, p.post_id, p.post_time, p.poster_id, p.post_username, u.user_id, u.username
+ $sql = 'SELECT p.' . $type . '_id, p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour
FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u
WHERE p.poster_id = u.user_id
AND ' . $db->sql_in_set('p.post_id', $last_post_ids);
@@ -156,8 +178,10 @@ function update_post_information($type, $ids, $return_update_sql = false)
while ($row = $db->sql_fetchrow($result))
{
$update_sql[$row["{$type}_id"]][] = $type . '_last_post_id = ' . (int) $row['post_id'];
+ $update_sql[$row["{$type}_id"]][] = "{$type}_last_post_subject = '" . $db->sql_escape($row['post_subject']) . "'";
$update_sql[$row["{$type}_id"]][] = $type . '_last_post_time = ' . (int) $row['post_time'];
$update_sql[$row["{$type}_id"]][] = $type . '_last_poster_id = ' . (int) $row['poster_id'];
+ $update_sql[$row["{$type}_id"]][] = "{$type}_last_poster_colour = '" . $db->sql_escape($row['user_colour']) . "'";
$update_sql[$row["{$type}_id"]][] = "{$type}_last_poster_name = '" . (($row['poster_id'] == ANONYMOUS) ? $db->sql_escape($row['post_username']) : $db->sql_escape($row['username'])) . "'";
}
$db->sql_freeresult($result);
@@ -190,8 +214,7 @@ function posting_gen_topic_icons($mode, $icon_id)
global $phpbb_root_path, $config, $template, $cache;
// Grab icons
- $icons = array();
- $cache->obtain_icons($icons);
+ $icons = $cache->obtain_icons();
if (!$icon_id)
{
@@ -311,13 +334,11 @@ function upload_attachment($form_name, $forum_id, $local = false, $local_storage
if (!$filedata['post_attach'])
{
- $filedata['error'][] = 'No filedata found';
+ $filedata['error'][] = $user->lang['NO_UPLOAD_FORM_FOUND'];
return $filedata;
}
- $extensions = array();
- $cache->obtain_attach_extensions($extensions, $forum_id);
-
+ $extensions = $cache->obtain_attach_extensions($forum_id);
$upload->set_allowed_extensions(array_keys($extensions['_allowed_']));
$file = ($local) ? $upload->local_upload($local_storage) : $upload->form_upload($form_name);
@@ -330,6 +351,16 @@ function upload_attachment($form_name, $forum_id, $local = false, $local_storage
$cat_id = (isset($extensions[$file->get('extension')]['display_cat'])) ? $extensions[$file->get('extension')]['display_cat'] : ATTACHMENT_CATEGORY_NONE;
+ // Make sure the image category only holds valid images...
+ if ($cat_id == ATTACHMENT_CATEGORY_IMAGE && !$file->is_image())
+ {
+ $file->remove();
+
+ // If this error occurs a user tried to exploit an IE Bug by renaming extensions
+ // Since the image category is displaying content inline we need to catch this.
+ trigger_error($user->lang['UNABLE_GET_IMAGE_SIZE']);
+ }
+
// Do we have to create a thumbnail?
$filedata['thumbnail'] = ($cat_id == ATTACHMENT_CATEGORY_IMAGE && $config['img_create_thumbnail']) ? 1 : 0;
@@ -421,8 +452,10 @@ function upload_attachment($form_name, $forum_id, $local = false, $local_storage
*/
function get_img_size_format($width, $height)
{
+ global $config;
+
// Maximum Width the Image can take
- $max_width = 400;
+ $max_width = ($config['img_max_thumb_width']) ? $config['img_max_thumb_width'] : 400;
if ($width > $height)
{
@@ -533,7 +566,8 @@ function create_thumbnail($source, $destination, $mimetype)
// Only use imagemagick if defined and the passthru function not disabled
if ($config['img_imagick'] && function_exists('passthru'))
{
- passthru(escapeshellcmd($config['img_imagick']) . 'convert' . ((defined('PHP_OS') && preg_match('#^win#i', PHP_OS)) ? '.exe' : '') . ' -quality 85 -antialias -sample ' . $new_width . 'x' . $new_height . ' "' . str_replace('\\', '/', $source) . '" +profile "*" "' . str_replace('\\', '/', $destination) . '"');
+ @passthru(escapeshellcmd($config['img_imagick']) . 'convert' . ((defined('PHP_OS') && preg_match('#^win#i', PHP_OS)) ? '.exe' : '') . ' -quality 85 -antialias -sample ' . $new_width . 'x' . $new_height . ' "' . str_replace('\\', '/', $source) . '" +profile "*" "' . str_replace('\\', '/', $destination) . '"');
+
if (file_exists($destination))
{
$used_imagick = true;
@@ -638,7 +672,7 @@ function posting_gen_inline_attachments(&$attachment_data)
foreach ($attachment_data as $i => $attachment)
{
- $s_inline_attachment_options .= '<option value="' . $i . '">' . $attachment['real_filename'] . '</option>';
+ $s_inline_attachment_options .= '<option value="' . $i . '">' . basename($attachment['real_filename']) . '</option>';
}
$template->assign_var('S_INLINE_ATTACHMENT_OPTIONS', $s_inline_attachment_options);
@@ -654,7 +688,7 @@ function posting_gen_inline_attachments(&$attachment_data)
*/
function posting_gen_attachment_entry(&$attachment_data, &$filename_data)
{
- global $template, $config, $phpbb_root_path, $phpEx;
+ global $template, $config, $phpbb_root_path, $phpEx, $user;
$template->assign_vars(array(
'S_SHOW_ATTACH_BOX' => true)
@@ -677,13 +711,13 @@ function posting_gen_attachment_entry(&$attachment_data, &$filename_data)
$hidden .= '<input type="hidden" name="attachment_data[' . $count . '][' . $key . ']" value="' . $value . '" />';
}
- $download_link = (!$attach_row['attach_id']) ? $phpbb_root_path . $config['upload_path'] . '/' . basename($attach_row['physical_filename']) : append_sid("{$phpbb_root_path}download.$phpEx", 'id=' . (int) $attach_row['attach_id']);
+ $download_link = append_sid("{$phpbb_root_path}download.$phpEx", 'id=' . (int) $attach_row['attach_id'], false, ($attach_row['is_orphan']) ? $user->session_id : false);
$template->assign_block_vars('attach_row', array(
'FILENAME' => basename($attach_row['real_filename']),
- 'ATTACH_FILENAME' => basename($attach_row['physical_filename']),
'FILE_COMMENT' => $attach_row['attach_comment'],
'ATTACH_ID' => $attach_row['attach_id'],
+ 'S_IS_ORPHAN' => $attach_row['is_orphan'],
'ASSOC_INDEX' => $count,
'U_VIEW_ATTACHMENT' => $download_link,
@@ -848,10 +882,10 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id
$db->sql_freeresult($result);
// Instantiate BBCode class
- if (!isset($bbcode) && $bbcode_bitfield)
+ if (!isset($bbcode) && $bbcode_bitfield !== '')
{
include_once($phpbb_root_path . 'includes/bbcode.' . $phpEx);
- $bbcode = new bbcode($bbcode_bitfield);
+ $bbcode = new bbcode(base64_encode($bbcode_bitfield));
}
foreach ($rowset as $i => $row)
@@ -868,6 +902,8 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id
$post_subject = $row['post_subject'];
$message = $row['post_text'];
+ $message = censor_text($message);
+ $message = str_replace("\n", '<br />', $message);
$decoded_message = false;
if ($show_quote_button && $auth->acl_get('f_reply', $forum_id))
@@ -887,20 +923,18 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id
$message = smiley_text($message, !$row['enable_smilies']);
$post_subject = censor_text($post_subject);
- $message = censor_text($message);
$template->assign_block_vars($mode . '_row', array(
'POSTER_NAME' => $poster,
'POST_SUBJECT' => $post_subject,
'MINI_POST_IMG' => $user->img('icon_post_target', $user->lang['POST']),
'POST_DATE' => $user->format_date($row['post_time']),
- 'MESSAGE' => str_replace("\n", '<br />', $message),
+ 'MESSAGE' => $message,
'DECODED_MESSAGE' => $decoded_message,
-
'U_POST_ID' => $row['post_id'],
'U_MINI_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'p=' . $row['post_id']) . '#p' . $row['post_id'],
'U_MCP_DETAILS' => ($auth->acl_get('m_info', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&amp;mode=post_details&amp;f=' . $forum_id . '&amp;p=' . $row['post_id'], true, $user->session_id) : '',
- 'U_QUOTE' => ($show_quote_button && $auth->acl_get('f_reply', $forum_id)) ? 'javascript:addquote(' . $row['post_id'] . ", '" . addslashes($poster) . "')" : '')
+ 'POSTER_QUOTE' => ($show_quote_button && $auth->acl_get('f_reply', $forum_id)) ? addslashes($poster) : '')
);
unset($rowset[$i]);
}
@@ -920,8 +954,8 @@ function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id
{
global $db, $user, $config, $phpbb_root_path, $phpEx, $auth;
- $topic_notification = ($mode == 'reply' || $mode == 'quote');
- $forum_notification = ($mode == 'post');
+ $topic_notification = ($mode == 'reply' || $mode == 'quote') ? true : false;
+ $forum_notification = ($mode == 'post') ? true : false;
if (!$topic_notification && !$forum_notification)
{
@@ -1053,8 +1087,6 @@ function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id
include_once($phpbb_root_path . 'includes/functions_messenger.'.$phpEx);
$messenger = new messenger();
- $email_sig = str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']);
-
$msg_list_ary = array();
foreach ($msg_users as $row)
{
@@ -1079,11 +1111,9 @@ function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id
$messenger->im($addr['jabber'], $addr['name']);
$messenger->assign_vars(array(
- 'EMAIL_SIG' => $email_sig,
- 'SITENAME' => html_entity_decode($config['sitename']),
- 'USERNAME' => html_entity_decode($addr['name']),
- 'TOPIC_TITLE' => html_entity_decode($topic_title),
- 'FORUM_NAME' => html_entity_decode($forum_name),
+ 'USERNAME' => htmlspecialchars_decode($addr['name']),
+ 'TOPIC_TITLE' => htmlspecialchars_decode($topic_title),
+ 'FORUM_NAME' => htmlspecialchars_decode($forum_name),
'U_FORUM' => generate_board_url() . "/viewforum.$phpEx?f=$forum_id&e=0",
'U_TOPIC' => generate_board_url() . "/viewtopic.$phpEx?f=$forum_id&t=$topic_id&e=0",
@@ -1197,7 +1227,7 @@ function delete_post($forum_id, $topic_id, $post_id, &$data)
break;
case 'delete_first_post':
- $sql = 'SELECT p.post_id, p.poster_id, p.post_username, u.username
+ $sql = 'SELECT p.post_id, p.poster_id, p.post_username, u.username, u.user_colour
FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u
WHERE p.topic_id = $topic_id
AND p.poster_id = u.user_id
@@ -1211,7 +1241,7 @@ function delete_post($forum_id, $topic_id, $post_id, &$data)
$sql_data[FORUMS_TABLE] = 'forum_posts = forum_posts - 1';
}
- $sql_data[TOPICS_TABLE] = 'topic_first_post_id = ' . intval($row['post_id']) . ", topic_first_poster_name = '" . (($row['poster_id'] == ANONYMOUS) ? $db->sql_escape($row['post_username']) : $db->sql_escape($row['username'])) . "'";
+ $sql_data[TOPICS_TABLE] = 'topic_first_post_id = ' . intval($row['post_id']) . ", topic_first_poster_colour = '" . $db->sql_escape($row['user_colour']) . ", topic_first_poster_name = '" . (($row['poster_id'] == ANONYMOUS) ? $db->sql_escape($row['post_username']) : $db->sql_escape($row['username'])) . "'";
$sql_data[TOPICS_TABLE] .= ', topic_replies_real = topic_replies_real - 1' . (($data['post_approved']) ? ', topic_replies = topic_replies - 1' : '');
$next_post_id = (int) $row['post_id'];
@@ -1381,8 +1411,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
'post_subject' => $subject,
'post_text' => $data['message'],
'post_checksum' => $data['message_md5'],
- 'post_encoding' => $user->lang['ENCODING'],
- 'post_attachment' => (isset($data['filename_data']['physical_filename']) && sizeof($data['filename_data'])) ? 1 : 0,
+ 'post_attachment' => (!empty($data['attachment_data'])) ? 1 : 0,
'bbcode_bitfield' => $data['bbcode_bitfield'],
'bbcode_uid' => $data['bbcode_uid'],
'post_postcount' => ($auth->acl_get('f_postcount', $data['forum_id'])) ? 1 : 0,
@@ -1435,8 +1464,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
'post_edit_reason' => $data['post_edit_reason'],
'post_edit_user' => (int) $data['post_edit_user'],
'post_checksum' => $data['message_md5'],
- 'post_encoding' => $user->lang['ENCODING'],
- 'post_attachment' => (isset($data['filename_data']['physical_filename']) && sizeof($data['filename_data'])) ? 1 : 0,
+ 'post_attachment' => (!empty($data['attachment_data'])) ? 1 : 0,
'bbcode_bitfield' => $data['bbcode_bitfield'],
'bbcode_uid' => $data['bbcode_uid'],
'post_edit_locked' => $data['post_edit_locked'])
@@ -1462,9 +1490,10 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
'topic_approved' => (!$auth->acl_get('f_noapprove', $data['forum_id']) && !$auth->acl_get('m_approve', $data['forum_id'])) ? 0 : 1,
'topic_title' => $subject,
'topic_first_poster_name' => (!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : ''),
+ 'topic_first_poster_colour' => (($user->data['user_id'] != ANONYMOUS) ? $user->data['user_colour'] : ''),
'topic_type' => $topic_type,
'topic_time_limit' => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data['topic_time_limit'] * 86400) : 0,
- 'topic_attachment' => (isset($data['filename_data']['physical_filename']) && sizeof($data['filename_data'])) ? 1 : 0
+ 'topic_attachment' => (!empty($data['attachment_data'])) ? 1 : 0,
);
if (isset($poll['poll_options']) && !empty($poll['poll_options']))
@@ -1517,7 +1546,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
'poll_length' => (isset($poll['poll_options'])) ? ($poll['poll_length'] * 86400) : 0,
'poll_vote_change' => (isset($poll['poll_vote_change'])) ? $poll['poll_vote_change'] : 0,
- 'topic_attachment' => ($post_mode == 'edit_topic') ? ((isset($data['filename_data']['physical_filename']) && sizeof($data['filename_data'])) ? 1 : 0) : (isset($data['topic_attachment']) ? $data['topic_attachment'] : 0)
+ 'topic_attachment' => (!empty($data['attachment_data'])) ? 1 : (isset($data['topic_attachment']) ? $data['topic_attachment'] : 0),
);
break;
}
@@ -1560,7 +1589,8 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
'topic_last_post_id' => $data['post_id'],
'topic_last_post_time' => $current_time,
'topic_last_poster_id' => (int) $user->data['user_id'],
- 'topic_last_poster_name'=> (!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : '')
+ 'topic_last_poster_name'=> (!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : ''),
+ 'topic_last_poster_colour' => (($user->data['user_id'] != ANONYMOUS) ? $user->data['user_colour'] : ''),
);
}
@@ -1675,24 +1705,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
}
}
- if (sizeof($sql_insert_ary))
- {
- switch (SQL_LAYER)
- {
- case 'mysql':
- case 'mysql4':
- case 'mysqli':
- $db->sql_query('INSERT INTO ' . POLL_OPTIONS_TABLE . ' ' . $db->sql_build_array('MULTI_INSERT', $sql_insert_ary));
- break;
-
- default:
- foreach ($sql_insert_ary as $ary)
- {
- $db->sql_query('INSERT INTO ' . POLL_OPTIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $ary));
- }
- break;
- }
- }
+ $db->sql_multi_insert(POLL_OPTIONS_TABLE, $sql_insert_ary);
if (sizeof($poll['poll_options']) < sizeof($cur_poll_options))
{
@@ -1704,67 +1717,81 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
}
// Submit Attachments
- if (sizeof($data['attachment_data']) && $data['post_id'] && in_array($mode, array('post', 'reply', 'quote', 'edit')))
+ if (!empty($data['attachment_data']) && $data['post_id'] && in_array($mode, array('post', 'reply', 'quote', 'edit')))
{
$space_taken = $files_added = 0;
+ $orphan_rows = array();
foreach ($data['attachment_data'] as $pos => $attach_row)
{
- if ($attach_row['attach_id'])
+ $orphan_rows[(int) $attach_row['attach_id']] = array();
+ }
+
+ if (sizeof($orphan_rows))
+ {
+ $sql = 'SELECT attach_id, filesize, physical_filename
+ FROM ' . ATTACHMENTS_TABLE . '
+ WHERE ' . $db->sql_in_set('attach_id', array_keys($orphan_rows)) . '
+ AND is_orphan = 1
+ AND poster_id = ' . $user->data['user_id'];
+ $result = $db->sql_query($sql);
+
+ $orphan_rows = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $orphan_rows[$row['attach_id']] = $row;
+ }
+ $db->sql_freeresult($result);
+ }
+
+ foreach ($data['attachment_data'] as $pos => $attach_row)
+ {
+ if ($attach_row['is_orphan'] && !in_array($attach_row['attach_id'], array_keys($orphan_rows)))
+ {
+ continue;
+ }
+
+ if (!$attach_row['is_orphan'])
{
// update entry in db if attachment already stored in db and filespace
$sql = 'UPDATE ' . ATTACHMENTS_TABLE . "
SET attach_comment = '" . $db->sql_escape($attach_row['attach_comment']) . "'
- WHERE attach_id = " . (int) $attach_row['attach_id'];
+ WHERE attach_id = " . (int) $attach_row['attach_id'] . '
+ AND is_orphan = 0';
$db->sql_query($sql);
}
else
{
// insert attachment into db
- if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . basename($attach_row['physical_filename'])))
+ if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . basename($orphan_rows[$attach_row['attach_id']]['physical_filename'])))
{
continue;
}
+ $space_taken += $orphan_rows[$attach_row['attach_id']]['filesize'];
+ $files_added++;
+
$attach_sql = array(
'post_msg_id' => $data['post_id'],
'topic_id' => $data['topic_id'],
- 'in_message' => 0,
+ 'is_orphan' => 0,
'poster_id' => $poster_id,
- 'physical_filename' => basename($attach_row['physical_filename']),
- 'real_filename' => basename($attach_row['real_filename']),
'attach_comment' => $attach_row['attach_comment'],
- 'extension' => $attach_row['extension'],
- 'mimetype' => $attach_row['mimetype'],
- 'filesize' => $attach_row['filesize'],
- 'filetime' => $attach_row['filetime'],
- 'thumbnail' => $attach_row['thumbnail']
);
- $sql = 'INSERT INTO ' . ATTACHMENTS_TABLE . ' ' .
- $db->sql_build_array('INSERT', $attach_sql);
+ $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $attach_sql) . '
+ WHERE attach_id = ' . $attach_row['attach_id'] . '
+ AND is_orphan = 1
+ AND poster_id = ' . $user->data['user_id'];
$db->sql_query($sql);
-
- $space_taken += $attach_row['filesize'];
- $files_added++;
}
}
- if (sizeof($data['attachment_data']))
+ if ($space_taken && $files_added)
{
- $sql = 'UPDATE ' . POSTS_TABLE . '
- SET post_attachment = 1
- WHERE post_id = ' . $data['post_id'];
- $db->sql_query($sql);
-
- $sql = 'UPDATE ' . TOPICS_TABLE . '
- SET topic_attachment = 1
- WHERE topic_id = ' . $data['topic_id'];
- $db->sql_query($sql);
+ set_config('upload_dir_size', $config['upload_dir_size'] + $space_taken, true);
+ set_config('num_files', $config['num_files'] + $files_added, true);
}
-
- set_config('upload_dir_size', $config['upload_dir_size'] + $space_taken, true);
- set_config('num_files', $config['num_files'] + $files_added, true);
}
$db->sql_transaction('commit');
@@ -1852,7 +1879,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
trigger_error('NO_SUCH_SEARCH_MODULE');
}
- require("{$phpbb_root_path}includes/search/$search_type.$phpEx");
+ require_once("{$phpbb_root_path}includes/search/$search_type.$phpEx");
$error = false;
$search = new $search_type($error);
@@ -1862,7 +1889,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
trigger_error($error);
}
- $search->index($mode, $data['post_id'], $data['message'], $subject, $user->lang['ENCODING'], $poster_id, ($topic_type == POST_GLOBAL) ? 0 : $data['forum_id']);
+ $search->index($mode, $data['post_id'], $data['message'], $subject, $poster_id, ($topic_type == POST_GLOBAL) ? 0 : $data['forum_id']);
}
$db->sql_transaction('commit');
@@ -1921,7 +1948,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
$f_mark_time = false;
}
- if ($config['load_db_lastread'] || $config['load_anon_lastread'] || $user->data['is_registered'])
+ if (($config['load_db_lastread'] && $user->data['is_registered']) || $config['load_anon_lastread'] || $user->data['is_registered'])
{
// Update forum info
$sql = 'SELECT forum_last_post_time
diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php
index fe38b6276b..58d854b928 100644
--- a/phpBB/includes/functions_privmsgs.php
+++ b/phpBB/includes/functions_privmsgs.php
@@ -279,9 +279,31 @@ function check_rule(&$rules, &$rule_row, &$message_row, $user_id)
case ACTION_MARK_AS_READ:
case ACTION_MARK_AS_IMPORTANT:
- case ACTION_DELETE_MESSAGE:
return array('action' => $rule_row['rule_action'], 'pm_unread' => $message_row['pm_unread'], 'pm_marked' => $message_row['pm_marked']);
break;
+
+ case ACTION_DELETE_MESSAGE:
+ global $db, $auth;
+
+ // Check for admins/mods - users are not allowed to remove those messages...
+ // We do the check here to make sure the data we use is consistent
+ $sql = 'SELECT user_id, user_type, user_permissions
+ FROM ' . USERS_TABLE . '
+ WHERE user_id = ' . (int) $message_row['author_id'];
+ $result = $db->sql_query($sql);
+ $userdata = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ $auth2 = new auth();
+ $auth2->acl($userdata);
+
+ if (!$auth2->acl_get('a_') && !$auth->acl_get('m_') && !$auth2->acl_getf_global('m_'))
+ {
+ return array('action' => $rule_row['rule_action'], 'pm_unread' => $message_row['pm_unread'], 'pm_marked' => $message_row['pm_marked']);
+ }
+
+ return false;
+ break;
default:
return false;
@@ -486,8 +508,8 @@ function place_pm_into_folder(&$global_privmsgs_rules, $release = false)
}
}
- $num_new += sizeof(array_unique($delete_ids));
- $num_unread += sizeof(array_unique($delete_ids));
+// $num_new += sizeof(array_unique($delete_ids));
+// $num_unread += sizeof(array_unique($delete_ids));
$num_unread += sizeof(array_unique($unread_ids));
// Do not change the order of processing
@@ -589,13 +611,12 @@ function place_pm_into_folder(&$global_privmsgs_rules, $release = false)
}
else if ($full_folder_action == FULL_FOLDER_DELETE)
{
- // Delete some messages ;)
- $sql = 'SELECT t.msg_id
- FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . " p
- WHERE t.msg_id = p.msg_id
- AND t.user_id = $user_id
- AND t.folder_id = $dest_folder
- ORDER BY p.message_time ASC";
+ // Delete some messages. NOTE: Ordered by msg_id here instead of message_time!
+ $sql = 'SELECT msg_id
+ FROM ' . PRIVMSGS_TO_TABLE . "
+ WHERE user_id = $user_id
+ AND folder_id = $dest_folder
+ ORDER BY msg_id ASC";
$result = $db->sql_query_limit($sql, (($folder[$dest_folder] + sizeof($msg_ary)) - $user->data['message_limit']));
$delete_ids = array();
@@ -668,6 +689,7 @@ function place_pm_into_folder(&$global_privmsgs_rules, $release = false)
}
$db->sql_query('UPDATE ' . USERS_TABLE . " SET $set_sql WHERE user_id = $user_id");
+
$user->data['user_new_privmsg'] -= $num_new;
$user->data['user_unread_privmsg'] -= $num_unread;
}
@@ -778,7 +800,7 @@ function update_unread_status($unread, $msg_id, $user_id, $folder_id)
return;
}
- global $db;
+ global $db, $user;
$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . "
SET pm_unread = 0
@@ -791,6 +813,11 @@ function update_unread_status($unread, $msg_id, $user_id, $folder_id)
SET user_unread_privmsg = user_unread_privmsg - 1
WHERE user_id = $user_id";
$db->sql_query($sql);
+
+ if ($user->data['user_id'] == $user_id)
+ {
+ $user->data['user_unread_privmsg']--;
+ }
}
/**
@@ -860,7 +887,7 @@ function handle_mark_actions($user_id, $mark_action)
*/
function delete_pm($user_id, $msg_ids, $folder_id)
{
- global $db;
+ global $db, $user;
$user_id = (int) $user_id;
$folder_id = (int) $folder_id;
@@ -957,6 +984,7 @@ function delete_pm($user_id, $msg_ids, $folder_id)
if ($num_unread || $num_new)
{
$set_sql = ($num_unread) ? 'user_unread_privmsg = user_unread_privmsg - ' . $num_unread : '';
+
if ($num_new)
{
$set_sql .= ($set_sql != '') ? ', ' : '';
@@ -964,6 +992,9 @@ function delete_pm($user_id, $msg_ids, $folder_id)
}
$db->sql_query('UPDATE ' . USERS_TABLE . " SET $set_sql WHERE user_id = $user_id");
+
+ $user->data['user_new_privmsg'] -= $num_new;
+ $user->data['user_unread_privmsg'] -= $num_unread;
}
// Now we have to check which messages we can delete completely
@@ -1141,7 +1172,7 @@ function write_pm_addresses($check_ary, $author_id, $plaintext = false)
'IS_USER' => ($type == 'user'),
'COLOUR' => ($row['colour']) ? $row['colour'] : '',
'UG_ID' => $id,
- 'U_VIEW' => ($type == 'user') ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&amp;u=' . $id) : append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&amp;g=' . $id),
+ 'U_VIEW' => ($type == 'user') ? (($id != ANONYMOUS) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&amp;u=' . $id) : '') : append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&amp;g=' . $id),
'TYPE' => $type)
);
}
@@ -1223,7 +1254,7 @@ function submit_pm($mode, $subject, &$data, $update_message, $put_in_outbox = tr
$id = (int) $id;
// Do not rely on the address list being "valid"
- if (!$id)
+ if (!$id || ($ug_type == 'u' && $id == ANONYMOUS))
{
continue;
}
@@ -1291,8 +1322,7 @@ function submit_pm($mode, $subject, &$data, $update_message, $put_in_outbox = tr
'enable_sig' => $data['enable_sig'],
'message_subject' => $subject,
'message_text' => $data['message'],
- 'message_encoding' => $user->lang['ENCODING'],
- 'message_attachment'=> (isset($data['filename_data']['physical_filename']) && sizeof($data['filename_data'])) ? 1 : 0,
+ 'message_attachment'=> (!empty($data['attachment_data'])) ? 1 : 0,
'bbcode_bitfield' => $data['bbcode_bitfield'],
'bbcode_uid' => $data['bbcode_uid'],
'to_address' => implode(':', $to),
@@ -1310,8 +1340,7 @@ function submit_pm($mode, $subject, &$data, $update_message, $put_in_outbox = tr
'enable_sig' => $data['enable_sig'],
'message_subject' => $subject,
'message_text' => $data['message'],
- 'message_encoding' => $user->lang['ENCODING'],
- 'message_attachment'=> (isset($data['filename_data']['physical_filename']) && sizeof($data['filename_data'])) ? 1 : 0,
+ 'message_attachment'=> (!empty($data['attachment_data'])) ? 1 : 0,
'bbcode_bitfield' => $data['bbcode_bitfield'],
'bbcode_uid' => $data['bbcode_uid']
);
@@ -1360,24 +1389,7 @@ function submit_pm($mode, $subject, &$data, $update_message, $put_in_outbox = tr
);
}
- if (sizeof($sql_ary))
- {
- switch (SQL_LAYER)
- {
- case 'mysql':
- case 'mysql4':
- case 'mysqli':
- $db->sql_query('INSERT INTO ' . PRIVMSGS_TO_TABLE . ' ' . $db->sql_build_array('MULTI_INSERT', $sql_ary));
- break;
-
- default:
- foreach ($sql_ary as $ary)
- {
- $db->sql_query('INSERT INTO ' . PRIVMSGS_TO_TABLE . ' ' . $db->sql_build_array('INSERT', $ary));
- }
- break;
- }
- }
+ $db->sql_multi_insert(PRIVMSGS_TO_TABLE, $sql_ary);
$sql = 'UPDATE ' . USERS_TABLE . '
SET user_new_privmsg = user_new_privmsg + 1, user_unread_privmsg = user_unread_privmsg + 1, user_last_privmsg = ' . time() . '
@@ -1416,52 +1428,74 @@ function submit_pm($mode, $subject, &$data, $update_message, $put_in_outbox = tr
if (!empty($data['attachment_data']) && $data['msg_id'] && in_array($mode, array('post', 'reply', 'quote', 'quotepost', 'edit', 'forward')))
{
$space_taken = $files_added = 0;
+ $orphan_rows = array();
+
+ foreach ($data['attachment_data'] as $pos => $attach_row)
+ {
+ $orphan_rows[(int) $attach_row['attach_id']] = array();
+ }
+
+ if (sizeof($orphan_rows))
+ {
+ $sql = 'SELECT attach_id, filesize, physical_filename
+ FROM ' . ATTACHMENTS_TABLE . '
+ WHERE ' . $db->sql_in_set('attach_id', array_keys($orphan_rows)) . '
+ AND in_message = 1
+ AND is_orphan = 1
+ AND poster_id = ' . $user->data['user_id'];
+ $result = $db->sql_query($sql);
+
+ $orphan_rows = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $orphan_rows[$row['attach_id']] = $row;
+ }
+ $db->sql_freeresult($result);
+ }
foreach ($data['attachment_data'] as $pos => $attach_row)
{
- if ($attach_row['attach_id'])
+ if ($attach_row['is_orphan'] && !in_array($attach_row['attach_id'], array_keys($orphan_rows)))
+ {
+ continue;
+ }
+
+ if (!$attach_row['is_orphan'])
{
// update entry in db if attachment already stored in db and filespace
- $sql = 'UPDATE ' . ATTACHMENTS_TABLE . "
- SET attach_comment = '" . $db->sql_escape($attach_row['attach_comment']) . "'
- WHERE attach_id = " . (int) $attach_row['attach_id'];
+ $sql = 'UPDATE ' . ATTACHMENTS_TABLE . "
+ SET attach_comment = '" . $db->sql_escape($attach_row['attach_comment']) . "'
+ WHERE attach_id = " . (int) $attach_row['attach_id'] . '
+ AND is_orphan = 0';
$db->sql_query($sql);
}
else
{
- // insert attachment into db
+ // insert attachment into db
+ if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . basename($orphan_rows[$attach_row['attach_id']]['physical_filename'])))
+ {
+ continue;
+ }
+
+ $space_taken += $orphan_rows[$attach_row['attach_id']]['filesize'];
+ $files_added++;
+
$attach_sql = array(
'post_msg_id' => $data['msg_id'],
'topic_id' => 0,
- 'in_message' => 1,
+ 'is_orphan' => 0,
'poster_id' => $data['from_user_id'],
- 'physical_filename' => basename($attach_row['physical_filename']),
- 'real_filename' => basename($attach_row['real_filename']),
'attach_comment' => $attach_row['attach_comment'],
- 'extension' => $attach_row['extension'],
- 'mimetype' => $attach_row['mimetype'],
- 'filesize' => $attach_row['filesize'],
- 'filetime' => $attach_row['filetime'],
- 'thumbnail' => $attach_row['thumbnail']
);
- $sql = 'INSERT INTO ' . ATTACHMENTS_TABLE . ' ' .
- $db->sql_build_array('INSERT', $attach_sql);
+ $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $attach_sql) . '
+ WHERE attach_id = ' . $attach_row['attach_id'] . '
+ AND is_orphan = 1
+ AND poster_id = ' . $user->data['user_id'];
$db->sql_query($sql);
-
- $space_taken += $attach_row['filesize'];
- $files_added++;
}
}
- if (sizeof($data['attachment_data']))
- {
- $sql = 'UPDATE ' . PRIVMSGS_TABLE . '
- SET message_attachment = 1
- WHERE msg_id = ' . $data['msg_id'];
- $db->sql_query($sql);
- }
-
if ($space_taken && $files_added)
{
set_config('upload_dir_size', $config['upload_dir_size'] + $space_taken, true);
@@ -1553,8 +1587,6 @@ function pm_notification($mode, $author, $recipients, $subject, $message)
include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
$messenger = new messenger();
- $email_sig = str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']);
-
foreach ($msg_list_ary as $pos => $addr)
{
$messenger->template('privmsg_notify', $addr['lang']);
@@ -1564,11 +1596,9 @@ function pm_notification($mode, $author, $recipients, $subject, $message)
$messenger->im($addr['jabber'], $addr['name']);
$messenger->assign_vars(array(
- 'EMAIL_SIG' => $email_sig,
- 'SITENAME' => $config['sitename'],
- 'SUBJECT' => html_entity_decode($subject),
- 'AUTHOR_NAME' => html_entity_decode($author),
- 'USERNAME' => html_entity_decode($addr['name']),
+ 'SUBJECT' => htmlspecialchars_decode($subject),
+ 'AUTHOR_NAME' => htmlspecialchars_decode($author),
+ 'USERNAME' => htmlspecialchars_decode($addr['name']),
'U_INBOX' => generate_board_url() . "/ucp.$phpEx?i=pm&folder=inbox")
);
diff --git a/phpBB/includes/functions_profile_fields.php b/phpBB/includes/functions_profile_fields.php
index 6f71724754..b35781e198 100644
--- a/phpBB/includes/functions_profile_fields.php
+++ b/phpBB/includes/functions_profile_fields.php
@@ -21,7 +21,7 @@ class custom_profile
/**
* Assign editable fields to template, mode can be profile (for profile change) or register (for registration)
* Called by ucp_profile and ucp_register
- * @access: public
+ * @access public
*/
function generate_profile_fields($mode, $lang_id)
{
@@ -74,7 +74,7 @@ class custom_profile
/**
* Validate entered profile field data
- * @access: public
+ * @access public
*/
function validate_profile_field($field_type, &$field_value, $field_data)
{
@@ -161,11 +161,11 @@ class custom_profile
return 'FIELD_REQUIRED';
}
- if ($field_data['field_minlen'] && strlen($field_value) < $field_data['field_minlen'])
+ if ($field_data['field_minlen'] && utf8_strlen($field_value) < $field_data['field_minlen'])
{
return 'FIELD_TOO_SHORT';
}
- else if ($field_data['field_maxlen'] && strlen($field_value) > $field_data['field_maxlen'])
+ else if ($field_data['field_maxlen'] && utf8_strlen($field_value) > $field_data['field_maxlen'])
{
return 'FIELD_TOO_LONG';
}
@@ -186,7 +186,7 @@ class custom_profile
/**
* Build profile cache, used for display
- * @access: private
+ * @access private
*/
function build_cache()
{
@@ -248,7 +248,7 @@ class custom_profile
/**
* Submit profile field
- * @access: public
+ * @access public
*/
function submit_cp_field($mode, $lang_id, &$cp_data, &$cp_error)
{
@@ -286,8 +286,8 @@ class custom_profile
while ($row = $db->sql_fetchrow($result))
{
- $cp_data['_' . $row['field_ident']] = $this->get_profile_field($row);
- $check_value = $cp_data['_' . $row['field_ident']];
+ $cp_data['pf_' . $row['field_ident']] = $this->get_profile_field($row);
+ $check_value = $cp_data['pf_' . $row['field_ident']];
if (($cp_result = $this->validate_profile_field($row['field_type'], $check_value, $row)) !== false)
{
@@ -340,7 +340,7 @@ class custom_profile
/**
* Assign fields to template, used for viewprofile, viewtopic and memberlist (if load setting is enabled)
* This is directly connected to the user -> mode == grab is to grab the user specific fields, mode == show is for assigning the row to the template
- * @access: public
+ * @access public
*/
function generate_profile_fields_template($mode, $user_id = 0, $profile_row = false)
{
@@ -382,7 +382,7 @@ class custom_profile
{
foreach ($field_data as $user_id => $row)
{
- $user_fields[$user_id][$used_ident]['value'] = $row['_' . $used_ident];
+ $user_fields[$user_id][$used_ident]['value'] = $row['pf_' . $used_ident];
$user_fields[$user_id][$used_ident]['data'] = $this->profile_cache[$used_ident];
}
}
@@ -535,14 +535,14 @@ class custom_profile
/**
* Get field value for registration/profile
- * @access: private
+ * @access private
*/
function get_var($field_validation, &$profile_row, $default_value, $preview)
{
global $user;
$profile_row['field_ident'] = (isset($profile_row['var_name'])) ? $profile_row['var_name'] : 'pf_' . $profile_row['field_ident'];
- $user_ident = '_' . str_replace('pf_', '', $profile_row['field_ident']);
+ $user_ident = 'pf_' . str_replace('pf_', '', $profile_row['field_ident']);
// checkbox - only testing for isset
if ($profile_row['field_type'] == FIELD_BOOL && $profile_row['field_length'] == 2)
@@ -576,6 +576,11 @@ class custom_profile
else
{
$value = (isset($_REQUEST[$profile_row['field_ident']])) ? request_var($profile_row['field_ident'], $default_value, true) : ((!isset($user->profile_fields[$user_ident]) || $preview) ? $default_value : $user->profile_fields[$user_ident]);
+
+ if (gettype($value) == 'string')
+ {
+ utf8_normalize_nfc(&$value);
+ }
}
switch ($field_validation)
@@ -590,7 +595,7 @@ class custom_profile
/**
* Process int-type
- * @access: private
+ * @access private
*/
function generate_int($profile_row, $preview = false)
{
@@ -602,14 +607,14 @@ class custom_profile
/**
* Process date-type
- * @access: private
+ * @access private
*/
function generate_date($profile_row, $preview = false)
{
global $user, $template;
$profile_row['field_ident'] = (isset($profile_row['var_name'])) ? $profile_row['var_name'] : 'pf_' . $profile_row['field_ident'];
- $user_ident = '_' . str_replace('pf_', '', $profile_row['field_ident']);
+ $user_ident = 'pf_' . str_replace('pf_', '', $profile_row['field_ident']);
$now = getdate();
@@ -661,7 +666,7 @@ class custom_profile
/**
* Process bool-type
- * @access: private
+ * @access private
*/
function generate_bool($profile_row, $preview = false)
{
@@ -692,7 +697,7 @@ class custom_profile
/**
* Process string-type
- * @access: private
+ * @access private
*/
function generate_string($profile_row, $preview = false)
{
@@ -704,7 +709,7 @@ class custom_profile
/**
* Process text-type
- * @access: private
+ * @access private
*/
function generate_text($profile_row, $preview = false)
{
@@ -721,7 +726,7 @@ class custom_profile
/**
* Process dropdown-type
- * @access: private
+ * @access private
*/
function generate_dropdown($profile_row, $preview = false)
{
@@ -750,7 +755,7 @@ class custom_profile
/**
* Return Templated value/field. Possible values for $mode are:
* change == user is able to set/enter profile values; preview == just show the value
- * @access: private
+ * @access private
*/
function process_field_row($mode, $profile_row)
{
@@ -787,7 +792,7 @@ class custom_profile
$sql_not_in = array();
foreach ($cp_data as $key => $null)
{
- $sql_not_in[] = (strncmp($key, '_', 1) === 0) ? substr($key, 1) : $key;
+ $sql_not_in[] = (strncmp($key, 'pf_', 3) === 0) ? substr($key, 3) : $key;
}
$sql = 'SELECT f.field_type, f.field_ident, f.field_default_value, l.lang_default_value
@@ -805,7 +810,7 @@ class custom_profile
$row['field_default_value'] = sprintf('%2d-%2d-%4d', $now['mday'], $now['mon'], $now['year']);
}
- $cp_data['_' . $row['field_ident']] = (in_array($row['field_type'], array(FIELD_TEXT, FIELD_STRING))) ? $row['lang_default_value'] : $row['field_default_value'];
+ $cp_data['pf_' . $row['field_ident']] = (in_array($row['field_type'], array(FIELD_TEXT, FIELD_STRING))) ? $row['lang_default_value'] : $row['field_default_value'];
}
$db->sql_freeresult($result);
@@ -814,7 +819,7 @@ class custom_profile
/**
* Get profile field value on submit
- * @access: private
+ * @access private
*/
function get_profile_field($profile_row)
{
@@ -861,6 +866,7 @@ class custom_profile
case FIELD_STRING:
case FIELD_TEXT:
$var = request_var($var_name, $profile_row['field_default_value'], true);
+ utf8_normalize_nfc(&$var);
break;
case FIELD_INT:
diff --git a/phpBB/includes/functions_template.php b/phpBB/includes/functions_template.php
index 7f29c2a040..47ff906a28 100644
--- a/phpBB/includes/functions_template.php
+++ b/phpBB/includes/functions_template.php
@@ -52,7 +52,7 @@ class template_compile
/**
* Load template source from file
- * @access: private
+ * @access private
*/
function _tpl_load_file($handle)
{
@@ -82,78 +82,19 @@ class template_compile
*/
function remove_php_tags(&$code)
{
- if (!function_exists('token_get_all'))
- {
- /**
- * If the tokenizer extension is not available, try to load it and if
- * it's still not available we fall back to some pattern replacement.
- *
- * Note that the pattern replacement may affect the well-formedness
- * of the HTML if a PHP tag is found because even if we escape PHP
- * opening tags we do NOT escape PHP closing tags and cannot do so
- * reliably without the use of a full-blown tokenizer.
- *
- * The bottom line is, a template should NEVER contain PHP because it
- * would comprise the security of the installation, that's why we
- * prevent it from being executed. Our job is to secure the installation,
- * not fix unsecure templates. if a template contains some PHP then it
- * should not be used at all.
- */
- @dl('tokenizer');
-
- if (!function_exists('token_get_all'))
- {
- $match = array(
- '\\?php[\n\r\s\t]+',
- '[\\?%]=',
- '[\\?%][^\w]',
- 'script[\n\r\s\t]+language[\n\r\s\t]*=[\n\r\s\t]*[\'"]php[\'"]'
- );
-
- $code = preg_replace('#<(' . implode('|', $match) . ')#is', '&lt;$1', $code);
- return;
- }
- }
-
- do
- {
- $tokens = token_get_all('<?php ?>' . $code);
- $code = '';
- $php_found = false;
-
- foreach ($tokens as $i => $token)
- {
- if (!is_array($token))
- {
- $code .= $token;
- }
- else if ($token[0] == T_OPEN_TAG || $token[0] == T_OPEN_TAG_WITH_ECHO || $token[0] == T_CLOSE_TAG)
- {
- if ($i > 1)
- {
- $code .= htmlspecialchars($token[1]);
- $php_found = true;
- }
- }
- else
- {
- $code .= $token[1];
- }
- }
- unset($tokens);
-
- // Fix for a tokenizer oddity
- if (!strncmp($code, '<?php ?&gt;', 11))
- {
- $code = substr($code, 11);
- }
- }
- while ($php_found);
+ // This matches the information gathered from the internal PHP lexer
+ $match = array(
+ '#<([\?%])=?.*?\1>#s',
+ '#<script\s+language\s*=\s*(["\']?)php\1\s*>.*?</script\s*>#s',
+ '#<\?php(?:\r\n?|[ \n\t]).*?\?>#s'
+ );
+
+ $code = preg_replace($match, '', $code);
}
/**
* The all seeing all doing compile method. Parts are inspired by or directly from Smarty
- * @access: private
+ * @access private
*/
function compile($code, $no_echo = false, $echo_var = '')
{
@@ -169,12 +110,6 @@ class template_compile
// php is a no-no. There is a potential issue here in that non-php
// content may be removed ... however designers should use entities
// if they wish to display < and >
-/*
- $match_php_tags = array('#\<\?php.*?\?\>#is', '#<[^\w<]*(script)(((?:"[^"]*"|\'[^\']*\'|[^<>\'"])+)?(language[^<>\'"]+("[^"]*php[^"]*"|\'[^\']*php[^\']*\'))((?:"[^"]*"|\'[^\']*\'|[^<>\'"])+)?)?>.*?</script>#is', '#\<\?.*?\?\>#s', '#\<%.*?%\>#s');
- $code = preg_replace($match_php_tags, '', $code);
-*/
-
- // An alternative to the above would be calling this function which would be the ultimate solution but also has its drawbacks.
$this->remove_php_tags($code);
// Pull out all block/statement level elements and seperate plain text
@@ -279,14 +214,14 @@ class template_compile
// There will be a number of occassions where we switch into and out of
// PHP mode instantaneously. Rather than "burden" the parser with this
// we'll strip out such occurences, minimising such switching
- $template_php = str_replace(' ?><?php ', '', $template_php);
+ $template_php = str_replace(' ?><?php ', ' ', $template_php);
return (!$no_echo) ? $template_php : "\$$echo_var .= '" . $template_php . "'";
}
/**
* Compile variables
- * @access: private
+ * @access private
*/
function compile_var_tags(&$text_blocks)
{
@@ -328,7 +263,7 @@ class template_compile
/**
* Compile blocks
- * @access: private
+ * @access private
*/
function compile_tag_block($tag_args)
{
@@ -419,7 +354,7 @@ class template_compile
/**
* Compile IF tags - much of this is from Smarty with
* some adaptions for our block level methods
- * @access: private
+ * @access private
*/
function compile_tag_if($tag_args, $elseif)
{
@@ -533,8 +468,10 @@ class template_compile
}
else if (preg_match('#^\.(([a-z0-9\-_]+\.?)+)$#s', $token, $varrefs))
{
+ // Allow checking if loops are set with .loopname
+ // It is also possible to check the loop count by doing <!-- IF .loopname > 1 --> for example
$_tok = $this->generate_block_data_ref($varrefs[1], false);
- $token = "(isset($_tok) && sizeof($_tok))";
+ $token = "sizeof($_tok)";
}
break;
@@ -546,7 +483,7 @@ class template_compile
/**
* Compile DEFINE tags
- * @access: private
+ * @access private
*/
function compile_tag_define($tag_args, $op)
{
@@ -599,7 +536,7 @@ class template_compile
/**
* Compile INCLUDE tag
- * @access: private
+ * @access private
*/
function compile_tag_include($tag_args)
{
@@ -608,21 +545,21 @@ class template_compile
/**
* Compile INCLUDE_PHP tag
- * @access: private
+ * @access private
*/
function compile_tag_include_php($tag_args)
{
- return "include('" . $this->template->root . '/' . $tag_args . "');";
+ return "include('" . $tag_args . "');";
}
/**
* parse expression
* This is from Smarty
- * @access: private
+ * @access private
*/
function _parse_is_expr($is_arg, $tokens)
{
- $expr_end = 0;
+ $expr_end = 0;
$negate_expr = false;
if (($first_token = array_shift($tokens)) == 'not')
@@ -641,12 +578,12 @@ class template_compile
if (@$tokens[$expr_end] == 'by')
{
$expr_end++;
- $expr_arg = $tokens[$expr_end++];
- $expr = "!(($is_arg / $expr_arg) % $expr_arg)";
+ $expr_arg = $tokens[$expr_end++];
+ $expr = "!(($is_arg / $expr_arg) % $expr_arg)";
}
else
{
- $expr = "!($is_arg % 2)";
+ $expr = "!($is_arg % 2)";
}
break;
@@ -654,12 +591,12 @@ class template_compile
if (@$tokens[$expr_end] == 'by')
{
$expr_end++;
- $expr_arg = $tokens[$expr_end++];
- $expr = "(($is_arg / $expr_arg) % $expr_arg)";
+ $expr_arg = $tokens[$expr_end++];
+ $expr = "(($is_arg / $expr_arg) % $expr_arg)";
}
else
{
- $expr = "($is_arg % 2)";
+ $expr = "($is_arg % 2)";
}
break;
@@ -667,18 +604,18 @@ class template_compile
if (@$tokens[$expr_end] == 'by')
{
$expr_end++;
- $expr_arg = $tokens[$expr_end++];
- $expr = "!($is_arg % $expr_arg)";
+ $expr_arg = $tokens[$expr_end++];
+ $expr = "!($is_arg % $expr_arg)";
}
break;
}
if ($negate_expr)
{
- $expr = "!($expr)";
+ $expr = "!($expr)";
}
- array_splice($tokens, 0, $expr_end, $expr);
+ array_splice($tokens, 0, $expr_end, $expr);
return $tokens;
}
@@ -689,7 +626,7 @@ class template_compile
* ' . $this->_tpldata['parent'][$_parent_i]['$child1'][$_child1_i]['$child2'][$_child2_i]...['varname'] . '
* It's ready to be inserted into an "echo" line in one of the templates.
* NOTE: expects a trailing "." on the namespace.
- * @access: private
+ * @access private
*/
function generate_block_varref($namespace, $varname, $echo = true, $defop = false)
{
@@ -714,7 +651,7 @@ class template_compile
*
* If $include_last_iterator is true, then [$_childN_i] will be appended to the form shown above.
* NOTE: does not expect a trailing "." on the blockname.
- * @access: private
+ * @access private
*/
function generate_block_data_ref($blockname, $include_last_iterator, $defop = false)
{
@@ -743,7 +680,7 @@ class template_compile
/**
* Write compiled file to cache directory
- * @access: private
+ * @access private
*/
function compile_write(&$handle, $data)
{
diff --git a/phpBB/includes/functions_transfer.php b/phpBB/includes/functions_transfer.php
index d2cc95f728..00ef78f933 100644
--- a/phpBB/includes/functions_transfer.php
+++ b/phpBB/includes/functions_transfer.php
@@ -189,6 +189,24 @@ class transfer
}
/**
+ * Check if a specified file exist...
+ */
+ function file_exists($directory, $filename)
+ {
+ global $phpbb_root_path;
+
+ $directory = $this->root_path . str_replace($phpbb_root_path, '', $directory);
+ $result = $this->_ls($directory);
+
+ if ($result !== false && is_array($result))
+ {
+ return (in_array($filename, $result)) ? true : false;
+ }
+
+ return false;
+ }
+
+ /**
* Open session
*/
function open_session()
@@ -245,7 +263,7 @@ class ftp extends transfer
// Make sure $this->root_path is layed out the same way as the $user->page['root_script_path'] value (/ at the end)
$this->root_path = str_replace('\\', '/', $this->root_path);
- $this->root_path = (($root_path{0} != '/' ) ? '/' : '') . $root_path . ((substr($root_path, -1, 1) == '/') ? '' : '/');
+ $this->root_path = (($root_path[0] != '/' ) ? '/' : '') . $root_path . ((substr($root_path, -1, 1) == '/') ? '' : '/');
// Init some needed values
transfer::transfer();
@@ -272,7 +290,7 @@ class ftp extends transfer
/**
* Init FTP Session
- * @access: private
+ * @access private
*/
function _init()
{
@@ -304,7 +322,7 @@ class ftp extends transfer
/**
* Create Directory (MKDIR)
- * @access: private
+ * @access private
*/
function _mkdir($dir)
{
@@ -313,7 +331,7 @@ class ftp extends transfer
/**
* Remove directory (RMDIR)
- * @access: private
+ * @access private
*/
function _rmdir($dir)
{
@@ -322,7 +340,7 @@ class ftp extends transfer
/**
* Rename file
- * @access: private
+ * @access private
*/
function _rename($old_handle, $new_handle)
{
@@ -331,7 +349,7 @@ class ftp extends transfer
/**
* Change current working directory (CHDIR)
- * @access: private
+ * @access private
*/
function _chdir($dir = '')
{
@@ -345,7 +363,7 @@ class ftp extends transfer
/**
* change file permissions (CHMOD)
- * @access: private
+ * @access private
*/
function _chmod($file, $perms)
{
@@ -364,7 +382,7 @@ class ftp extends transfer
/**
* Upload file to location (PUT)
- * @access: private
+ * @access private
*/
function _put($from_file, $to_file)
{
@@ -386,7 +404,7 @@ class ftp extends transfer
/**
* Delete file (DELETE)
- * @access: private
+ * @access private
*/
function _delete($file)
{
@@ -395,7 +413,7 @@ class ftp extends transfer
/**
* Close ftp session (CLOSE)
- * @access: private
+ * @access private
*/
function _close()
{
@@ -410,7 +428,7 @@ class ftp extends transfer
/**
* Return current working directory (CWD)
* At the moment not used by parent class
- * @access: private
+ * @access private
*/
function _cwd()
{
@@ -419,8 +437,7 @@ class ftp extends transfer
/**
* Return list of files in a given directory (LS)
- * At the moment not used by parent class
- * @access: private
+ * @access private
*/
function _ls($dir = './')
{
@@ -429,7 +446,7 @@ class ftp extends transfer
/**
* FTP SITE command (ftp-only function)
- * @access: private
+ * @access private
*/
function _site($command)
{
@@ -458,9 +475,9 @@ class ftp_fsock extends transfer
$this->password = $password;
$this->timeout = $timeout;
- // Make sure $this->root_path is layed out the same way as the $user->page['root_script_path'] value (prefixed with / and no / at the end)
+ // Make sure $this->root_path is layed out the same way as the $user->page['root_script_path'] value (/ at the end)
$this->root_path = str_replace('\\', '/', $this->root_path);
- $this->root_path = (($root_path{0} != '/' ) ? '/' : '') . $root_path . ((substr($root_path, -1, 1) == '/') ? '' : '/');
+ $this->root_path = (($root_path[0] != '/' ) ? '/' : '') . $root_path . ((substr($root_path, -1, 1) == '/') ? '' : '/');
// Init some needed values
transfer::transfer();
@@ -487,7 +504,7 @@ class ftp_fsock extends transfer
/**
* Init FTP Session
- * @access: private
+ * @access private
*/
function _init()
{
@@ -526,7 +543,7 @@ class ftp_fsock extends transfer
/**
* Create Directory (MKDIR)
- * @access: private
+ * @access private
*/
function _mkdir($dir)
{
@@ -535,7 +552,7 @@ class ftp_fsock extends transfer
/**
* Remove directory (RMDIR)
- * @access: private
+ * @access private
*/
function _rmdir($dir)
{
@@ -544,7 +561,7 @@ class ftp_fsock extends transfer
/**
* Rename File
- * @access: private
+ * @access private
*/
function _rename($old_handle, $new_handle)
{
@@ -554,7 +571,7 @@ class ftp_fsock extends transfer
/**
* Change current working directory (CHDIR)
- * @access: private
+ * @access private
*/
function _chdir($dir = '')
{
@@ -568,7 +585,7 @@ class ftp_fsock extends transfer
/**
* change file permissions (CHMOD)
- * @access: private
+ * @access private
*/
function _chmod($file, $perms)
{
@@ -577,7 +594,7 @@ class ftp_fsock extends transfer
/**
* Upload file to location (PUT)
- * @access: private
+ * @access private
*/
function _put($from_file, $to_file)
{
@@ -613,7 +630,7 @@ class ftp_fsock extends transfer
/**
* Delete file (DELETE)
- * @access: private
+ * @access private
*/
function _delete($file)
{
@@ -622,7 +639,7 @@ class ftp_fsock extends transfer
/**
* Close ftp session (CLOSE)
- * @access: private
+ * @access private
*/
function _close()
{
@@ -637,7 +654,7 @@ class ftp_fsock extends transfer
/**
* Return current working directory (CWD)
* At the moment not used by parent class
- * @access: private
+ * @access private
*/
function _cwd()
{
@@ -647,8 +664,7 @@ class ftp_fsock extends transfer
/**
* Return list of files in a given directory (LS)
- * At the moment not used by parent class
- * @access: private
+ * @access private
*/
function _ls($dir = './')
{
@@ -671,7 +687,7 @@ class ftp_fsock extends transfer
/**
* Send a command to server (FTP fsock only function)
- * @access: private
+ * @access private
*/
function _send_command($command, $args = '', $check = true)
{
@@ -692,7 +708,7 @@ class ftp_fsock extends transfer
/**
* Opens a connection to send data (FTP fosck only function)
- * @access: private
+ * @access private
*/
function _open_data_connection()
{
@@ -727,7 +743,7 @@ class ftp_fsock extends transfer
/**
* Closes a connection used to send data
- * @access: private
+ * @access private
*/
function _close_data_connection()
{
@@ -736,7 +752,7 @@ class ftp_fsock extends transfer
/**
* Check to make sure command was successful (FTP fsock only function)
- * @access: private
+ * @access private
*/
function _check_command($return = false)
{
diff --git a/phpBB/includes/functions_upload.php b/phpBB/includes/functions_upload.php
index 28701339e4..a7a76cf526 100644
--- a/phpBB/includes/functions_upload.php
+++ b/phpBB/includes/functions_upload.php
@@ -38,7 +38,7 @@ class filespec
/**
* File Class
- * @access: private
+ * @access private
*/
function filespec($upload_ary, $upload_namespace)
{
@@ -138,7 +138,7 @@ class filespec
/**
* Check if the file got correctly uploaded
*
- * @return true if it is a valid upload and the file exist, false if not
+ * @return true if it is a valid upload, false if not
*/
function is_uploaded()
{
@@ -147,7 +147,12 @@ class filespec
return false;
}
- return (file_exists($this->filename)) ? true : false;
+ if ($this->local && !file_exists($this->filename))
+ {
+ return false;
+ }
+
+ return true;
}
/**
@@ -221,24 +226,27 @@ class filespec
return false;
}
- // Adjust destination path (no trailing slash)
- if ($destination{(sizeof($destination)-1)} == '/' || $destination{(sizeof($destination)-1)} == '\\')
- {
- $destination = substr($destination, 0, sizeof($destination)-2);
- }
+ // We need to trust the admin in specifying valid upload directories and an attacker not being able to overwrite it...
+ $this->destination_path = $phpbb_root_path . $destination;
- $destination = str_replace(array('../', '..\\', './', '.\\'), '', $destination);
- if ($destination && ($destination{0} == '/' || $destination{0} == "\\"))
+ // Check if the destination path exist...
+ if (!file_exists($this->destination_path))
{
- $destination = '';
+ @unlink($this->filename);
+ return false;
}
- $this->destination_path = $phpbb_root_path . $destination;
-
$upload_mode = (@ini_get('open_basedir') || @ini_get('safe_mode')) ? 'move' : 'copy';
$upload_mode = ($this->local) ? 'local' : $upload_mode;
$this->destination_file = $this->destination_path . '/' . basename($this->realname);
+ // Check if the file already exist, else there is something wrong...
+ if (file_exists($this->destination_file))
+ {
+ @unlink($this->filename);
+ return false;
+ }
+
switch ($upload_mode)
{
case 'copy':
@@ -305,6 +313,25 @@ class filespec
{
$this->mimetype = $this->image_info['mime'];
}
+
+ // Check image type
+ $types = $this->upload->image_types();
+
+ if (!isset($types[$this->image_info[2]]) || !in_array($this->extension, $types[$this->image_info[2]]))
+ {
+ if (!isset($types[$this->image_info[2]]))
+ {
+ $this->error[] = sprintf($user->lang['IMAGE_FILETYPE_INVALID'], $this->image_info[2], $this->mimetype);
+ }
+ else
+ {
+ $this->error[] = sprintf($user->lang['IMAGE_FILETYPE_MISMATCH'], $types[$this->image_info[2]][0], $this->extension);
+ }
+ }
+ }
+ else
+ {
+ $this->error[] = $user->lang['UNABLE_GET_IMAGE_SIZE'];
}
}
@@ -790,6 +817,31 @@ class fileupload
{
return (isset($_FILES[$form_name]) && $_FILES[$form_name]['name'] != 'none') ? true : false;
}
+
+ /**
+ * Return image type/extension mapping
+ */
+ function image_types()
+ {
+ return array(
+ 1 => array('gif'),
+ 2 => array('jpg', 'jpeg'),
+ 3 => array('png'),
+ 4 => array('swf'),
+ 5 => array('psd'),
+ 6 => array('bmp'),
+ 7 => array('tif', 'tiff'),
+ 8 => array('tif', 'tiff'),
+ 9 => array('jpg', 'jpeg'),
+ 10 => array('jpg', 'jpeg'),
+ 11 => array('jpg', 'jpeg'),
+ 12 => array('jpg', 'jpeg'),
+ 13 => array('swc'),
+ 14 => array('iff'),
+ 15 => array('wbmp'),
+ 16 => array('xbm'),
+ );
+ }
}
?> \ No newline at end of file
diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php
index c03e92d0b0..15daa0c999 100644
--- a/phpBB/includes/functions_user.php
+++ b/phpBB/includes/functions_user.php
@@ -12,7 +12,7 @@
* Obtain user_ids from usernames or vice versa. Returns false on
* success else the error string
*/
-function user_get_id_name(&$user_id_ary, &$username_ary)
+function user_get_id_name(&$user_id_ary, &$username_ary, $only_active = false)
{
global $db;
@@ -34,16 +34,22 @@ function user_get_id_name(&$user_id_ary, &$username_ary)
$$which_ary = array($$which_ary);
}
- $sql_in = ($which_ary == 'user_id_ary') ? array_map('intval', $$which_ary) : $$which_ary;
+ $sql_in = ($which_ary == 'user_id_ary') ? array_map('intval', $$which_ary) : array_map('utf8_clean_string', $$which_ary);
unset($$which_ary);
$user_id_ary = $username_ary = array();
// Grab the user id/username records
- $sql_where = ($which_ary == 'user_id_ary') ? 'user_id' : 'username';
+ $sql_where = ($which_ary == 'user_id_ary') ? 'user_id' : 'username_clean';
$sql = 'SELECT user_id, username
FROM ' . USERS_TABLE . '
WHERE ' . $db->sql_in_set($sql_where, $sql_in);
+
+ if ($only_active)
+ {
+ $sql .= ' AND user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')';
+ }
+
$result = $db->sql_query($sql);
if (!($row = $db->sql_fetchrow($result)))
@@ -134,6 +140,7 @@ function user_add($user_row, $cp_data = false)
$sql_ary = array(
'username' => $user_row['username'],
+ 'username_clean' => utf8_clean_string($user_row['username']),
'user_password' => (isset($user_row['user_password'])) ? $user_row['user_password'] : '',
'user_email' => $user_row['user_email'],
'user_email_hash' => (int) crc32(strtolower($user_row['user_email'])) . strlen($user_row['user_email']),
@@ -141,10 +148,6 @@ function user_add($user_row, $cp_data = false)
'user_type' => $user_row['user_type'],
);
- /**
- * @todo user_allow_email is not used anywhere. Think about removing it.
- */
-
// These are the additional vars able to be specified
$additional_vars = array(
'user_permissions' => '',
@@ -156,7 +159,10 @@ function user_add($user_row, $cp_data = false)
'user_actkey' => '',
'user_ip' => '',
'user_regdate' => time(),
+ 'user_passchg' => time(),
+ 'user_inactive_reason' => 0,
+ 'user_inactive_time' => 0,
'user_lastmark' => time(),
'user_lastvisit' => 0,
'user_lastpost_time' => 0,
@@ -164,6 +170,7 @@ function user_add($user_row, $cp_data = false)
'user_posts' => 0,
'user_dst' => 0,
'user_colour' => '',
+ 'user_interests' => '',
'user_avatar' => '',
'user_avatar_type' => 0,
'user_avatar_width' => 0,
@@ -179,7 +186,6 @@ function user_add($user_row, $cp_data = false)
'user_notify_pm' => 1,
'user_notify_type' => NOTIFY_EMAIL,
'user_allow_pm' => 1,
- 'user_allow_email' => 1,
'user_allow_viewonline' => 1,
'user_allow_viewemail' => 1,
'user_allow_massemail' => 1,
@@ -254,39 +260,67 @@ function user_add($user_row, $cp_data = false)
*/
function user_delete($mode, $user_id, $post_username = false)
{
- global $config, $db, $user, $auth;
+ global $cache, $config, $db, $user, $auth;
+ global $phpbb_root_path, $phpEx;
$db->sql_transaction('begin');
switch ($mode)
{
case 'retain':
+
+ if ($post_username === false)
+ {
+ $post_username = $user->lang['GUEST'];
+ }
+
$sql = 'UPDATE ' . FORUMS_TABLE . '
- SET forum_last_poster_id = ' . ANONYMOUS . (($post_username !== false) ? ", forum_last_poster_name = '" . $db->sql_escape($post_username) . "'" : '') . "
+ SET forum_last_poster_id = ' . ANONYMOUS . ", forum_last_poster_name = '" . $db->sql_escape($post_username) . "', forum_last_poster_colour = ''
WHERE forum_last_poster_id = $user_id";
$db->sql_query($sql);
$sql = 'UPDATE ' . POSTS_TABLE . '
- SET poster_id = ' . ANONYMOUS . (($post_username !== false) ? ", post_username = '" . $db->sql_escape($post_username) . "'" : '') . "
+ SET poster_id = ' . ANONYMOUS . ", post_username = '" . $db->sql_escape($post_username) . "'
WHERE poster_id = $user_id";
$db->sql_query($sql);
+ $sql = 'UPDATE ' . POSTS_TABLE . '
+ SET post_edit_user = ' . ANONYMOUS . "
+ WHERE post_edit_user = $user_id";
+ $db->sql_query($sql);
+
$sql = 'UPDATE ' . TOPICS_TABLE . '
- SET topic_poster = ' . ANONYMOUS . "
+ SET topic_poster = ' . ANONYMOUS . ", topic_first_poster_name = '" . $db->sql_escape($post_username) . "', topic_first_poster_colour = ''
WHERE topic_poster = $user_id";
$db->sql_query($sql);
$sql = 'UPDATE ' . TOPICS_TABLE . '
- SET topic_last_poster_id = ' . ANONYMOUS . (($post_username !== false) ? ", topic_last_poster_name = '" . $db->sql_escape($post_username) . "'" : '') . "
+ SET topic_last_poster_id = ' . ANONYMOUS . ", topic_last_poster_name = '" . $db->sql_escape($post_username) . "', topic_last_poster_colour = ''
WHERE topic_last_poster_id = $user_id";
$db->sql_query($sql);
+
+ // Since we change every post by this author, we need to count this amount towards the anonymous user
+ $sql = 'SELECT user_posts
+ FROM ' . USERS_TABLE . '
+ WHERE user_id = ' . $user_id;
+ $result = $db->sql_query($sql);
+ $num_posts = (int) $db->sql_fetchfield('user_posts');
+ $db->sql_freeresult($result);
+
+ // Update the post count for the anonymous user
+ if ($num_posts)
+ {
+ $sql = 'UPDATE ' . USERS_TABLE . '
+ SET user_posts = user_posts + ' . $num_posts . '
+ WHERE user_id = ' . ANONYMOUS;
+ $db->sql_query($sql);
+ }
break;
case 'remove':
if (!function_exists('delete_posts'))
{
- global $phpbb_root_path, $phpEx;
include_once($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
}
@@ -334,7 +368,7 @@ function user_delete($mode, $user_id, $post_username = false)
break;
}
- $table_ary = array(USERS_TABLE, USER_GROUP_TABLE, TOPICS_WATCH_TABLE, FORUMS_WATCH_TABLE, ACL_USERS_TABLE, TOPICS_TRACK_TABLE, TOPICS_POSTED_TABLE, FORUMS_TRACK_TABLE, PROFILE_FIELDS_DATA_TABLE);
+ $table_ary = array(USERS_TABLE, USER_GROUP_TABLE, TOPICS_WATCH_TABLE, FORUMS_WATCH_TABLE, ACL_USERS_TABLE, TOPICS_TRACK_TABLE, TOPICS_POSTED_TABLE, FORUMS_TRACK_TABLE, PROFILE_FIELDS_DATA_TABLE, MODERATOR_CACHE_TABLE);
foreach ($table_ary as $table)
{
@@ -343,6 +377,67 @@ function user_delete($mode, $user_id, $post_username = false)
$db->sql_query($sql);
}
+ $cache->destroy('sql', MODERATOR_CACHE_TABLE);
+
+ include_once($phpbb_root_path . 'includes/functions_privmsgs.' . $phpEx);
+
+ // Remove any undelivered mails...
+ $sql = 'SELECT msg_id, user_id
+ FROM ' . PRIVMSGS_TO_TABLE . '
+ WHERE author_id = ' . $user_id . '
+ AND folder_id = ' . PRIVMSGS_NO_BOX;
+ $result = $db->sql_query($sql);
+
+ $undelivered_msg = $undelivered_user = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $undelivered_msg[] = $row['msg_id'];
+ $undelivered_user[$row['user_id']][] = true;
+ }
+ $db->sql_freeresult($result);
+
+ if (sizeof($undelivered_msg))
+ {
+ $sql = 'DELETE FROM ' . PRIVMSGS_TABLE . '
+ WHERE ' . $db->sql_in_set('msg_id', $undelivered_msg);
+ $db->sql_query($sql);
+ }
+
+ $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . '
+ WHERE author_id = ' . $user_id . '
+ AND folder_id = ' . PRIVMSGS_NO_BOX;
+ $db->sql_query($sql);
+
+ // Delete all to-informations
+ $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . '
+ WHERE user_id = ' . $user_id;
+ $db->sql_query($sql);
+
+ // Set the remaining author id to anonymous - this way users are still able to read messages from users being removed
+ $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
+ SET author_id = ' . ANONYMOUS . '
+ WHERE author_id = ' . $user_id;
+ $db->sql_query($sql);
+
+ $sql = 'UPDATE ' . PRIVMSGS_TABLE . '
+ SET author_id = ' . ANONYMOUS . '
+ WHERE author_id = ' . $user_id;
+ $db->sql_query($sql);
+
+ foreach ($undelivered_user as $_user_id => $ary)
+ {
+ if ($_user_id == $user_id)
+ {
+ continue;
+ }
+
+ $sql = 'UPDATE ' . USERS_TABLE . '
+ SET user_new_privmsg = user_new_privmsg - ' . sizeof($ary) . ',
+ user_unread_privmsg = user_unread_privmsg - ' . sizeof($ary) . '
+ WHERE user_id = ' . $_user_id;
+ $db->sql_query($sql);
+ }
+
// Reset newest user info if appropriate
if ($config['newest_user_id'] == $user_id)
{
@@ -351,98 +446,96 @@ function user_delete($mode, $user_id, $post_username = false)
set_config('num_users', $config['num_users'] - 1, true);
- // Adjust last post info...
-
-
$db->sql_transaction('commit');
return false;
}
/**
-* Flips user_type from active to inactive and vice versa, handles
-* group membership updates
+* Flips user_type from active to inactive and vice versa, handles group membership updates
+*
+* @param string $mode can be flip for flipping from active/inactive, activate or deactivate
*/
-function user_active_flip($user_id, $user_type, $user_actkey = false, $username = false, $no_log = false)
+function user_active_flip($mode, $user_id_ary, $reason = INACTIVE_MANUAL)
{
- global $db, $user, $auth;
+ global $config, $db, $user, $auth;
- $sql = 'SELECT group_id, group_name
- FROM ' . GROUPS_TABLE . "
- WHERE group_name IN ('REGISTERED', 'REGISTERED_COPPA', 'INACTIVE', 'INACTIVE_COPPA')";
- $result = $db->sql_query($sql);
+ $deactivated = $activated = 0;
+ $sql_statements = array();
- $group_id_ary = array();
- while ($row = $db->sql_fetchrow($result))
+ if (!is_array($user_id_ary))
{
- $group_id_ary[$row['group_name']] = $row['group_id'];
+ $user_id_ary = array($user_id_ary);
+ }
+
+ if (!sizeof($user_id_ary))
+ {
+ return;
}
- $db->sql_freeresult($result);
- $sql = 'SELECT group_id
- FROM ' . USER_GROUP_TABLE . "
- WHERE user_id = $user_id";
+ $sql = 'SELECT user_id, group_id, user_type, user_inactive_reason
+ FROM ' . USERS_TABLE . '
+ WHERE ' . $db->sql_in_set('user_id', $user_id_ary);
$result = $db->sql_query($sql);
- $group_name = ($user_type == USER_NORMAL) ? 'REGISTERED' : 'INACTIVE';
while ($row = $db->sql_fetchrow($result))
{
- if ($name = array_search($row['group_id'], $group_id_ary))
+ $sql_ary = array();
+
+ if ($row['user_type'] == USER_IGNORE || $row['user_type'] == USER_FOUNDER ||
+ ($mode == 'activate' && $row['user_type'] != USER_INACTIVE) ||
+ ($mode == 'deactivate' && $row['user_type'] == USER_INACTIVE))
{
- $group_name = $name;
- break;
+ continue;
}
- }
- $db->sql_freeresult($result);
- $current_group = ($user_type == USER_NORMAL) ? 'REGISTERED' : 'INACTIVE';
- $switch_group = ($user_type == USER_NORMAL) ? 'INACTIVE' : 'REGISTERED';
+ if ($row['user_type'] == USER_INACTIVE)
+ {
+ $activated++;
+ }
+ else
+ {
+ $deactivated++;
- $new_group_id = $group_id_ary[str_replace($current_group, $switch_group, $group_name)];
+ // Remove the users session key...
+ $user->reset_login_keys($row['user_id']);
+ }
- $sql = 'UPDATE ' . USER_GROUP_TABLE . "
- SET group_id = $new_group_id
- WHERE user_id = $user_id
- AND group_id = " . $group_id_ary[$group_name];
- $db->sql_query($sql);
+ $sql_ary += array(
+ 'user_type' => ($row['user_type'] == USER_NORMAL) ? USER_INACTIVE : USER_NORMAL,
+ 'user_inactive_time' => ($row['user_type'] == USER_NORMAL) ? time() : 0,
+ 'user_inactive_reason' => ($row['user_type'] == USER_NORMAL) ? $reason : 0,
+ );
- $sql_ary = array(
- 'user_type' => ($user_type == USER_NORMAL) ? USER_INACTIVE : USER_NORMAL
- );
+ $sql_statements[$row['user_id']] = $sql_ary;
+ }
+ $db->sql_freeresult($result);
- if ($new_group_id == $group_id_ary[$group_name])
+ if (sizeof($sql_statements))
{
- $sql_ary['group_id'] = $new_group_id;
+ foreach ($sql_statements as $user_id => $sql_ary)
+ {
+ $sql = 'UPDATE ' . USERS_TABLE . '
+ SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
+ WHERE user_id = ' . $user_id;
+ $db->sql_query($sql);
+ }
+
+ $auth->acl_clear_prefetch(array_keys($sql_statements));
}
- if ($user_actkey !== false)
+ if ($deactivated)
{
- $sql_ary['user_actkey'] = $user_actkey;
+ set_config('num_users', $config['num_users'] - $deactivated, true);
}
- $sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . "
- WHERE user_id = $user_id";
- $db->sql_query($sql);
-
- $auth->acl_clear_prefetch($user_id);
-
- if (!$no_log)
+ if ($activated)
{
- if ($username === false)
- {
- $sql = 'SELECT username
- FROM ' . USERS_TABLE . "
- WHERE user_id = $user_id";
- $result = $db->sql_query($sql);
- $username = (string) $db->sql_fetchfield('username');
- $db->sql_freeresult($result);
- }
-
- $log = ($user_type == USER_NORMAL) ? 'LOG_USER_INACTIVE' : 'LOG_USER_ACTIVE';
- add_log('admin', $log, $username);
+ set_config('num_users', $config['num_users'] + $activated, true);
}
- return false;
+ // Update latest username
+ update_last_username();
}
/**
@@ -528,7 +621,7 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas
$username = trim($username);
if ($username != '')
{
- $sql_usernames[] = strtolower($username);
+ $sql_usernames[] = utf8_clean_string($username);
}
}
@@ -540,11 +633,16 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas
$sql = 'SELECT user_id
FROM ' . USERS_TABLE . '
- WHERE ' . $db->sql_in_set('LOWER(username)', $sql_usernames);
+ WHERE ' . $db->sql_in_set('username_clean', $sql_usernames);
+ // Do not allow banning yourself
if (sizeof($founder))
{
- $sql .= ' AND ' . $db->sql_in_set('user_id', array_keys($founder), true);
+ $sql .= ' AND ' . $db->sql_in_set('user_id', array_merge(array_keys($founder), array($user->data['user_id'])), true);
+ }
+ else
+ {
+ $sql .= ' AND user_id <> ' . $user->data['user_id'];
}
$result = $db->sql_query($sql);
@@ -736,24 +834,7 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas
);
}
- if (sizeof($sql_ary))
- {
- switch (SQL_LAYER)
- {
- case 'mysql':
- case 'mysql4':
- case 'mysqli':
- $db->sql_query('INSERT INTO ' . BANLIST_TABLE . ' ' . $db->sql_build_array('MULTI_INSERT', $sql_ary));
- break;
-
- default:
- foreach ($sql_ary as $ary)
- {
- $db->sql_query('INSERT INTO ' . BANLIST_TABLE . ' ' . $db->sql_build_array('INSERT', $ary));
- }
- break;
- }
- }
+ $db->sql_multi_insert(BANLIST_TABLE, $sql_ary);
// If we are banning we want to logout anyone matching the ban
if (!$ban_exclude)
@@ -973,11 +1054,11 @@ function validate_string($string, $optional = false, $min = 0, $max = 0)
return false;
}
- if ($min && strlen($string) < $min)
+ if ($min && utf8_strlen(htmlspecialchars_decode($string)) < $min)
{
return 'TOO_SHORT';
}
- else if ($max && strlen($string) > $max)
+ else if ($max && utf8_strlen(htmlspecialchars_decode($string)) > $max)
{
return 'TOO_LONG';
}
@@ -1034,25 +1115,28 @@ function validate_match($string, $optional = false, $match)
* Also checks if it includes the " character, which we don't allow in usernames.
* Used for registering, changing names, and posting anonymously with a username
*
+* @todo do we really check and disallow the " character in usernames as written above. Has it only be forgotten to include the check?
* @return boolean|string Either false if validation succeeded or a string which will be used as the error message (with the variable name appended)
*/
function validate_username($username)
{
- global $config, $db, $user;
+ global $config, $db, $user, $cache;
- if (strtolower($user->data['username']) == strtolower($username))
+ $clean_username = utf8_clean_string($username);
+
+ if (utf8_clean_string($user->data['username']) == $clean_username)
{
return false;
}
- if (!preg_match('#^' . str_replace('\\\\', '\\', $config['allow_name_chars']) . '$#i', $username))
+ if (!preg_match('#^' . str_replace('\\\\', '\\', $config['allow_name_chars']) . '$#i', $username) || strpos($username, '&quot;') !== false || strpos($username, '"') !== false)
{
return 'INVALID_CHARS';
}
$sql = 'SELECT username
FROM ' . USERS_TABLE . "
- WHERE LOWER(username) = '" . strtolower($db->sql_escape($username)) . "'";
+ WHERE username_clean = '" . $db->sql_escape($clean_username) . "'";
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
@@ -1064,7 +1148,7 @@ function validate_username($username)
$sql = 'SELECT group_name
FROM ' . GROUPS_TABLE . "
- WHERE LOWER(group_name) = '" . strtolower($db->sql_escape($username)) . "'";
+ WHERE LOWER(group_name) = '" . $db->sql_escape(utf8_strtolower($username)) . "'";
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
@@ -1074,19 +1158,16 @@ function validate_username($username)
return 'USERNAME_TAKEN';
}
- $sql = 'SELECT disallow_username
- FROM ' . DISALLOW_TABLE;
- $result = $db->sql_query($sql);
- while ($row = $db->sql_fetchrow($result))
+ $bad_usernames = $cache->obtain_disallowed_usernames();
+
+ foreach ($bad_usernames as $bad_username)
{
- if (preg_match('#^' . str_replace('%', '.*?', preg_quote($row['disallow_username'], '$#')) . '#i', $username))
+ if (preg_match('#^' . $bad_username . '#', $clean_username))
{
- $db->sql_freeresult($result);
return 'USERNAME_DISALLOWED';
}
}
- $db->sql_freeresult($result);
$sql = 'SELECT word
FROM ' . WORDS_TABLE;
@@ -1106,6 +1187,29 @@ function validate_username($username)
}
/**
+* Check to see if the password meets the complexity settings
+*
+* @return boolean|string Either false if validation succeeded or a string which will be used as the error message (with the variable name appended)
+*/
+function validate_password($password)
+{
+ global $config, $db, $user;
+
+ if (!$password)
+ {
+ return false;
+ }
+
+ // We only check for existance of characters
+ if (!preg_match('#' . str_replace('\\\\', '\\', $config['pass_complex']) . '#i', $password))
+ {
+ return 'INVALID_CHARS';
+ }
+
+ return false;
+}
+
+/**
* Check to see if email address is banned or already present in the DB
*
* @return boolean|string Either false if validation succeeded or a string which will be used as the error message (with the variable name appended)
@@ -1124,6 +1228,18 @@ function validate_email($email)
return 'EMAIL_INVALID';
}
+ // Check MX record.
+ // The idea for this is from reading the UseBB blog/announcement. :)
+ if ($config['email_check_mx'])
+ {
+ list(, $domain) = explode('@', $email);
+
+ if (phpbb_checkdnsrr($domain, 'MX') === false)
+ {
+ return 'DOMAIN_NO_MX_RECORD';
+ }
+ }
+
if ($user->check_ban(false, false, $email, true) == true)
{
return 'EMAIL_BANNED';
@@ -1150,13 +1266,23 @@ function validate_email($email)
/**
* Remove avatar
*/
-function avatar_delete($id)
+function avatar_delete($mode, $row)
{
global $phpbb_root_path, $config, $db, $user;
- if (file_exists($phpbb_root_path . $config['avatar_path'] . '/' . basename($id)))
+ // Check if the users avatar is actually *not* a group avatar
+ if ($mode == 'user')
{
- @unlink($phpbb_root_path . $config['avatar_path'] . '/' . basename($id));
+ if (strpos($row['user_avatar'], 'g' . $row['group_id'] . '_') === 0 || strpos($row['user_avatar'], $row['user_id'] . '_') !== 0)
+ {
+ return false;
+ }
+ }
+
+ if (file_exists($phpbb_root_path . $config['avatar_path'] . '/' . basename($row[$mode . '_avatar'])))
+ {
+ @unlink($phpbb_root_path . $config['avatar_path'] . '/' . basename($row[$mode . '_avatar']));
+ return true;
}
return false;
@@ -1167,7 +1293,7 @@ function avatar_delete($id)
*/
function avatar_remote($data, &$error)
{
- global $config, $db, $user, $phpbb_root_path;
+ global $config, $db, $user, $phpbb_root_path, $phpEx;
if (!preg_match('#^(http|https|ftp)://#i', $data['remotelink']))
{
@@ -1196,6 +1322,24 @@ function avatar_remote($data, &$error)
return false;
}
+ // Check image type
+ include_once($phpbb_root_path . 'includes/functions_upload.' . $phpEx);
+ $types = fileupload::image_types();
+ $extension = strtolower(filespec::get_extension($data['remotelink']));
+
+ if (!isset($types[$image_data[2]]) || !in_array($extension, $types[$image_data[2]]))
+ {
+ if (!isset($types[$image_data[2]]))
+ {
+ $error[] = $user->lang['UNABLE_GET_IMAGE_SIZE'];
+ }
+ else
+ {
+ $error[] = sprintf($user->lang['IMAGE_FILETYPE_MISMATCH'], $types[$image_data[2]][0], $extension);
+ }
+ return false;
+ }
+
if ($config['avatar_max_width'] || $config['avatar_max_height'])
{
if ($width > $config['avatar_max_width'] || $height > $config['avatar_max_height'])
@@ -1238,7 +1382,21 @@ function avatar_upload($data, &$error)
}
$file->clean_filename('real', $data['user_id'] . '_');
- $file->move_file($config['avatar_path']);
+
+ $destination = $config['avatar_path'];
+
+ if ($destination{(sizeof($destination)-1)} == '/' || $destination{(sizeof($destination)-1)} == '\\')
+ {
+ $destination = substr($destination, 0, sizeof($destination)-2);
+ }
+
+ $destination = str_replace(array('../', '..\\', './', '.\\'), '', $destination);
+ if ($destination && ($destination[0] == '/' || $destination[0] == "\\"))
+ {
+ $destination = '';
+ }
+
+ $file->move_file($destination);
if (sizeof($file->error))
{
@@ -1272,7 +1430,7 @@ function avatar_gallery($category, $avatar_select, $items_per_column, $block_var
while (($file = readdir($dp)) !== false)
{
- if ($file{0} != '.' && is_dir("$path/$file"))
+ if ($file[0] != '.' && is_dir("$path/$file"))
{
$avatar_row_count = $avatar_col_count = 0;
@@ -1376,12 +1534,12 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow
$group_only_ary = array('group_receive_pm', 'group_legend', 'group_message_limit');
// Check data
- if (!strlen($name) || strlen($name) > 40)
+ if (!utf8_strlen($name) || utf8_strlen($name) > 40)
{
- $error[] = (!strlen($name)) ? $user->lang['GROUP_ERR_USERNAME'] : $user->lang['GROUP_ERR_USER_LONG'];
+ $error[] = (!utf8_strlen($name)) ? $user->lang['GROUP_ERR_USERNAME'] : $user->lang['GROUP_ERR_USER_LONG'];
}
- if (strlen($desc) > 255)
+ if (utf8_strlen($desc) > 255)
{
$error[] = $user->lang['GROUP_ERR_DESC_LONG'];
}
@@ -1455,33 +1613,30 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow
continue;
}
- $sql_ary[str_replace('group', 'user', $attribute)] = $group_attributes[$attribute];
+ $sql_ary[$attribute] = $group_attributes[$attribute];
}
}
}
if (sizeof($sql_ary))
{
- // Before we update the user attributes, we will make a list of those having now the group avatar assigned
- if (in_array('user_avatar', array_keys($sql_ary)))
- {
- // Ok, get the original avatar data from users having an uploaded one (we need to remove these from the filesystem)
- $sql = 'SELECT user_id, user_avatar
- FROM ' . USERS_TABLE . '
- WHERE group_id = ' . $group_id . '
- AND user_avatar_type = ' . AVATAR_UPLOAD;
- $result = $db->sql_query($sql);
+ $sql = 'SELECT user_id
+ FROM ' . USERS_TABLE . '
+ WHERE group_id = ' . $group_id;
+ $result = $db->sql_query($sql);
- while ($row = $db->sql_fetchrow($result))
- {
- avatar_delete($row['user_avatar']);
- }
- $db->sql_freeresult($result);
+ $user_ary = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $user_ary[] = $row['user_id'];
}
- $sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . "
- WHERE group_id = $group_id";
- $db->sql_query($sql);
+ $db->sql_freeresult($result);
+
+ if (sizeof($user_ary))
+ {
+ group_set_user_default($group_id, $user_ary, $sql_ary);
+ }
}
$name = ($type == GROUP_SPECIAL) ? $user->lang['G_' . $name] : $name;
@@ -1496,7 +1651,7 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow
*/
function group_delete($group_id, $group_name = false)
{
- global $db;
+ global $db, $phpbb_root_path, $phpEx;
if (!$group_name)
{
@@ -1548,6 +1703,11 @@ function group_delete($group_id, $group_name = false)
$db->sql_query($sql);
// Re-cache moderators
+ if (!function_exists('cache_moderators'))
+ {
+ include($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
+ }
+
cache_moderators();
add_log('admin', 'LOG_GROUP_DELETE', $group_name);
@@ -1557,6 +1717,8 @@ function group_delete($group_id, $group_name = false)
/**
* Add user(s) to group
+*
+* @return false if no errors occurred, else the user lang string for the relevant error, for example 'NO_USER'
*/
function group_user_add($group_id, $user_id_ary = false, $username_ary = false, $group_name = false, $default = false, $leader = 0, $pending = 0, $group_attributes = false)
{
@@ -1580,11 +1742,11 @@ function group_user_add($group_id, $user_id_ary = false, $username_ary = false,
$add_id_ary = $update_id_ary = array();
while ($row = $db->sql_fetchrow($result))
{
- $add_id_ary[] = $row['user_id'];
+ $add_id_ary[] = (int) $row['user_id'];
if ($leader && !$row['group_leader'])
{
- $update_id_ary[] = $row['user_id'];
+ $update_id_ary[] = (int) $row['user_id'];
}
}
$db->sql_freeresult($result);
@@ -1598,31 +1760,24 @@ function group_user_add($group_id, $user_id_ary = false, $username_ary = false,
return 'GROUP_USERS_EXIST';
}
+ $db->sql_transaction('begin');
+
+ // Insert the new users
if (sizeof($add_id_ary))
{
- // Insert the new users
- switch (SQL_LAYER)
- {
- case 'mysql':
- case 'mysql4':
- case 'mysqli':
- case 'mssql':
- case 'mssql_odbc':
- case 'sqlite':
- $sql = 'INSERT INTO ' . USER_GROUP_TABLE . " (user_id, group_id, group_leader, user_pending)
- VALUES " . implode(', ', preg_replace('#^([0-9]+)$#', "(\\1, $group_id, $leader, $pending)", $add_id_ary));
- $db->sql_query($sql);
- break;
+ $sql_ary = array();
- default:
- foreach ($add_id_ary as $user_id)
- {
- $sql = 'INSERT INTO ' . USER_GROUP_TABLE . " (user_id, group_id, group_leader, user_pending)
- VALUES ($user_id, $group_id, $leader, $pending)";
- $db->sql_query($sql);
- }
- break;
+ foreach ($add_id_ary as $user_id)
+ {
+ $sql_ary[] = array(
+ 'user_id' => $user_id,
+ 'group_id' => $group_id,
+ 'group_leader' => $leader,
+ 'user_pending' => $pending,
+ );
}
+
+ $db->sql_multi_insert(USER_GROUP_TABLE, $sql_ary);
}
if (sizeof($update_id_ary))
@@ -1639,6 +1794,8 @@ function group_user_add($group_id, $user_id_ary = false, $username_ary = false,
group_set_user_default($group_id, $user_id_ary, $group_attributes);
}
+ $db->sql_transaction('commit');
+
// Clear permissions cache of relevant users
$auth->acl_clear_prefetch($user_id_ary);
@@ -1651,13 +1808,18 @@ function group_user_add($group_id, $user_id_ary = false, $username_ary = false,
add_log('admin', $log, $group_name, implode(', ', $username_ary));
- return ($leader) ? 'GROUP_LEADERS_ADDED' : 'GROUP_USERS_ADDED';
+ group_update_listings($group_id);
+
+ // Return false - no error
+ return false;
}
/**
* Remove a user/s from a given group. When we remove users we update their
* default group_id. We do this by examining which "special" groups they belong
* to. The selection is made based on a reasonable priority system
+*
+* @return false if no errors occurred, else the user lang string for the relevant error, for example 'NO_USER'
*/
function group_user_del($group_id, $user_id_ary = false, $username_ary = false, $group_name = false)
{
@@ -1684,18 +1846,18 @@ function group_user_del($group_id, $user_id_ary = false, $username_ary = false,
$group_order_id[$row['group_name']] = $row['group_id'];
$special_group_data[$row['group_id']] = array(
- 'user_colour' => $row['group_colour'],
- 'user_rank' => $row['group_rank'],
+ 'group_colour' => $row['group_colour'],
+ 'group_rank' => $row['group_rank'],
);
// Only set the group avatar if one is defined...
if ($row['group_avatar'])
{
$special_group_data[$row['group_id']] = array_merge($special_group_data[$row['group_id']], array(
- 'user_avatar' => $row['group_avatar'],
- 'user_avatar_type' => $row['group_avatar_type'],
- 'user_avatar_width' => $row['group_avatar_width'],
- 'user_avatar_height' => $row['group_avatar_height'])
+ 'group_avatar' => $row['group_avatar'],
+ 'group_avatar_type' => $row['group_avatar_type'],
+ 'group_avatar_width' => $row['group_avatar_width'],
+ 'group_avatar_height' => $row['group_avatar_height'])
);
}
}
@@ -1745,28 +1907,7 @@ function group_user_del($group_id, $user_id_ary = false, $username_ary = false,
{
if (isset($sql_where_ary[$gid]) && sizeof($sql_where_ary[$gid]))
{
- $special_group_data[$gid]['group_id'] = $gid;
-
- // Before we update the user attributes, we will make a list of those having now the group avatar assigned
- if (in_array('user_avatar', array_keys($special_group_data[$gid])))
- {
- // Ok, get the original avatar data from users having an uploaded one (we need to remove these from the filesystem)
- $sql = 'SELECT user_id, user_avatar
- FROM ' . USERS_TABLE . '
- WHERE ' . $db->sql_in_set('user_id', $sql_where_ary[$gid]) . '
- AND user_avatar_type = ' . AVATAR_UPLOAD;
- $result = $db->sql_query($sql);
-
- while ($row = $db->sql_fetchrow($result))
- {
- avatar_delete($row['user_avatar']);
- }
- $db->sql_freeresult($result);
- }
-
- $sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $special_group_data[$gid]) . '
- WHERE ' . $db->sql_in_set('user_id', $sql_where_ary[$gid]);
- $db->sql_query($sql);
+ group_set_user_default($gid, $sql_where_ary[$gid], $special_group_data[$gid]);
}
}
unset($special_group_data);
@@ -1788,7 +1929,8 @@ function group_user_del($group_id, $user_id_ary = false, $username_ary = false,
add_log('admin', $log, $group_name, implode(', ', $username_ary));
- return 'GROUP_USERS_REMOVE';
+ // Return false - no error
+ return false;
}
/**
@@ -1857,8 +1999,6 @@ function group_user_attributes($action, $group_id, $user_id_ary = false, $userna
include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
$messenger = new messenger();
- $email_sig = str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']);
-
foreach ($email_users as $row)
{
$messenger->template('group_approved', $row['user_lang']);
@@ -1868,11 +2008,8 @@ function group_user_attributes($action, $group_id, $user_id_ary = false, $userna
$messenger->im($row['user_jabber'], $row['username']);
$messenger->assign_vars(array(
- 'EMAIL_SIG' => $email_sig,
- 'SITENAME' => $config['sitename'],
- 'USERNAME' => html_entity_decode($row['username']),
- 'GROUP_NAME' => html_entity_decode($group_name),
-
+ 'USERNAME' => htmlspecialchars_decode($row['username']),
+ 'GROUP_NAME' => htmlspecialchars_decode($group_name),
'U_GROUP' => generate_board_url() . "/ucp.$phpEx?i=groups&mode=membership")
);
@@ -1954,7 +2091,7 @@ function group_set_user_default($group_id, $user_id_ary, $group_attributes = fal
if (in_array('user_avatar', array_keys($sql_ary)))
{
// Ok, get the original avatar data from users having an uploaded one (we need to remove these from the filesystem)
- $sql = 'SELECT user_id, user_avatar
+ $sql = 'SELECT user_id, group_id, user_avatar
FROM ' . USERS_TABLE . '
WHERE ' . $db->sql_in_set('user_id', $user_id_ary) . '
AND user_avatar_type = ' . AVATAR_UPLOAD;
@@ -1962,7 +2099,7 @@ function group_set_user_default($group_id, $user_id_ary, $group_attributes = fal
while ($row = $db->sql_fetchrow($result))
{
- avatar_delete($row['user_avatar']);
+ avatar_delete('user', $row);
}
$db->sql_freeresult($result);
}
@@ -1970,6 +2107,22 @@ function group_set_user_default($group_id, $user_id_ary, $group_attributes = fal
$sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
WHERE ' . $db->sql_in_set('user_id', $user_id_ary);
$db->sql_query($sql);
+
+ if (in_array('user_colour', array_keys($sql_ary)))
+ {
+ // Update any cached colour information for these users
+ $sql = 'UPDATE ' . FORUMS_TABLE . " SET forum_last_poster_colour = '" . $db->sql_escape($sql_ary['user_colour']) . "'
+ WHERE " . $db->sql_in_set('forum_last_poster_id', $user_id_ary);
+ $db->sql_query($sql);
+
+ $sql = 'UPDATE ' . TOPICS_TABLE . " SET topic_first_poster_colour = '" . $db->sql_escape($sql_ary['user_colour']) . "'
+ WHERE " . $db->sql_in_set('topic_poster', $user_id_ary);
+ $db->sql_query($sql);
+
+ $sql = 'UPDATE ' . TOPICS_TABLE . " SET topic_last_poster_colour = '" . $db->sql_escape($sql_ary['user_colour']) . "'
+ WHERE " . $db->sql_in_set('topic_last_poster_id', $user_id_ary);
+ $db->sql_query($sql);
+ }
}
/**
@@ -2062,4 +2215,64 @@ function group_memberships($group_id_ary = false, $user_id_ary = false, $return_
return $return;
}
+/**
+* Re-cache moderators and foes if group has a_ or m_ permissions
+*/
+function group_update_listings($group_id)
+{
+ global $auth;
+
+ $hold_ary = $auth->acl_group_raw_data($group_id, array('a_', 'm_'));
+
+ if (!sizeof($hold_ary))
+ {
+ return;
+ }
+
+ $mod_permissions = $admin_permissions = false;
+
+ foreach ($hold_ary as $g_id => $forum_ary)
+ {
+ foreach ($forum_ary as $forum_id => $auth_ary)
+ {
+ foreach ($auth_ary as $auth_option => $setting)
+ {
+ if ($mod_permissions && $admin_permissions)
+ {
+ break 3;
+ }
+
+ if ($setting != ACL_YES)
+ {
+ continue;
+ }
+
+ if ($auth_option == 'm_')
+ {
+ $mod_permissions = true;
+ }
+
+ if ($auth_option == 'a_')
+ {
+ $admin_permissions = true;
+ }
+ }
+ }
+ }
+
+ if ($mod_permissions)
+ {
+ if (!function_exists('cache_moderators'))
+ {
+ include($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
+ }
+ cache_moderators();
+ }
+
+ if ($mod_permissions || $admin_permissions)
+ {
+ update_foes();
+ }
+}
+
?> \ No newline at end of file
diff --git a/phpBB/includes/mcp/mcp_forum.php b/phpBB/includes/mcp/mcp_forum.php
index 09470b8269..b20bd63a08 100644
--- a/phpBB/includes/mcp/mcp_forum.php
+++ b/phpBB/includes/mcp/mcp_forum.php
@@ -74,6 +74,7 @@ function mcp_forum_view($id, $mode, $action, $forum_info)
'S_CAN_LOCK' => $auth->acl_get('m_lock', $forum_id),
'S_CAN_SYNC' => $auth->acl_get('m_', $forum_id),
'S_CAN_APPROVE' => $auth->acl_get('m_approve', $forum_id),
+ 'S_MERGE_SELECT' => ($action == 'merge_select') ? true : false,
'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id),
'U_VIEW_FORUM_LOGS' => ($auth->acl_gets('a_', 'm_', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=logs&amp;mode=forum_logs&amp;f=' . $forum_id) : '',
@@ -86,8 +87,7 @@ function mcp_forum_view($id, $mode, $action, $forum_info)
);
// Grab icons
- $icons = array();
- $cache->obtain_icons($icons);
+ $icons = $cache->obtain_icons();
$topic_rows = array();
@@ -117,8 +117,8 @@ function mcp_forum_view($id, $mode, $action, $forum_info)
$topic_title = censor_text($row['topic_title']);
- $topic_unapproved = (!$row['topic_approved'] && $auth->acl_gets('m_approve', $row['forum_id'])) ? true : false;
- $posts_unapproved = ($row['topic_approved'] && $row['topic_replies'] < $row['topic_replies_real'] && $auth->acl_gets('m_approve', $row['forum_id'])) ? true : false;
+ $topic_unapproved = (!$row['topic_approved'] && $auth->acl_get('m_approve', $row['forum_id'])) ? true : false;
+ $posts_unapproved = ($row['topic_approved'] && $row['topic_replies'] < $row['topic_replies_real'] && $auth->acl_get('m_approve', $row['forum_id'])) ? true : false;
$u_mcp_queue = ($topic_unapproved || $posts_unapproved) ? $url . '&amp;i=queue&amp;mode=' . (($topic_unapproved) ? 'approve_details' : 'unapproved_posts') . '&amp;t=' . $row['topic_id'] : '';
$template->assign_block_vars('topicrow', array(
@@ -129,7 +129,7 @@ function mcp_forum_view($id, $mode, $action, $forum_info)
'U_MCP_QUEUE' => $u_mcp_queue,
'U_MCP_REPORT' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&amp;mode=topic_view&amp;t=' . $row['topic_id'] . '&amp;action=reports'),
- 'ATTACH_ICON_IMG' => ($auth->acl_gets('f_download', 'u_download', $row['forum_id']) && $row['topic_attachment']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '',
+ 'ATTACH_ICON_IMG' => ($auth->acl_get('u_download') && $auth->acl_get('f_download', $row['forum_id']) && $row['topic_attachment']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '',
'TOPIC_FOLDER_IMG' => $user->img($folder_img, $folder_alt),
'TOPIC_FOLDER_IMG_SRC' => $user->img($folder_img, $folder_alt, false, '', 'src'),
'TOPIC_ICON_IMG' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['img'] : '',
@@ -144,7 +144,7 @@ function mcp_forum_view($id, $mode, $action, $forum_info)
'TOPIC_ID' => $row['topic_id'],
'S_TOPIC_CHECKED' => ($topic_id_list && in_array($row['topic_id'], $topic_id_list)) ? 'checked="checked" ' : '',
- 'S_TOPIC_REPORTED' => (!empty($row['topic_reported']) && $auth->acl_gets('m_report', $row['forum_id'])) ? true : false,
+ 'S_TOPIC_REPORTED' => (!empty($row['topic_reported']) && $auth->acl_get('m_report', $row['forum_id'])) ? true : false,
'S_TOPIC_UNAPPROVED' => $topic_unapproved,
'S_POSTS_UNAPPROVED' => $posts_unapproved)
);
@@ -191,7 +191,7 @@ function mcp_resync_topics($topic_ids)
$redirect = request_var('redirect', $user->data['session_page']);
- meta_refresh(2, $redirect);
+ meta_refresh(3, $redirect);
trigger_error($msg . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>'));
return;
diff --git a/phpBB/includes/mcp/mcp_front.php b/phpBB/includes/mcp/mcp_front.php
index 745b2c0d61..8b798fc1b2 100644
--- a/phpBB/includes/mcp/mcp_front.php
+++ b/phpBB/includes/mcp/mcp_front.php
@@ -114,7 +114,7 @@ function mcp_front_view($id, $mode, $action)
}
// Latest 5 reported
- $forum_list = get_forum_list('m_');
+ $forum_list = get_forum_list('m_report');
$template->assign_var('S_SHOW_REPORTS', (!empty($forum_list)) ? true : false);
diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php
index b77c3e4451..1fe9233ba9 100644
--- a/phpBB/includes/mcp/mcp_main.php
+++ b/phpBB/includes/mcp/mcp_main.php
@@ -207,9 +207,18 @@ function lock_unlock($action, $ids)
$l_prefix = 'POST';
}
- if (!($forum_id = check_ids($ids, $table, $sql_id, array('f_user_lock', 'm_lock'))))
+ if (!($forum_id = check_ids($ids, $table, $sql_id, array('m_lock'))))
{
- return;
+ // Make sure that for f_user_lock only the lock action is triggered.
+ if ($action != 'lock')
+ {
+ return;
+ }
+
+ if (!($forum_id = check_ids($ids, $table, $sql_id, array('f_user_lock'))))
+ {
+ return;
+ }
}
$redirect = request_var('redirect', $user->data['session_page']);
@@ -474,8 +483,17 @@ function mcp_move_topic($topic_ids)
$forum_ids[] = $row['forum_id'];
add_log('mod', $to_forum_id, $topic_id, 'LOG_MOVE', $row['forum_name']);
+ // If we have moved a global announcement, we need to correct the topic type
+ if ($row['topic_type'] == POST_GLOBAL)
+ {
+ $sql = 'UPDATE ' . TOPICS_TABLE . '
+ SET topic_type = ' . POST_ANNOUNCE . '
+ WHERE topic_id = ' . (int) $row['topic_id'];
+ $db->sql_query($sql);
+ }
+
// Leave a redirection if required and only if the topic is visible to users
- if ($leave_shadow && $row['topic_approved'])
+ if ($leave_shadow && $row['topic_approved'] && $row['topic_type'] != POST_GLOBAL)
{
$shadow = array(
'forum_id' => (int) $row['forum_id'],
@@ -884,7 +902,6 @@ function mcp_fork_topic($topic_ids)
'post_edit_reason' => (string) $row['post_edit_reason'],
'post_edit_user' => (int) $row['post_edit_user'],
'post_checksum' => (string) $row['post_checksum'],
- 'post_encoding' => (string) $row['post_encoding'],
'post_attachment' => (int) $row['post_attachment'],
'bbcode_bitfield' => $row['bbcode_bitfield'],
'bbcode_uid' => (string) $row['bbcode_uid'],
diff --git a/phpBB/includes/mcp/mcp_notes.php b/phpBB/includes/mcp/mcp_notes.php
index cc4ed0e72b..302ace9755 100755
--- a/phpBB/includes/mcp/mcp_notes.php
+++ b/phpBB/includes/mcp/mcp_notes.php
@@ -68,13 +68,13 @@ class mcp_notes
global $template, $db, $user, $auth;
$user_id = request_var('u', 0);
- $username = request_var('username', '');
+ $username = request_var('username', '', true);
$start = request_var('start', 0);
$st = request_var('st', 0);
$sk = request_var('sk', 'b');
$sd = request_var('sd', 'd');
- $sql_where = ($user_id) ? "user_id = $user_id" : "username = '" . $db->sql_escape($username) . "'";
+ $sql_where = ($user_id) ? "user_id = $user_id" : "username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'";
$sql = 'SELECT *
FROM ' . USERS_TABLE . "
@@ -161,7 +161,7 @@ class mcp_notes
$limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']);
$sort_by_text = array('a' => $user->lang['SORT_USERNAME'], 'b' => $user->lang['SORT_DATE'], 'c' => $user->lang['SORT_IP'], 'd' => $user->lang['SORT_ACTION']);
- $sort_by_sql = array('a' => 'l.username', 'b' => 'l.log_time', 'c' => 'l.log_ip', 'd' => 'l.log_operation');
+ $sort_by_sql = array('a' => 'u.username', 'b' => 'l.log_time', 'c' => 'l.log_ip', 'd' => 'l.log_operation');
$s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = '';
gen_sort_selects($limit_days, $sort_by_text, $st, $sk, $sd, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param);
diff --git a/phpBB/includes/mcp/mcp_post.php b/phpBB/includes/mcp/mcp_post.php
index 08bcc713f8..201137a9a4 100644
--- a/phpBB/includes/mcp/mcp_post.php
+++ b/phpBB/includes/mcp/mcp_post.php
@@ -42,7 +42,7 @@ function mcp_post_details($id, $mode, $action)
$whois = user_ipwhois($ip);
$whois = preg_replace('#(\s)([\w\-\._\+]+@[\w\-\.]+)(\s)#', '\1<a href="mailto:\2">\2</a>\3', $whois);
- $whois = preg_replace('#(\s)(http:/{2}[^\s]*)(\s)#', '\1<a href="\2" target="_blank">\2</a>\3', $whois);
+ $whois = preg_replace('#(\s)(http:/{2}[^\s]*)(\s)#', '\1<a href="\2">\2</a>\3', $whois);
$template->assign_vars(array(
'RETURN_POST' => sprintf($user->lang['RETURN_POST'], '<a href="' . append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&amp;mode=$mode&amp;p=$post_id") . '">', '</a>'),
@@ -59,8 +59,8 @@ function mcp_post_details($id, $mode, $action)
if ($action == 'chgposter')
{
- $username = request_var('username', '');
- $sql_where = "username = '" . $db->sql_escape($username) . "'";
+ $username = request_var('username', '', true);
+ $sql_where = "username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'";
}
else
{
@@ -89,12 +89,13 @@ function mcp_post_details($id, $mode, $action)
}
// Set some vars
- $users_ary = array();
+ $users_ary = $usernames_ary = array();
$post_id = $post_info['post_id'];
$poster = ($post_info['user_colour']) ? '<span style="color:#' . $post_info['user_colour'] . '">' . $post_info['username'] . '</span>' : $post_info['username'];
// Process message, leave it uncensored
$message = $post_info['post_text'];
+ $message = str_replace("\n", '<br />', $message);
if ($post_info['bbcode_bitfield'])
{
include_once($phpbb_root_path . 'includes/bbcode.' . $phpEx);
@@ -102,7 +103,6 @@ function mcp_post_details($id, $mode, $action)
$bbcode->bbcode_second_pass($message, $post_info['bbcode_uid'], $post_info['bbcode_bitfield']);
}
$message = smiley_text($message);
- $message = str_replace("\n", '<br />', $message);
$template->assign_vars(array(
'U_MCP_ACTION' => "$url&amp;i=main&amp;quickmod=1", // Use this for mode paramaters
@@ -134,6 +134,7 @@ function mcp_post_details($id, $mode, $action)
'REPORTED_IMG' => $user->img('icon_topic_reported', $user->lang['POST_REPORTED']),
'UNAPPROVED_IMG' => $user->img('icon_topic_unapproved', $user->lang['POST_UNAPPROVED']),
'EDIT_IMG' => $user->img('icon_post_edit', $user->lang['EDIT_POST']),
+ 'SEARCH_IMG' => $user->img('icon_user_search', $user->lang['SEARCH']),
'POSTER_NAME' => $poster,
'POST_PREVIEW' => $message,
@@ -217,75 +218,62 @@ function mcp_post_details($id, $mode, $action)
}
// Get other users who've posted under this IP
+ $sql = 'SELECT poster_id, COUNT(poster_id) as postings
+ FROM ' . POSTS_TABLE . "
+ WHERE poster_ip = '" . $db->sql_escape($post_info['poster_ip']) . "'
+ GROUP BY poster_id
+ ORDER BY postings DESC";
+ $result = $db->sql_query($sql);
- // Firebird does not support ORDER BY on aliased columns
- // MySQL does not support ORDER BY on functions
- switch (SQL_LAYER)
+ while ($row = $db->sql_fetchrow($result))
{
- case 'firebird':
- $sql = 'SELECT u.user_id, u.username, COUNT(*) as postings
- FROM ' . USERS_TABLE . ' u, ' . POSTS_TABLE . " p
- WHERE p.poster_id = u.user_id
- AND p.poster_ip = '" . $db->sql_escape($post_info['poster_ip']) . "'
- AND p.poster_id <> {$post_info['user_id']}
- GROUP BY u.user_id, u.username
- ORDER BY COUNT(*) DESC";
- break;
-
- default:
- $sql = 'SELECT u.user_id, u.username, COUNT(*) as postings
- FROM ' . USERS_TABLE . ' u, ' . POSTS_TABLE . " p
- WHERE p.poster_id = u.user_id
- AND p.poster_ip = '" . $db->sql_escape($post_info['poster_ip']) . "'
- AND p.poster_id <> {$post_info['user_id']}
- GROUP BY u.user_id, u.username
- ORDER BY postings DESC";
- break;
+ // Fill the user select list with users who have posted under this IP
+ if ($row['poster_id'] != $post_info['poster_id'])
+ {
+ $users_ary[$row['poster_id']] = $row;
+ }
}
- $result = $db->sql_query($sql);
+ $db->sql_freeresult($result);
- while ($row = $db->sql_fetchrow($result))
+ if (sizeof($users_ary))
{
- // Fill the user select list with users who have posted
- // under this IP
- if ($row['user_id'] != $post_info['poster_id'])
+ // Get the usernames
+ $sql = 'SELECT user_id, username
+ FROM ' . USERS_TABLE . '
+ WHERE ' . $db->sql_in_set('user_id', array_keys($users_ary));
+ $result = $db->sql_query($sql);
+
+ while ($row = $db->sql_fetchrow($result))
{
- $users_ary[strtolower($row['username'])] = $row;
+ $users_ary[$row['user_id']]['username'] = $row['username'];
+ $usernames_ary[utf8_clean_string($row['username'])] = $users_ary[$row['user_id']];
}
+ $db->sql_freeresult($result);
- $template->assign_block_vars('userrow', array(
- 'USERNAME' => ($row['user_id'] == ANONYMOUS) ? $user->lang['GUEST'] : $row['username'],
- 'NUM_POSTS' => $row['postings'],
- 'L_POST_S' => ($row['postings'] == 1) ? $user->lang['POST'] : $user->lang['POSTS'],
+ foreach ($users_ary as $user_id => $user_row)
+ {
+ $template->assign_block_vars('userrow', array(
+ 'USERNAME' => ($user_id == ANONYMOUS) ? $user->lang['GUEST'] : $user_row['username'],
+ 'NUM_POSTS' => $user_row['postings'],
+ 'L_POST_S' => ($user_row['postings'] == 1) ? $user->lang['POST'] : $user->lang['POSTS'],
- 'U_PROFILE' => ($row['user_id'] == ANONYMOUS) ? '' : append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&amp;u=' . $row['user_id']),
- 'U_SEARCHPOSTS' => append_sid("{$phpbb_root_path}search.$phpEx", 'author=' . urlencode($row['username']) . '&amp;sr=topics'))
- );
+ 'U_PROFILE' => ($user_id == ANONYMOUS) ? '' : append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&amp;u=' . $user_id),
+ 'U_SEARCHPOSTS' => append_sid("{$phpbb_root_path}search.$phpEx", 'author_id=' . $user_id . '&amp;sr=topics'))
+ );
+ }
}
- $db->sql_freeresult($result);
// Get other IP's this user has posted under
- // Firebird does not support ORDER BY on aliased columns
- // MySQL does not support ORDER BY on functions
- switch (SQL_LAYER)
- {
- case 'firebird':
- $sql = 'SELECT poster_ip, COUNT(*) AS postings
- FROM ' . POSTS_TABLE . '
- WHERE poster_id = ' . $post_info['poster_id'] . '
- GROUP BY poster_ip
- ORDER BY COUNT(*) DESC';
- break;
-
- default:
- $sql = 'SELECT poster_ip, COUNT(*) AS postings
- FROM ' . POSTS_TABLE . '
- WHERE poster_id = ' . $post_info['poster_id'] . '
- GROUP BY poster_ip
- ORDER BY postings DESC';
- break;
- }
+ // A compound index on poster_id, poster_ip (posts table) would help speed up this query a lot,
+ // but the extra size is only valuable if there are persons having more than a thousands posts.
+ // This is better left to the really really big forums.
+
+ $sql = 'SELECT poster_ip, COUNT(poster_ip) AS postings
+ FROM ' . POSTS_TABLE . '
+ WHERE poster_id = ' . $post_info['poster_id'] . '
+ GROUP BY poster_ip
+ ORDER BY postings DESC';
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
@@ -305,12 +293,17 @@ function mcp_post_details($id, $mode, $action)
$db->sql_freeresult($result);
$user_select = '';
- ksort($users_ary);
- foreach ($users_ary as $row)
+ if (sizeof($usernames_ary))
{
- $user_select .= '<option value="' . $row['user_id'] . '">' . $row['username'] . "</option>\n";
+ ksort($usernames_ary);
+
+ foreach ($usernames_ary as $row)
+ {
+ $user_select .= '<option value="' . $row['poster_id'] . '">' . $row['username'] . "</option>\n";
+ }
}
+
$template->assign_var('S_USER_SELECT', $user_select);
}
@@ -379,7 +372,16 @@ function change_poster(&$post_info, $userdata)
}
}
- // Do not change the poster_id within the attachments table, since they were still posted by the original user
+ // change the poster_id within the attachments table, else the data becomes out of sync and errors displayed because of wrong ownership
+ if ($post_info['post_attachment'])
+ {
+ $sql = 'UPDATE ' . ATTACHMENTS_TABLE . '
+ SET poster_id = ' . $userdata['user_id'] . '
+ WHERE poster_id = ' . $post_info['user_id'] . '
+ AND post_msg_id = ' . $post_info['post_id'] . '
+ AND topic_id = ' . $post_info['topic_id'];
+ $db->sql_query($sql);
+ }
$from_username = $post_info['username'];
$to_username = $userdata['username'];
diff --git a/phpBB/includes/mcp/mcp_queue.php b/phpBB/includes/mcp/mcp_queue.php
index 95e89fa9dc..0f6fae18ee 100644
--- a/phpBB/includes/mcp/mcp_queue.php
+++ b/phpBB/includes/mcp/mcp_queue.php
@@ -109,6 +109,7 @@ class mcp_queue
// Process message, leave it uncensored
$message = $post_info['post_text'];
+ $message = str_replace("\n", '<br />', $message);
if ($post_info['bbcode_bitfield'])
{
include_once($phpbb_root_path . 'includes/bbcode.' . $phpEx);
@@ -181,13 +182,15 @@ class mcp_queue
$forum_list[] = $row['forum_id'];
}
- $global_id = $forum_list[0];
-
- if (!($forum_list = implode(', ', $forum_list)))
+ if (!sizeof($forum_list))
{
trigger_error('NOT_MODERATOR');
}
+ $global_id = $forum_list[0];
+
+ $forum_list = implode(', ', $forum_list);
+
$sql = 'SELECT SUM(forum_topics) as sum_forum_topics
FROM ' . FORUMS_TABLE . "
WHERE forum_id IN (0, $forum_list)";
@@ -228,10 +231,10 @@ class mcp_queue
if ($mode == 'unapproved_posts')
{
$sql = 'SELECT p.post_id
- FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t' . (($sort_order_sql{0} == 'u') ? ', ' . USERS_TABLE . ' u' : '') . "
+ FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t' . (($sort_order_sql[0] == 'u') ? ', ' . USERS_TABLE . ' u' : '') . "
WHERE p.forum_id IN (0, $forum_list)
AND p.post_approved = 0
- " . (($sort_order_sql{0} == 'u') ? 'AND u.user_id = p.poster_id' : '') . '
+ " . (($sort_order_sql[0] == 'u') ? 'AND u.user_id = p.poster_id' : '') . '
' . (($topic_id) ? 'AND p.topic_id = ' . $topic_id : '') . "
AND t.topic_id = p.topic_id
AND t.topic_first_post_id <> p.post_id
@@ -283,8 +286,8 @@ class mcp_queue
{
$sql = 'SELECT t.forum_id, t.topic_id, t.topic_title, t.topic_title AS post_subject, t.topic_time AS post_time, t.topic_poster AS poster_id, t.topic_first_post_id AS post_id, t.topic_first_poster_name AS username
FROM ' . TOPICS_TABLE . " t
- WHERE topic_approved = 0
- AND forum_id IN (0, $forum_list)
+ WHERE forum_id IN (0, $forum_list)
+ AND topic_approved = 0
$limit_time_sql
ORDER BY $sort_order_sql";
$result = $db->sql_query_limit($sql, $config['topics_per_page'], $start);
@@ -409,6 +412,8 @@ function approve_post($post_id_list, $mode)
$total_topics = $total_posts = $forum_topics = $forum_posts = 0;
$topic_approve_sql = $topic_replies_sql = $post_approve_sql = $topic_id_list = array();
+ $update_forum_information = false;
+
foreach ($post_info as $post_id => $post_data)
{
$topic_id_list[$post_data['topic_id']] = 1;
@@ -443,6 +448,12 @@ function approve_post($post_id_list, $mode)
}
$post_approve_sql[] = $post_id;
+
+ // If the post is newer than the last post information stored we need to update the forum information
+ if ($post_data['post_time'] >= $post_data['forum_last_post_time'])
+ {
+ $update_forum_information = true;
+ }
}
if (sizeof($topic_approve_sql))
@@ -496,7 +507,11 @@ function approve_post($post_id_list, $mode)
unset($topic_approve_sql, $topic_replies_sql, $post_approve_sql);
update_post_information('topic', array_keys($topic_id_list));
- update_post_information('forum', $forum_id);
+
+ if ($update_forum_information)
+ {
+ update_post_information('forum', $forum_id);
+ }
unset($topic_id_list);
$messenger = new messenger();
@@ -504,8 +519,6 @@ function approve_post($post_id_list, $mode)
// Notify Poster?
if ($notify_poster)
{
- $email_sig = str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']);
-
foreach ($post_info as $post_id => $post_data)
{
if ($post_data['poster_id'] == ANONYMOUS)
@@ -522,11 +535,9 @@ function approve_post($post_id_list, $mode)
$messenger->im($post_data['user_jabber'], $post_data['username']);
$messenger->assign_vars(array(
- 'EMAIL_SIG' => $email_sig,
- 'SITENAME' => $config['sitename'],
- 'USERNAME' => html_entity_decode($post_data['username']),
- 'POST_SUBJECT' => html_entity_decode(censor_text($post_data['post_subject'])),
- 'TOPIC_TITLE' => html_entity_decode(censor_text($post_data['topic_title'])),
+ 'USERNAME' => htmlspecialchars_decode($post_data['username']),
+ 'POST_SUBJECT' => htmlspecialchars_decode(censor_text($post_data['post_subject'])),
+ 'TOPIC_TITLE' => htmlspecialchars_decode(censor_text($post_data['topic_title'])),
'U_VIEW_TOPIC' => generate_board_url() . "/viewtopic.$phpEx?f=$forum_id&t={$post_data['topic_id']}&e=0",
'U_VIEW_POST' => generate_board_url() . "/viewtopic.$phpEx?f=$forum_id&t={$post_data['topic_id']}&p=$post_id&e=$post_id")
@@ -629,7 +640,7 @@ function disapprove_post($post_id_list, $mode)
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
- if (!$row || (!$reason && $row['reason_title'] == 'other'))
+ if (!$row || (!$reason && strtolower($row['reason_title']) == 'other'))
{
$additional_msg = $user->lang['NO_REASON_DISAPPROVAL'];
unset($_POST['confirm']);
@@ -637,7 +648,7 @@ function disapprove_post($post_id_list, $mode)
else
{
// If the reason is defined within the language file, we will use the localized version, else just use the database entry...
- $disapprove_reason = ($row['reason_title'] != 'other') ? ((isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])])) ? $user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])] : $row['reason_description']) : '';
+ $disapprove_reason = (strtolower($row['reason_title']) != 'other') ? ((isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])])) ? $user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])] : $row['reason_description']) : '';
$disapprove_reason .= ($reason) ? "\n\n" . $reason : '';
}
}
@@ -719,8 +730,6 @@ function disapprove_post($post_id_list, $mode)
// Notify Poster?
if ($notify_poster)
{
- $email_sig = str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']);
-
foreach ($post_info as $post_id => $post_data)
{
if ($post_data['poster_id'] == ANONYMOUS)
@@ -737,12 +746,10 @@ function disapprove_post($post_id_list, $mode)
$messenger->im($post_data['user_jabber'], $post_data['username']);
$messenger->assign_vars(array(
- 'EMAIL_SIG' => $email_sig,
- 'SITENAME' => $config['sitename'],
- 'USERNAME' => html_entity_decode($post_data['username']),
- 'REASON' => html_entity_decode($disapprove_reason),
- 'POST_SUBJECT' => html_entity_decode(censor_text($post_data['post_subject'])),
- 'TOPIC_TITLE' => html_entity_decode(censor_text($post_data['topic_title'])))
+ 'USERNAME' => htmlspecialchars_decode($post_data['username']),
+ 'REASON' => htmlspecialchars_decode($disapprove_reason),
+ 'POST_SUBJECT' => htmlspecialchars_decode(censor_text($post_data['post_subject'])),
+ 'TOPIC_TITLE' => htmlspecialchars_decode(censor_text($post_data['topic_title'])))
);
$messenger->send($post_data['user_notify_type']);
diff --git a/phpBB/includes/mcp/mcp_reports.php b/phpBB/includes/mcp/mcp_reports.php
index a52bc02359..ebd1295090 100755
--- a/phpBB/includes/mcp/mcp_reports.php
+++ b/phpBB/includes/mcp/mcp_reports.php
@@ -117,6 +117,7 @@ class mcp_reports
// Process message, leave it uncensored
$message = $post_info['post_text'];
+ $message = str_replace("\n", '<br />', $message);
if ($post_info['bbcode_bitfield'])
{
include_once($phpbb_root_path . 'includes/bbcode.' . $phpEx);
@@ -200,13 +201,13 @@ class mcp_reports
$forum_list[] = $row['forum_id'];
}
- $global_id = $forum_list[0];
-
if (!sizeof($forum_list))
{
trigger_error('NOT_MODERATOR');
}
+ $global_id = $forum_list[0];
+
$sql = 'SELECT SUM(forum_topics) as sum_forum_topics
FROM ' . FORUMS_TABLE . '
WHERE ' . $db->sql_in_set('forum_id', $forum_list);
@@ -363,7 +364,7 @@ function close_report($post_id_list, $mode, $action)
trigger_error('NOT_AUTHORIZED');
}
- if (($action == 'delete') && (strpos($user->data['session_page'], 'mode=report_details') !== false))
+ if ($action == 'delete' && strpos($user->data['session_page'], 'mode=report_details') !== false)
{
$redirect = request_var('redirect', build_url(array('mode')) . '&amp;mode=reports');
}
@@ -474,8 +475,6 @@ function close_report($post_id_list, $mode, $action)
// Notify reporters
if (sizeof($notify_reporters))
{
- $email_sig = str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']);
-
foreach ($notify_reporters as $post_id => $reporter)
{
if ($reporter['user_id'] == ANONYMOUS)
@@ -490,12 +489,10 @@ function close_report($post_id_list, $mode, $action)
$messenger->im($reporter['user_jabber'], $reporter['username']);
$messenger->assign_vars(array(
- 'EMAIL_SIG' => $email_sig,
- 'SITENAME' => $config['sitename'],
- 'USERNAME' => html_entity_decode($reporter['username']),
- 'CLOSER_NAME' => html_entity_decode($user->data['username']),
- 'POST_SUBJECT' => html_entity_decode(censor_text($post_info[$post_id]['post_subject'])),
- 'TOPIC_TITLE' => html_entity_decode(censor_text($post_info[$post_id]['topic_title'])))
+ 'USERNAME' => htmlspecialchars_decode($reporter['username']),
+ 'CLOSER_NAME' => htmlspecialchars_decode($user->data['username']),
+ 'POST_SUBJECT' => htmlspecialchars_decode(censor_text($post_info[$post_id]['post_subject'])),
+ 'TOPIC_TITLE' => htmlspecialchars_decode(censor_text($post_info[$post_id]['topic_title'])))
);
$messenger->send($reporter['user_notify_type']);
diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php
index 691b92bd36..3b674139e9 100644
--- a/phpBB/includes/mcp/mcp_topic.php
+++ b/phpBB/includes/mcp/mcp_topic.php
@@ -37,6 +37,8 @@ function mcp_topic_view($id, $mode, $action)
$to_topic_id = request_var('to_topic_id', 0);
$to_forum_id = request_var('to_forum_id', 0);
$post_id_list = request_var('post_id_list', array(0));
+
+ utf8_normalize_nfc(&$subject);
// Split Topic?
if ($action == 'split_all' || $action == 'split_beyond')
@@ -96,10 +98,10 @@ function mcp_topic_view($id, $mode, $action)
}
$db->sql_freeresult($result);
- if ($bbcode_bitfield)
+ if ($bbcode_bitfield !== '')
{
include_once($phpbb_root_path . 'includes/bbcode.' . $phpEx);
- $bbcode = new bbcode($bbcode_bitfield);
+ $bbcode = new bbcode(base64_encode($bbcode_bitfield));
}
foreach ($rowset as $i => $row)
@@ -110,6 +112,7 @@ function mcp_topic_view($id, $mode, $action)
$message = $row['post_text'];
$post_subject = ($row['post_subject'] != '') ? $row['post_subject'] : $topic_info['topic_title'];
+ $message = str_replace("\n", '<br />', $message);
if ($row['bbcode_bitfield'])
{
@@ -117,7 +120,6 @@ function mcp_topic_view($id, $mode, $action)
}
$message = smiley_text($message);
- $message = str_replace("\n", '<br />', $message);
if (!$row['post_approved'])
{
@@ -180,7 +182,7 @@ function mcp_topic_view($id, $mode, $action)
'U_VIEWTOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $topic_info['forum_id'] . '&amp;t=' . $topic_info['topic_id']),
'TO_TOPIC_ID' => $to_topic_id,
- 'TO_TOPIC_INFO' => ($to_topic_id) ? sprintf($user->lang['YOU_SELECTED_TOPIC'], $to_topic_id, '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $to_topic_info['forum_id'] . '&amp;t=' . $to_topic_id) . '" target="_new">' . $to_topic_info['topic_title'] . '</a>') : '',
+ 'TO_TOPIC_INFO' => ($to_topic_id) ? sprintf($user->lang['YOU_SELECTED_TOPIC'], $to_topic_id, '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $to_topic_info['forum_id'] . '&amp;t=' . $to_topic_id) . '">' . $to_topic_info['topic_title'] . '</a>') : '',
'SPLIT_SUBJECT' => $subject,
'POSTS_PER_PAGE' => $posts_per_page,
@@ -197,6 +199,7 @@ function mcp_topic_view($id, $mode, $action)
'S_CAN_APPROVE' => ($has_unapproved_posts && $auth->acl_get('m_approve', $topic_info['forum_id'])) ? true : false,
'S_CAN_LOCK' => ($auth->acl_get('m_lock', $topic_info['forum_id'])) ? true : false,
'S_REPORT_VIEW' => ($action == 'reports') ? true : false,
+ 'S_MERGE_VIEW' => ($action == 'merge') ? true : false,
'S_SHOW_TOPIC_ICONS' => $s_topic_icons,
'S_TOPIC_ICON' => $icon_id,
@@ -302,7 +305,7 @@ function split_topic($action, $topic_id, $to_forum_id, $subject)
$limit_time_sql = ($sort_days) ? 'AND t.topic_last_post_time >= ' . (time() - ($sort_days * 86400)) : '';
- if ($sort_order_sql{0} == 'u')
+ if ($sort_order_sql[0] == 'u')
{
$sql = 'SELECT p.post_id, p.forum_id, p.post_approved
FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u
diff --git a/phpBB/includes/mcp/mcp_warn.php b/phpBB/includes/mcp/mcp_warn.php
index bc428570ab..da76dc8b58 100755
--- a/phpBB/includes/mcp/mcp_warn.php
+++ b/phpBB/includes/mcp/mcp_warn.php
@@ -247,6 +247,7 @@ function mcp_warn_post_view($id, $mode, $action)
// We want to make the message available here as a reminder
// Parse the message and subject
$message = $userrow['post_text'];
+ $message = str_replace("\n", '<br />', censor_text($message));
// Second parse bbcode here
if ($userrow['bbcode_bitfield'])
@@ -260,9 +261,6 @@ function mcp_warn_post_view($id, $mode, $action)
// Always process smilies after parsing bbcodes
$message = smiley_text($message);
- // Replace naughty words such as farty pants
- $message = str_replace("\n", '<br />', censor_text($message));
-
// Generate the appropriate user information for the user we are looking at
$rank_title = $rank_img = '';
// get_user_rank($userrow['user_rank'], $userrow['user_posts'], $rank_title, $rank_img);
@@ -312,11 +310,11 @@ function mcp_warn_user_view($id, $mode, $action)
global $template, $db, $user, $auth;
$user_id = request_var('u', 0);
- $username = request_var('username', '');
+ $username = request_var('username', '', true);
$notify = (isset($_REQUEST['notify_user'])) ? true : false;
$warning = request_var('warning', '', true);
- $sql_where = ($user_id) ? "user_id = $user_id" : "username = '" . $db->sql_escape($username) . "'";
+ $sql_where = ($user_id) ? "user_id = $user_id" : "username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'";
$sql = 'SELECT *
FROM ' . USERS_TABLE . '
@@ -405,7 +403,7 @@ function add_warning($userrow, $warning, $send_pm = true, $post_id = 0)
$message_parser = new parse_message();
$message_parser->message = sprintf($lang['WARNING_PM_BODY'], $warning);
- $message_parser->parse(true, true, true, false, false, true);
+ $message_parser->parse(true, true, true, false, false, true, true);
$pm_data = array(
'from_user_id' => $user->data['user_id'],
diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php
index 6aa78d091f..6538bd7721 100644
--- a/phpBB/includes/message_parser.php
+++ b/phpBB/includes/message_parser.php
@@ -47,7 +47,6 @@ class bbcode_firstpass extends bbcode
$this->bbcode_bitfield = '';
$bitfield = new bitfield();
- $size = strlen($this->message);
foreach ($this->bbcodes as $bbcode_name => $bbcode_data)
{
if (isset($bbcode_data['disabled']) && $bbcode_data['disabled'])
@@ -65,18 +64,15 @@ class bbcode_firstpass extends bbcode
{
foreach ($bbcode_data['regexp'] as $regexp => $replacement)
{
- $this->message = preg_replace($regexp, $replacement, $this->message);
+ // The pattern gets compiled and cached by the PCRE extension,
+ // it should not demand recompilation
+ if (preg_match($regexp, $this->message))
+ {
+ $this->message = preg_replace($regexp, $replacement, $this->message);
+ $bitfield->set($bbcode_data['bbcode_id']);
+ }
}
}
-
- // Because we add bbcode_uid to all tags, the message length
- // will increase whenever a tag is found
- $new_size = strlen($this->message);
- if ($size != $new_size)
- {
- $bitfield->set($bbcode_data['bbcode_id']);
- $size = $new_size;
- }
}
$this->bbcode_bitfield = $bitfield->get_base64();
@@ -368,15 +364,11 @@ class bbcode_firstpass extends bbcode
// We remove the hardcoded elements from the code block here because it is not used in code blocks
// Having it here saves us one preg_replace per message containing [code] blocks
// Additionally, magic url parsing should go after parsing bbcodes, but for safety those are stripped out too...
- $htm_match = array(
- '#<!\-\- e \-\-><a href="mailto:(.*?)">.*?</a><!\-\- e \-\->#',
- '#<!\-\- m \-\-><a href="(.*?)" target="_blank">.*?</a><!\-\- m \-\->#',
- '#<!\-\- w \-\-><a href="http:\/\/(.*?)" target="_blank">.*?</a><!\-\- w \-\->#',
- '#<!\-\- l \-\-><a href="(.*?)">.*?</a><!\-\- l \-\->#',
- '#<!\-\- s(.*?) \-\-><img src="\{SMILIES_PATH\}\/.*? \/><!\-\- s\1 \-\->#',
- '#&\#([0-9]+);#',
- );
- $htm_replace = array('\1', '\1', '\1', '\1', '\1', '&amp;#\1;');
+ $htm_match = get_preg_expression('bbcode_htm');
+// $htm_match[3] = '/&#([0-9]+);/';
+ unset($htm_match[3], $htm_match[4]);
+
+ $htm_replace = array('\1', '\2', '\1'); //, '&amp;#\1;');
$out = '';
@@ -427,7 +419,7 @@ class bbcode_firstpass extends bbcode
}
// Because highlight_string is specialcharing the text (but we already did this before), we have to reverse this in order to get correct results
- $code = html_entity_decode($code);
+ $code = htmlspecialchars_decode($code);
$code = highlight_string($code, true);
$str_from = array('<span style="color: ', '<font color="syntax', '</font>', '<code>', '</code>','[', ']', '.', ':');
@@ -507,13 +499,15 @@ class bbcode_firstpass extends bbcode
$tok = ']';
$out = '[';
+ // First character is [
$in = substr($in, 1);
$list_end_tags = array();
do
{
$pos = strlen($in);
- for ($i = 0; $i < strlen($tok); ++$i)
+
+ for ($i = 0, $tok_len = strlen($tok); $i < $tok_len; ++$i)
{
$tmp_pos = strpos($in, $tok{$i});
@@ -531,7 +525,7 @@ class bbcode_firstpass extends bbcode
if ($tok == ']')
{
// if $tok is ']' the buffer holds a tag
- if ($buffer == '/list' && sizeof($list_end_tags))
+ if (strtolower($buffer) == '/list' && sizeof($list_end_tags))
{
$out .= array_pop($list_end_tags) . ']';
$tok = '[';
@@ -547,6 +541,12 @@ class bbcode_firstpass extends bbcode
{
array_push($list_end_tags, '/list:o:' . $this->bbcode_uid);
}
+
+ if (strtolower(substr($buffer, 0, 4)) == 'list')
+ {
+ $buffer = 'list' . substr($buffer, 4, $pos);
+ }
+
$out .= $buffer . ':' . $this->bbcode_uid . ']';
$tok = '[';
}
@@ -598,7 +598,7 @@ class bbcode_firstpass extends bbcode
do
{
$pos = strlen($in);
- for ($i = 0; $i < strlen($tok); ++$i)
+ for ($i = 0, $tok_len = strlen($tok); $i < $tok_len; ++$i)
{
$tmp_pos = strpos($in, $tok{$i});
if ($tmp_pos !== false && $tmp_pos < $pos)
@@ -649,7 +649,7 @@ class bbcode_firstpass extends bbcode
preg_match_all('#\[((?:/)?(?:[a-z]+))#i', $username, $tags);
foreach ($tags[1] as $tag)
{
- if ($tag{0} != '/')
+ if ($tag[0] != '/')
{
$end_tags[] = '/' . $tag;
}
@@ -807,7 +807,7 @@ class bbcode_firstpass extends bbcode
* @param string $url the url to check
* @return true if the url is pointing to this domain/script_path/php-file, false if not
*
- * @access: private
+ * @access private
*/
function path_in_domain($url)
{
@@ -857,6 +857,7 @@ class parse_message extends bbcode_firstpass
var $allow_img_bbcode = true;
var $allow_flash_bbcode = true;
var $allow_quote_bbcode = true;
+ var $allow_url_bbcode = true;
var $mode;
@@ -877,7 +878,7 @@ class parse_message extends bbcode_firstpass
/**
* Parse Message
*/
- function parse($allow_bbcode, $allow_magic_url, $allow_smilies, $allow_img_bbcode = true, $allow_flash_bbcode = true, $allow_quote_bbcode = true, $update_this_message = true, $mode = 'post')
+ function parse($allow_bbcode, $allow_magic_url, $allow_smilies, $allow_img_bbcode = true, $allow_flash_bbcode = true, $allow_quote_bbcode = true, $allow_url_bbcode = true, $update_this_message = true, $mode = 'post')
{
global $config, $db, $user;
@@ -888,6 +889,7 @@ class parse_message extends bbcode_firstpass
$this->allow_img_bbcode = $allow_img_bbcode;
$this->allow_flash_bbcode = $allow_flash_bbcode;
$this->allow_quote_bbcode = $allow_quote_bbcode;
+ $this->allow_url_bbcode = $allow_url_bbcode;
// If false, then $this->message won't be altered, the text will be returned instead.
if (!$update_this_message)
@@ -911,7 +913,7 @@ class parse_message extends bbcode_firstpass
// Message length check. -1 disables this check completely.
if ($config['max_' . $mode . '_chars'] != -1)
{
- $msg_len = ($mode == 'post') ? strlen($this->message) : strlen(preg_replace('#\[\/?[a-z\*\+\-]+(=[\S]+)?\]#is', ' ', $this->message));
+ $msg_len = ($mode == 'post') ? utf8_strlen($this->message) : utf8_strlen(preg_replace('#\[\/?[a-z\*\+\-]+(=[\S]+)?\]#is', ' ', $this->message));
if ((!$msg_len && $mode !== 'sig') || $config['max_' . $mode . '_chars'] && $msg_len > $config['max_' . $mode . '_chars'])
{
@@ -924,7 +926,7 @@ class parse_message extends bbcode_firstpass
if ($allow_bbcode && strpos($this->message, '[') !== false)
{
$this->bbcode_init();
- $disallow = array('img', 'flash', 'quote');
+ $disallow = array('img', 'flash', 'quote', 'url');
foreach ($disallow as $bool)
{
if (!${'allow_' . $bool . '_bbcode'})
@@ -995,7 +997,7 @@ class parse_message extends bbcode_firstpass
if ($this->message_status == 'plain')
{
// Force updating message - of course.
- $this->parse($allow_bbcode, $allow_magic_url, $allow_smilies, $this->allow_img_bbcode, $this->allow_flash_bbcode, $this->allow_quote_bbcode, true);
+ $this->parse($allow_bbcode, $allow_magic_url, $allow_smilies, $this->allow_img_bbcode, $this->allow_flash_bbcode, $this->allow_quote_bbcode, $this->allow_url_bbcode, true);
}
// Parse BBcode
@@ -1076,7 +1078,7 @@ class parse_message extends bbcode_firstpass
// NOTE: obtain_* function? chaching the table contents?
// For now setting the ttl to 10 minutes
- switch (SQL_LAYER)
+ switch ($db->sql_layer)
{
case 'mssql':
case 'mssql_odbc':
@@ -1088,7 +1090,7 @@ class parse_message extends bbcode_firstpass
case 'firebird':
$sql = 'SELECT *
FROM ' . SMILIES_TABLE . '
- ORDER BY STRLEN(code) DESC';
+ ORDER BY CHAR_LENGTH(code) DESC';
break;
// LENGTH supported by MySQL, IBM DB2, Oracle and Access for sure...
@@ -1104,7 +1106,7 @@ class parse_message extends bbcode_firstpass
{
// (assertion)
$match[] = '#(?<=^|[\n ]|\.)' . preg_quote($row['code'], '#') . '#';
- $replace[] = '<!-- s' . $row['code'] . ' --><img src="{SMILIES_PATH}/' . $row['smiley_url'] . '" border="0" alt="' . $row['emotion'] . '" title="' . $row['emotion'] . '" /><!-- s' . $row['code'] . ' -->';
+ $replace[] = '<!-- s' . $row['code'] . ' --><img src="{SMILIES_PATH}/' . $row['smiley_url'] . '" alt="' . $row['emotion'] . '" title="' . $row['emotion'] . '" /><!-- s' . $row['code'] . ' -->';
}
$db->sql_freeresult($result);
}
@@ -1131,12 +1133,13 @@ class parse_message extends bbcode_firstpass
*/
function parse_attachments($form_name, $mode, $forum_id, $submit, $preview, $refresh, $is_message = false)
{
- global $config, $auth, $user, $phpbb_root_path, $phpEx;
+ global $config, $auth, $user, $phpbb_root_path, $phpEx, $db;
$error = array();
$num_attachments = sizeof($this->attachment_data);
$this->filename_data['filecomment'] = request_var('filecomment', '', true);
+ utf8_normalize_nfc(&$this->filename_data['filecomment']);
$upload_file = (isset($_FILES[$form_name]) && $_FILES[$form_name]['name'] != 'none' && trim($_FILES[$form_name]['name'])) ? true : false;
$add_file = (isset($_POST['add_file'])) ? true : false;
@@ -1156,7 +1159,7 @@ class parse_message extends bbcode_firstpass
if ($filedata['post_attach'] && !sizeof($error))
{
- $new_entry = array(
+ $sql_ary = array(
'physical_filename' => $filedata['physical_filename'],
'attach_comment' => $this->filename_data['filecomment'],
'real_filename' => $filedata['real_filename'],
@@ -1164,8 +1167,19 @@ class parse_message extends bbcode_firstpass
'mimetype' => $filedata['mimetype'],
'filesize' => $filedata['filesize'],
'filetime' => $filedata['filetime'],
- 'attach_id' => 0,
- 'thumbnail' => $filedata['thumbnail']
+ 'thumbnail' => $filedata['thumbnail'],
+ 'is_orphan' => 1,
+ 'in_message' => ($is_message) ? 1 : 0,
+ 'poster_id' => $user->data['user_id'],
+ );
+
+ $db->sql_query('INSERT INTO ' . ATTACHMENTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
+
+ $new_entry = array(
+ 'attach_id' => $db->sql_nextid(),
+ 'is_orphan' => 1,
+ 'real_filename' => $filedata['real_filename'],
+ 'attach_comment'=> $this->filename_data['filecomment'],
);
$this->attachment_data = array_merge(array(0 => $new_entry), $this->attachment_data);
@@ -1199,32 +1213,51 @@ class parse_message extends bbcode_firstpass
$index = (int) key($_POST['delete_file']);
- // delete selected attachment
- if (!$this->attachment_data[$index]['attach_id'])
+ if (!empty($this->attachment_data[$index]))
{
- phpbb_unlink($this->attachment_data[$index]['physical_filename'], 'file');
- if ($this->attachment_data[$index]['thumbnail'])
+ // delete selected attachment
+ if ($this->attachment_data[$index]['is_orphan'])
{
- phpbb_unlink($this->attachment_data[$index]['physical_filename'], 'thumbnail');
+ $sql = 'SELECT attach_id, physical_filename, thumbnail
+ FROM ' . ATTACHMENTS_TABLE . '
+ WHERE attach_id = ' . (int) $this->attachment_data[$index]['attach_id'] . '
+ AND is_orphan = 1
+ AND poster_id = ' . $user->data['user_id'];
+ $result = $db->sql_query($sql);
+ $row = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ if ($row)
+ {
+ phpbb_unlink($row['physical_filename'], 'file');
+
+ if ($row['thumbnail'])
+ {
+ phpbb_unlink($row['physical_filename'], 'thumbnail');
+ }
+
+ $db->sql_query('DELETE FROM ' . ATTACHMENTS_TABLE . ' WHERE attach_id = ' . (int) $this->attachment_data[$index]['attach_id']);
+ }
+ }
+ else
+ {
+ delete_attachments('attach', array(intval($this->attachment_data[$index]['attach_id'])));
}
- }
- else
- {
- delete_attachments('attach', array(intval($this->attachment_data[$index]['attach_id'])));
- }
- unset($this->attachment_data[$index]);
- $this->message = preg_replace('#\[attachment=([0-9]+)\](.*?)\[\/attachment\]#e', "(\\1 == \$index) ? '' : ((\\1 > \$index) ? '[attachment=' . (\\1 - 1) . ']\\2[/attachment]' : '\\0')", $this->message);
+ unset($this->attachment_data[$index]);
+ $this->message = preg_replace('#\[attachment=([0-9]+)\](.*?)\[\/attachment\]#e', "(\\1 == \$index) ? '' : ((\\1 > \$index) ? '[attachment=' . (\\1 - 1) . ']\\2[/attachment]' : '\\0')", $this->message);
- // Reindex Array
- $this->attachment_data = array_values($this->attachment_data);
+ // Reindex Array
+ $this->attachment_data = array_values($this->attachment_data);
+ }
}
else if ($edit_comment || $add_file || $preview)
{
if ($edit_comment)
{
$actual_comment_list = request_var('comment_list', array(''), true);
+ utf8_normalize_nfc(&$actual_comment_list);
$edit_comment = request_var('edit_comment', array(0 => ''));
$edit_comment = key($edit_comment);
@@ -1233,14 +1266,14 @@ class parse_message extends bbcode_firstpass
if (($add_file || $preview) && $upload_file)
{
- if ($num_attachments < $cfg['max_attachments'] || $auth->acl_gets('m_', 'a_'))
+ if ($num_attachments < $cfg['max_attachments'] || $auth->acl_gets('m_', 'a_', $forum_id))
{
$filedata = upload_attachment($form_name, $forum_id, false, '', $is_message);
$error = array_merge($error, $filedata['error']);
if (!sizeof($error))
{
- $new_entry = array(
+ $sql_ary = array(
'physical_filename' => $filedata['physical_filename'],
'attach_comment' => $this->filename_data['filecomment'],
'real_filename' => $filedata['real_filename'],
@@ -1248,8 +1281,19 @@ class parse_message extends bbcode_firstpass
'mimetype' => $filedata['mimetype'],
'filesize' => $filedata['filesize'],
'filetime' => $filedata['filetime'],
- 'attach_id' => 0,
- 'thumbnail' => $filedata['thumbnail']
+ 'thumbnail' => $filedata['thumbnail'],
+ 'is_orphan' => 1,
+ 'in_message' => ($is_message) ? 1 : 0,
+ 'poster_id' => $user->data['user_id'],
+ );
+
+ $db->sql_query('INSERT INTO ' . ATTACHMENTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
+
+ $new_entry = array(
+ 'attach_id' => $db->sql_nextid(),
+ 'is_orphan' => 1,
+ 'real_filename' => $filedata['real_filename'],
+ 'attach_comment'=> $this->filename_data['filecomment'],
);
$this->attachment_data = array_merge(array(0 => $new_entry), $this->attachment_data);
@@ -1279,99 +1323,84 @@ class parse_message extends bbcode_firstpass
global $user, $db, $phpbb_root_path, $phpEx, $config;
$this->filename_data['filecomment'] = request_var('filecomment', '', true);
- $this->attachment_data = (isset($_POST['attachment_data'])) ? $_POST['attachment_data'] : array();
+ utf8_normalize_nfc(&$this->filename_data['filecomment']);
+ $attachment_data = (isset($_POST['attachment_data'])) ? $_POST['attachment_data'] : array();
+ $this->attachment_data = array();
$check_user_id = ($check_user_id === false) ? $user->data['user_id'] : $check_user_id;
- // Regenerate data array...
- $attach_ids = $filenames = array();
+ if (!sizeof($attachment_data))
+ {
+ return;
+ }
- foreach ($this->attachment_data as $pos => $var_ary)
+ $not_orphan = $orphan = array();
+
+ foreach ($attachment_data as $pos => $var_ary)
{
- if ($var_ary['attach_id'])
+ if ($var_ary['is_orphan'])
{
- $attach_ids[(int) $this->attachment_data[$pos]['attach_id']] = $pos;
+ $orphan[(int) $var_ary['attach_id']] = $pos;
}
else
{
- $filenames[$pos] = '';
- set_var($filenames[$pos], $this->attachment_data[$pos]['physical_filename'], 'string');
- $filenames[$pos] = basename($filenames[$pos]);
+ $not_orphan[(int) $var_ary['attach_id']] = $pos;
}
}
- $this->attachment_data = array();
-
- // Regenerate already posted attachments...
- if (sizeof($attach_ids))
+ // Regenerate already posted attachments
+ if (sizeof($not_orphan))
{
- // Get the data from the attachments
- $sql = 'SELECT attach_id, physical_filename, real_filename, extension, mimetype, filesize, filetime, thumbnail
+ // Get the attachment data, based on the poster id...
+ $sql = 'SELECT attach_id, is_orphan, real_filename, attach_comment
FROM ' . ATTACHMENTS_TABLE . '
- WHERE ' . $db->sql_in_set('attach_id', array_keys($attach_ids)) . '
+ WHERE ' . $db->sql_in_set('attach_id', array_keys($not_orphan)) . '
AND poster_id = ' . $check_user_id;
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
- if (isset($attach_ids[$row['attach_id']]))
- {
- $pos = $attach_ids[$row['attach_id']];
- $this->attachment_data[$pos] = $row;
- set_var($this->attachment_data[$pos]['attach_comment'], $_POST['attachment_data'][$pos]['attach_comment'], 'string', true);
+ $pos = $not_orphan[$row['attach_id']];
+ $this->attachment_data[$pos] = $row;
+ set_var($this->attachment_data[$pos]['attach_comment'], $_POST['attachment_data'][$pos]['attach_comment'], 'string', true);
- unset($attach_ids[$row['attach_id']]);
- }
+ unset($not_orphan[$row['attach_id']]);
}
$db->sql_freeresult($result);
+ }
- if (sizeof($attach_ids))
- {
- trigger_error($user->lang['NO_ACCESS_ATTACHMENT'], E_USER_ERROR);
- }
+ if (sizeof($not_orphan))
+ {
+ trigger_error($user->lang['NO_ACCESS_ATTACHMENT'], E_USER_ERROR);
}
// Regenerate newly uploaded attachments
- if (sizeof($filenames))
+ if (sizeof($orphan))
{
- include_once($phpbb_root_path . 'includes/functions_upload.' . $phpEx);
-
- $sql = 'SELECT attach_id
+ $sql = 'SELECT attach_id, is_orphan, real_filename, attach_comment
FROM ' . ATTACHMENTS_TABLE . '
- WHERE ' . $db->sql_in_set('LOWER(physical_filename)', array_map('strtolower', $filenames));
- $result = $db->sql_query_limit($sql, 1);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if ($row)
- {
- trigger_error($user->lang['NO_ACCESS_ATTACHMENT'], E_USER_ERROR);
- }
+ WHERE ' . $db->sql_in_set('attach_id', array_keys($orphan)) . '
+ AND poster_id = ' . $user->data['user_id'] . '
+ AND is_orphan = 1';
+ $result = $db->sql_query($sql);
- foreach ($filenames as $pos => $physical_filename)
+ while ($row = $db->sql_fetchrow($result))
{
- $this->attachment_data[$pos] = array(
- 'physical_filename' => $physical_filename,
- 'extension' => strtolower(filespec::get_extension($phpbb_root_path . $config['upload_path'] . '/' . $physical_filename)),
- 'filesize' => filespec::get_filesize($phpbb_root_path . $config['upload_path'] . '/' . $physical_filename),
- 'attach_id' => 0,
- 'thumbnail' => (file_exists($phpbb_root_path . $config['upload_path'] . '/thumb_' . $physical_filename)) ? 1 : 0,
- );
-
+ $pos = $orphan[$row['attach_id']];
+ $this->attachment_data[$pos] = $row;
set_var($this->attachment_data[$pos]['attach_comment'], $_POST['attachment_data'][$pos]['attach_comment'], 'string', true);
- set_var($this->attachment_data[$pos]['real_filename'], $_POST['attachment_data'][$pos]['real_filename'], 'string', true);
- set_var($this->attachment_data[$pos]['filetime'], $_POST['attachment_data'][$pos]['filetime'], 'int');
- if (strpos($_POST['attachment_data'][$pos]['mimetype'], 'image/') !== false)
- {
- set_var($this->attachment_data[$pos]['mimetype'], $_POST['attachment_data'][$pos]['mimetype'], 'string');
- }
- else
- {
- $this->attachment_data[$pos]['mimetype'] = filespec::get_mimetype($phpbb_root_path . $config['upload_path'] . '/' . $physical_filename);
- }
+ unset($orphan[$row['attach_id']]);
}
+ $db->sql_freeresult($result);
+ }
+
+ if (sizeof($orphan))
+ {
+ trigger_error($user->lang['NO_ACCESS_ATTACHMENT'], E_USER_ERROR);
}
+
+ ksort($this->attachment_data);
}
/**
@@ -1388,8 +1417,7 @@ class parse_message extends bbcode_firstpass
$this->message = $poll['poll_option_text'];
- $poll['poll_option_text'] = $this->parse($poll['enable_bbcode'], $poll['enable_urls'], $poll['enable_smilies'], $poll['img_status'], false, false, false);
-
+ $poll['poll_option_text'] = $this->parse($poll['enable_bbcode'], ($config['allow_post_links']) ? $poll['enable_urls'] : false, $poll['enable_smilies'], $poll['img_status'], false, false, $config['allow_post_links'], false);
$this->message = $tmp_message;
@@ -1398,8 +1426,7 @@ class parse_message extends bbcode_firstpass
$this->message = $poll['poll_title'];
- $poll['poll_title'] = $this->parse($poll['enable_bbcode'], $poll['enable_urls'], $poll['enable_smilies'], $poll['img_status'], false, false, false);
-
+ $poll['poll_title'] = $this->parse($poll['enable_bbcode'], ($config['allow_post_links']) ? $poll['enable_urls'] : false, $poll['enable_smilies'], $poll['img_status'], false, false, $config['allow_post_links'], false);
$this->message = $tmp_message;
diff --git a/phpBB/includes/search/fulltext_mysql.php b/phpBB/includes/search/fulltext_mysql.php
index 4a9a57df34..755bd5b814 100644
--- a/phpBB/includes/search/fulltext_mysql.php
+++ b/phpBB/includes/search/fulltext_mysql.php
@@ -49,7 +49,7 @@ class fulltext_mysql extends search_backend
{
global $db, $user;
- if (strpos(SQL_LAYER, 'mysql') === false)
+ if (strpos($db->sql_layer, 'mysql') === false)
{
return $user->lang['FULLTEXT_MYSQL_INCOMPATIBLE_VERSION'];
}
@@ -153,7 +153,7 @@ class fulltext_mysql extends search_backend
$clean_word = preg_replace('#^[+\-|]#', '', $word);
// check word length
- $clean_len = strlen(str_replace('*', '', $clean_word));
+ $clean_len = utf8_strlen(str_replace('*', '', $clean_word));
if (($clean_len < $config['fulltext_mysql_min_word_len']) || ($clean_len > $config['fulltext_mysql_max_word_len']))
{
$this->common_words[] = $word;
@@ -203,7 +203,7 @@ class fulltext_mysql extends search_backend
for ($i = 0, $n = sizeof($text); $i < $n; $i++)
{
$text[$i] = trim($text[$i]);
- if (strlen($text[$i]) < $config['fulltext_mysql_min_word_len'] || strlen($text[$i]) > $config['fulltext_mysql_max_word_len'])
+ if (utf8_strlen($text[$i]) < $config['fulltext_mysql_min_word_len'] || utf8_strlen($text[$i]) > $config['fulltext_mysql_max_word_len'])
{
unset($text[$i]);
}
@@ -561,7 +561,7 @@ class fulltext_mysql extends search_backend
*
* @param string $mode contains the post mode: edit, post, reply, quote ...
*/
- function index($mode, $post_id, &$message, &$subject, $encoding, $poster_id, $forum_id)
+ function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id)
{
global $db;
@@ -732,7 +732,7 @@ class fulltext_mysql extends search_backend
{
global $db;
- if (strpos(SQL_LAYER, 'mysql') === false)
+ if (strpos($db->sql_layer, 'mysql') === false)
{
$this->stats = array();
return;
diff --git a/phpBB/includes/search/fulltext_native.php b/phpBB/includes/search/fulltext_native.php
index bc11d2ed20..b47076228a 100755
--- a/phpBB/includes/search/fulltext_native.php
+++ b/phpBB/includes/search/fulltext_native.php
@@ -56,10 +56,6 @@ class fulltext_native extends search_backend
{
include($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx);
}
- if (!function_exists('utf8_strlen'))
- {
- include($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx);
- }
$error = false;
@@ -86,38 +82,89 @@ class fulltext_native extends search_backend
{
global $db, $config, $user;
- // Clean up the query search
- $match = array(
- // Replace multiple spaces with a single space
- '# +#',
+ $keywords = trim($this->cleanup($keywords, '+-|()*'));
- // Strip spaces after: +-|(
- '#([+\\-|(]) #',
+ // allow word|word|word without brackets
+ if ((strpos($keywords, ' ') === false) && (strpos($keywords, '|') !== false) && (strpos($keywords, '(') === false))
+ {
+ $keywords = '(' . $keywords . ')';
+ }
- // Strip spaces before: |*)
- '# ([|*)])#',
+ $open_bracket = $space = false;
+ for ($i = 0, $n = strlen($keywords); $i < $n; $i++)
+ {
+ if ($open_bracket !== false)
+ {
+ switch ($keywords[$i])
+ {
+ case ')':
+ if ($open_bracket + 1 == $i)
+ {
+ $keywords[$i - 1] = '|';
+ $keywords[$i] = '|';
+ }
+ $open_bracket = false;
+ break;
+ case '(':
+ $keywords[$i] = '|';
+ break;
+ case '+':
+ case '-':
+ case ' ':
+ $keywords[$i] = '|';
+ break;
+ }
+ }
+ else
+ {
+ switch ($keywords[$i])
+ {
+ case ')':
+ $keywords[$i] = ' ';
+ break;
+ case '(':
+ $open_bracket = $i;
+ break;
+ case '|':
+ $keywords[$i] = ' ';
+ break;
+ case '-':
+ case '+':
+ $space = $keywords[$i];
+ break;
+ case ' ':
+ if ($space !== false)
+ {
+ $keywords[$i] = $space;
+ }
+ break;
+ default:
+ $space = false;
+ }
+ }
+ }
- // Make word|word|word work without brackets
- '#^[^()]*\\|[^()]*$#',
+ if ($open_bracket)
+ {
+ $keywords .= ')';
+ }
- // Remove nested brackets
- '#(\\([^()]*)(?=\\()#',
- '#\\)([^()]*)(?=\\))#',
+ $match = array(
+ '# +#',
+ '#\|\|+#',
+ '#(\+|\-)(?:\+|\-)+#',
+ '#\(\|#',
+ '#\|\)#',
);
-
$replace = array(
' ',
+ '|',
'$1',
- '$1',
- '($0)',
- '$1)',
- '$1',
+ '(',
+ ')',
);
- $keywords = trim(preg_replace($match, $replace, $this->cleanup($keywords, '+-|()*', $user->lang['ENCODING'])));
-
- // remove some useless bracket combinations which might be created by the previous regexps
- $keywords = str_replace(array('()', ')|('), array('', '|'), $keywords);
+ $keywords = preg_replace($match, $replace, $keywords);
// $keywords input format: each word seperated by a space, words in a bracket are not seperated
@@ -134,7 +181,7 @@ class fulltext_native extends search_backend
}
// set the search_query which is shown to the user
- $this->search_query = utf8_encode_ncr($keywords, ENT_QUOTES);
+ $this->search_query = $keywords;
$exact_words = array();
preg_match_all('#([^\\s+\\-|*()]+)(?:$|[\\s+\\-|()])#', $keywords, $exact_words);
@@ -152,7 +199,7 @@ class fulltext_native extends search_backend
{
if ($row['word_common'])
{
- $this->common_words[] = $row['wort_text'];
+ $this->common_words[] = $row['word_text'];
continue;
}
@@ -187,7 +234,7 @@ class fulltext_native extends search_backend
// a group of which at least one may not be in the resulting posts
if ($word[0] == '(')
{
- $word = explode('|', substr($word, 1, -1));
+ $word = array_unique(explode('|', substr($word, 1, -1)));
$mode = 'must_exclude_one';
}
// one word which should not be in the resulting posts
@@ -209,12 +256,17 @@ class fulltext_native extends search_backend
// a group of words of which at least one word should be in every resulting post
if ($word[0] == '(')
{
- $word = explode('|', substr($word, 1, -1));
+ $word = array_unique(explode('|', substr($word, 1, -1)));
}
$ignore_no_id = false;
$mode = 'must_contain';
}
+ if (empty($word))
+ {
+ continue;
+ }
+
// if this is an array of words then retrieve an id for each
if (is_array($word))
{
@@ -246,7 +298,7 @@ class fulltext_native extends search_backend
// throw an error if we shall not ignore unexistant words
else if (!$ignore_no_id)
{
- trigger_error(sprintf($user->lang['WORDS_IN_NO_POST'], utf8_encode_ncr(implode(', ', $word))));
+ trigger_error(sprintf($user->lang['WORDS_IN_NO_POST'], implode(', ', $word)));
}
}
// else we only need one id
@@ -264,7 +316,7 @@ class fulltext_native extends search_backend
// throw an error if we shall not ignore unexistant words
else if (!$ignore_no_id)
{
- trigger_error(sprintf($user->lang['WORD_IN_NO_POST'], utf8_encode_ncr($word)));
+ trigger_error(sprintf($user->lang['WORD_IN_NO_POST'], $word));
}
}
@@ -357,12 +409,6 @@ class fulltext_native extends search_backend
);
$sql_where[] = 'm0.post_id = p.post_id';
- if ($type == 'topics')
- {
- $sql_array['FROM'][TOPICS_TABLE] = 't';
- $group_by = true;
- }
-
$title_match = '';
$group_by = true;
// Build some display specific sql strings
@@ -383,6 +429,16 @@ class fulltext_native extends search_backend
break;
}
+ if ($type == 'topics')
+ {
+ if (!isset($sql_array['FROM'][TOPICS_TABLE]))
+ {
+ $sql_array['FROM'][TOPICS_TABLE] = 't';
+ $sql_where[] = 'p.topic_id = t.topic_id';
+ }
+ $group_by = true;
+ }
+
/**
* @todo Add a query optimizer (handle stuff like "+(4|3) +4")
*/
@@ -540,20 +596,24 @@ class fulltext_native extends search_backend
$sql = '';
$sql_array_count = $sql_array;
- switch (SQL_LAYER)
+ switch ($db->sql_layer)
{
- case 'mysql':
case 'mysql4':
case 'mysqli':
+
+ // 3.x does not support SQL_CALC_FOUND_ROWS
$sql_array['SELECT'] = 'SQL_CALC_FOUND_ROWS ' . $sql_array['SELECT'];
$is_mysql = true;
+
break;
case 'sqlite':
$sql_array_count['SELECT'] = ($type == 'posts') ? 'DISTINCT p.post_id' : 'DISTINCT p.topic_id';
$sql = 'SELECT COUNT(' . (($type == 'posts') ? 'post_id' : 'topic_id') . ') as total_results
FROM (' . $db->sql_build_query('SELECT', $sql_array_count) . ')';
+
// no break
+
default:
$sql_array_count['SELECT'] = ($type == 'posts') ? 'COUNT(DISTINCT p.post_id) AS total_results' : 'COUNT(DISTINCT p.topic_id) AS total_results';
$sql = (!$sql) ? $db->sql_build_query('SELECT', $sql_array_count) : $sql;
@@ -735,9 +795,8 @@ class fulltext_native extends search_backend
// If the cache was completely empty count the results
if (!$total_results)
{
- switch (SQL_LAYER)
+ switch ($db->sql_layer)
{
- case 'mysql':
case 'mysql4':
case 'mysqli':
$select = 'SQL_CALC_FOUND_ROWS ' . $select;
@@ -757,7 +816,7 @@ class fulltext_native extends search_backend
}
else
{
- if (SQL_LAYER == 'sqlite')
+ if ($db->sql_layer == 'sqlite')
{
$sql = 'SELECT COUNT(topic_id) as total_results
FROM (SELECT DISTINCT t.topic_id';
@@ -773,7 +832,7 @@ class fulltext_native extends search_backend
$m_approve_fid_sql
$sql_fora
AND t.topic_id = p.topic_id
- $sql_time" . ((SQL_LAYER == 'sqlite') ? ')' : '');
+ $sql_time" . (($db->sql_layer == 'sqlite') ? ')' : '');
}
$result = $db->sql_query($sql);
@@ -858,7 +917,7 @@ class fulltext_native extends search_backend
*
* NOTE: duplicates are NOT removed from the return array
*
- * @param string $text Text to split, encoded in user's encoding
+ * @param string $text Text to split, encoded in UTF-8
* @return array Array of UTF-8 words
*
* @access private
@@ -876,7 +935,7 @@ class fulltext_native extends search_backend
// Do not index code
$match[] = '#\[code(?:=.*?)?(\:?[0-9a-z]{5,})\].*?\[\/code(\:?[0-9a-z]{5,})\]#is';
// BBcode
- $match[] = '#\[\/?[a-z\*\+\-]+(?:=.*?)?(\:?[0-9a-z]{5,})\]#';
+ $match[] = '#\[\/?[a-z0-9\*\+\-]+(?:=.*?)?(?::[a-z])?(\:?[0-9a-z]{5,})\]#';
$min = $config['fulltext_native_min_chars'];
$max = $config['fulltext_native_max_chars'];
@@ -886,15 +945,15 @@ class fulltext_native extends search_backend
/**
* Clean up the string, remove HTML tags, remove BBCodes
*/
- $word = strtok($this->cleanup(preg_replace($match, ' ', strip_tags($text)), '', $user->lang['ENCODING']), ' ');
+ $word = strtok($this->cleanup(preg_replace($match, ' ', strip_tags($text)), -1), ' ');
while (isset($word[0]))
{
- if (isset($word[252])
+ if (isset($word[255])
|| !isset($word[$isset_min]))
{
/**
- * Words longer than 252 bytes are ignored. This will have to be
+ * Words longer than 255 bytes are ignored. This will have to be
* changed whenever we change the length of search_wordlist.word_text
*
* Words shorter than $isset_min bytes are ignored, too
@@ -939,13 +998,12 @@ class fulltext_native extends search_backend
* @param int $post_id The id of the post which is modified/created
* @param string $message New or updated post content
* @param string $subject New or updated post subject
- * @param string $encoding The post content's encoding
* @param int $poster_id Post author's user id
* @param int $forum_id The id of the forum in which the post is located
*
* @access public
*/
- function index($mode, $post_id, &$message, &$subject, $encoding, $poster_id, $forum_id)
+ function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id)
{
global $config, $db, $user;
@@ -1024,26 +1082,16 @@ class fulltext_native extends search_backend
if (sizeof($new_words))
{
- switch (SQL_LAYER)
- {
- case 'mysql':
- case 'mysql4':
- case 'mysqli':
- $sql = 'INSERT INTO ' . SEARCH_WORDLIST_TABLE . " (word_text)
- VALUES ('" . implode("'),('", array_map(array(&$db, 'sql_escape'), $new_words)) . "')";
- $db->sql_query($sql);
- break;
+ $sql_ary = array();
- default:
- foreach ($new_words as $word)
- {
- $sql = 'INSERT INTO ' . SEARCH_WORDLIST_TABLE . " (word_text)
- VALUES ('" . $db->sql_escape($word) . "')";
- $db->sql_query($sql);
- }
+ foreach ($new_words as $word)
+ {
+ $sql_ary[] = array('word_text' => $word);
}
+
+ $db->sql_multi_insert(SEARCH_WORDLIST_TABLE, $sql_ary);
}
- unset($new_words);
+ unset($new_words, $sql_ary);
}
// now update the search match table, remove links to removed words and add links to new words
@@ -1091,22 +1139,6 @@ class fulltext_native extends search_backend
}
/**
- * Used by index() to sort strings by string length, longest first
- */
- function strlencmp($a, $b)
- {
- $len_a = strlen($a);
- $len_b = strlen($b);
-
- if ($len_a == $len_b)
- {
- return 0;
- }
-
- return ($len_a > $len_b) ? -1 : 1;
- }
-
- /**
* Removes entries from the wordmatch table for the specified post_ids
*/
function index_remove($post_ids, $author_ids, $forum_ids)
@@ -1142,14 +1174,14 @@ class fulltext_native extends search_backend
$destroy_cache_words = array();
- // Remove common (> 60% of posts ) words
+ // Remove common (> 20% of posts ) words
if ($config['num_posts'] >= 100)
{
// First, get the IDs of common words
$sql = 'SELECT word_id
FROM ' . SEARCH_WORDMATCH_TABLE . '
GROUP BY word_id
- HAVING COUNT(word_id) > ' . floor($config['num_posts'] * 0.6);
+ HAVING COUNT(word_id) > ' . floor($config['num_posts'] * 0.2);
$result = $db->sql_query($sql);
$sql_in = array();
@@ -1200,9 +1232,9 @@ class fulltext_native extends search_backend
{
global $db;
- $db->sql_query(((SQL_LAYER != 'sqlite') ? 'TRUNCATE TABLE ' : 'DELETE FROM ') . SEARCH_WORDLIST_TABLE);
- $db->sql_query(((SQL_LAYER != 'sqlite') ? 'TRUNCATE TABLE ' : 'DELETE FROM ') . SEARCH_WORDMATCH_TABLE);
- $db->sql_query(((SQL_LAYER != 'sqlite') ? 'TRUNCATE TABLE ' : 'DELETE FROM ') . SEARCH_RESULTS_TABLE);
+ $db->sql_query((($db->sql_layer != 'sqlite') ? 'TRUNCATE TABLE ' : 'DELETE FROM ') . SEARCH_WORDLIST_TABLE);
+ $db->sql_query((($db->sql_layer != 'sqlite') ? 'TRUNCATE TABLE ' : 'DELETE FROM ') . SEARCH_WORDMATCH_TABLE);
+ $db->sql_query((($db->sql_layer != 'sqlite') ? 'TRUNCATE TABLE ' : 'DELETE FROM ') . SEARCH_RESULTS_TABLE);
}
/**
@@ -1265,7 +1297,7 @@ class fulltext_native extends search_backend
* @param string $encoding Text encoding
* @return string Cleaned up text, only alphanumeric chars are left
*/
- function cleanup($text, $allowed_chars = null, $encoding = 'iso-8859-1')
+ function cleanup($text, $allowed_chars = null, $encoding = 'utf-8')
{
global $phpbb_root_path, $phpEx;
static $conv = array(), $conv_loaded = array();
@@ -1290,7 +1322,7 @@ class fulltext_native extends search_backend
/**
* Replace HTML entities and NCRs
*/
- $text = html_entity_decode(utf8_decode_ncr($text), ENT_QUOTES);
+ $text = htmlspecialchars_decode(utf8_decode_ncr($text), ENT_QUOTES);
/**
* Load the UTF-8 normalizer
@@ -1524,7 +1556,7 @@ class fulltext_native extends search_backend
// These are fields required in the config table
return array(
'tpl' => $tpl,
- 'config' => array('fulltext_native_load_upd' => 'bool', 'fulltext_native_min_chars' => 'integer:0:252', 'fulltext_native_max_chars' => 'integer:0:252')
+ 'config' => array('fulltext_native_load_upd' => 'bool', 'fulltext_native_min_chars' => 'integer:0:255', 'fulltext_native_max_chars' => 'integer:0:255')
);
}
}
diff --git a/phpBB/includes/search/search.php b/phpBB/includes/search/search.php
index fa91b9eef5..4c8387bd22 100755
--- a/phpBB/includes/search/search.php
+++ b/phpBB/includes/search/search.php
@@ -285,7 +285,7 @@ class search_backend
{
$cache->destroy('_search_results_' . $row['search_key']);
}
- $db->sql_freeresult();
+ $db->sql_freeresult($result);
}
// clear all searches that searched for the specified authors
@@ -306,7 +306,7 @@ class search_backend
{
$cache->destroy('_search_results_' . $row['search_key']);
}
- $db->sql_freeresult();
+ $db->sql_freeresult($result);
}
$sql = 'DELETE
diff --git a/phpBB/includes/session.php b/phpBB/includes/session.php
index 64a203e0bf..b69bcc5f44 100644
--- a/phpBB/includes/session.php
+++ b/phpBB/includes/session.php
@@ -64,7 +64,8 @@ class session
$query_string = trim(implode('&', $args));
// basenamed page name (for example: index.php)
- $page_name = htmlspecialchars(basename($script_name));
+ $page_name = basename($script_name);
+ $page_name = urlencode(htmlspecialchars($page_name));
// current directory within the phpBB root (for example: adm)
$root_dirs = explode('/', str_replace('\\', '/', phpbb_realpath($root_path)));
@@ -112,6 +113,13 @@ class session
'page' => $page
);
+/*
+ if (!file_exists($page_name))
+ {
+ trigger_error('You are on a page that does not exist!', E_USER_ERROR);
+ }
+*/
+
return $page_array;
}
@@ -127,9 +135,6 @@ class session
*
* @param bool $update_session_page if true the session page gets updated.
* This can be set to circumvent certain scripts to update the users last visited page.
- *
- * @todo Introduce further user types, bot, guest
- * @todo Change user_type (as above) to a bitfield? user_type & USER_FOUNDER for example
*/
function session_begin($update_session_page = true)
{
@@ -148,12 +153,9 @@ class session
if (isset($_COOKIE[$config['cookie_name'] . '_sid']) || isset($_COOKIE[$config['cookie_name'] . '_u']))
{
- // Switch to request_var ... can this cause issues, can a _GET/_POST param
- // be used to poison this? Not sure that it makes any difference in terms of
- // the end result, be it a cookie or param.
- $this->cookie_data['u'] = request_var($config['cookie_name'] . '_u', 0);
- $this->cookie_data['k'] = request_var($config['cookie_name'] . '_k', '');
- $this->session_id = request_var($config['cookie_name'] . '_sid', '');
+ $this->cookie_data['u'] = request_var($config['cookie_name'] . '_u', 0, false, true);
+ $this->cookie_data['k'] = request_var($config['cookie_name'] . '_k', '', false, true);
+ $this->session_id = request_var($config['cookie_name'] . '_sid', '', false, true);
$SID = (defined('NEED_SID')) ? '?sid=' . $this->session_id : '?sid=';
$_SID = (defined('NEED_SID')) ? $this->session_id : '';
@@ -265,7 +267,6 @@ class session
$db->sql_query($sql);
}
- // Ultimately to be removed
$this->data['is_registered'] = ($this->data['user_id'] != ANONYMOUS && ($this->data['user_type'] == USER_NORMAL || $this->data['user_type'] == USER_FOUNDER)) ? true : false;
$this->data['is_bot'] = (!$this->data['is_registered'] && $this->data['user_id'] != ANONYMOUS) ? true : false;
@@ -275,7 +276,10 @@ class session
else
{
// Added logging temporarly to help debug bugs...
- add_log('critical', 'LOG_IP_BROWSER_CHECK', $u_ip, $s_ip, $u_browser, $s_browser);
+ if (defined('DEBUG_EXTRA'))
+ {
+ add_log('critical', 'LOG_IP_BROWSER_CHECK', $u_ip, $s_ip, $u_browser, $s_browser);
+ }
}
}
}
@@ -320,8 +324,7 @@ class session
* bot, act accordingly
*/
$bot = false;
- $active_bots = array();
- $cache->obtain_bots($active_bots);
+ $active_bots = $cache->obtain_bots();
foreach ($active_bots as $row)
{
@@ -374,7 +377,7 @@ class session
$sql = 'SELECT u.*
FROM ' . USERS_TABLE . ' u, ' . SESSIONS_KEYS_TABLE . ' k
WHERE u.user_id = ' . (int) $this->cookie_data['u'] . '
- AND u.user_type <> ' . USER_INACTIVE . "
+ AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ")
AND k.user_id = u.user_id
AND k.key_id = '" . $db->sql_escape(md5($this->cookie_data['k'])) . "'";
$result = $db->sql_query($sql);
@@ -389,7 +392,7 @@ class session
$sql = 'SELECT *
FROM ' . USERS_TABLE . '
WHERE user_id = ' . (int) $this->cookie_data['u'] . '
- AND user_type <> ' . USER_INACTIVE;
+ AND user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')';
$result = $db->sql_query($sql);
$this->data = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
@@ -405,9 +408,21 @@ class session
$this->cookie_data['k'] = '';
$this->cookie_data['u'] = ($bot) ? $bot : ANONYMOUS;
- $sql = 'SELECT *
- FROM ' . USERS_TABLE . '
- WHERE user_id = ' . (int) $this->cookie_data['u'];
+ if (!$bot)
+ {
+ $sql = 'SELECT *
+ FROM ' . USERS_TABLE . '
+ WHERE user_id = ' . (int) $this->cookie_data['u'];
+ }
+ else
+ {
+ // We give bots always the same session if it is not yet expired.
+ $sql = 'SELECT u.*, s.*
+ FROM ' . USERS_TABLE . ' u
+ LEFT JOIN ' . SESSIONS_TABLE . ' s ON (s.session_user_id = u.user_id)
+ WHERE u.user_id = ' . (int) $bot;
+ }
+
$result = $db->sql_query($sql);
$this->data = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
@@ -422,26 +437,66 @@ class session
$this->data['session_last_visit'] = $this->time_now;
}
+ // Force user id to be integer...
+ $this->data['user_id'] = (int) $this->data['user_id'];
+
// At this stage we should have a filled data array, defined cookie u and k data.
// data array should contain recent session info if we're a real user and a recent
// session exists in which case session_id will also be set
// Is user banned? Are they excluded? Won't return on ban, exists within method
- // @todo Change to !$this->data['user_type'] & USER_FOUNDER && !$this->data['user_type'] & USER_BOT in time
if ($this->data['user_type'] != USER_FOUNDER)
{
$this->check_ban($this->data['user_id'], $this->ip);
}
- //
- // Do away with ultimately?
- $this->data['is_registered'] = (!$bot && $this->data['user_id'] != ANONYMOUS) ? true : false;
+
+ $this->data['is_registered'] = (!$bot && $this->data['user_id'] != ANONYMOUS && ($this->data['user_type'] == USER_NORMAL || $this->data['user_type'] == USER_FOUNDER)) ? true : false;
$this->data['is_bot'] = ($bot) ? true : false;
- //
- //
- // @todo Change this ... check for "... && user_type & USER_NORMAL" ?
+ // If our friend is a bot, we re-assign a previously assigned session
+ if ($this->data['is_bot'] && $bot == $this->data['user_id'] && $this->data['session_id'])
+ {
+ // Only assign the current session if the ip and browser match...
+ $s_ip = implode('.', array_slice(explode('.', $this->data['session_ip']), 0, $config['ip_check']));
+ $u_ip = implode('.', array_slice(explode('.', $this->ip), 0, $config['ip_check']));
+
+ $s_browser = ($config['browser_check']) ? strtolower(substr($this->data['session_browser'], 0, 149)) : '';
+ $u_browser = ($config['browser_check']) ? strtolower(substr($this->browser, 0, 149)) : '';
+
+ if ($u_ip === $s_ip && $s_browser === $u_browser)
+ {
+ $this->session_id = $this->data['session_id'];
+
+ // Only update session DB a minute or so after last update or if page changes
+ if ($this->time_now - $this->data['session_time'] > 60 || ($this->update_session_page && $this->data['session_page'] != $this->page['page']))
+ {
+ $sql_ary = array('session_time' => $this->time_now, 'session_last_visit' => $this->time_now, 'session_admin' => 0);
+
+ if ($this->update_session_page)
+ {
+ $sql_ary['session_page'] = substr($this->page['page'], 0, 199);
+ }
+
+ $sql = 'UPDATE ' . SESSIONS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . "
+ WHERE session_id = '" . $db->sql_escape($this->session_id) . "'";
+ $db->sql_query($sql);
+ }
+
+ $SID = '?sid=';
+ $_SID = '';
+
+ return true;
+ }
+ else
+ {
+ // If the ip and browser does not match make sure we only have one bot assigned to one session
+ $db->sql_query('DELETE FROM ' . SESSIONS_TABLE . ' WHERE session_user_id = ' . $this->data['user_id']);
+ }
+ }
+
$session_autologin = (($this->cookie_data['k'] || $persist_login) && $this->data['is_registered']) ? true : false;
+ $set_admin = ($set_admin && $this->data['is_registered']) ? true : false;
// Create or update the session
$sql_ary = array(
@@ -516,6 +571,11 @@ class session
unset($cookie_expire);
}
+ else
+ {
+ $SID = '?sid=';
+ $_SID = '';
+ }
return true;
}
@@ -588,6 +648,9 @@ class session
$SID = '?sid=';
$this->session_id = $_SID = '';
+ // To make sure a valid session is created we create one for the anonymous user
+ $this->session_create(ANONYMOUS);
+
return true;
}
@@ -610,88 +673,48 @@ class session
$this->time_now = time();
}
- switch (SQL_LAYER)
- {
- case 'mysql4':
- case 'mysqli':
- // Firstly, delete guest sessions
- $sql = 'DELETE FROM ' . SESSIONS_TABLE . '
- WHERE session_user_id = ' . ANONYMOUS . '
- AND session_time < ' . (int) ($this->time_now - $config['session_length']);
- $db->sql_query($sql);
-
- // Keep only the most recent session for each user
- // Note: if the user is currently browsing the board, his
- // last_visit field won't be updated, which I believe should be
- // the normal behavior anyway
- $db->sql_return_on_error(true);
-
- $sql = 'DELETE FROM ' . SESSIONS_TABLE . '
- USING ' . SESSIONS_TABLE . ' s1, ' . SESSIONS_TABLE . ' s2
- WHERE s1.session_user_id = s2.session_user_id
- AND s1.session_time < s2.session_time';
- $db->sql_query($sql);
-
- $db->sql_return_on_error(false);
-
- // Update last visit time
- $sql = 'UPDATE ' . USERS_TABLE. ' u, ' . SESSIONS_TABLE . ' s
- SET u.user_lastvisit = s.session_time, u.user_lastpage = s.session_page
- WHERE s.session_time < ' . (int) ($this->time_now - $config['session_length']) . '
- AND u.user_id = s.session_user_id';
- $db->sql_query($sql);
-
- // Delete everything else now
- $sql = 'DELETE FROM ' . SESSIONS_TABLE . '
- WHERE session_time < ' . (int) ($this->time_now - $config['session_length']);
- $db->sql_query($sql);
-
- set_config('session_last_gc', $this->time_now, true);
- break;
-
- default:
+ // Firstly, delete guest sessions
+ $sql = 'DELETE FROM ' . SESSIONS_TABLE . '
+ WHERE session_user_id = ' . ANONYMOUS . '
+ AND session_time < ' . (int) ($this->time_now - $config['session_length']);
+ $db->sql_query($sql);
- // Get expired sessions, only most recent for each user
- $sql = 'SELECT session_user_id, session_page, MAX(session_time) AS recent_time
- FROM ' . SESSIONS_TABLE . '
- WHERE session_time < ' . ($this->time_now - $config['session_length']) . '
- GROUP BY session_user_id, session_page';
- $result = $db->sql_query_limit($sql, 5);
+ // Get expired sessions, only most recent for each user
+ $sql = 'SELECT session_user_id, session_page, MAX(session_time) AS recent_time
+ FROM ' . SESSIONS_TABLE . '
+ WHERE session_time < ' . ($this->time_now - $config['session_length']) . '
+ GROUP BY session_user_id, session_page';
+ $result = $db->sql_query_limit($sql, 10);
- $del_user_id = array();
- $del_sessions = 0;
+ $del_user_id = array();
+ $del_sessions = 0;
- while ($row = $db->sql_fetchrow($result));
- {
- if ($row['session_user_id'] != ANONYMOUS)
- {
- $sql = 'UPDATE ' . USERS_TABLE . '
- SET user_lastvisit = ' . (int) $row['recent_time'] . ", user_lastpage = '" . $db->sql_escape($row['session_page']) . "'
- WHERE user_id = " . (int) $row['session_user_id'];
- $db->sql_query($sql);
- }
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $sql = 'UPDATE ' . USERS_TABLE . '
+ SET user_lastvisit = ' . (int) $row['recent_time'] . ", user_lastpage = '" . $db->sql_escape($row['session_page']) . "'
+ WHERE user_id = " . (int) $row['session_user_id'];
+ $db->sql_query($sql);
- $del_user_id[] = (int) $row['session_user_id'];
- $del_sessions++;
- }
- $db->sql_freeresult($result);
+ $del_user_id[] = (int) $row['session_user_id'];
+ $del_sessions++;
+ }
+ $db->sql_freeresult($result);
- if (sizeof($del_user_id))
- {
- // Delete expired sessions
- $sql = 'DELETE FROM ' . SESSIONS_TABLE . '
- WHERE ' . $db->sql_in_set('session_user_id', $del_user_id) . '
- AND session_time < ' . ($this->time_now - $config['session_length']);
- $db->sql_query($sql);
- }
+ if (sizeof($del_user_id))
+ {
+ // Delete expired sessions
+ $sql = 'DELETE FROM ' . SESSIONS_TABLE . '
+ WHERE ' . $db->sql_in_set('session_user_id', $del_user_id) . '
+ AND session_time < ' . ($this->time_now - $config['session_length']);
+ $db->sql_query($sql);
+ }
- if ($del_sessions < 5)
- {
- // Less than 5 sessions, update gc timer ... else we want gc
- // called again to delete other sessions
- set_config('session_last_gc', $this->time_now, true);
- }
- break;
+ if ($del_sessions < 10)
+ {
+ // Less than 10 sessions, update gc timer ... else we want gc
+ // called again to delete other sessions
+ set_config('session_last_gc', $this->time_now, true);
}
if ($config['max_autologin_time'])
@@ -713,20 +736,11 @@ class session
{
global $config;
- if (!$config['cookie_domain'] || $config['cookie_domain'] == 'localhost' || $config['cookie_domain'] == '127.0.0.1')
- {
- @setcookie($config['cookie_name'] . '_' . $name, $cookiedata, $cookietime, $config['cookie_path']);
- }
- else
- {
- // Firefox does not allow setting cookies with a domain containing no periods.
- if (strpos($config['cookie_domain'], '.') === false)
- {
- $config['cookie_domain'] = '.' . $config['cookie_domain'];
- }
+ $name_data = rawurlencode($config['cookie_name'] . '_' . $name) . '=' . rawurlencode($cookiedata);
+ $expire = gmdate('D, d-M-Y H:i:s \\G\\M\\T', $cookietime);
+ $domain = (!$config['cookie_domain'] || $config['cookie_domain'] == 'localhost' || $config['cookie_domain'] == '127.0.0.1') ? '' : '; domain=' . $config['cookie_domain'];
- @setcookie($config['cookie_name'] . '_' . $name, $cookiedata, $cookietime, $config['cookie_path'], $config['cookie_domain'], $config['cookie_secure']);
- }
+ header('Set-Cookie: ' . $name_data . '; expires=' . $expire . '; path=' . $config['cookie_path'] . $domain . ((!$config['cookie_secure']) ? '' : '; secure') . '; HttpOnly', false);
}
/**
@@ -781,6 +795,7 @@ class session
$result = $db->sql_query($sql);
+ $ban_triggered_by = 'user';
while ($row = $db->sql_fetchrow($result))
{
if ((!empty($row['ban_userid']) && intval($row['ban_userid']) == $user_id) ||
@@ -796,6 +811,20 @@ class session
{
$banned = true;
$ban_row = $row;
+
+ if (!empty($row['ban_userid']) && intval($row['ban_userid']) == $user_id)
+ {
+ $ban_triggered_by = 'user';
+ }
+ else if (!empty($row['ban_ip']) && preg_match('#^' . str_replace('*', '.*?', $row['ban_ip']) . '$#i', $user_ip))
+ {
+ $ban_triggered_by = 'ip';
+ }
+ else
+ {
+ $ban_triggered_by = 'email';
+ }
+
// Don't break. Check if there is an exclude rule for this user
}
}
@@ -819,6 +848,8 @@ class session
$message = sprintf($this->lang[$message], $till_date, '<a href="mailto:' . $config['board_contact'] . '">', '</a>');
$message .= ($ban_row['ban_give_reason']) ? '<br /><br />' . sprintf($this->lang['BOARD_BAN_REASON'], $ban_row['ban_give_reason']) : '';
+ $message .= '<br /><br /><em>' . $this->lang['BAN_TRIGGERED_BY_' . strtoupper($ban_triggered_by)] . '</em>';
+
trigger_error($message);
}
@@ -826,6 +857,45 @@ class session
}
/**
+ * Check if ip is blacklisted
+ * This should be called only where absolutly necessary
+ *
+ * Only IPv4 (rbldns does not support AAAA records/IPv6 lookups)
+ *
+ * @author satmd (from the php manual)
+ * @return false if ip is not blacklisted, else an array([checked server], [lookup])
+ */
+ function check_dnsbl($ip = false)
+ {
+ if ($ip === false)
+ {
+ $ip = $this->ip;
+ }
+
+ $dnsbl_check = array(
+ 'bl.spamcop.net' => 'http://spamcop.net/bl.shtml?',
+ 'list.dsbl.org' => 'http://dsbl.org/listing?',
+ 'sbl-xbl.spamhaus.org' => 'http://www.spamhaus.org/query/bl?ip=',
+ );
+
+ if ($ip)
+ {
+ $quads = explode('.', $ip);
+ $reverse_ip = $quads[3] . '.' . $quads[2] . '.' . $quads[1] . '.' . $quads[0];
+
+ foreach ($dnsbl_check as $dnsbl => $lookup)
+ {
+ if (phpbb_checkdnsrr($reverse_ip . '.' . $dnsbl . '.', 'A') === true)
+ {
+ return array($dnsbl, $lookup . $ip);
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
* Set/Update a persistent login key
*
* This method creates or updates a persistent session key. When a user makes
@@ -960,15 +1030,20 @@ class user extends session
$this->timezone = $config['board_timezone'] * 3600;
$this->dst = $config['board_dst'] * 3600;
-/* Browser-specific language setting removed - might re-appear later
+ /**
+ * If a guest user is surfing, we try to guess his/her language first by obtaining the browser language
+ * @todo if re-enabled we need to make sure only those languages installed are checked
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
{
$accept_lang_ary = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
+
foreach ($accept_lang_ary as $accept_lang)
{
// Set correct format ... guess full xx_YY form
$accept_lang = substr($accept_lang, 0, 2) . '_' . strtoupper(substr($accept_lang, 3, 2));
+ $accept_lang = basename($accept_lang);
+
if (file_exists($phpbb_root_path . 'language/' . $accept_lang . "/common.$phpEx"))
{
$this->lang_name = $config['default_lang'] = $accept_lang;
@@ -979,6 +1054,8 @@ class user extends session
{
// No match on xx_YY so try xx
$accept_lang = substr($accept_lang, 0, 2);
+ $accept_lang = basename($accept_lang);
+
if (file_exists($phpbb_root_path . 'language/' . $accept_lang . "/common.$phpEx"))
{
$this->lang_name = $config['default_lang'] = $accept_lang;
@@ -988,7 +1065,7 @@ class user extends session
}
}
}
-*/
+ */
}
// We include common language file here to not load it every time a custom language file is included
@@ -1141,7 +1218,7 @@ class user extends session
// Does the user need to change their password? If so, redirect to the
// ucp profile reg_details page ... of course do not redirect if we're already in the ucp
- if (!defined('IN_ADMIN') && $config['chg_passforce'] && $this->data['is_registered'] && $this->data['user_passchg'] < time() - ($config['chg_passforce'] * 86400))
+ if (!defined('IN_ADMIN') && !defined('ADMIN_START') && $config['chg_passforce'] && $this->data['is_registered'] && $this->data['user_passchg'] < time() - ($config['chg_passforce'] * 86400))
{
if (strpos($this->page['query_string'], 'mode=reg_details') === false && $this->page['page_name'] != "ucp.$phpEx")
{
@@ -1207,7 +1284,7 @@ class user extends session
/**
* Set language entry (called by add_lang)
- * @access: private
+ * @access private
*/
function set_lang(&$lang, &$help, $lang_file, $use_db = false, $use_help = false)
{
@@ -1263,12 +1340,17 @@ class user extends session
$midnight = gmmktime(0, 0, 0, $m, $d, $y) - $this->timezone - $this->dst;
}
- if (strpos($format, '|') === false || (!($gmepoch > $midnight && !$forcedate) && !($gmepoch > $midnight - 86400 && !$forcedate)))
+ if (strpos($format, '|') === false || ($gmepoch < $midnight - 86400 && !$forcedate) || ($gmepoch > $midnight + 172800 && !$forcedate))
{
return strtr(@gmdate(str_replace('|', '', $format), $gmepoch + $this->timezone + $this->dst), $lang_dates);
}
- if ($gmepoch > $midnight && !$forcedate)
+ if ($gmepoch > $midnight + 86400 && !$forcedate)
+ {
+ $format = substr($format, 0, strpos($format, '|')) . '||' . substr(strrchr($format, '|'), 1);
+ return str_replace('||', $this->lang['datetime']['TOMORROW'], strtr(@gmdate($format, $gmepoch + $this->timezone + $this->dst), $lang_dates));
+ }
+ else if ($gmepoch > $midnight && !$forcedate)
{
$format = substr($format, 0, strpos($format, '|')) . '||' . substr(strrchr($format, '|'), 1);
return str_replace('||', $this->lang['datetime']['TODAY'], strtr(@gmdate($format, $gmepoch + $this->timezone + $this->dst), $lang_dates));
@@ -1337,13 +1419,15 @@ class user extends session
static $imgs;
global $phpbb_root_path;
- if (empty($imgs[$img . $suffix]) || $width !== false)
+ $img_data = &$imgs[$img . $suffix];
+
+ if (empty($img_data) || $width !== false)
{
if (!isset($this->theme[$img]) || !$this->theme[$img])
{
// Do not fill the image to let designers decide what to do if the image is empty
- $imgs[$img . $suffix] = '';
- return $imgs[$img . $suffix];
+ $img_data = '';
+ return $img_data;
}
// Do not include dimensions?
@@ -1369,9 +1453,9 @@ class user extends session
$imgsrc = str_replace('{SUFFIX}', $suffix, $imgsrc);
}
- $imgs[$img . $suffix]['src'] = $phpbb_root_path . 'styles/' . $this->theme['imageset_path'] . '/imageset/' . str_replace('{LANG}', $this->img_lang, $imgsrc);
- $imgs[$img . $suffix]['width'] = $width;
- $imgs[$img . $suffix]['height'] = $height;
+ $img_data['src'] = $phpbb_root_path . 'styles/' . $this->theme['imageset_path'] . '/imageset/' . str_replace('{LANG}', $this->img_lang, $imgsrc);
+ $img_data['width'] = $width;
+ $img_data['height'] = $height;
}
$alt = (!empty($this->lang[$alt])) ? $this->lang[$alt] : $alt;
@@ -1379,19 +1463,19 @@ class user extends session
switch ($type)
{
case 'src':
- return $imgs[$img . $suffix]['src'];
+ return $img_data['src'];
break;
case 'width':
- return $imgs[$img . $suffix]['width'];
+ return $img_data['width'];
break;
case 'height':
- return $imgs[$img . $suffix]['height'];
+ return $img_data['height'];
break;
default:
- return '<img src="' . $imgs[$img . $suffix]['src'] . '"' . (($imgs[$img . $suffix]['width']) ? ' width="' . $imgs[$img . $suffix]['width'] . '"' : '') . (($imgs[$img . $suffix]['height']) ? ' height="' . $imgs[$img . $suffix]['height'] . '"' : '') . ' alt="' . $alt . '" title="' . $alt . '" />';
+ return '<img src="' . $img_data['src'] . '"' . (($img_data['width']) ? ' width="' . $img_data['width'] . '"' : '') . (($img_data['height']) ? ' height="' . $img_data['height'] . '"' : '') . ' alt="' . $alt . '" title="' . $alt . '" />';
break;
}
}
diff --git a/phpBB/includes/template.php b/phpBB/includes/template.php
index 5281860ac5..36a0b8920b 100644
--- a/phpBB/includes/template.php
+++ b/phpBB/includes/template.php
@@ -39,11 +39,11 @@ class template
/**
* Set template location
- * @access: public
+ * @access public
*/
function set_template()
{
- global $phpbb_root_path, $config, $user;
+ global $phpbb_root_path, $user;
if (file_exists($phpbb_root_path . 'styles/' . $user->theme['template_path'] . '/template'))
{
@@ -60,7 +60,7 @@ class template
/**
* Set custom template location (able to use directory outside of phpBB)
- * @access: public
+ * @access public
*/
function set_custom_template($template_path, $template_name)
{
@@ -75,7 +75,7 @@ class template
/**
* Sets the template filenames for handles. $filename_array
* should be a hash of handle => filename pairs.
- * @access: public
+ * @access public
*/
function set_filenames($filename_array)
{
@@ -100,7 +100,7 @@ class template
/**
* Destroy template data set
- * @access: public
+ * @access public
*/
function destroy()
{
@@ -109,7 +109,7 @@ class template
/**
* Reset/empty complete block
- * @access: public
+ * @access public
*/
function destroy_block_vars($blockname)
{
@@ -139,7 +139,7 @@ class template
/**
* Display handle
- * @access: public
+ * @access public
*/
function display($handle, $include_once = true)
{
@@ -159,7 +159,7 @@ class template
/**
* Display the handle and assign the output to a template variable or return the compiled result.
- * @access: public
+ * @access public
*/
function assign_display($handle, $template_var = '', $return_content = true, $include_once = false)
{
@@ -179,7 +179,7 @@ class template
/**
* Load a compiled template if possible, if not, recompile it
- * @access: private
+ * @access private
*/
function _tpl_load(&$handle)
{
@@ -197,7 +197,11 @@ class template
global $db, $phpbb_root_path;
- include_once($phpbb_root_path . 'includes/functions_template.' . $phpEx);
+ if (!class_exists('template_compile'))
+ {
+ include($phpbb_root_path . 'includes/functions_template.' . $phpEx);
+ }
+
$compile = new template_compile($this);
// If the file for this handle is already loaded and compiled, do nothing.
@@ -271,7 +275,7 @@ class template
/**
* Assign key variable pairs from an array
- * @access: public
+ * @access public
*/
function assign_vars($vararray)
{
@@ -285,7 +289,7 @@ class template
/**
* Assign a single variable to a single key
- * @access: public
+ * @access public
*/
function assign_var($varname, $varval)
{
@@ -296,7 +300,7 @@ class template
/**
* Assign key variable pairs from an array to a specified block
- * @access: public
+ * @access public
*/
function assign_block_vars($blockname, $vararray)
{
@@ -398,7 +402,7 @@ class template
* and inserting at position 1 will result in this array: array(first positioned array, vararray, following vars)
*
* @return false on error, true on success
- * @access: public
+ * @access public
*/
function alter_block_array($blockname, $vararray, $key = false, $mode = 'insert')
{
@@ -484,7 +488,7 @@ class template
/**
* Include a seperate template
- * @access: private
+ * @access private
*/
function _tpl_include($filename, $include = true)
{
@@ -500,7 +504,7 @@ class template
if ($filename)
{
- include_once($filename);
+ include($filename);
return;
}
eval(' ?>' . $this->compiled_code[$handle] . '<?php ');
diff --git a/phpBB/includes/ucp/info/ucp_attachments.php b/phpBB/includes/ucp/info/ucp_attachments.php
index 6028b5922a..a6aa393da5 100644
--- a/phpBB/includes/ucp/info/ucp_attachments.php
+++ b/phpBB/includes/ucp/info/ucp_attachments.php
@@ -20,7 +20,7 @@ class ucp_attachments_info
'title' => 'UCP_ATTACHMENTS',
'version' => '1.0.0',
'modes' => array(
- 'attachments' => array('title' => 'UCP_ATTACHMENTS', 'auth' => 'acl_u_attach', 'cat' => array('UCP_ATTACHMENTS')),
+ 'attachments' => array('title' => 'UCP_MAIN_ATTACHMENTS', 'auth' => 'acl_u_attach', 'cat' => array('UCP_MAIN')),
),
);
}
diff --git a/phpBB/includes/ucp/info/ucp_prefs.php b/phpBB/includes/ucp/info/ucp_prefs.php
index 4700ebc43a..53a012ea3c 100644
--- a/phpBB/includes/ucp/info/ucp_prefs.php
+++ b/phpBB/includes/ucp/info/ucp_prefs.php
@@ -21,8 +21,8 @@ class ucp_prefs_info
'version' => '1.0.0',
'modes' => array(
'personal' => array('title' => 'UCP_PREFS_PERSONAL', 'auth' => '', 'cat' => array('UCP_PREFS')),
- 'view' => array('title' => 'UCP_PREFS_VIEW', 'auth' => '', 'cat' => array('UCP_PREFS')),
'post' => array('title' => 'UCP_PREFS_POST', 'auth' => '', 'cat' => array('UCP_PREFS')),
+ 'view' => array('title' => 'UCP_PREFS_VIEW', 'auth' => '', 'cat' => array('UCP_PREFS')),
),
);
}
diff --git a/phpBB/includes/ucp/info/ucp_profile.php b/phpBB/includes/ucp/info/ucp_profile.php
index 61daccda45..86b731c280 100644
--- a/phpBB/includes/ucp/info/ucp_profile.php
+++ b/phpBB/includes/ucp/info/ucp_profile.php
@@ -20,10 +20,10 @@ class ucp_profile_info
'title' => 'UCP_PROFILE',
'version' => '1.0.0',
'modes' => array(
- 'reg_details' => array('title' => 'UCP_PROFILE_REG_DETAILS', 'auth' => '', 'cat' => array('UCP_PROFILE')),
'profile_info' => array('title' => 'UCP_PROFILE_PROFILE_INFO', 'auth' => '', 'cat' => array('UCP_PROFILE')),
'signature' => array('title' => 'UCP_PROFILE_SIGNATURE', 'auth' => '', 'cat' => array('UCP_PROFILE')),
'avatar' => array('title' => 'UCP_PROFILE_AVATAR', 'auth' => '', 'cat' => array('UCP_PROFILE')),
+ 'reg_details' => array('title' => 'UCP_PROFILE_REG_DETAILS', 'auth' => '', 'cat' => array('UCP_PROFILE')),
),
);
}
diff --git a/phpBB/includes/ucp/ucp_activate.php b/phpBB/includes/ucp/ucp_activate.php
index 5f7ba150f4..b3cb27223a 100644
--- a/phpBB/includes/ucp/ucp_activate.php
+++ b/phpBB/includes/ucp/ucp_activate.php
@@ -53,7 +53,6 @@ class ucp_activate
if ($update_password)
{
$sql_ary = array(
- 'user_type' => USER_NORMAL,
'user_actkey' => '',
'user_password' => $user_row['user_newpasswd'],
'user_newpasswd' => ''
@@ -69,12 +68,12 @@ class ucp_activate
{
include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx);
- // Now we need to demote the user from the inactive group and add him to the registered group
- user_active_flip($user_row['user_id'], $user_row['user_type'], '', $user_row['username'], true);
+ user_active_flip('activate', $user_row['user_id']);
- // Update last username
- update_last_username();
- set_config('num_users', $config['num_users'] + 1, true);
+ $sql = 'UPDATE ' . USERS_TABLE . "
+ SET user_actkey = ''
+ WHERE user_id = {$user_row['user_id']}";
+ $db->sql_query($sql);
}
if ($config['require_activation'] == USER_ACTIVATION_ADMIN && !$update_password)
@@ -94,10 +93,7 @@ class ucp_activate
$messenger->headers('X-AntiAbuse: User IP - ' . $user->ip);
$messenger->assign_vars(array(
- 'SITENAME' => $config['sitename'],
- 'USERNAME' => html_entity_decode($user_row['username']),
-
- 'EMAIL_SIG' => str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']))
+ 'USERNAME' => htmlspecialchars_decode($user_row['username']))
);
$messenger->send($user_row['user_notify_type']);
diff --git a/phpBB/includes/ucp/ucp_attachments.php b/phpBB/includes/ucp/ucp_attachments.php
index 549e3a11b2..2312d1f30d 100644
--- a/phpBB/includes/ucp/ucp_attachments.php
+++ b/phpBB/includes/ucp/ucp_attachments.php
@@ -78,11 +78,17 @@ class ucp_attachments
$s_sort_dir .= '<option value="' . $key . '"' . $selected . '>' . $value . '</option>';
}
+ if (!isset($sort_key_sql[$sort_key]))
+ {
+ $sort_key = 'a';
+ }
+
$order_by = $sort_key_sql[$sort_key] . ' ' . (($sort_dir == 'a') ? 'ASC' : 'DESC');
$sql = 'SELECT COUNT(attach_id) as num_attachments
FROM ' . ATTACHMENTS_TABLE . '
- WHERE poster_id = ' . $user->data['user_id'];
+ WHERE poster_id = ' . $user->data['user_id'] . '
+ AND is_orphan = 0';
$result = $db->sql_query($sql);
$num_attachments = $db->sql_fetchfield('num_attachments');
$db->sql_freeresult($result);
@@ -92,6 +98,7 @@ class ucp_attachments
LEFT JOIN ' . TOPICS_TABLE . ' t ON (a.topic_id = t.topic_id AND a.in_message = 0)
LEFT JOIN ' . PRIVMSGS_TABLE . ' p ON (a.post_msg_id = p.msg_id AND a.in_message = 1)
WHERE a.poster_id = ' . $user->data['user_id'] . "
+ AND a.is_orphan = 0
ORDER BY $order_by";
$result = $db->sql_query_limit($sql, $config['topics_per_page'], $start);
diff --git a/phpBB/includes/ucp/ucp_confirm.php b/phpBB/includes/ucp/ucp_confirm.php
index 2c83306e5e..087a186fa7 100644
--- a/phpBB/includes/ucp/ucp_confirm.php
+++ b/phpBB/includes/ucp/ucp_confirm.php
@@ -54,37 +54,9 @@ class ucp_confirm
exit;
}
- // Some people might want the olde style CAPTCHA even if they have GD enabled, this also saves us from people who have GD but no TTF
- $policy_modules = array('policy_entropy', 'policy_3dbitmap');
-
- if (function_exists('imagettfbbox') && function_exists('imagettftext'))
- {
- $policy_modules = array_merge($policy_modules, array('policy_overlap', 'policy_shape', 'policy_cells', 'policy_stencil', 'policy_composite'));
- }
-
- foreach ($policy_modules as $key => $name)
+ if ($config['captcha_gd'])
{
- if ($config[$name] === '0')
- {
- unset($policy_modules[$key]);
- }
- }
-
- $policy = '';
- if (@extension_loaded('gd') && sizeof($policy_modules))
- {
- $change_lang = request_var('change_lang', '');
-
- if ($change_lang)
- {
- $lang = $change_lang;
- $user->lang_name = $lang = $change_lang;
- $user->lang_path = $phpbb_root_path . 'language/' . $lang . '/';
- $user->lang = array();
- $user->add_lang(array('common', 'ucp'));
- }
include($phpbb_root_path . 'includes/captcha/captcha_gd.' . $phpEx);
- $policy = $policy_modules[array_rand($policy_modules)];
}
else
{
@@ -92,7 +64,7 @@ class ucp_confirm
}
$captcha = new captcha();
- $captcha->execute($row['code'], $policy);
+ $captcha->execute($row['code']);
exit;
}
}
diff --git a/phpBB/includes/ucp/ucp_groups.php b/phpBB/includes/ucp/ucp_groups.php
index 47403c83da..ad6bde9be7 100644
--- a/phpBB/includes/ucp/ucp_groups.php
+++ b/phpBB/includes/ucp/ucp_groups.php
@@ -172,8 +172,6 @@ class ucp_groups
include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
$messenger = new messenger();
- $email_sig = str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']);
-
$sql = 'SELECT u.username, u.user_email, u.user_notify_type, u.user_jabber, u.user_lang
FROM ' . USER_GROUP_TABLE . ' ug, ' . USERS_TABLE . ' u
WHERE ug.user_id = u.user_id
@@ -190,10 +188,8 @@ class ucp_groups
$messenger->im($row['user_jabber'], $row['username']);
$messenger->assign_vars(array(
- 'EMAIL_SIG' => $email_sig,
- 'SITENAME' => $config['sitename'],
- 'USERNAME' => html_entity_decode($row['username']),
- 'GROUP_NAME' => html_entity_decode($group_row[$group_id]['group_name']),
+ 'USERNAME' => htmlspecialchars_decode($row['username']),
+ 'GROUP_NAME' => htmlspecialchars_decode($group_row[$group_id]['group_name']),
'U_PENDING' => generate_board_url() . "/ucp.$phpEx?i=groups&mode=manage&action=list&g=$group_id",
'U_GROUP' => generate_board_url() . "/memberlist.$phpEx?mode=group&g=$group_id")
@@ -496,7 +492,7 @@ class ucp_groups
{
if (isset($group_row['group_avatar']) && $group_row['group_avatar'])
{
- avatar_delete($group_row['group_avatar']);
+ avatar_delete('group', $group_row);
}
}
@@ -723,7 +719,8 @@ class ucp_groups
'PAGINATION' => generate_pagination($this->u_action . "&amp;action=$action&amp;g=$group_id", $total_members, $config['topics_per_page'], $start, true),
'U_ACTION' => $this->u_action . "&amp;g=$group_id",
- 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&amp;form=ucp&amp;field=usernames'))
+ 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&amp;form=ucp&amp;field=usernames'),
+ 'UA_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=ucp&field=usernames', false))
);
break;
@@ -862,7 +859,7 @@ class ucp_groups
$user->add_lang(array('acp/groups', 'acp/common'));
- $name_ary = request_var('usernames', '');
+ $name_ary = request_var('usernames', '', true);
if (!$group_id)
{
diff --git a/phpBB/includes/ucp/ucp_main.php b/phpBB/includes/ucp/ucp_main.php
index 8936a7728b..67e1c4d155 100644
--- a/phpBB/includes/ucp/ucp_main.php
+++ b/phpBB/includes/ucp/ucp_main.php
@@ -65,7 +65,7 @@ class ucp_main
if (sizeof($forum_ary))
{
- $sql .= ' AND ' . $db->sql_in_set('forum_id', $forum_ary);
+ $sql .= ' AND ' . $db->sql_in_set('forum_id', $forum_ary, true);
}
$result = $db->sql_query_limit($sql, 1);
$g_forum_id = (int) $db->sql_fetchfield('forum_id');
@@ -76,15 +76,20 @@ class ucp_main
WHERE t.forum_id = 0
AND t.topic_type = " . POST_GLOBAL . '
ORDER BY t.topic_last_post_time DESC';
- $result = $db->sql_query($sql);
$topic_list = $rowset = array();
- while ($row = $db->sql_fetchrow($result))
+ // If the user can't see any forums, he can't read any posts because fid of 0 is invalid
+ if ($g_forum_id)
{
- $topic_list[] = $row['topic_id'];
- $rowset[$row['topic_id']] = $row;
+ $result = $db->sql_query($sql);
+
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $topic_list[] = $row['topic_id'];
+ $rowset[$row['topic_id']] = $row;
+ }
+ $db->sql_freeresult($result);
}
- $db->sql_freeresult($result);
$topic_tracking_info = array();
if ($config['load_db_lastread'])
@@ -122,8 +127,10 @@ class ucp_main
$template->assign_block_vars('topicrow', array(
'FORUM_ID' => $forum_id,
'TOPIC_ID' => $topic_id,
+ 'LAST_POST_SUBJECT' => $row['topic_last_post_subject'],
'LAST_POST_TIME' => $user->format_date($row['topic_last_post_time']),
'LAST_POST_AUTHOR' => ($row['topic_last_poster_id'] == ANONYMOUS) ? (($row['topic_last_poster_name'] != '') ? $row['topic_last_poster_name'] . ' ' : $user->lang['GUEST'] . ' ') : $row['topic_last_poster_name'],
+ 'LAST_POST_AUTHOR_COLOUR' => ($row['topic_last_poster_colour']) ? '#' . $row['topic_last_poster_colour'] : '',
'TOPIC_TITLE' => censor_text($row['topic_title']),
'TOPIC_TYPE' => $topic_type,
@@ -131,7 +138,7 @@ class ucp_main
'NEWEST_POST_IMG' => $user->img('icon_topic_newest', 'VIEW_NEWEST_POST'),
'TOPIC_FOLDER_IMG' => $user->img($folder_img, $folder_alt),
'TOPIC_FOLDER_IMG_SRC' => $user->img($folder_img, $folder_alt, false, '', 'src'),
- 'ATTACH_ICON_IMG' => ($auth->acl_gets('f_download', 'u_download', $forum_id) && $row['topic_attachment']) ? $user->img('icon_topic_attach', '') : '',
+ 'ATTACH_ICON_IMG' => ($auth->acl_get('u_download') && $auth->acl_get('f_download', $forum_id) && $row['topic_attachment']) ? $user->img('icon_topic_attach', '') : '',
'S_USER_POSTED' => (!empty($row['topic_posted']) && $row['topic_posted']) ? true : false,
'S_UNREAD' => $unread_topic,
@@ -170,7 +177,6 @@ class ucp_main
'INTERESTS' => (!empty($row['user_interests'])) ? $row['user_interests'] : '',
// 'S_GROUP_OPTIONS' => $group_options,
- 'S_SHOW_ACTIVITY' => ($config['load_user_activity']) ? true : false,
'U_SEARCH_USER' => ($auth->acl_get('u_search')) ? append_sid("{$phpbb_root_path}search.$phpEx", 'author_id=' . $user->data['user_id'] . '&amp;sr=posts') : '')
);
@@ -286,6 +292,7 @@ class ucp_main
$last_post_time = $user->format_date($row['forum_last_post_time']);
$last_poster = ($row['forum_last_poster_name'] != '') ? $row['forum_last_poster_name'] : $user->lang['GUEST'];
+ $last_poster_colour = ($row['forum_last_poster_colour']) ? '#' . $row['forum_last_poster_colour'] : '';
$last_poster_url = ($row['forum_last_poster_id'] == ANONYMOUS) ? '' : append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&amp;u=' . $row['forum_last_poster_id']);
$last_post_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;p=" . $row['forum_last_post_id']) . '#p' . $row['forum_last_post_id'];
@@ -299,10 +306,14 @@ class ucp_main
'FORUM_ID' => $forum_id,
'FORUM_FOLDER_IMG' => $user->img($folder_image, $folder_alt),
'FORUM_FOLDER_IMG_SRC' => $user->img($folder_image, $folder_alt, false, '', 'src'),
+ 'FORUM_IMAGE' => ($row['forum_image']) ? '<img src="' . $phpbb_root_path . $row['forum_image'] . '" alt="' . $user->lang[$folder_alt] . '" />' : '',
+ 'FORUM_IMAGE_SRC' => ($row['forum_image']) ? $phpbb_root_path . $row['forum_image'] : '',
'FORUM_NAME' => $row['forum_name'],
'LAST_POST_IMG' => $user->img('icon_topic_latest', 'VIEW_LATEST_POST'),
+ 'LAST_POST_SUBJECT' => $row['forum_last_post_subject'],
'LAST_POST_TIME' => $last_post_time,
'LAST_POST_AUTHOR' => $last_poster,
+ 'LAST_POST_AUTHOR_COLOUR' => $last_poster_colour,
'U_LAST_POST_AUTHOR' => $last_poster_url,
'U_LAST_POST' => $last_post_url,
@@ -417,13 +428,17 @@ class ucp_main
// Send vars to template
$template->assign_block_vars('topicrow', array(
- 'FORUM_ID' => $forum_id,
- 'TOPIC_ID' => $topic_id,
- 'TOPIC_AUTHOR' => topic_topic_author($row),
- 'FIRST_POST_TIME' => $user->format_date($row['topic_time']),
- 'LAST_POST_TIME' => $user->format_date($row['topic_last_post_time']),
- 'LAST_VIEW_TIME' => $user->format_date($row['topic_last_view_time']),
- 'LAST_POST_AUTHOR' => ($row['topic_last_poster_name'] != '') ? $row['topic_last_poster_name'] : $user->lang['GUEST'],
+ 'FORUM_ID' => $forum_id,
+ 'TOPIC_ID' => $topic_id,
+ 'TOPIC_AUTHOR' => ($row['topic_first_poster_name']) ? $row['topic_first_poster_name'] : $user->lang['GUEST'],
+ 'TOPIC_AUTHOR_COLOUR' => ($row['topic_first_poster_colour']) ? '#' . $row['topic_first_poster_colour'] : '',
+ 'FIRST_POST_TIME' => $user->format_date($row['topic_time']),
+ 'LAST_POST_SUBJECT' => $row['topic_last_post_subject'],
+ 'LAST_POST_TIME' => $user->format_date($row['topic_last_post_time']),
+ 'LAST_VIEW_TIME' => $user->format_date($row['topic_last_view_time']),
+ 'LAST_POST_AUTHOR' => ($row['topic_last_poster_name'] != '') ? $row['topic_last_poster_name'] : $user->lang['GUEST'],
+ 'LAST_POST_AUTHOR_COLOUR' => ($row['topic_last_poster_colour']) ? '#' . $row['topic_last_poster_colour'] : '',
+
'PAGINATION' => topic_generate_pagination($replies, append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . (($row['forum_id']) ? $row['forum_id'] : $forum_id) . "&amp;t=$topic_id")),
'REPLIES' => $replies,
'VIEWS' => $row['topic_views'],
@@ -437,7 +452,7 @@ class ucp_main
'TOPIC_ICON_IMG' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['img'] : '',
'TOPIC_ICON_IMG_WIDTH' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['width'] : '',
'TOPIC_ICON_IMG_HEIGHT' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['height'] : '',
- 'ATTACH_ICON_IMG' => ($auth->acl_gets('f_download', 'u_download', $forum_id) && $row['topic_attachment']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '',
+ 'ATTACH_ICON_IMG' => ($auth->acl_get('u_download') && $auth->acl_get('f_download', $forum_id) && $row['topic_attachment']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '',
'S_TOPIC_TYPE' => $row['topic_type'],
'S_USER_POSTED' => (!empty($row['topic_posted'])) ? true : false,
@@ -446,6 +461,7 @@ class ucp_main
'U_NEWEST_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&amp;t=$topic_id&amp;view=unread") . '#unread',
'U_LAST_POST' => $view_topic_url . '&amp;p=' . $row['topic_last_post_id'] . '#p' . $row['topic_last_post_id'],
'U_LAST_POST_AUTHOR' => ($row['topic_last_poster_id'] != ANONYMOUS && $row['topic_last_poster_id']) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&amp;u=' . $row['topic_last_poster_id']) : '',
+ 'U_TOPIC_AUTHOR' => ($row['topic_poster'] != ANONYMOUS && $row['topic_poster']) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&amp;u=' . $row['topic_poster']) : '',
'U_VIEW_TOPIC' => $view_topic_url)
);
}
@@ -578,22 +594,26 @@ class ucp_main
'S_DELETED_TOPIC' => (!$row['topic_id']) ? true : false,
'S_GLOBAL_TOPIC' => (!$forum_id) ? true : false,
- 'TOPIC_AUTHOR' => topic_topic_author($row),
- 'FIRST_POST_TIME' => $user->format_date($row['topic_time']),
- 'LAST_POST_TIME' => $user->format_date($row['topic_last_post_time']),
- 'LAST_VIEW_TIME' => $user->format_date($row['topic_last_view_time']),
- 'LAST_POST_AUTHOR' => ($row['topic_last_poster_name'] != '') ? $row['topic_last_poster_name'] : $user->lang['GUEST'],
- 'PAGINATION' => topic_generate_pagination($replies, append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . (($row['forum_id']) ? $row['forum_id'] : $forum_id) . "&amp;t=$topic_id")),
+ 'TOPIC_AUTHOR' => ($row['topic_first_poster_name']) ? $row['topic_first_poster_name'] : $user->lang['GUEST'],
+ 'TOPIC_AUTHOR_COLOUR' => ($row['topic_first_poster_colour']) ? '#' . $row['topic_first_poster_colour'] : '',
+ 'FIRST_POST_TIME' => $user->format_date($row['topic_time']),
+ 'LAST_POST_SUBJECT' => $row['topic_last_post_subject'],
+ 'LAST_POST_TIME' => $user->format_date($row['topic_last_post_time']),
+ 'LAST_VIEW_TIME' => $user->format_date($row['topic_last_view_time']),
+ 'LAST_POST_AUTHOR' => ($row['topic_last_poster_name'] != '') ? $row['topic_last_poster_name'] : $user->lang['GUEST'],
+ 'LAST_POST_AUTHOR_COLOUR' => ($row['topic_last_poster_colour']) ? '#' . $row['topic_last_poster_colour'] : '',
+ 'PAGINATION' => topic_generate_pagination($replies, append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . (($row['forum_id']) ? $row['forum_id'] : $forum_id) . "&amp;t=$topic_id")),
'POSTED_AT' => $user->format_date($row['topic_time']),
'TOPIC_FOLDER_IMG' => $user->img($folder_img, $folder_alt),
'TOPIC_FOLDER_IMG_SRC' => $user->img($folder_img, $folder_alt, false, '', 'src'),
- 'ATTACH_ICON_IMG' => ($auth->acl_gets('f_download', 'u_download', $forum_id) && $row['topic_attachment']) ? $user->img('icon_topic_attach', '') : '',
+ 'ATTACH_ICON_IMG' => ($auth->acl_get('u_download') && $auth->acl_get('f_download', $forum_id) && $row['topic_attachment']) ? $user->img('icon_topic_attach', '') : '',
'LAST_POST_IMG' => $user->img('icon_topic_latest', 'VIEW_LATEST_POST'),
'U_LAST_POST' => $view_topic_url . '&amp;p=' . $row['topic_last_post_id'] . '#p' . $row['topic_last_post_id'],
'U_LAST_POST_AUTHOR' => ($row['topic_last_poster_id'] != ANONYMOUS && $row['topic_last_poster_id']) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&amp;u=' . $row['topic_last_poster_id']) : '',
+ 'U_TOPIC_AUTHOR' => ($row['topic_poster'] != ANONYMOUS && $row['topic_poster']) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&amp;u=' . $row['topic_poster']) : '',
'U_VIEW_TOPIC' => $view_topic_url,
'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id),
'U_MOVE_UP' => ($row['order_id'] != 1) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=main&amp;mode=bookmarks&amp;move_up=' . $row['order_id']) : '',
@@ -642,6 +662,8 @@ class ucp_main
{
$draft_subject = request_var('subject', '', true);
$draft_message = request_var('message', '', true);
+
+ utf8_normalize_nfc(array(&$draft_subject, &$draft_message));
if ($draft_message && $draft_subject)
{
diff --git a/phpBB/includes/ucp/ucp_pm.php b/phpBB/includes/ucp/ucp_pm.php
index 5d1a4297ee..14afc81686 100644
--- a/phpBB/includes/ucp/ucp_pm.php
+++ b/phpBB/includes/ucp/ucp_pm.php
@@ -96,7 +96,7 @@ class ucp_pm
$template->assign_vars(array(
'MESSAGE' => $l_new_message,
'S_NOT_LOGGED_IN' => ($user->data['user_id'] == ANONYMOUS) ? true : false,
- 'CLICK_TO_VIEW' => sprintf($user->lang['CLICK_VIEW_PRIVMSG'], '<a href="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;folder=inbox') . '" onclick="jump_to_inbox();return false;" target="_new">', '</a>'),
+ 'CLICK_TO_VIEW' => sprintf($user->lang['CLICK_VIEW_PRIVMSG'], '<a href="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;folder=inbox') . '" onclick="jump_to_inbox(); return false;">', '</a>'),
'U_INBOX' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;folder=inbox'),
'UA_INBOX' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&folder=inbox', false))
);
@@ -246,6 +246,17 @@ class ucp_pm
{
place_pm_into_folder($global_privmsgs_rules, request_var('release', 0));
$num_not_moved = $user->data['user_new_privmsg'];
+
+ // Make sure num_not_moved is valid.
+ if ($num_not_moved < 0)
+ {
+ $sql = 'UPDATE ' . USERS_TABLE . '
+ SET user_new_privmsg = 0, user_unread_privmsg = 0
+ WHERE user_id = ' . $user->data['user_id'];
+ $db->sql_query($sql);
+
+ $num_not_moved = $user->data['user_new_privmsg'] = $user->data['user_unread_privmsg'] = 0;
+ }
}
if (!$msg_id && $folder_id == PRIVMSGS_NO_BOX)
@@ -392,7 +403,7 @@ class ucp_pm
break;
default:
- trigger_error('NO_ACTION_MODE');
+ trigger_error('NO_ACTION_MODE', E_USER_ERROR);
break;
}
diff --git a/phpBB/includes/ucp/ucp_pm_compose.php b/phpBB/includes/ucp/ucp_pm_compose.php
index ff95bfc307..98aa35117b 100644
--- a/phpBB/includes/ucp/ucp_pm_compose.php
+++ b/phpBB/includes/ucp/ucp_pm_compose.php
@@ -66,6 +66,34 @@ function compose_pm($id, $mode, $action)
redirect(append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm'));
}
+ // Output PM_TO box if message composing
+ if ($action != 'edit')
+ {
+ if ($config['allow_mass_pm'] && $auth->acl_get('u_masspm'))
+ {
+ $sql = 'SELECT group_id, group_name, group_type
+ FROM ' . GROUPS_TABLE . '
+ WHERE group_type NOT IN (' . GROUP_HIDDEN . ', ' . GROUP_CLOSED . ')
+ AND group_receive_pm = 1
+ ORDER BY group_type DESC';
+ $result = $db->sql_query($sql);
+
+ $group_options = '';
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="blue"' : '') . ' value="' . $row['group_id'] . '">' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . '</option>';
+ }
+ $db->sql_freeresult($result);
+ }
+
+ $template->assign_vars(array(
+ 'S_SHOW_PM_BOX' => true,
+ 'S_ALLOW_MASS_PM' => ($config['allow_mass_pm'] && $auth->acl_get('u_masspm')) ? true : false,
+ 'S_GROUP_OPTIONS' => ($config['allow_mass_pm'] && $auth->acl_get('u_masspm')) ? $group_options : '',
+ 'U_SEARCH_USER' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&amp;form=post&amp;field=username_list'))
+ );
+ }
+
$sql = '';
// What is all this following SQL for? Well, we need to know
@@ -149,7 +177,7 @@ function compose_pm($id, $mode, $action)
break;
default:
- trigger_error('NO_ACTION_MODE');
+ trigger_error('NO_ACTION_MODE', E_USER_ERROR);
}
if ($action == 'forward' && (!$config['forward_pm'] || !$auth->acl_get('u_pm_forward')))
@@ -177,7 +205,7 @@ function compose_pm($id, $mode, $action)
$folder_id = (isset($post['folder_id'])) ? $post['folder_id'] : 0;
$message_text = (isset($post['message_text'])) ? $post['message_text'] : '';
- if (!$post['author_id'] && $msg_id)
+ if ((!$post['author_id'] || ($post['author_id'] == ANONYMOUS && $action != 'delete')) && $msg_id)
{
trigger_error('NO_AUTHOR');
}
@@ -307,19 +335,21 @@ function compose_pm($id, $mode, $action)
$error[] = $user->lang['TOO_MANY_RECIPIENTS'];
}
+ // Always check if the submitted attachment data is valid and belongs to the user.
+ // Further down (especially in submit_post()) we do not check this again.
$message_parser->get_submitted_attachment_data();
if ($message_attachment && !$submit && !$refresh && !$preview && $action == 'edit')
{
- $sql = 'SELECT attach_id, physical_filename, attach_comment, real_filename, extension, mimetype, filesize, filetime, thumbnail
+ // Do not change to SELECT *
+ $sql = 'SELECT attach_id, is_orphan, attach_comment, real_filename
FROM ' . ATTACHMENTS_TABLE . "
WHERE post_msg_id = $msg_id
AND in_message = 1
- ORDER BY filetime " . ((!$config['display_order']) ? 'DESC' : 'ASC');
+ AND is_orphan = 0
+ ORDER BY filetime " . ((!$config['display_order']) ? 'DESC' : 'ASC');
$result = $db->sql_query($sql);
-
$message_parser->attachment_data = array_merge($message_parser->attachment_data, $db->sql_fetchrowset($result));
-
$db->sql_freeresult($result);
}
@@ -361,6 +391,7 @@ function compose_pm($id, $mode, $action)
$smilies_status = ($config['allow_smilies'] && $config['auth_smilies_pm'] && $auth->acl_get('u_pm_smilies')) ? true : false;
$img_status = ($config['auth_img_pm'] && $auth->acl_get('u_pm_img')) ? true : false;
$flash_status = ($config['auth_flash_pm'] && $auth->acl_get('u_pm_flash')) ? true : false;
+ $url_status = ($config['allow_post_links']) ? true : false;
// Save Draft
if ($save && $auth->acl_get('u_savedrafts'))
@@ -368,6 +399,8 @@ function compose_pm($id, $mode, $action)
$subject = request_var('subject', '', true);
$subject = (!$subject && $action != 'post') ? $user->lang['NEW_MESSAGE'] : $subject;
$message = request_var('message', '', true);
+
+ utf8_normalize_nfc(array(&$subject, &$message));
if ($subject && $message)
{
@@ -444,13 +477,9 @@ function compose_pm($id, $mode, $action)
if ($submit || $preview || $refresh)
{
$subject = request_var('subject', '', true);
-
- if (strcmp($subject, strtoupper($subject)) == 0 && $subject)
- {
- $subject = strtolower($subject);
- }
-
$message_parser->message = request_var('message', '', true);
+
+ utf8_normalize_nfc(array(&$subject, &$message_parser->message));
$icon_id = request_var('icon', 0);
@@ -473,7 +502,7 @@ function compose_pm($id, $mode, $action)
$message_parser->parse_attachments('fileupload', $action, 0, $submit, $preview, $refresh, true);
// Parse message
- $message_parser->parse($enable_bbcode, $enable_urls, $enable_smilies, $img_status, $flash_status, true);
+ $message_parser->parse($enable_bbcode, ($config['allow_post_links']) ? $enable_urls : false, $enable_smilies, $img_status, $flash_status, true, $config['allow_sig_links']);
if ($action != 'edit' && !$preview && !$refresh && $config['flood_interval'] && !$auth->acl_get('u_ignoreflood'))
{
@@ -604,7 +633,14 @@ function compose_pm($id, $mode, $action)
if ($action == 'quotepost')
{
$post_id = request_var('p', 0);
- $message_link = "[url=" . generate_board_url() . "/viewtopic.$phpEx?p={$post_id}#p{$post_id}]{$message_subject}[/url]\n";
+ if ($config['allow_post_links'])
+ {
+ $message_link = "[url=" . generate_board_url() . "/viewtopic.$phpEx?p={$post_id}#p{$post_id}]{$message_subject}[/url]\n\n";
+ }
+ else
+ {
+ $message_link = $user->lang['SUBJECT'] . ': ' . $message_subject . " (" . generate_board_url() . "/viewtopic.$phpEx?p={$post_id}#p{$post_id})\n\n";
+ }
}
else
{
@@ -622,14 +658,23 @@ function compose_pm($id, $mode, $action)
{
$fwd_to_field = write_pm_addresses(array('to' => $post['to_address']), 0, true);
+ if ($config['allow_post_links'])
+ {
+ $quote_username_text = '[url=' . generate_board_url() . "/memberlist.$phpEx?mode=viewprofile&u={$post['author_id']}]{$quote_username}[/url]";
+ }
+ else
+ {
+ $quote_username_text = $quote_username . ' (' . generate_board_url() . "/memberlist.$phpEx?mode=viewprofile&u={$post['author_id']})";
+ }
+
$forward_text = array();
$forward_text[] = $user->lang['FWD_ORIGINAL_MESSAGE'];
$forward_text[] = sprintf($user->lang['FWD_SUBJECT'], censor_text($message_subject));
$forward_text[] = sprintf($user->lang['FWD_DATE'], $user->format_date($message_time));
- $forward_text[] = sprintf($user->lang['FWD_FROM'], $quote_username);
+ $forward_text[] = sprintf($user->lang['FWD_FROM'], $quote_username_text);
$forward_text[] = sprintf($user->lang['FWD_TO'], implode(', ', $fwd_to_field['to']));
- $message_parser->message = implode("\n", $forward_text) . "\n\n[quote=\"[url=" . generate_board_url() . "/memberlist.$phpEx?mode=viewprofile&u={$post['author_id']}]{$quote_username}[/url]\"]\n" . censor_text(trim($message_parser->message)) . "\n[/quote]";
+ $message_parser->message = implode("\n", $forward_text) . "\n\n[quote=\"{$quote_username}\"]\n" . censor_text(trim($message_parser->message)) . "\n[/quote]";
$message_subject = ((!preg_match('/^Fwd:/', $message_subject)) ? 'Fwd: ' : '') . censor_text($message_subject);
}
@@ -783,10 +828,11 @@ function compose_pm($id, $mode, $action)
'SUBJECT' => (isset($message_subject)) ? $message_subject : '',
'MESSAGE' => $message_text,
- 'BBCODE_STATUS' => ($bbcode_status) ? sprintf($user->lang['BBCODE_IS_ON'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '" onclick="target=\'_phpbbcode\';">', '</a>') : sprintf($user->lang['BBCODE_IS_OFF'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '" onclick="target=\'_phpbbcode\';">', '</a>'),
+ 'BBCODE_STATUS' => ($bbcode_status) ? sprintf($user->lang['BBCODE_IS_ON'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>') : sprintf($user->lang['BBCODE_IS_OFF'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>'),
'IMG_STATUS' => ($img_status) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'],
'FLASH_STATUS' => ($flash_status) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'],
'SMILIES_STATUS' => ($smilies_status) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'],
+ 'URL_STATUS' => ($url_status) ? $user->lang['URL_IS_ON'] : $user->lang['URL_IS_OFF'],
'MINI_POST_IMG' => $user->img('icon_post_target', $user->lang['PM']),
'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '',
@@ -798,6 +844,7 @@ function compose_pm($id, $mode, $action)
'S_SMILIES_CHECKED' => ($smilies_checked) ? ' checked="checked"' : '',
'S_SIG_ALLOWED' => ($config['allow_sig'] && $auth->acl_get('u_sig')),
'S_SIGNATURE_CHECKED' => ($sig_checked) ? ' checked="checked"' : '',
+ 'S_LINKS_ALLOWED' => $url_status,
'S_MAGIC_URL_CHECKED' => ($urls_checked) ? ' checked="checked"' : '',
'S_SAVE_ALLOWED' => $auth->acl_get('u_savedrafts'),
'S_HAS_DRAFTS' => ($auth->acl_get('u_savedrafts') && $drafts),
@@ -806,6 +853,7 @@ function compose_pm($id, $mode, $action)
'S_BBCODE_IMG' => $img_status,
'S_BBCODE_FLASH' => $flash_status,
'S_BBCODE_QUOTE' => true,
+ 'S_BBCODE_URL' => $url_status,
'S_POST_ACTION' => $s_action,
'S_HIDDEN_ADDRESS_FIELD' => $s_hidden_address_field,
@@ -868,8 +916,8 @@ function handle_message_list_actions(&$address_list, $remove_u, $remove_g, $add_
$user_id_ary = array();
// Build usernames to add
- $usernames = (isset($_REQUEST['username'])) ? array(request_var('username', '')) : array();
- $username_list = request_var('username_list', '');
+ $usernames = (isset($_REQUEST['username'])) ? array(request_var('username', '', true)) : array();
+ $username_list = request_var('username_list', '', true);
if ($username_list)
{
$usernames = array_merge($usernames, explode("\n", $username_list));
@@ -900,6 +948,11 @@ function handle_message_list_actions(&$address_list, $remove_u, $remove_g, $add_
while ($row = $db->sql_fetchrow($result))
{
+ if ($row['user_id'] == ANONYMOUS)
+ {
+ continue;
+ }
+
$address_list['u'][$row['user_id']] = $type;
}
$db->sql_freeresult($result);
@@ -908,6 +961,11 @@ function handle_message_list_actions(&$address_list, $remove_u, $remove_g, $add_
{
foreach ($user_id_ary as $user_id)
{
+ if ($user_id == ANONYMOUS)
+ {
+ continue;
+ }
+
$address_list['u'][$user_id] = $type;
}
}
diff --git a/phpBB/includes/ucp/ucp_pm_options.php b/phpBB/includes/ucp/ucp_pm_options.php
index c9e911b5f4..9b86553569 100644
--- a/phpBB/includes/ucp/ucp_pm_options.php
+++ b/phpBB/includes/ucp/ucp_pm_options.php
@@ -250,6 +250,8 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit
$rule_string = ($cond_option != 'none') ? request_var('rule_string', '', true) : '';
$rule_user_id = ($cond_option != 'none') ? request_var('rule_user_id', 0) : 0;
$rule_group_id = ($cond_option != 'none') ? request_var('rule_group_id', 0) : 0;
+
+ utf8_normalize_nfc(&$rule_string);
$action = (int) $action_option[0];
$folder_id = (int) $action_option[1];
@@ -433,7 +435,8 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit
'DEFAULT_ACTION' => ($config['full_folder_action'] == 1) ? $user->lang['DELETE_OLDEST_MESSAGES'] : $user->lang['HOLD_NEW_MESSAGES'],
- 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&amp;form=ucp&amp;field=rule_string'))
+ 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&amp;form=ucp&amp;field=rule_string'),
+ 'UA_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=ucp&field=rule_string', true))
);
$rule_lang = $action_lang = $check_lang = array();
@@ -478,6 +481,11 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit
}
// Check
+ if (!isset($global_privmsgs_rules[$check_option]))
+ {
+ $check_option = 0;
+ }
+
define_check_option(($check_option && !isset($back['rule'])) ? true : false, $check_option, $check_lang);
if ($check_option && !isset($back['rule']))
@@ -633,6 +641,8 @@ function define_cond_option($hardcoded, $cond_option, $rule_option, $global_rule
{
case 'text':
$rule_string = request_var('rule_string', '', true);
+
+ utf8_normalize_nfc(&$rule_string);
$template->assign_vars(array(
'S_TEXT_CONDITION' => true,
@@ -647,12 +657,14 @@ function define_cond_option($hardcoded, $cond_option, $rule_option, $global_rule
case 'user':
$rule_user_id = request_var('rule_user_id', 0);
$rule_string = request_var('rule_string', '', true);
+
+ utf8_normalize_nfc(&$rule_string);
if ($rule_string && !$rule_user_id)
{
$sql = 'SELECT user_id
FROM ' . USERS_TABLE . "
- WHERE LOWER(username) = '" . $db->sql_escape(strtolower($rule_string)) . "'";
+ WHERE username_clean = '" . $db->sql_escape(utf8_clean_string($rule_string)) . "'";
$result = $db->sql_query($sql);
$rule_user_id = (int) $db->sql_fetchfield('user_id');
$db->sql_freeresult($result);
@@ -690,6 +702,8 @@ function define_cond_option($hardcoded, $cond_option, $rule_option, $global_rule
case 'group':
$rule_group_id = request_var('rule_group_id', 0);
$rule_string = request_var('rule_string', '', true);
+
+ utf8_normalize_nfc(&$rule_string);
$sql_and = ($auth->acl_gets('a_group', 'a_groupadd', 'a_groupdel')) ? '<> ' . GROUP_SPECIAL : 'NOT IN (' . GROUP_SPECIAL . ', ' . GROUP_HIDDEN . ')';
$sql = 'SELECT group_id, group_name, group_type
diff --git a/phpBB/includes/ucp/ucp_pm_viewfolder.php b/phpBB/includes/ucp/ucp_pm_viewfolder.php
index 91a44c31c1..862702d7fc 100644
--- a/phpBB/includes/ucp/ucp_pm_viewfolder.php
+++ b/phpBB/includes/ucp/ucp_pm_viewfolder.php
@@ -26,8 +26,7 @@ function view_folder($id, $mode, $folder_id, $folder)
$user->add_lang('viewforum');
// Grab icons
- $icons = array();
- $cache->obtain_icons($icons);
+ $icons = $cache->obtain_icons();
$color_rows = array('marked', 'replied');
@@ -164,7 +163,18 @@ function view_folder($id, $mode, $folder_id, $folder)
{
foreach ($id_ary as $ug_id => $_id)
{
- $address_list[$message_id][] = (($type == 'u') ? '<a href="' . append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&amp;u=' . $ug_id) . '">' : '<a href="' . append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&amp;g=' . $ug_id) . '">') . (($recipient_list[$type][$ug_id]['colour']) ? '<span style="color:#' . $recipient_list[$type][$ug_id]['colour'] . '">' : '<span>') . $recipient_list[$type][$ug_id]['name'] . '</span></a>';
+ $user_colour = ($recipient_list[$type][$ug_id]['colour']) ? ' style="color:#' . $recipient_list[$type][$ug_id]['colour'] . '"' : '';
+
+ if ($type == 'u')
+ {
+ $link = ($ug_id != ANONYMOUS) ? '<a href="' . append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&amp;u=' . $ug_id) . '"' . $user_colour . '>' : '';
+ }
+ else
+ {
+ $link = '<a href="' . append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&amp;g=' . $ug_id) . '"' . $user_colour . '>';
+ }
+
+ $address_list[$message_id][] = $link . $recipient_list[$type][$ug_id]['name'] . (($link) ? '</a>' : '');
}
}
}
@@ -181,7 +191,7 @@ function view_folder($id, $mode, $folder_id, $folder)
$folder_alt = ($row['pm_unread']) ? 'NEW_MESSAGES' : 'NO_NEW_MESSAGES';
// Generate all URIs ...
- $message_author = '<a href="' . append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&amp;u=' . $row['author_id']) . '">' . $row['username'] . '</a>';
+ $message_author = ($row['author_id'] != ANONYMOUS) ? '<a href="' . append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&amp;u=' . $row['author_id']) . '">' . $row['username'] . '</a>' : $row['username'];
$view_message_url = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=$id&amp;mode=view&amp;f=$folder_id&amp;p=$message_id");
$remove_message_url = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=$id&amp;mode=compose&amp;action=delete&amp;p=$message_id");
@@ -215,6 +225,7 @@ function view_folder($id, $mode, $folder_id, $folder)
'ATTACH_ICON_IMG' => ($auth->acl_get('u_pm_download') && $row['message_attachment'] && $config['allow_pm_attach']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '',
'S_PM_DELETED' => ($row['pm_deleted']) ? true : false,
+ 'S_AUTHOR_DELETED' => ($row['author_id'] == ANONYMOUS) ? true : false,
'U_VIEW_PM' => ($row['pm_deleted']) ? '' : $view_message_url,
'U_REMOVE_PM' => ($row['pm_deleted']) ? $remove_message_url : '',
@@ -428,8 +439,6 @@ function get_pm_from($folder_id, $folder, $user_id)
$sort_by_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIME'], 's' => $user->lang['SUBJECT']);
$sort_by_sql = array('a' => 'u.username', 't' => 'p.message_time', 's' => 'p.message_subject');
- $sort_key = (!in_array($sort_key, array('a', 't', 's'))) ? 't' : $sort_key;
-
$s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = '';
gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param);
diff --git a/phpBB/includes/ucp/ucp_pm_viewmessage.php b/phpBB/includes/ucp/ucp_pm_viewmessage.php
index 4a399d847d..8da8f0bd18 100644
--- a/phpBB/includes/ucp/ucp_pm_viewmessage.php
+++ b/phpBB/includes/ucp/ucp_pm_viewmessage.php
@@ -35,8 +35,7 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row)
}
// Grab icons
- $icons = array();
- $cache->obtain_icons($icons);
+ $icons = $cache->obtain_icons();
$bbcode = false;
@@ -54,6 +53,7 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row)
// Parse the message and subject
$message = $message_row['message_text'];
+ $message = str_replace("\n", '<br />', censor_text($message));
// Second parse bbcode here
if ($message_row['bbcode_bitfield'])
@@ -66,7 +66,6 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row)
// Replace naughty words such as farty pants
$message_row['message_subject'] = censor_text($message_row['message_subject']);
- $message = str_replace("\n", '<br />', censor_text($message));
// Editing information
if ($message_row['message_edit_count'] && $config['display_last_edited'])
@@ -146,6 +145,9 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row)
// End signature parsing, only if needed
if ($signature)
{
+ $signature = censor_text($signature);
+ $signature = str_replace("\n", '<br />', censor_text($signature));
+
if ($user_info['user_sig_bbcode_bitfield'])
{
if ($bbcode === false)
@@ -158,7 +160,6 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row)
}
$signature = smiley_text($signature);
- $signature = str_replace("\n", '<br />', censor_text($signature));
}
$url = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm');
@@ -191,16 +192,17 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row)
'U_INFO' => ($auth->acl_get('m_info') && $message_row['pm_forwarded']) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'mode=pm_details&amp;p=' . $message_row['msg_id'], true, $user->session_id) : '',
'U_DELETE' => ($auth->acl_get('u_pm_delete')) ? "$url&amp;mode=compose&amp;action=delete&amp;f=$folder_id&amp;p=" . $message_row['msg_id'] : '',
- 'U_AUTHOR_PROFILE' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&amp;u=' . $author_id),
+ 'U_AUTHOR_PROFILE' => ($author_id != ANONYMOUS) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&amp;u=' . $author_id) : '',
'U_EMAIL' => $user_info['email'],
- 'U_QUOTE' => ($auth->acl_get('u_sendpm')) ? "$url&amp;mode=compose&amp;action=quote&amp;f=$folder_id&amp;p=" . $message_row['msg_id'] : '',
+ 'U_QUOTE' => ($auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&amp;mode=compose&amp;action=quote&amp;f=$folder_id&amp;p=" . $message_row['msg_id'] : '',
'U_EDIT' => (($message_row['message_time'] > time() - ($config['pm_edit_time'] * 60) || !$config['pm_edit_time']) && $folder_id == PRIVMSGS_OUTBOX && $auth->acl_get('u_pm_edit')) ? "$url&amp;mode=compose&amp;action=edit&amp;f=$folder_id&amp;p=" . $message_row['msg_id'] : '',
- 'U_POST_REPLY_PM' => ($auth->acl_get('u_sendpm')) ? "$url&amp;mode=compose&amp;action=reply&amp;f=$folder_id&amp;p=" . $message_row['msg_id'] : '',
+ 'U_POST_REPLY_PM' => ($auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&amp;mode=compose&amp;action=reply&amp;f=$folder_id&amp;p=" . $message_row['msg_id'] : '',
'U_PREVIOUS_PM' => "$url&amp;f=$folder_id&amp;p=" . $message_row['msg_id'] . "&amp;view=previous",
'U_NEXT_PM' => "$url&amp;f=$folder_id&amp;p=" . $message_row['msg_id'] . "&amp;view=next",
'S_HAS_ATTACHMENTS' => (sizeof($attachments)) ? true : false,
'S_DISPLAY_NOTICE' => $display_notice && $message_row['message_attachment'],
+ 'S_AUTHOR_DELETED' => ($author_id == ANONYMOUS) ? true : false,
'U_PRINT_PM' => ($config['print_pm'] && $auth->acl_get('u_pm_printpm')) ? "$url&amp;f=$folder_id&amp;p=" . $message_row['msg_id'] . "&amp;view=print" : '',
'U_FORWARD_PM' => ($config['forward_pm'] && $auth->acl_get('u_pm_forward')) ? "$url&amp;mode=compose&amp;action=forward&amp;f=$folder_id&amp;p=" . $message_row['msg_id'] : '')
@@ -295,13 +297,13 @@ function message_history($msg_id, $user_id, $message_row, $folder)
}
// Instantiate BBCode class
- if ((empty($bbcode) || $bbcode === false) && $bbcode_bitfield)
+ if ((empty($bbcode) || $bbcode === false) && $bbcode_bitfield !== '')
{
if (!class_exists('bbcode'))
{
include($phpbb_root_path . 'includes/bbcode.' . $phpEx);
}
- $bbcode = new bbcode($bbcode_bitfield);
+ $bbcode = new bbcode(base64_encode($bbcode_bitfield));
}
$title = censor_text($title);
@@ -318,6 +320,9 @@ function message_history($msg_id, $user_id, $message_row, $folder)
$subject = $row['message_subject'];
$message = $row['message_text'];
+ $message = censor_text($message);
+ $message = str_replace("\n", '<br />', $message);
+
if ($row['bbcode_bitfield'])
{
$bbcode->bbcode_second_pass($message, $row['bbcode_uid'], $row['bbcode_bitfield']);
@@ -326,7 +331,6 @@ function message_history($msg_id, $user_id, $message_row, $folder)
$message = smiley_text($message, !$row['enable_smilies']);
$subject = censor_text($subject);
- $message = censor_text($message);
if ($id == $msg_id)
{
@@ -339,16 +343,17 @@ function message_history($msg_id, $user_id, $message_row, $folder)
'AUTHOR_NAME' => $author,
'SUBJECT' => $subject,
'SENT_DATE' => $user->format_date($row['message_time']),
- 'MESSAGE' => str_replace("\n", '<br />', $message),
+ 'MESSAGE' => $message,
'FOLDER' => implode(', ', $row['folder']),
- 'S_CURRENT_MSG' => ($row['msg_id'] == $msg_id),
-
+ 'S_CURRENT_MSG' => ($row['msg_id'] == $msg_id),
+ 'S_AUTHOR_DELETED' => ($author_id == ANONYMOUS) ? true : false,
+
'U_MSG_ID' => $row['msg_id'],
'U_VIEW_MESSAGE' => "$url&amp;f=$folder_id&amp;p=" . $row['msg_id'],
- 'U_AUTHOR_PROFILE' => append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=viewprofile&amp;u=$author_id"),
- 'U_QUOTE' => ($auth->acl_get('u_sendpm') && $author_id != $user->data['user_id']) ? "$url&amp;mode=compose&amp;action=quote&amp;f=" . $folder_id . "&amp;p=" . $row['msg_id'] : '',
- 'U_POST_REPLY_PM' => ($author_id != $user->data['user_id'] && $auth->acl_get('u_sendpm')) ? "$url&amp;mode=compose&amp;action=reply&amp;f=$folder_id&amp;p=" . $row['msg_id'] : '')
+ 'U_AUTHOR_PROFILE' => ($author_id != ANONYMOUS) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=viewprofile&amp;u=$author_id") : '',
+ 'U_QUOTE' => ($auth->acl_get('u_sendpm') && $author_id != ANONYMOUS && $author_id != $user->data['user_id']) ? "$url&amp;mode=compose&amp;action=quote&amp;f=" . $folder_id . "&amp;p=" . $row['msg_id'] : '',
+ 'U_POST_REPLY_PM' => ($author_id != $user->data['user_id'] && $author_id != ANONYMOUS && $auth->acl_get('u_sendpm')) ? "$url&amp;mode=compose&amp;action=reply&amp;f=$folder_id&amp;p=" . $row['msg_id'] : '')
);
unset($rowset[$id]);
$prev_id = $id;
@@ -389,8 +394,7 @@ function get_user_informations($user_id, $user_row)
}
// Grab ranks
- $ranks = array();
- $cache->obtain_ranks($ranks);
+ $ranks = $cache->obtain_ranks();
// Generate online information for user
if ($config['load_onlinetrack'])
@@ -429,7 +433,7 @@ function get_user_informations($user_id, $user_row)
}
$avatar_img .= $user_row['user_avatar'];
- $user_row['avatar'] = '<img src="' . $avatar_img . '" width="' . $user_row['user_avatar_width'] . '" height="' . $user_row['user_avatar_height'] . '" border="0" alt="" />';
+ $user_row['avatar'] = '<img src="' . $avatar_img . '" width="' . $user_row['user_avatar_width'] . '" height="' . $user_row['user_avatar_height'] . '" alt="' . $user->lang['USER_AVATAR'] . '" />';
}
$user_row['rank_title'] = $user_row['rank_image'] = '';
@@ -437,7 +441,7 @@ function get_user_informations($user_id, $user_row)
if (!empty($user_row['user_rank']))
{
$user_row['rank_title'] = (isset($ranks['special'][$user_row['user_rank']])) ? $ranks['special'][$user_row['user_rank']]['rank_title'] : '';
- $user_row['rank_image'] = (!empty($ranks['special'][$user_row['user_rank']]['rank_image'])) ? '<img src="' . $config['ranks_path'] . '/' . $ranks['special'][$user_row['user_rank']]['rank_image'] . '" border="0" alt="' . $ranks['special'][$user_row['user_rank']]['rank_title'] . '" title="' . $ranks['special'][$user_row['user_rank']]['rank_title'] . '" /><br />' : '';
+ $user_row['rank_image'] = (!empty($ranks['special'][$user_row['user_rank']]['rank_image'])) ? '<img src="' . $config['ranks_path'] . '/' . $ranks['special'][$user_row['user_rank']]['rank_image'] . '" alt="' . $ranks['special'][$user_row['user_rank']]['rank_title'] . '" title="' . $ranks['special'][$user_row['user_rank']]['rank_title'] . '" /><br />' : '';
}
else
{
@@ -448,7 +452,7 @@ function get_user_informations($user_id, $user_row)
if ($user_row['user_posts'] >= $rank['rank_min'])
{
$user_row['rank_title'] = $rank['rank_title'];
- $user_row['rank_image'] = (!empty($rank['rank_image'])) ? '<img src="' . $config['ranks_path'] . '/' . $rank['rank_image'] . '" border="0" alt="' . $rank['rank_title'] . '" title="' . $rank['rank_title'] . '" /><br />' : '';
+ $user_row['rank_image'] = (!empty($rank['rank_image'])) ? '<img src="' . $config['ranks_path'] . '/' . $rank['rank_image'] . '" alt="' . $rank['rank_title'] . '" title="' . $rank['rank_title'] . '" /><br />' : '';
break;
}
}
diff --git a/phpBB/includes/ucp/ucp_prefs.php b/phpBB/includes/ucp/ucp_prefs.php
index ff8df44148..378562a2dd 100644
--- a/phpBB/includes/ucp/ucp_prefs.php
+++ b/phpBB/includes/ucp/ucp_prefs.php
@@ -30,42 +30,30 @@ class ucp_prefs
case 'personal':
$data = array(
- 'notifymethod' => $user->data['user_notify_type'],
- 'dateformat' => $user->data['user_dateformat'],
- 'lang' => $user->data['user_lang'],
- 'style' => $user->data['user_style'],
- 'tz' => $user->data['user_timezone'],
+ 'notifymethod' => request_var('notifymethod', $user->data['user_notify_type']),
+ 'dateformat' => request_var('dateformat', $user->data['user_dateformat']),
+ 'lang' => request_var('lang', $user->data['user_lang']),
+ 'style' => request_var('style', (int) $user->data['user_style']),
+ 'tz' => request_var('tz', (float) $user->data['user_timezone']),
+
+ 'dst' => request_var('dst', (bool) $user->data['user_dst']),
+ 'viewemail' => request_var('viewemail', (bool) $user->data['user_allow_viewemail']),
+ 'massemail' => request_var('massemail', (bool) $user->data['user_allow_massemail']),
+ 'hideonline' => request_var('hideonline', (bool) !$user->data['user_allow_viewonline']),
+ 'notifypm' => request_var('notifypm', (bool) $user->data['user_notify_pm']),
+ 'popuppm' => request_var('popuppm', (bool) $user->optionget('popuppm')),
+ 'allowpm' => request_var('allowpm', (bool) $user->data['user_allow_pm']),
);
if ($submit)
{
- $var_ary = array(
- 'dateformat' => (string) $config['default_dateformat'],
- 'lang' => (string) $config['default_lang'],
- 'tz' => (float) $config['board_timezone'],
- 'style' => (int) $config['default_style'],
- 'dst' => (bool) $config['board_dst'],
- 'viewemail' => false,
- 'massemail' => true,
- 'hideonline' => false,
- 'notifymethod' => 0,
- 'notifypm' => true,
- 'popuppm' => false,
- 'allowpm' => true,
- );
+ $data['style'] = ($config['override_user_style']) ? $config['default_style'] : $data['style'];
- foreach ($var_ary as $var => $default)
- {
- $data[$var] = request_var($var, $default);
- }
-
- $var_ary = array(
+ $error = validate_data($data, array(
'dateformat' => array('string', false, 3, 30),
- 'lang' => array('match', false, '#^[a-z_\-]{2,}$#i'),
+ 'lang' => array('match', false, '#^[a-z0-9_\-]{2,}$#i'),
'tz' => array('num', false, -14, 14),
- );
-
- $error = validate_data($data, $var_ary);
+ ));
if (!sizeof($error))
{
@@ -126,13 +114,13 @@ class ucp_prefs
'S_NOTIFY_EMAIL' => ($data['notifymethod'] == NOTIFY_EMAIL) ? true : false,
'S_NOTIFY_IM' => ($data['notifymethod'] == NOTIFY_IM) ? true : false,
'S_NOTIFY_BOTH' => ($data['notifymethod'] == NOTIFY_BOTH) ? true : false,
- 'S_VIEW_EMAIL' => (isset($data['viewemail'])) ? $data['viewemail'] : $user->data['user_allow_viewemail'],
- 'S_MASS_EMAIL' => (isset($data['massemail'])) ? $data['massemail'] : $user->data['user_allow_massemail'],
- 'S_ALLOW_PM' => (isset($data['allowpm'])) ? $data['allowpm'] : $user->data['user_allow_pm'],
- 'S_HIDE_ONLINE' => (isset($data['hideonline'])) ? $data['hideonline'] : !$user->data['user_allow_viewonline'],
- 'S_NOTIFY_PM' => (isset($data['notifypm'])) ? $data['notifypm'] : $user->data['user_notify_pm'],
- 'S_POPUP_PM' => (isset($data['popuppm'])) ? $data['popuppm'] : $user->optionget('popuppm'),
- 'S_DST' => (isset($data['dst'])) ? $data['dst'] : $user->data['user_dst'],
+ 'S_VIEW_EMAIL' => $data['viewemail'],
+ 'S_MASS_EMAIL' => $data['massemail'],
+ 'S_ALLOW_PM' => $data['allowpm'],
+ 'S_HIDE_ONLINE' => $data['hideonline'],
+ 'S_NOTIFY_PM' => $data['notifypm'],
+ 'S_POPUP_PM' => $data['popuppm'],
+ 'S_DST' => $data['dst'],
'DATE_FORMAT' => $data['dateformat'],
'S_DATEFORMAT_OPTIONS' => $dateformat_options,
@@ -141,7 +129,7 @@ class ucp_prefs
'A_DEFAULT_DATEFORMAT' => addslashes($config['default_dateformat']),
'S_LANG_OPTIONS' => language_select($data['lang']),
- 'S_STYLE_OPTIONS' => style_select($data['style']),
+ 'S_STYLE_OPTIONS' => ($config['override_user_style']) ? '' : style_select($data['style']),
'S_TZ_OPTIONS' => tz_select($data['tz']),
'S_CAN_HIDE_ONLINE' => ($auth->acl_get('u_hideonline')) ? true : false,
'S_SELECT_NOTIFY' => ($config['jab_enable'] && $user->data['user_jabber'] && @extension_loaded('xml')) ? true : false)
@@ -159,32 +147,23 @@ class ucp_prefs
'post_sk' => (!empty($user->data['user_post_sortby_type'])) ? $user->data['user_post_sortby_type'] : 't',
'post_sd' => (!empty($user->data['user_post_sortby_dir'])) ? $user->data['user_post_sortby_dir'] : 'a',
'post_st' => (!empty($user->data['user_post_show_days'])) ? $user->data['user_post_show_days'] : 0,
+
+ 'images' => request_var('images', (bool) $user->optionget('viewimg')),
+ 'flash' => request_var('flash', (bool) $user->optionget('viewflash')),
+ 'smilies' => request_var('smilies', (bool) $user->optionget('viewsmilies')),
+ 'sigs' => request_var('sigs', (bool) $user->optionget('viewsigs')),
+ 'avatars' => request_var('avatars', (bool) $user->optionget('viewavatars')),
+ 'wordcensor' => request_var('wordcensor', (bool) $user->optionget('viewcensors')),
);
if ($submit)
{
- $var_ary = array_merge($data, array(
- 'images' => true,
- 'flash' => false,
- 'smilies' => true,
- 'sigs' => true,
- 'avatars' => true,
- 'wordcensor'=> false,
- ));
-
- foreach ($var_ary as $var => $default)
- {
- $data[$var] = request_var($var, $default);
- }
-
- $var_ary = array(
+ $error = validate_data($data, array(
'topic_sk' => array('string', false, 1, 1),
'topic_sd' => array('string', false, 1, 1),
'post_sk' => array('string', false, 1, 1),
'post_sd' => array('string', false, 1, 1),
- );
-
- $error = validate_data($data, $var_ary);
+ ));
if (!sizeof($error))
{
@@ -269,12 +248,12 @@ class ucp_prefs
$template->assign_vars(array(
'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '',
- 'S_IMAGES' => (isset($data['images'])) ? $data['images'] : $user->optionget('viewimg'),
- 'S_FLASH' => (isset($data['flash'])) ? $data['flash'] : $user->optionget('viewflash'),
- 'S_SMILIES' => (isset($data['smilies'])) ? $data['smilies'] : $user->optionget('viewsmilies'),
- 'S_SIGS' => (isset($data['sigs'])) ? $data['sigs'] : $user->optionget('viewsigs'),
- 'S_AVATARS' => (isset($data['avatars'])) ? $data['avatars'] : $user->optionget('viewavatars'),
- 'S_DISABLE_CENSORS' => (isset($data['wordcensor'])) ? $data['wordcensor'] : $user->optionget('viewcensors'),
+ 'S_IMAGES' => $data['images'],
+ 'S_FLASH' => $data['flash'],
+ 'S_SMILIES' => $data['smilies'],
+ 'S_SIGS' => $data['sigs'],
+ 'S_AVATARS' => $data['avatars'],
+ 'S_DISABLE_CENSORS' => $data['wordcensor'],
'S_CHANGE_CENSORS' => ($auth->acl_get('u_chgcensors')) ? true : false,
@@ -291,21 +270,14 @@ class ucp_prefs
case 'post':
$data = array(
- 'bbcode' => $user->optionget('bbcode'),
- 'smilies' => $user->optionget('smilies'),
- 'sig' => $user->optionget('attachsig'),
- 'notify' => $user->data['user_notify'],
+ 'bbcode' => request_var('bbcode', $user->optionget('bbcode')),
+ 'smilies' => request_var('smilies', $user->optionget('smilies')),
+ 'sig' => request_var('sig', $user->optionget('attachsig')),
+ 'notify' => request_var('notify', $user->data['user_notify']),
);
if ($submit)
{
- $var_ary = $data;
-
- foreach ($var_ary as $var => $default)
- {
- $data[$var] = request_var($var, $default);
- }
-
$user->optionset('bbcode', $data['bbcode']);
$user->optionset('smilies', $data['smilies']);
$user->optionset('attachsig', $data['sig']);
diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php
index d757d6e14d..840f63ff48 100644
--- a/phpBB/includes/ucp/ucp_profile.php
+++ b/phpBB/includes/ucp/ucp_profile.php
@@ -33,25 +33,22 @@ class ucp_profile
{
case 'reg_details':
+ $data = array(
+ 'username' => request_var('username', $user->data['username'], true),
+ 'email' => request_var('email', $user->data['user_email']),
+ 'email_confirm' => request_var('email_confirm', ''),
+ 'new_password' => request_var('new_password', '', true),
+ 'cur_password' => request_var('cur_password', '', true),
+ 'password_confirm' => request_var('password_confirm', '', true),
+ );
+
if ($submit)
{
- $var_ary = array(
- 'username' => $user->data['username'],
- 'email' => $user->data['user_email'],
- 'email_confirm' => (string) '',
- 'new_password' => (string) '',
- 'cur_password' => (string) '',
- 'password_confirm' => (string) '',
- );
-
- foreach ($var_ary as $var => $default)
- {
- $data[$var] = request_var($var, $default);
- }
-
// Do not check cur_password, it is the old one.
- $var_ary = array(
- 'new_password' => array('string', true, $config['min_pass_chars'], $config['max_pass_chars']),
+ $check_ary = array(
+ 'new_password' => array(
+ array('string', true, $config['min_pass_chars'], $config['max_pass_chars']),
+ array('password')),
'password_confirm' => array('string', true, $config['min_pass_chars'], $config['max_pass_chars']),
'email' => array(
array('string', false, 6, 60),
@@ -61,27 +58,31 @@ class ucp_profile
if ($auth->acl_get('u_chgname') && $config['allow_namechange'])
{
- $var_ary['username'] = array(
+ $check_ary['username'] = array(
array('string', false, $config['min_name_chars'], $config['max_name_chars']),
array('username', $data['username']),
);
}
- $error = validate_data($data, $var_ary);
- extract($data);
- unset($data);
+ $error = validate_data($data, $check_ary);
- if ($auth->acl_get('u_chgpasswd') && $new_password && $password_confirm != $new_password)
+ if ($auth->acl_get('u_chgpasswd') && $data['new_password'] && $data['password_confirm'] != $data['new_password'])
{
$error[] = 'NEW_PASSWORD_ERROR';
}
- if (($new_password || ($auth->acl_get('u_chgemail') && $email != $user->data['user_email']) || ($username != $user->data['username'] && $auth->acl_get('u_chgname') && $config['allow_namechange'])) && md5($cur_password) != $user->data['user_password'])
+ if (($data['new_password'] || ($auth->acl_get('u_chgemail') && $data['email'] != $user->data['user_email']) || ($data['username'] != $user->data['username'] && $auth->acl_get('u_chgname') && $config['allow_namechange'])) && md5($data['cur_password']) != $user->data['user_password'])
{
$error[] = 'CUR_PASSWORD_ERROR';
}
- if ($auth->acl_get('u_chgemail') && $email != $user->data['user_email'] && $email_confirm != $email)
+ // Only check the new password against the previous password if there have been no errors
+ if (!sizeof($error) && $auth->acl_get('u_chgpasswd') && $data['new_password'] && md5($data['new_password']) == $user->data['user_password'])
+ {
+ $error[] = 'SAME_PASSWORD_ERROR';
+ }
+
+ if ($auth->acl_get('u_chgemail') && $data['email'] != $user->data['user_email'] && $data['email_confirm'] != $data['email'])
{
$error[] = 'NEW_EMAIL_ERROR';
}
@@ -89,32 +90,33 @@ class ucp_profile
if (!sizeof($error))
{
$sql_ary = array(
- 'username' => ($auth->acl_get('u_chgname') && $config['allow_namechange']) ? $username : $user->data['username'],
- 'user_email' => ($auth->acl_get('u_chgemail')) ? $email : $user->data['user_email'],
- 'user_email_hash' => ($auth->acl_get('u_chgemail')) ? crc32(strtolower($email)) . strlen($email) : $user->data['user_email_hash'],
- 'user_password' => ($auth->acl_get('u_chgpasswd') && $new_password) ? md5($new_password) : $user->data['user_password'],
- 'user_passchg' => ($auth->acl_get('u_chgpasswd') && $new_password) ? time() : 0,
+ 'username' => ($auth->acl_get('u_chgname') && $config['allow_namechange']) ? $data['username'] : $user->data['username'],
+ 'username_clean' => ($auth->acl_get('u_chgname') && $config['allow_namechange']) ? utf8_clean_string($data['username']) : $user->data['username_clean'],
+ 'user_email' => ($auth->acl_get('u_chgemail')) ? $data['email'] : $user->data['user_email'],
+ 'user_email_hash' => ($auth->acl_get('u_chgemail')) ? crc32(strtolower($data['email'])) . strlen($data['email']) : $user->data['user_email_hash'],
+ 'user_password' => ($auth->acl_get('u_chgpasswd') && $data['new_password']) ? md5($data['new_password']) : $user->data['user_password'],
+ 'user_passchg' => ($auth->acl_get('u_chgpasswd') && $data['new_password']) ? time() : 0,
);
- if ($auth->acl_get('u_chgname') && $config['allow_namechange'] && $username != $user->data['username'])
+ if ($auth->acl_get('u_chgname') && $config['allow_namechange'] && $data['username'] != $user->data['username'])
{
- add_log('user', $user->data['user_id'], 'LOG_USER_UPDATE_NAME', $user->data['username'], $username);
+ add_log('user', $user->data['user_id'], 'LOG_USER_UPDATE_NAME', $user->data['username'], $data['username']);
}
- if ($auth->acl_get('u_chgpasswd') && $new_password && md5($new_password) != $user->data['user_password'])
+ if ($auth->acl_get('u_chgpasswd') && $data['new_password'] && md5($data['new_password']) != $user->data['user_password'])
{
$user->reset_login_keys();
- add_log('user', $user->data['user_id'], 'LOG_USER_NEW_PASSWORD', $username);
+ add_log('user', $user->data['user_id'], 'LOG_USER_NEW_PASSWORD', $data['username']);
}
- if ($auth->acl_get('u_chgemail') && $email != $user->data['user_email'])
+ if ($auth->acl_get('u_chgemail') && $data['email'] != $user->data['user_email'])
{
- add_log('user', $user->data['user_id'], 'LOG_USER_UPDATE_EMAIL', $username, $user->data['user_email'], $email);
+ add_log('user', $user->data['user_id'], 'LOG_USER_UPDATE_EMAIL', $data['username'], $user->data['user_email'], $data['email']);
}
- if ($config['email_enable'] && $email != $user->data['user_email'] && ($config['require_activation'] == USER_ACTIVATION_SELF || $config['require_activation'] == USER_ACTIVATION_ADMIN))
+ if ($config['email_enable'] && $data['email'] != $user->data['user_email'] && $user->data['user_type'] != USER_FOUNDER && ($config['require_activation'] == USER_ACTIVATION_SELF || $config['require_activation'] == USER_ACTIVATION_ADMIN))
{
- include_once($phpbb_root_path . 'includes/functions_messenger.'.$phpEx);
+ include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
$server_url = generate_board_url();
@@ -129,7 +131,7 @@ class ucp_profile
$messenger->template($template_file, $user->data['user_lang']);
$messenger->replyto($config['board_contact']);
- $messenger->to($email, $username);
+ $messenger->to($data['email'], $data['username']);
$messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']);
$messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']);
@@ -137,10 +139,7 @@ class ucp_profile
$messenger->headers('X-AntiAbuse: User IP - ' . $user->ip);
$messenger->assign_vars(array(
- 'SITENAME' => $config['sitename'],
- 'USERNAME' => html_entity_decode($username),
- 'EMAIL_SIG' => str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']),
-
+ 'USERNAME' => htmlspecialchars_decode($username),
'U_ACTIVATE' => "$server_url/ucp.$phpEx?mode=activate&u={$user->data['user_id']}&k=$user_actkey")
);
@@ -148,12 +147,21 @@ class ucp_profile
if ($config['require_activation'] == USER_ACTIVATION_ADMIN)
{
- // Grab an array of user_id's with a_user permissions
+ // Grab an array of user_id's with a_user permissions ... these users can activate a user
$admin_ary = $auth->acl_get_list(false, 'a_user', false);
+ $admin_ary = (!empty($admin_ary[0]['a_user'])) ? $admin_ary[0]['a_user'] : array();
+
+ // Also include founders
+ $where_sql = ' WHERE user_type = ' . USER_FOUNDER;
+
+ if (sizeof($admin_ary))
+ {
+ $where_sql .= ' OR ' . $db->sql_in_set('user_id', $admin_ary);
+ }
$sql = 'SELECT user_id, username, user_email, user_lang, user_jabber, user_notify_type
- FROM ' . USERS_TABLE . '
- WHERE ' . $db->sql_in_set('user_id', $admin_ary[0]['a_user']);
+ FROM ' . USERS_TABLE . ' ' .
+ $where_sql;
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
@@ -164,9 +172,7 @@ class ucp_profile
$messenger->im($row['user_jabber'], $row['username']);
$messenger->assign_vars(array(
- 'USERNAME' => html_entity_decode($username),
- 'EMAIL_SIG' => str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']),
-
+ 'USERNAME' => htmlspecialchars_decode($username),
'U_ACTIVATE' => "$server_url/ucp.$phpEx?mode=activate&u={$user->data['user_id']}&k=$user_actkey")
);
@@ -177,9 +183,10 @@ class ucp_profile
$messenger->save_queue();
+ user_active_flip('deactivate', $user->data['user_id'], INACTIVE_PROFILE);
+
$sql_ary += array(
- 'user_type' => USER_INACTIVE,
- 'user_actkey' => $user_actkey
+ 'user_actkey' => $user_actkey,
);
}
@@ -192,9 +199,9 @@ class ucp_profile
}
// Need to update config, forum, topic, posting, messages, etc.
- if ($username != $user->data['username'] && $auth->acl_get('u_chgname') && $config['allow_namechange'])
+ if ($data['username'] != $user->data['username'] && $auth->acl_get('u_chgname') && $config['allow_namechange'])
{
- user_update_name($user->data['username'], $username);
+ user_update_name($user->data['username'], $data['username']);
}
meta_refresh(3, $this->u_action);
@@ -207,18 +214,19 @@ class ucp_profile
}
$user_char_ary = array('.*' => 'USERNAME_CHARS_ANY', '[\w]+' => 'USERNAME_ALPHA_ONLY', '[\w_\+\. \-\[\]]+' => 'USERNAME_ALPHA_SPACERS');
+ $pass_char_ary = array('.*' => 'PASS_TYPE_ANY', '[a-zA-Z]' => 'PASS_TYPE_CASE', '[a-zA-Z0-9]' => 'PASS_TYPE_ALPHA', '[a-zA-Z\W]' => 'PASS_TYPE_SYMBOL');
$template->assign_vars(array(
'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '',
- 'USERNAME' => (isset($username)) ? $username : $user->data['username'],
- 'EMAIL' => (isset($email)) ? $email : $user->data['user_email'],
- 'PASSWORD_CONFIRM' => (isset($password_confirm)) ? $password_confirm : '',
- 'NEW_PASSWORD' => (isset($new_password)) ? $new_password : '',
+ 'USERNAME' => $data['username'],
+ 'EMAIL' => $data['email'],
+ 'PASSWORD_CONFIRM' => $data['password_confirm'],
+ 'NEW_PASSWORD' => $data['new_password'],
'CUR_PASSWORD' => '',
'L_USERNAME_EXPLAIN' => sprintf($user->lang[$user_char_ary[str_replace('\\\\', '\\', $config['allow_name_chars'])] . '_EXPLAIN'], $config['min_name_chars'], $config['max_name_chars']),
- 'L_CHANGE_PASSWORD_EXPLAIN' => sprintf($user->lang['CHANGE_PASSWORD_EXPLAIN'], $config['min_pass_chars'], $config['max_pass_chars']),
+ 'L_CHANGE_PASSWORD_EXPLAIN' => sprintf($user->lang[$pass_char_ary[str_replace('\\\\', '\\', $config['pass_complex'])] . '_EXPLAIN'], $config['min_pass_chars'], $config['max_pass_chars']),
'S_FORCE_PASSWORD' => ($config['chg_passforce'] && $user->data['user_passchg'] < time() - $config['chg_passforce']) ? true : false,
'S_CHANGE_USERNAME' => ($config['allow_namechange'] && $auth->acl_get('u_chgname')) ? true : false,
@@ -235,29 +243,35 @@ class ucp_profile
$cp_data = $cp_error = array();
- if ($submit)
+ $data = array(
+ 'icq' => request_var('icq', $user->data['user_icq']),
+ 'aim' => request_var('aim', $user->data['user_aim']),
+ 'msn' => request_var('msn', $user->data['user_msnm']),
+ 'yim' => request_var('yim', $user->data['user_yim']),
+ 'jabber' => request_var('jabber', $user->data['user_jabber']),
+ 'website' => request_var('website', $user->data['user_website']),
+ 'location' => request_var('location', $user->data['user_from'], true),
+ 'occupation' => request_var('occupation', $user->data['user_occ'], true),
+ 'interests' => request_var('interests', $user->data['user_interests'], true),
+ 'bday_day' => 0,
+ 'bday_month' => 0,
+ 'bday_year' => 0,
+ );
+
+ utf8_normalize_nfc(array(&$data['location'], &$data['occupation'], &$data['interests']));
+
+ if ($user->data['user_birthday'])
{
- $var_ary = array(
- 'icq' => (string) '',
- 'aim' => (string) '',
- 'msn' => (string) '',
- 'yim' => (string) '',
- 'jabber' => (string) '',
- 'website' => (string) '',
- 'location' => (string) '',
- 'occupation' => (string) '',
- 'interests' => (string) '',
- 'bday_day' => 0,
- 'bday_month' => 0,
- 'bday_year' => 0,
- );
+ list($data['bday_day'], $data['bday_month'], $data['bday_year']) = explode('-', $user->data['user_birthday']);
+ }
- foreach ($var_ary as $var => $default)
- {
- $data[$var] = (in_array($var, array('location', 'occupation', 'interests'))) ? request_var($var, $default, true) : request_var($var, $default);
- }
+ $data['bday_day'] = request_var('bday_day', $data['bday_day']);
+ $data['bday_month'] = request_var('bday_month', $data['bday_month']);
+ $data['bday_year'] = request_var('bday_year', $data['bday_year']);
- $var_ary = array(
+ if ($submit)
+ {
+ $error = validate_data($data, array(
'icq' => array(
array('string', true, 3, 15),
array('match', true, '#^[0-9]+$#i')),
@@ -276,11 +290,7 @@ class ucp_profile
'bday_day' => array('num', true, 1, 31),
'bday_month' => array('num', true, 1, 12),
'bday_year' => array('num', true, 1901, gmdate('Y', time())),
- );
-
- $error = validate_data($data, $var_ary);
- extract($data);
- unset($data);
+ ));
// validate custom profile fields
$cp->submit_cp_field('profile', $user->get_iso_lang_id(), $cp_data, $cp_error);
@@ -293,16 +303,16 @@ class ucp_profile
if (!sizeof($error))
{
$sql_ary = array(
- 'user_icq' => $icq,
- 'user_aim' => $aim,
- 'user_msnm' => $msn,
- 'user_yim' => $yim,
- 'user_jabber' => $jabber,
- 'user_website' => $website,
- 'user_from' => $location,
- 'user_occ' => $occupation,
- 'user_interests'=> $interests,
- 'user_birthday' => sprintf('%2d-%2d-%4d', $bday_day, $bday_month, $bday_year),
+ 'user_icq' => $data['icq'],
+ 'user_aim' => $data['aim'],
+ 'user_msnm' => $data['msn'],
+ 'user_yim' => $data['yim'],
+ 'user_jabber' => $data['jabber'],
+ 'user_website' => $data['website'],
+ 'user_from' => $data['location'],
+ 'user_occ' => $data['occupation'],
+ 'user_interests'=> $data['interests'],
+ 'user_birthday' => sprintf('%2d-%2d-%4d', $data['bday_day'], $data['bday_month'], $data['bday_year']),
);
$sql = 'UPDATE ' . USERS_TABLE . '
@@ -340,38 +350,26 @@ class ucp_profile
$error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error);
}
- if (!isset($bday_day))
- {
- if ($user->data['user_birthday'])
- {
- list($bday_day, $bday_month, $bday_year) = explode('-', $user->data['user_birthday']);
- }
- else
- {
- $bday_day = $bday_month = $bday_year = 0;
- }
- }
-
- $s_birthday_day_options = '<option value="0"' . ((!$bday_day) ? ' selected="selected"' : '') . '>--</option>';
+ $s_birthday_day_options = '<option value="0"' . ((!$data['bday_day']) ? ' selected="selected"' : '') . '>--</option>';
for ($i = 1; $i < 32; $i++)
{
- $selected = ($i == $bday_day) ? ' selected="selected"' : '';
+ $selected = ($i == $data['bday_day']) ? ' selected="selected"' : '';
$s_birthday_day_options .= "<option value=\"$i\"$selected>$i</option>";
}
- $s_birthday_month_options = '<option value="0"' . ((!$bday_month) ? ' selected="selected"' : '') . '>--</option>';
+ $s_birthday_month_options = '<option value="0"' . ((!$data['bday_month']) ? ' selected="selected"' : '') . '>--</option>';
for ($i = 1; $i < 13; $i++)
{
- $selected = ($i == $bday_month) ? ' selected="selected"' : '';
+ $selected = ($i == $data['bday_month']) ? ' selected="selected"' : '';
$s_birthday_month_options .= "<option value=\"$i\"$selected>$i</option>";
}
$s_birthday_year_options = '';
$now = getdate();
- $s_birthday_year_options = '<option value="0"' . ((!$bday_year) ? ' selected="selected"' : '') . '>--</option>';
+ $s_birthday_year_options = '<option value="0"' . ((!$data['bday_year']) ? ' selected="selected"' : '') . '>--</option>';
for ($i = $now['year'] - 100; $i < $now['year']; $i++)
{
- $selected = ($i == $bday_year) ? ' selected="selected"' : '';
+ $selected = ($i == $data['bday_year']) ? ' selected="selected"' : '';
$s_birthday_year_options .= "<option value=\"$i\"$selected>$i</option>";
}
unset($now);
@@ -379,15 +377,15 @@ class ucp_profile
$template->assign_vars(array(
'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '',
- 'ICQ' => (isset($icq)) ? $icq : $user->data['user_icq'],
- 'YIM' => (isset($yim)) ? $yim : $user->data['user_yim'],
- 'AIM' => (isset($aim)) ? $aim : $user->data['user_aim'],
- 'MSN' => (isset($msn)) ? $msn : $user->data['user_msnm'],
- 'JABBER' => (isset($jabber)) ? $jabber : $user->data['user_jabber'],
- 'WEBSITE' => (isset($website)) ? $website : $user->data['user_website'],
- 'LOCATION' => (isset($location)) ? $location : $user->data['user_from'],
- 'OCCUPATION'=> (isset($occupation)) ? $occupation : $user->data['user_occ'],
- 'INTERESTS' => (isset($interests)) ? $interests : $user->data['user_interests'],
+ 'ICQ' => $data['icq'],
+ 'YIM' => $data['yim'],
+ 'AIM' => $data['aim'],
+ 'MSN' => $data['msn'],
+ 'JABBER' => $data['jabber'],
+ 'WEBSITE' => $data['website'],
+ 'LOCATION' => $data['location'],
+ 'OCCUPATION'=> $data['occupation'],
+ 'INTERESTS' => $data['interests'],
'S_BIRTHDAY_DAY_OPTIONS' => $s_birthday_day_options,
'S_BIRTHDAY_MONTH_OPTIONS' => $s_birthday_month_options,
@@ -416,6 +414,8 @@ class ucp_profile
$enable_urls = request_var('enable_urls', true);
$signature = request_var('signature', (string) $user->data['user_sig'], true);
+ utf8_normalize_nfc(&$signature);
+
if ($submit || $preview)
{
include($phpbb_root_path . 'includes/message_parser.'.$phpEx);
@@ -425,7 +425,7 @@ class ucp_profile
$message_parser = new parse_message($signature);
// Allowing Quote BBCode
- $message_parser->parse($enable_bbcode, $enable_urls, $enable_smilies, $config['allow_sig_img'], $config['allow_sig_flash'], true, true, 'sig');
+ $message_parser->parse($enable_bbcode, ($config['allow_sig_links']) ? $enable_urls : false, $enable_smilies, $config['allow_sig_img'], $config['allow_sig_flash'], true, $config['allow_sig_links'], true, 'sig');
if (sizeof($message_parser->warn_msg))
{
@@ -473,17 +473,19 @@ class ucp_profile
'S_SMILIES_CHECKED' => (!$enable_smilies) ? 'checked="checked"' : '',
'S_MAGIC_URL_CHECKED' => (!$enable_urls) ? 'checked="checked"' : '',
- 'BBCODE_STATUS' => ($config['allow_sig_bbcode']) ? sprintf($user->lang['BBCODE_IS_ON'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '" onclick="target=\'_phpbbcode\';">', '</a>') : sprintf($user->lang['BBCODE_IS_OFF'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '" onclick="target=\'_phpbbcode\';">', '</a>'),
+ 'BBCODE_STATUS' => ($config['allow_sig_bbcode']) ? sprintf($user->lang['BBCODE_IS_ON'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>') : sprintf($user->lang['BBCODE_IS_OFF'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>'),
'SMILIES_STATUS' => ($config['allow_sig_smilies']) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'],
'IMG_STATUS' => ($config['allow_sig_img']) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'],
'FLASH_STATUS' => ($config['allow_sig_flash']) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'],
+ 'URL_STATUS' => ($config['allow_sig_links']) ? $user->lang['URL_IS_ON'] : $user->lang['URL_IS_OFF'],
'L_SIGNATURE_EXPLAIN' => sprintf($user->lang['SIGNATURE_EXPLAIN'], $config['max_sig_chars']),
'S_BBCODE_ALLOWED' => $config['allow_sig_bbcode'],
'S_SMILIES_ALLOWED' => $config['allow_sig_smilies'],
'S_BBCODE_IMG' => ($config['allow_sig_img']) ? true : false,
- 'S_BBCODE_FLASH' => ($config['allow_sig_flash']) ? true : false)
+ 'S_BBCODE_FLASH' => ($config['allow_sig_flash']) ? true : false,
+ 'S_LINKS_ALLOWED' => ($config['allow_sig_links']) ? true : false)
);
// Build custom bbcodes array
@@ -504,26 +506,19 @@ class ucp_profile
if ($submit)
{
- $var_ary = array(
- 'uploadurl' => (string) '',
- 'remotelink' => (string) '',
- 'width' => (string) '',
- 'height' => (string) '',
+ $data = array(
+ 'uploadurl' => request_var('uploadurl', ''),
+ 'remotelink' => request_var('remotelink', ''),
+ 'width' => request_var('width', ''),
+ 'height' => request_var('height', ''),
);
- foreach ($var_ary as $var => $default)
- {
- $data[$var] = request_var($var, $default);
- }
-
- $var_ary = array(
+ $error = validate_data($data, array(
'uploadurl' => array('string', true, 5, 255),
'remotelink' => array('string', true, 5, 255),
'width' => array('string', true, 1, 3),
'height' => array('string', true, 1, 3),
- );
-
- $error = validate_data($data, $var_ary);
+ ));
if (!sizeof($error))
{
@@ -585,11 +580,7 @@ class ucp_profile
// Delete old avatar if present
if ($user->data['user_avatar'] && $filename != $user->data['user_avatar'] && $user->data['user_avatar_type'] != AVATAR_GALLERY)
{
- // Check if the users avatar is actually a group avatar
- if (strpos($user->data['user_avatar'], 'g' . $user->data['group_id'] . '_') !== 0 && strpos($user->data['user_avatar'], $user->data['user_id'] . '_') === 0)
- {
- avatar_delete($user->data['user_avatar']);
- }
+ avatar_delete('user', $user->data);
}
}
@@ -598,9 +589,6 @@ class ucp_profile
trigger_error($message);
}
- extract($data);
- unset($data);
-
// Replace "error" strings with their real, localised form
$error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error);
}
@@ -644,8 +632,8 @@ class ucp_profile
$template->assign_vars(array(
'AVATAR' => $avatar_img,
'AVATAR_SIZE' => $config['avatar_filesize'],
- 'WIDTH' => (isset($width)) ? $width : $user->data['user_avatar_width'],
- 'HEIGHT' => (isset($height)) ? $height : $user->data['user_avatar_height'],
+ 'WIDTH' => (isset($data['width'])) ? $data['width'] : $user->data['user_avatar_width'],
+ 'HEIGHT' => (isset($data['height'])) ? $data['height'] : $user->data['user_avatar_height'],
'S_UPLOAD_AVATAR_FILE' => $can_upload,
'S_UPLOAD_AVATAR_URL' => $can_upload,
diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php
index 01b92125ac..1e8ff69733 100644
--- a/phpBB/includes/ucp/ucp_register.php
+++ b/phpBB/includes/ucp/ucp_register.php
@@ -37,21 +37,35 @@ class ucp_register
if ($change_lang)
{
- $submit = false;
- $lang = $change_lang;
- $user->lang_name = $lang = $change_lang;
- $user->lang_path = $phpbb_root_path . 'language/' . $lang . '/';
- $user->lang = array();
- $user->add_lang(array('common', 'ucp'));
+ $change_lang = basename($change_lang);
+
+ if (file_exists($phpbb_root_path . 'language/' . $change_lang . '/'))
+ {
+ $submit = false;
+
+ $user->lang_name = $lang = $change_lang;
+ $user->lang_path = $phpbb_root_path . 'language/' . $lang . '/';
+ $user->lang = array();
+ $user->add_lang(array('common', 'ucp'));
+
+ // Setting back agreed to let the user view the agreement in his/her language
+ $agreed = (empty($_GET['change_lang'])) ? 0 : $agreed;
+ }
+ else
+ {
+ $change_lang = '';
+ }
}
$cp = new custom_profile();
- $error = $data = $cp_data = $cp_error = array();
+ $error = $cp_data = $cp_error = array();
//
if (!$agreed)
{
+ $add_lang = ($change_lang) ? '&amp;change_lang=' . urlencode($change_lang) : '';
+
if ($coppa === false && $config['coppa_enable'])
{
$now = getdate();
@@ -62,11 +76,12 @@ class ucp_register
'L_COPPA_NO' => sprintf($user->lang['UCP_COPPA_BEFORE'], $coppa_birthday),
'L_COPPA_YES' => sprintf($user->lang['UCP_COPPA_ON_AFTER'], $coppa_birthday),
- 'U_COPPA_NO' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register&amp;coppa=0'),
- 'U_COPPA_YES' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register&amp;coppa=1'),
+ 'U_COPPA_NO' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register&amp;coppa=0' . $add_lang),
+ 'U_COPPA_YES' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register&amp;coppa=1' . $add_lang),
'S_SHOW_COPPA' => true,
- 'S_REGISTER_ACTION' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register'))
+ 'S_HIDDEN_FIELDS' => ($confirm_id) ? '<input type="hidden" name="confirm_id" value="' . $confirm_id . '" />' : '',
+ 'S_UCP_ACTION' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register' . $add_lang))
);
}
else
@@ -76,7 +91,8 @@ class ucp_register
'S_SHOW_COPPA' => false,
'S_REGISTRATION' => true,
- 'S_REGISTER_ACTION' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register'))
+ 'S_HIDDEN_FIELDS' => ($confirm_id) ? '<input type="hidden" name="confirm_id" value="' . $confirm_id . '" />' : '',
+ 'S_UCP_ACTION' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register' . $add_lang))
);
}
@@ -84,40 +100,38 @@ class ucp_register
return;
}
- $var_ary = array(
- 'username' => (string) '',
- 'password_confirm' => (string) '',
- 'new_password' => (string) '',
- 'cur_password' => (string) '',
- 'email' => (string) '',
- 'email_confirm' => (string) '',
- 'confirm_code' => (string) '',
- 'lang' => (string) $config['default_lang'],
- 'tz' => (float) $config['board_timezone'],
- );
+ // Try to manually determine the timezone
+ $timezone = date('Z') / 3600;
+ $is_dst = date('I');
+ $timezone = ($is_dst) ? $timezone - 1 : $timezone;
- // If we change the language inline, we do not want to display errors, but pre-fill already filled out values
- if ($change_lang)
+ if (!isset($user->lang['tz_zones'][(string) $timezone]))
{
- foreach ($var_ary as $var => $default)
- {
- $$var = request_var($var, $default, true);
- }
+ $timezone = $config['board_timezone'];
}
+ $data = array(
+ 'username' => request_var('username', '', true),
+ 'password_confirm' => request_var('password_confirm', '', true),
+ 'new_password' => request_var('new_password', '', true),
+ 'cur_password' => request_var('cur_password', '', true),
+ 'email' => request_var('email', ''),
+ 'email_confirm' => request_var('email_confirm', ''),
+ 'confirm_code' => request_var('confirm_code', ''),
+ 'lang' => request_var('lang', $user->lang_name),
+ 'tz' => request_var('tz', (float) $timezone),
+ );
+
// Check and initialize some variables if needed
if ($submit)
{
- foreach ($var_ary as $var => $default)
- {
- $data[$var] = request_var($var, $default, true);
- }
-
- $var_ary = array(
+ $error = validate_data($data, array(
'username' => array(
array('string', false, $config['min_name_chars'], $config['max_name_chars']),
array('username')),
- 'new_password' => array('string', false, $config['min_pass_chars'], $config['max_pass_chars']),
+ 'new_password' => array(
+ array('string', false, $config['min_pass_chars'], $config['max_pass_chars']),
+ array('password')),
'password_confirm' => array('string', false, $config['min_pass_chars'], $config['max_pass_chars']),
'email' => array(
array('string', false, 6, 60),
@@ -126,15 +140,20 @@ class ucp_register
'confirm_code' => array('string', !$config['enable_confirm'], 5, 8),
'tz' => array('num', false, -14, 14),
'lang' => array('match', false, '#^[a-z_\-]{2,}$#i'),
- );
-
- $error = validate_data($data, $var_ary);
- extract($data);
- unset($data);
+ ));
// Replace "error" strings with their real, localised form
$error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error);
+ // DNSBL check
+ if ($config['check_dnsbl'])
+ {
+ if (($dnsbl = $user->check_dnsbl()) !== false)
+ {
+ $error[] = sprintf($user->lang['IP_BLACKLISTED'], $user->ip, $dnsbl[1]);
+ }
+ }
+
// validate custom profile fields
$cp->submit_cp_field('register', $user->get_iso_lang_id(), $cp_data, $error);
@@ -160,7 +179,7 @@ class ucp_register
if ($row)
{
- if (strcasecmp($row['code'], $confirm_code) === 0)
+ if (strcasecmp($row['code'], $data['confirm_code']) === 0)
{
$sql = 'DELETE FROM ' . CONFIRM_TABLE . "
WHERE confirm_id = '" . $db->sql_escape($confirm_id) . "'
@@ -184,12 +203,12 @@ class ucp_register
if (!sizeof($error))
{
- if ($new_password != $password_confirm)
+ if ($data['new_password'] != $data['password_confirm'])
{
$error[] = $user->lang['NEW_PASSWORD_ERROR'];
}
- if ($email != $email_confirm)
+ if ($data['email'] != $data['email_confirm'])
{
$error[] = $user->lang['NEW_EMAIL_ERROR'];
}
@@ -200,9 +219,7 @@ class ucp_register
$server_url = generate_board_url();
// Which group by default?
- $group_reg = ($coppa) ? 'REGISTERED_COPPA' : 'REGISTERED';
- $group_inactive = ($coppa) ? 'INACTIVE_COPPA' : 'INACTIVE';
- $group_name = ($config['require_activation'] == USER_ACTIVATION_NONE || !$config['email_enable']) ? $group_reg : $group_inactive;
+ $group_name = ($coppa) ? 'REGISTERED_COPPA' : 'REGISTERED';
$sql = 'SELECT group_id
FROM ' . GROUPS_TABLE . "
@@ -227,25 +244,33 @@ class ucp_register
$key_len = 54 - (strlen($server_url));
$key_len = ($key_len < 6) ? 6 : $key_len;
$user_actkey = substr($user_actkey, 0, $key_len);
+
$user_type = USER_INACTIVE;
+ $user_inactive_reason = INACTIVE_REGISTER;
+ $user_inactive_time = time();
}
else
{
$user_type = USER_NORMAL;
$user_actkey = '';
+ $user_inactive_reason = 0;
+ $user_inactive_time = 0;
}
$user_row = array(
- 'username' => $username,
- 'user_password' => md5($new_password),
- 'user_email' => $email,
- 'group_id' => (int) $group_id,
- 'user_timezone' => (float) $tz,
- 'user_lang' => $lang,
- 'user_type' => $user_type,
- 'user_actkey' => $user_actkey,
- 'user_ip' => $user->ip,
- 'user_regdate' => time(),
+ 'username' => $data['username'],
+ 'user_password' => md5($data['new_password']),
+ 'user_email' => $data['email'],
+ 'group_id' => (int) $group_id,
+ 'user_timezone' => (float) $data['tz'],
+ 'user_dst' => $is_dst,
+ 'user_lang' => $data['lang'],
+ 'user_type' => $user_type,
+ 'user_actkey' => $user_actkey,
+ 'user_ip' => $user->ip,
+ 'user_regdate' => time(),
+ 'user_inactive_reason' => $user_inactive_reason,
+ 'user_inactive_time' => $user_inactive_time,
);
// Register user...
@@ -284,10 +309,10 @@ class ucp_register
$messenger = new messenger(false);
- $messenger->template($email_template, $lang);
+ $messenger->template($email_template, $data['lang']);
$messenger->replyto($config['board_contact']);
- $messenger->to($email, $username);
+ $messenger->to($data['email'], $data['username']);
$messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']);
$messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']);
@@ -295,12 +320,9 @@ class ucp_register
$messenger->headers('X-AntiAbuse: User IP - ' . $user->ip);
$messenger->assign_vars(array(
- 'SITENAME' => $config['sitename'],
- 'WELCOME_MSG' => sprintf($user->lang['WELCOME_SUBJECT'], $config['sitename']),
- 'USERNAME' => html_entity_decode($username),
- 'PASSWORD' => html_entity_decode($password_confirm),
- 'EMAIL_SIG' => str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']),
-
+ 'WELCOME_MSG' => htmlspecialchars_decode(sprintf($user->lang['WELCOME_SUBJECT'], $config['sitename'])),
+ 'USERNAME' => htmlspecialchars_decode($data['username']),
+ 'PASSWORD' => htmlspecialchars_decode($data['new_password']),
'U_ACTIVATE' => "$server_url/ucp.$phpEx?mode=activate&u=$user_id&k=$user_actkey")
);
@@ -309,8 +331,7 @@ class ucp_register
$messenger->assign_vars(array(
'FAX_INFO' => $config['coppa_fax'],
'MAIL_INFO' => $config['coppa_mail'],
- 'EMAIL_ADDRESS' => $email,
- 'SITENAME' => $config['sitename'])
+ 'EMAIL_ADDRESS' => $data['email'])
);
}
@@ -320,10 +341,19 @@ class ucp_register
{
// Grab an array of user_id's with a_user permissions ... these users can activate a user
$admin_ary = $auth->acl_get_list(false, 'a_user', false);
+ $admin_ary = (!empty($admin_ary[0]['a_user'])) ? $admin_ary[0]['a_user'] : array();
+
+ // Also include founders
+ $where_sql = ' WHERE user_type = ' . USER_FOUNDER;
+
+ if (sizeof($admin_ary))
+ {
+ $where_sql .= ' OR ' . $db->sql_in_set('user_id', $admin_ary);
+ }
$sql = 'SELECT user_id, username, user_email, user_lang, user_jabber, user_notify_type
- FROM ' . USERS_TABLE . '
- WHERE ' . $db->sql_in_set('user_id', $admin_ary[0]['a_user']);
+ FROM ' . USERS_TABLE . ' ' .
+ $where_sql;
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
@@ -334,9 +364,7 @@ class ucp_register
$messenger->im($row['user_jabber'], $row['username']);
$messenger->assign_vars(array(
- 'USERNAME' => html_entity_decode($username),
- 'EMAIL_SIG' => str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']),
-
+ 'USERNAME' => htmlspecialchars_decode($data['username']),
'U_ACTIVATE' => "$server_url/ucp.$phpEx?mode=activate&u=$user_id&k=$user_actkey")
);
@@ -345,7 +373,6 @@ class ucp_register
$db->sql_freeresult($result);
}
}
- unset($data);
$message = $message . '<br /><br />' . sprintf($user->lang['RETURN_INDEX'], '<a href="' . append_sid("{$phpbb_root_path}index.$phpEx") . '">', '</a>');
trigger_error($message);
@@ -379,10 +406,13 @@ class ucp_register
}
while ($row = $db->sql_fetchrow($result));
- $sql = 'DELETE FROM ' . CONFIRM_TABLE . '
- WHERE ' . $db->sql_in_set('session_id', $sql_in, true) . '
- AND confirm_type = ' . CONFIRM_REG;
- $db->sql_query($sql);
+ if (sizeof($sql_in))
+ {
+ $sql = 'DELETE FROM ' . CONFIRM_TABLE . '
+ WHERE ' . $db->sql_in_set('session_id', $sql_in, true) . '
+ AND confirm_type = ' . CONFIRM_REG;
+ $db->sql_query($sql);
+ }
}
$db->sql_freeresult($result);
@@ -433,27 +463,25 @@ class ucp_register
}
$user_char_ary = array('.*' => 'USERNAME_CHARS_ANY', '[\w]+' => 'USERNAME_ALPHA_ONLY', '[\w_\+\. \-\[\]]+' => 'USERNAME_ALPHA_SPACERS');
-
- $lang = (isset($lang)) ? $lang : $config['default_lang'];
- $tz = (isset($tz)) ? $tz : $config['board_timezone'];
+ $pass_char_ary = array('.*' => 'PASS_TYPE_ANY', '[a-zA-Z]' => 'PASS_TYPE_CASE', '[a-zA-Z0-9]' => 'PASS_TYPE_ALPHA', '[a-zA-Z\W]' => 'PASS_TYPE_SYMBOL');
//
$template->assign_vars(array(
'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '',
- 'USERNAME' => (isset($username)) ? $username : '',
- 'PASSWORD' => (isset($new_password)) ? $new_password : '',
- 'PASSWORD_CONFIRM' => (isset($password_confirm)) ? $password_confirm : '',
- 'EMAIL' => (isset($email)) ? $email : '',
- 'EMAIL_CONFIRM' => (isset($email_confirm)) ? $email_confirm : '',
+ 'USERNAME' => $data['username'],
+ 'PASSWORD' => $data['new_password'],
+ 'PASSWORD_CONFIRM' => $data['password_confirm'],
+ 'EMAIL' => $data['email'],
+ 'EMAIL_CONFIRM' => $data['email_confirm'],
'CONFIRM_IMG' => $confirm_image,
- 'L_CONFIRM_EXPLAIN' => sprintf($user->lang['CONFIRM_EXPLAIN'], '<a href="mailto:' . htmlentities($config['board_contact']) . '">', '</a>'),
+ 'L_CONFIRM_EXPLAIN' => sprintf($user->lang['CONFIRM_EXPLAIN'], '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>'),
'L_REG_COND' => $l_reg_cond,
'L_USERNAME_EXPLAIN' => sprintf($user->lang[$user_char_ary[str_replace('\\\\', '\\', $config['allow_name_chars'])] . '_EXPLAIN'], $config['min_name_chars'], $config['max_name_chars']),
- 'L_NEW_PASSWORD_EXPLAIN' => sprintf($user->lang['NEW_PASSWORD_EXPLAIN'], $config['min_pass_chars'], $config['max_pass_chars']),
+ 'L_NEW_PASSWORD_EXPLAIN' => sprintf($user->lang[$pass_char_ary[str_replace('\\\\', '\\', $config['pass_complex'])] . '_EXPLAIN'], $config['min_pass_chars'], $config['max_pass_chars']),
- 'S_LANG_OPTIONS' => language_select($lang),
- 'S_TZ_OPTIONS' => tz_select($tz),
+ 'S_LANG_OPTIONS' => language_select($data['lang']),
+ 'S_TZ_OPTIONS' => tz_select($data['tz']),
'S_CONFIRM_CODE' => ($config['enable_confirm']) ? true : false,
'S_COPPA' => $coppa,
'S_HIDDEN_FIELDS' => $s_hidden_fields,
diff --git a/phpBB/includes/ucp/ucp_remind.php b/phpBB/includes/ucp/ucp_remind.php
index 11edb54b95..7ce82093ca 100644
--- a/phpBB/includes/ucp/ucp_remind.php
+++ b/phpBB/includes/ucp/ucp_remind.php
@@ -22,7 +22,7 @@ class ucp_remind
global $config, $phpbb_root_path, $phpEx;
global $db, $user, $auth, $template;
- $username = request_var('username', '');
+ $username = request_var('username', '', true);
$email = request_var('email', '');
$submit = (isset($_POST['submit'])) ? true : false;
@@ -31,7 +31,7 @@ class ucp_remind
$sql = 'SELECT user_id, username, user_email, user_jabber, user_notify_type, user_type, user_lang
FROM ' . USERS_TABLE . "
WHERE user_email = '" . $db->sql_escape($email) . "'
- AND LOWER(username) = '" . $db->sql_escape(strtolower($username)) . "'";
+ AND username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'";
$result = $db->sql_query($sql);
$user_row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
@@ -69,11 +69,8 @@ class ucp_remind
$messenger->im($user_row['user_jabber'], $user_row['username']);
$messenger->assign_vars(array(
- 'SITENAME' => $config['sitename'],
- 'USERNAME' => html_entity_decode($user_row['username']),
- 'PASSWORD' => html_entity_decode($user_password),
- 'EMAIL_SIG' => str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']),
-
+ 'USERNAME' => htmlspecialchars_decode($user_row['username']),
+ 'PASSWORD' => htmlspecialchars_decode($user_password),
'U_ACTIVATE' => "$server_url/ucp.$phpEx?mode=activate&u={$user_row['user_id']}&k=$user_actkey")
);
diff --git a/phpBB/includes/ucp/ucp_resend.php b/phpBB/includes/ucp/ucp_resend.php
index 84ce3fe9b7..62e796bc4b 100644
--- a/phpBB/includes/ucp/ucp_resend.php
+++ b/phpBB/includes/ucp/ucp_resend.php
@@ -22,7 +22,7 @@ class ucp_resend
global $config, $phpbb_root_path, $phpEx;
global $db, $user, $auth, $template;
- $username = request_var('username', '');
+ $username = request_var('username', '', true);
$email = request_var('email', '');
$submit = (isset($_POST['submit'])) ? true : false;
@@ -31,7 +31,7 @@ class ucp_resend
$sql = 'SELECT user_id, group_id, username, user_email, user_type, user_lang, user_actkey
FROM ' . USERS_TABLE . "
WHERE user_email = '" . $db->sql_escape($email) . "'
- AND LOWER(username) = '" . $db->sql_escape(strtolower($username)) . "'";
+ AND username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'";
$result = $db->sql_query($sql);
$user_row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
@@ -46,7 +46,7 @@ class ucp_resend
trigger_error('ACCOUNT_ALREADY_ACTIVATED');
}
- // Determine coppa status on group (INACTIVE(_COPPA))
+ // Determine coppa status on group (REGISTERED(_COPPA))
$sql = 'SELECT group_name, group_type
FROM ' . GROUPS_TABLE . '
WHERE group_id = ' . $user_row['group_id'];
@@ -59,7 +59,7 @@ class ucp_resend
trigger_error('NO_GROUP');
}
- $coppa = ($row['group_name'] == 'INACTIVE_COPPA' && $row['group_type'] == GROUP_SPECIAL) ? true : false;
+ $coppa = ($row['group_name'] == 'REGISTERED_COPPA' && $row['group_type'] == GROUP_SPECIAL) ? true : false;
include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
$messenger = new messenger(false);
@@ -77,11 +77,8 @@ class ucp_resend
$messenger->headers('X-AntiAbuse: User IP - ' . $user->ip);
$messenger->assign_vars(array(
- 'SITENAME' => $config['sitename'],
- 'WELCOME_MSG' => sprintf($user->lang['WELCOME_SUBJECT'], $config['sitename']),
- 'USERNAME' => html_entity_decode($user_row['username']),
- 'EMAIL_SIG' => str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']),
-
+ 'WELCOME_MSG' => htmlspecialchars_decode(sprintf($user->lang['WELCOME_SUBJECT'], $config['sitename'])),
+ 'USERNAME' => htmlspecialchars_decode($user_row['username']),
'U_ACTIVATE' => generate_board_url() . "/ucp.$phpEx?mode=activate&u={$user_row['user_id']}&k={$user_row['user_actkey']}")
);
@@ -90,8 +87,7 @@ class ucp_resend
$messenger->assign_vars(array(
'FAX_INFO' => $config['coppa_fax'],
'MAIL_INFO' => $config['coppa_mail'],
- 'EMAIL_ADDRESS' => $user_row['user_email'],
- 'SITENAME' => $config['sitename'])
+ 'EMAIL_ADDRESS' => $user_row['user_email'])
);
}
@@ -116,9 +112,7 @@ class ucp_resend
$messenger->im($row['user_jabber'], $row['username']);
$messenger->assign_vars(array(
- 'USERNAME' => html_entity_decode($user_row['username']),
- 'EMAIL_SIG' => str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']),
-
+ 'USERNAME' => htmlspecialchars_decode($user_row['username']),
'U_ACTIVATE' => generate_board_url() . "/ucp.$phpEx?mode=activate&u={$user_row['user_id']}&k={$user_row['user_actkey']}")
);
diff --git a/phpBB/includes/ucp/ucp_zebra.php b/phpBB/includes/ucp/ucp_zebra.php
index 2cf6edcac4..2548037b10 100644
--- a/phpBB/includes/ucp/ucp_zebra.php
+++ b/phpBB/includes/ucp/ucp_zebra.php
@@ -20,7 +20,7 @@ class ucp_zebra
{
global $config, $db, $user, $auth, $template, $phpbb_root_path, $phpEx;
- $submit = (isset($_POST['submit']) || isset($_GET['add'])) ? true : false;
+ $submit = (isset($_POST['submit']) || isset($_GET['add']) || isset($_GET['remove'])) ? true : false;
$s_hidden_fields = '';
$l_mode = strtoupper($mode);
@@ -32,17 +32,17 @@ class ucp_zebra
$var_ary = array(
'usernames' => array(0),
- 'add' => '',
+ 'add' => '',
);
foreach ($var_ary as $var => $default)
{
- $data[$var] = request_var($var, $default);
+ $data[$var] = request_var($var, $default, true);
}
if ($data['add'])
{
- $data['add'] = array_map('trim', array_map('strtolower', explode("\n", $data['add'])));
+ $data['add'] = array_map('trim', array_map('utf8_clean_string', explode("\n", $data['add'])));
// Do these name/s exist on a list already? If so, ignore ... we could be
// 'nice' and automatically handle names added to one list present on
@@ -59,11 +59,11 @@ class ucp_zebra
{
if ($row['friend'])
{
- $friends[] = strtolower($row['username']);
+ $friends[] = utf8_clean_string($row['username']);
}
else
{
- $foes[] = strtolower($row['username']);
+ $foes[] = utf8_clean_string($row['username']);
}
}
$db->sql_freeresult($result);
@@ -88,7 +88,7 @@ class ucp_zebra
// remove the user himself from the username array
$n = sizeof($data['add']);
- $data['add'] = array_diff($data['add'], array(strtolower($user->data['username'])));
+ $data['add'] = array_diff($data['add'], array(utf8_clean_string($user->data['username'])));
if (sizeof($data['add']) < $n)
{
@@ -101,7 +101,7 @@ class ucp_zebra
{
$sql = 'SELECT user_id, user_type
FROM ' . USERS_TABLE . '
- WHERE ' . $db->sql_in_set('LOWER(username)', $data['add']) . '
+ WHERE ' . $db->sql_in_set('username_clean', $data['add']) . '
AND user_type <> ' . USER_INACTIVE;
$result = $db->sql_query($sql);
@@ -159,24 +159,7 @@ class ucp_zebra
);
}
- if (sizeof($sql_ary))
- {
- switch (SQL_LAYER)
- {
- case 'mysql':
- case 'mysql4':
- case 'mysqli':
- $db->sql_query('INSERT INTO ' . ZEBRA_TABLE . ' ' . $db->sql_build_array('MULTI_INSERT', $sql_ary));
- break;
-
- default:
- foreach ($sql_ary as $ary)
- {
- $db->sql_query('INSERT INTO ' . ZEBRA_TABLE . ' ' . $db->sql_build_array('INSERT', $ary));
- }
- break;
- }
- }
+ $db->sql_multi_insert(ZEBRA_TABLE, $sql_ary);
$updated = true;
}
@@ -197,6 +180,8 @@ class ucp_zebra
WHERE user_id = ' . $user->data['user_id'] . '
AND ' . $db->sql_in_set('zebra_id', $data['usernames']);
$db->sql_query($sql);
+
+ $updated = true;
}
if ($updated)
diff --git a/phpBB/includes/utf/data/case_fold_c.php b/phpBB/includes/utf/data/case_fold_c.php
new file mode 100644
index 0000000000..00de1ba349
--- /dev/null
+++ b/phpBB/includes/utf/data/case_fold_c.php
@@ -0,0 +1 @@
+<?php return array('A'=>'a','B'=>'b','C'=>'c','D'=>'d','E'=>'e','F'=>'f','G'=>'g','H'=>'h','I'=>'i','J'=>'j','K'=>'k','L'=>'l','M'=>'m','N'=>'n','O'=>'o','P'=>'p','Q'=>'q','R'=>'r','S'=>'s','T'=>'t','U'=>'u','V'=>'v','W'=>'w','X'=>'x','Y'=>'y','Z'=>'z','µ'=>'μ','À'=>'à','Á'=>'á','Â'=>'â','Ã'=>'ã','Ä'=>'ä','Å'=>'å','Æ'=>'æ','Ç'=>'ç','È'=>'è','É'=>'é','Ê'=>'ê','Ë'=>'ë','Ì'=>'ì','Í'=>'í','Î'=>'î','Ï'=>'ï','Ð'=>'ð','Ñ'=>'ñ','Ò'=>'ò','Ó'=>'ó','Ô'=>'ô','Õ'=>'õ','Ö'=>'ö','Ø'=>'ø','Ù'=>'ù','Ú'=>'ú','Û'=>'û','Ü'=>'ü','Ý'=>'ý','Þ'=>'þ','Ā'=>'ā','Ă'=>'ă','Ą'=>'ą','Ć'=>'ć','Ĉ'=>'ĉ','Ċ'=>'ċ','Č'=>'č','Ď'=>'ď','Đ'=>'đ','Ē'=>'ē','Ĕ'=>'ĕ','Ė'=>'ė','Ę'=>'ę','Ě'=>'ě','Ĝ'=>'ĝ','Ğ'=>'ğ','Ġ'=>'ġ','Ģ'=>'ģ','Ĥ'=>'ĥ','Ħ'=>'ħ','Ĩ'=>'ĩ','Ī'=>'ī','Ĭ'=>'ĭ','Į'=>'į','IJ'=>'ij','Ĵ'=>'ĵ','Ķ'=>'ķ','Ĺ'=>'ĺ','Ļ'=>'ļ','Ľ'=>'ľ','Ŀ'=>'ŀ','Ł'=>'ł','Ń'=>'ń','Ņ'=>'ņ','Ň'=>'ň','Ŋ'=>'ŋ','Ō'=>'ō','Ŏ'=>'ŏ','Ő'=>'ő','Œ'=>'œ','Ŕ'=>'ŕ','Ŗ'=>'ŗ','Ř'=>'ř','Ś'=>'ś','Ŝ'=>'ŝ','Ş'=>'ş','Š'=>'š','Ţ'=>'ţ','Ť'=>'ť','Ŧ'=>'ŧ','Ũ'=>'ũ','Ū'=>'ū','Ŭ'=>'ŭ','Ů'=>'ů','Ű'=>'ű','Ų'=>'ų','Ŵ'=>'ŵ','Ŷ'=>'ŷ','Ÿ'=>'ÿ','Ź'=>'ź','Ż'=>'ż','Ž'=>'ž','ſ'=>'s','Ɓ'=>'ɓ','Ƃ'=>'ƃ','Ƅ'=>'ƅ','Ɔ'=>'ɔ','Ƈ'=>'ƈ','Ɖ'=>'ɖ','Ɗ'=>'ɗ','Ƌ'=>'ƌ','Ǝ'=>'ǝ','Ə'=>'ə','Ɛ'=>'ɛ','Ƒ'=>'ƒ','Ɠ'=>'ɠ','Ɣ'=>'ɣ','Ɩ'=>'ɩ','Ɨ'=>'ɨ','Ƙ'=>'ƙ','Ɯ'=>'ɯ','Ɲ'=>'ɲ','Ɵ'=>'ɵ','Ơ'=>'ơ','Ƣ'=>'ƣ','Ƥ'=>'ƥ','Ʀ'=>'ʀ','Ƨ'=>'ƨ','Ʃ'=>'ʃ','Ƭ'=>'ƭ','Ʈ'=>'ʈ','Ư'=>'ư','Ʊ'=>'ʊ','Ʋ'=>'ʋ','Ƴ'=>'ƴ','Ƶ'=>'ƶ','Ʒ'=>'ʒ','Ƹ'=>'ƹ','Ƽ'=>'ƽ','DŽ'=>'dž','Dž'=>'dž','LJ'=>'lj','Lj'=>'lj','NJ'=>'nj','Nj'=>'nj','Ǎ'=>'ǎ','Ǐ'=>'ǐ','Ǒ'=>'ǒ','Ǔ'=>'ǔ','Ǖ'=>'ǖ','Ǘ'=>'ǘ','Ǚ'=>'ǚ','Ǜ'=>'ǜ','Ǟ'=>'ǟ','Ǡ'=>'ǡ','Ǣ'=>'ǣ','Ǥ'=>'ǥ','Ǧ'=>'ǧ','Ǩ'=>'ǩ','Ǫ'=>'ǫ','Ǭ'=>'ǭ','Ǯ'=>'ǯ','DZ'=>'dz','Dz'=>'dz','Ǵ'=>'ǵ','Ƕ'=>'ƕ','Ƿ'=>'ƿ','Ǹ'=>'ǹ','Ǻ'=>'ǻ','Ǽ'=>'ǽ','Ǿ'=>'ǿ','Ȁ'=>'ȁ','Ȃ'=>'ȃ','Ȅ'=>'ȅ','Ȇ'=>'ȇ','Ȉ'=>'ȉ','Ȋ'=>'ȋ','Ȍ'=>'ȍ','Ȏ'=>'ȏ','Ȑ'=>'ȑ','Ȓ'=>'ȓ','Ȕ'=>'ȕ','Ȗ'=>'ȗ','Ș'=>'ș','Ț'=>'ț','Ȝ'=>'ȝ','Ȟ'=>'ȟ','Ƞ'=>'ƞ','Ȣ'=>'ȣ','Ȥ'=>'ȥ','Ȧ'=>'ȧ','Ȩ'=>'ȩ','Ȫ'=>'ȫ','Ȭ'=>'ȭ','Ȯ'=>'ȯ','Ȱ'=>'ȱ','Ȳ'=>'ȳ','Ⱥ'=>'ⱥ','Ȼ'=>'ȼ','Ƚ'=>'ƚ','Ⱦ'=>'ⱦ','Ɂ'=>'ɂ','Ƀ'=>'ƀ','Ʉ'=>'ʉ','Ʌ'=>'ʌ','Ɇ'=>'ɇ','Ɉ'=>'ɉ','Ɋ'=>'ɋ','Ɍ'=>'ɍ','Ɏ'=>'ɏ','ͅ'=>'ι','Ά'=>'ά','Έ'=>'έ','Ή'=>'ή','Ί'=>'ί','Ό'=>'ό','Ύ'=>'ύ','Ώ'=>'ώ','Α'=>'α','Β'=>'β','Γ'=>'γ','Δ'=>'δ','Ε'=>'ε','Ζ'=>'ζ','Η'=>'η','Θ'=>'θ','Ι'=>'ι','Κ'=>'κ','Λ'=>'λ','Μ'=>'μ','Ν'=>'ν','Ξ'=>'ξ','Ο'=>'ο','Π'=>'π','Ρ'=>'ρ','Σ'=>'σ','Τ'=>'τ','Υ'=>'υ','Φ'=>'φ','Χ'=>'χ','Ψ'=>'ψ','Ω'=>'ω','Ϊ'=>'ϊ','Ϋ'=>'ϋ','ς'=>'σ','ϐ'=>'β','ϑ'=>'θ','ϕ'=>'φ','ϖ'=>'π','Ϙ'=>'ϙ','Ϛ'=>'ϛ','Ϝ'=>'ϝ','Ϟ'=>'ϟ','Ϡ'=>'ϡ','Ϣ'=>'ϣ','Ϥ'=>'ϥ','Ϧ'=>'ϧ','Ϩ'=>'ϩ','Ϫ'=>'ϫ','Ϭ'=>'ϭ','Ϯ'=>'ϯ','ϰ'=>'κ','ϱ'=>'ρ','ϴ'=>'θ','ϵ'=>'ε','Ϸ'=>'ϸ','Ϲ'=>'ϲ','Ϻ'=>'ϻ','Ͻ'=>'ͻ','Ͼ'=>'ͼ','Ͽ'=>'ͽ','Ѐ'=>'ѐ','Ё'=>'ё','Ђ'=>'ђ','Ѓ'=>'ѓ','Є'=>'є','Ѕ'=>'ѕ','І'=>'і','Ї'=>'ї','Ј'=>'ј','Љ'=>'љ','Њ'=>'њ','Ћ'=>'ћ','Ќ'=>'ќ','Ѝ'=>'ѝ','Ў'=>'ў','Џ'=>'џ','А'=>'а','Б'=>'б','В'=>'в','Г'=>'г','Д'=>'д','Е'=>'е','Ж'=>'ж','З'=>'з','И'=>'и','Й'=>'й','К'=>'к','Л'=>'л','М'=>'м','Н'=>'н','О'=>'о','П'=>'п','Р'=>'р','С'=>'с','Т'=>'т','У'=>'у','Ф'=>'ф','Х'=>'х','Ц'=>'ц','Ч'=>'ч','Ш'=>'ш','Щ'=>'щ','Ъ'=>'ъ','Ы'=>'ы','Ь'=>'ь','Э'=>'э','Ю'=>'ю','Я'=>'я','Ѡ'=>'ѡ','Ѣ'=>'ѣ','Ѥ'=>'ѥ','Ѧ'=>'ѧ','Ѩ'=>'ѩ','Ѫ'=>'ѫ','Ѭ'=>'ѭ','Ѯ'=>'ѯ','Ѱ'=>'ѱ','Ѳ'=>'ѳ','Ѵ'=>'ѵ','Ѷ'=>'ѷ','Ѹ'=>'ѹ','Ѻ'=>'ѻ','Ѽ'=>'ѽ','Ѿ'=>'ѿ','Ҁ'=>'ҁ','Ҋ'=>'ҋ','Ҍ'=>'ҍ','Ҏ'=>'ҏ','Ґ'=>'ґ','Ғ'=>'ғ','Ҕ'=>'ҕ','Җ'=>'җ','Ҙ'=>'ҙ','Қ'=>'қ','Ҝ'=>'ҝ','Ҟ'=>'ҟ','Ҡ'=>'ҡ','Ң'=>'ң','Ҥ'=>'ҥ','Ҧ'=>'ҧ','Ҩ'=>'ҩ','Ҫ'=>'ҫ','Ҭ'=>'ҭ','Ү'=>'ү','Ұ'=>'ұ','Ҳ'=>'ҳ','Ҵ'=>'ҵ','Ҷ'=>'ҷ','Ҹ'=>'ҹ','Һ'=>'һ','Ҽ'=>'ҽ','Ҿ'=>'ҿ','Ӏ'=>'ӏ','Ӂ'=>'ӂ','Ӄ'=>'ӄ','Ӆ'=>'ӆ','Ӈ'=>'ӈ','Ӊ'=>'ӊ','Ӌ'=>'ӌ','Ӎ'=>'ӎ','Ӑ'=>'ӑ','Ӓ'=>'ӓ','Ӕ'=>'ӕ','Ӗ'=>'ӗ','Ә'=>'ә','Ӛ'=>'ӛ','Ӝ'=>'ӝ','Ӟ'=>'ӟ','Ӡ'=>'ӡ','Ӣ'=>'ӣ','Ӥ'=>'ӥ','Ӧ'=>'ӧ','Ө'=>'ө','Ӫ'=>'ӫ','Ӭ'=>'ӭ','Ӯ'=>'ӯ','Ӱ'=>'ӱ','Ӳ'=>'ӳ','Ӵ'=>'ӵ','Ӷ'=>'ӷ','Ӹ'=>'ӹ','Ӻ'=>'ӻ','Ӽ'=>'ӽ','Ӿ'=>'ӿ','Ԁ'=>'ԁ','Ԃ'=>'ԃ','Ԅ'=>'ԅ','Ԇ'=>'ԇ','Ԉ'=>'ԉ','Ԋ'=>'ԋ','Ԍ'=>'ԍ','Ԏ'=>'ԏ','Ԑ'=>'ԑ','Ԓ'=>'ԓ','Ա'=>'ա','Բ'=>'բ','Գ'=>'գ','Դ'=>'դ','Ե'=>'ե','Զ'=>'զ','Է'=>'է','Ը'=>'ը','Թ'=>'թ','Ժ'=>'ժ','Ի'=>'ի','Լ'=>'լ','Խ'=>'խ','Ծ'=>'ծ','Կ'=>'կ','Հ'=>'հ','Ձ'=>'ձ','Ղ'=>'ղ','Ճ'=>'ճ','Մ'=>'մ','Յ'=>'յ','Ն'=>'ն','Շ'=>'շ','Ո'=>'ո','Չ'=>'չ','Պ'=>'պ','Ջ'=>'ջ','Ռ'=>'ռ','Ս'=>'ս','Վ'=>'վ','Տ'=>'տ','Ր'=>'ր','Ց'=>'ց','Ւ'=>'ւ','Փ'=>'փ','Ք'=>'ք','Օ'=>'օ','Ֆ'=>'ֆ','Ⴀ'=>'ⴀ','Ⴁ'=>'ⴁ','Ⴂ'=>'ⴂ','Ⴃ'=>'ⴃ','Ⴄ'=>'ⴄ','Ⴅ'=>'ⴅ','Ⴆ'=>'ⴆ','Ⴇ'=>'ⴇ','Ⴈ'=>'ⴈ','Ⴉ'=>'ⴉ','Ⴊ'=>'ⴊ','Ⴋ'=>'ⴋ','Ⴌ'=>'ⴌ','Ⴍ'=>'ⴍ','Ⴎ'=>'ⴎ','Ⴏ'=>'ⴏ','Ⴐ'=>'ⴐ','Ⴑ'=>'ⴑ','Ⴒ'=>'ⴒ','Ⴓ'=>'ⴓ','Ⴔ'=>'ⴔ','Ⴕ'=>'ⴕ','Ⴖ'=>'ⴖ','Ⴗ'=>'ⴗ','Ⴘ'=>'ⴘ','Ⴙ'=>'ⴙ','Ⴚ'=>'ⴚ','Ⴛ'=>'ⴛ','Ⴜ'=>'ⴜ','Ⴝ'=>'ⴝ','Ⴞ'=>'ⴞ','Ⴟ'=>'ⴟ','Ⴠ'=>'ⴠ','Ⴡ'=>'ⴡ','Ⴢ'=>'ⴢ','Ⴣ'=>'ⴣ','Ⴤ'=>'ⴤ','Ⴥ'=>'ⴥ','Ḁ'=>'ḁ','Ḃ'=>'ḃ','Ḅ'=>'ḅ','Ḇ'=>'ḇ','Ḉ'=>'ḉ','Ḋ'=>'ḋ','Ḍ'=>'ḍ','Ḏ'=>'ḏ','Ḑ'=>'ḑ','Ḓ'=>'ḓ','Ḕ'=>'ḕ','Ḗ'=>'ḗ','Ḙ'=>'ḙ','Ḛ'=>'ḛ','Ḝ'=>'ḝ','Ḟ'=>'ḟ','Ḡ'=>'ḡ','Ḣ'=>'ḣ','Ḥ'=>'ḥ','Ḧ'=>'ḧ','Ḩ'=>'ḩ','Ḫ'=>'ḫ','Ḭ'=>'ḭ','Ḯ'=>'ḯ','Ḱ'=>'ḱ','Ḳ'=>'ḳ','Ḵ'=>'ḵ','Ḷ'=>'ḷ','Ḹ'=>'ḹ','Ḻ'=>'ḻ','Ḽ'=>'ḽ','Ḿ'=>'ḿ','Ṁ'=>'ṁ','Ṃ'=>'ṃ','Ṅ'=>'ṅ','Ṇ'=>'ṇ','Ṉ'=>'ṉ','Ṋ'=>'ṋ','Ṍ'=>'ṍ','Ṏ'=>'ṏ','Ṑ'=>'ṑ','Ṓ'=>'ṓ','Ṕ'=>'ṕ','Ṗ'=>'ṗ','Ṙ'=>'ṙ','Ṛ'=>'ṛ','Ṝ'=>'ṝ','Ṟ'=>'ṟ','Ṡ'=>'ṡ','Ṣ'=>'ṣ','Ṥ'=>'ṥ','Ṧ'=>'ṧ','Ṩ'=>'ṩ','Ṫ'=>'ṫ','Ṭ'=>'ṭ','Ṯ'=>'ṯ','Ṱ'=>'ṱ','Ṳ'=>'ṳ','Ṵ'=>'ṵ','Ṷ'=>'ṷ','Ṹ'=>'ṹ','Ṻ'=>'ṻ','Ṽ'=>'ṽ','Ṿ'=>'ṿ','Ẁ'=>'ẁ','Ẃ'=>'ẃ','Ẅ'=>'ẅ','Ẇ'=>'ẇ','Ẉ'=>'ẉ','Ẋ'=>'ẋ','Ẍ'=>'ẍ','Ẏ'=>'ẏ','Ẑ'=>'ẑ','Ẓ'=>'ẓ','Ẕ'=>'ẕ','ẛ'=>'ṡ','Ạ'=>'ạ','Ả'=>'ả','Ấ'=>'ấ','Ầ'=>'ầ','Ẩ'=>'ẩ','Ẫ'=>'ẫ','Ậ'=>'ậ','Ắ'=>'ắ','Ằ'=>'ằ','Ẳ'=>'ẳ','Ẵ'=>'ẵ','Ặ'=>'ặ','Ẹ'=>'ẹ','Ẻ'=>'ẻ','Ẽ'=>'ẽ','Ế'=>'ế','Ề'=>'ề','Ể'=>'ể','Ễ'=>'ễ','Ệ'=>'ệ','Ỉ'=>'ỉ','Ị'=>'ị','Ọ'=>'ọ','Ỏ'=>'ỏ','Ố'=>'ố','Ồ'=>'ồ','Ổ'=>'ổ','Ỗ'=>'ỗ','Ộ'=>'ộ','Ớ'=>'ớ','Ờ'=>'ờ','Ở'=>'ở','Ỡ'=>'ỡ','Ợ'=>'ợ','Ụ'=>'ụ','Ủ'=>'ủ','Ứ'=>'ứ','Ừ'=>'ừ','Ử'=>'ử','Ữ'=>'ữ','Ự'=>'ự','Ỳ'=>'ỳ','Ỵ'=>'ỵ','Ỷ'=>'ỷ','Ỹ'=>'ỹ','Ἀ'=>'ἀ','Ἁ'=>'ἁ','Ἂ'=>'ἂ','Ἃ'=>'ἃ','Ἄ'=>'ἄ','Ἅ'=>'ἅ','Ἆ'=>'ἆ','Ἇ'=>'ἇ','Ἐ'=>'ἐ','Ἑ'=>'ἑ','Ἒ'=>'ἒ','Ἓ'=>'ἓ','Ἔ'=>'ἔ','Ἕ'=>'ἕ','Ἠ'=>'ἠ','Ἡ'=>'ἡ','Ἢ'=>'ἢ','Ἣ'=>'ἣ','Ἤ'=>'ἤ','Ἥ'=>'ἥ','Ἦ'=>'ἦ','Ἧ'=>'ἧ','Ἰ'=>'ἰ','Ἱ'=>'ἱ','Ἲ'=>'ἲ','Ἳ'=>'ἳ','Ἴ'=>'ἴ','Ἵ'=>'ἵ','Ἶ'=>'ἶ','Ἷ'=>'ἷ','Ὀ'=>'ὀ','Ὁ'=>'ὁ','Ὂ'=>'ὂ','Ὃ'=>'ὃ','Ὄ'=>'ὄ','Ὅ'=>'ὅ','Ὑ'=>'ὑ','Ὓ'=>'ὓ','Ὕ'=>'ὕ','Ὗ'=>'ὗ','Ὠ'=>'ὠ','Ὡ'=>'ὡ','Ὢ'=>'ὢ','Ὣ'=>'ὣ','Ὤ'=>'ὤ','Ὥ'=>'ὥ','Ὦ'=>'ὦ','Ὧ'=>'ὧ','Ᾰ'=>'ᾰ','Ᾱ'=>'ᾱ','Ὰ'=>'ὰ','Ά'=>'ά','ι'=>'ι','Ὲ'=>'ὲ','Έ'=>'έ','Ὴ'=>'ὴ','Ή'=>'ή','Ῐ'=>'ῐ','Ῑ'=>'ῑ','Ὶ'=>'ὶ','Ί'=>'ί','Ῠ'=>'ῠ','Ῡ'=>'ῡ','Ὺ'=>'ὺ','Ύ'=>'ύ','Ῥ'=>'ῥ','Ὸ'=>'ὸ','Ό'=>'ό','Ὼ'=>'ὼ','Ώ'=>'ώ','Ω'=>'ω','K'=>'k','Å'=>'å','Ⅎ'=>'ⅎ','Ⅰ'=>'ⅰ','Ⅱ'=>'ⅱ','Ⅲ'=>'ⅲ','Ⅳ'=>'ⅳ','Ⅴ'=>'ⅴ','Ⅵ'=>'ⅵ','Ⅶ'=>'ⅶ','Ⅷ'=>'ⅷ','Ⅸ'=>'ⅸ','Ⅹ'=>'ⅹ','Ⅺ'=>'ⅺ','Ⅻ'=>'ⅻ','Ⅼ'=>'ⅼ','Ⅽ'=>'ⅽ','Ⅾ'=>'ⅾ','Ⅿ'=>'ⅿ','Ↄ'=>'ↄ','Ⓐ'=>'ⓐ','Ⓑ'=>'ⓑ','Ⓒ'=>'ⓒ','Ⓓ'=>'ⓓ','Ⓔ'=>'ⓔ','Ⓕ'=>'ⓕ','Ⓖ'=>'ⓖ','Ⓗ'=>'ⓗ','Ⓘ'=>'ⓘ','Ⓙ'=>'ⓙ','Ⓚ'=>'ⓚ','Ⓛ'=>'ⓛ','Ⓜ'=>'ⓜ','Ⓝ'=>'ⓝ','Ⓞ'=>'ⓞ','Ⓟ'=>'ⓟ','Ⓠ'=>'ⓠ','Ⓡ'=>'ⓡ','Ⓢ'=>'ⓢ','Ⓣ'=>'ⓣ','Ⓤ'=>'ⓤ','Ⓥ'=>'ⓥ','Ⓦ'=>'ⓦ','Ⓧ'=>'ⓧ','Ⓨ'=>'ⓨ','Ⓩ'=>'ⓩ','Ⰰ'=>'ⰰ','Ⰱ'=>'ⰱ','Ⰲ'=>'ⰲ','Ⰳ'=>'ⰳ','Ⰴ'=>'ⰴ','Ⰵ'=>'ⰵ','Ⰶ'=>'ⰶ','Ⰷ'=>'ⰷ','Ⰸ'=>'ⰸ','Ⰹ'=>'ⰹ','Ⰺ'=>'ⰺ','Ⰻ'=>'ⰻ','Ⰼ'=>'ⰼ','Ⰽ'=>'ⰽ','Ⰾ'=>'ⰾ','Ⰿ'=>'ⰿ','Ⱀ'=>'ⱀ','Ⱁ'=>'ⱁ','Ⱂ'=>'ⱂ','Ⱃ'=>'ⱃ','Ⱄ'=>'ⱄ','Ⱅ'=>'ⱅ','Ⱆ'=>'ⱆ','Ⱇ'=>'ⱇ','Ⱈ'=>'ⱈ','Ⱉ'=>'ⱉ','Ⱊ'=>'ⱊ','Ⱋ'=>'ⱋ','Ⱌ'=>'ⱌ','Ⱍ'=>'ⱍ','Ⱎ'=>'ⱎ','Ⱏ'=>'ⱏ','Ⱐ'=>'ⱐ','Ⱑ'=>'ⱑ','Ⱒ'=>'ⱒ','Ⱓ'=>'ⱓ','Ⱔ'=>'ⱔ','Ⱕ'=>'ⱕ','Ⱖ'=>'ⱖ','Ⱗ'=>'ⱗ','Ⱘ'=>'ⱘ','Ⱙ'=>'ⱙ','Ⱚ'=>'ⱚ','Ⱛ'=>'ⱛ','Ⱜ'=>'ⱜ','Ⱝ'=>'ⱝ','Ⱞ'=>'ⱞ','Ⱡ'=>'ⱡ','Ɫ'=>'ɫ','Ᵽ'=>'ᵽ','Ɽ'=>'ɽ','Ⱨ'=>'ⱨ','Ⱪ'=>'ⱪ','Ⱬ'=>'ⱬ','Ⱶ'=>'ⱶ','Ⲁ'=>'ⲁ','Ⲃ'=>'ⲃ','Ⲅ'=>'ⲅ','Ⲇ'=>'ⲇ','Ⲉ'=>'ⲉ','Ⲋ'=>'ⲋ','Ⲍ'=>'ⲍ','Ⲏ'=>'ⲏ','Ⲑ'=>'ⲑ','Ⲓ'=>'ⲓ','Ⲕ'=>'ⲕ','Ⲗ'=>'ⲗ','Ⲙ'=>'ⲙ','Ⲛ'=>'ⲛ','Ⲝ'=>'ⲝ','Ⲟ'=>'ⲟ','Ⲡ'=>'ⲡ','Ⲣ'=>'ⲣ','Ⲥ'=>'ⲥ','Ⲧ'=>'ⲧ','Ⲩ'=>'ⲩ','Ⲫ'=>'ⲫ','Ⲭ'=>'ⲭ','Ⲯ'=>'ⲯ','Ⲱ'=>'ⲱ','Ⲳ'=>'ⲳ','Ⲵ'=>'ⲵ','Ⲷ'=>'ⲷ','Ⲹ'=>'ⲹ','Ⲻ'=>'ⲻ','Ⲽ'=>'ⲽ','Ⲿ'=>'ⲿ','Ⳁ'=>'ⳁ','Ⳃ'=>'ⳃ','Ⳅ'=>'ⳅ','Ⳇ'=>'ⳇ','Ⳉ'=>'ⳉ','Ⳋ'=>'ⳋ','Ⳍ'=>'ⳍ','Ⳏ'=>'ⳏ','Ⳑ'=>'ⳑ','Ⳓ'=>'ⳓ','Ⳕ'=>'ⳕ','Ⳗ'=>'ⳗ','Ⳙ'=>'ⳙ','Ⳛ'=>'ⳛ','Ⳝ'=>'ⳝ','Ⳟ'=>'ⳟ','Ⳡ'=>'ⳡ','Ⳣ'=>'ⳣ','A'=>'a','B'=>'b','C'=>'c','D'=>'d','E'=>'e','F'=>'f','G'=>'g','H'=>'h','I'=>'i','J'=>'j','K'=>'k','L'=>'l','M'=>'m','N'=>'n','O'=>'o','P'=>'p','Q'=>'q','R'=>'r','S'=>'s','T'=>'t','U'=>'u','V'=>'v','W'=>'w','X'=>'x','Y'=>'y','Z'=>'z','𐐀'=>'𐐨','𐐁'=>'𐐩','𐐂'=>'𐐪','𐐃'=>'𐐫','𐐄'=>'𐐬','𐐅'=>'𐐭','𐐆'=>'𐐮','𐐇'=>'𐐯','𐐈'=>'𐐰','𐐉'=>'𐐱','𐐊'=>'𐐲','𐐋'=>'𐐳','𐐌'=>'𐐴','𐐍'=>'𐐵','𐐎'=>'𐐶','𐐏'=>'𐐷','𐐐'=>'𐐸','𐐑'=>'𐐹','𐐒'=>'𐐺','𐐓'=>'𐐻','𐐔'=>'𐐼','𐐕'=>'𐐽','𐐖'=>'𐐾','𐐗'=>'𐐿','𐐘'=>'𐑀','𐐙'=>'𐑁','𐐚'=>'𐑂','𐐛'=>'𐑃','𐐜'=>'𐑄','𐐝'=>'𐑅','𐐞'=>'𐑆','𐐟'=>'𐑇','𐐠'=>'𐑈','𐐡'=>'𐑉','𐐢'=>'𐑊','𐐣'=>'𐑋','𐐤'=>'𐑌','𐐥'=>'𐑍','𐐦'=>'𐑎','𐐧'=>'𐑏'); \ No newline at end of file
diff --git a/phpBB/includes/utf/data/case_fold_f.php b/phpBB/includes/utf/data/case_fold_f.php
new file mode 100644
index 0000000000..7e2ffb25ec
--- /dev/null
+++ b/phpBB/includes/utf/data/case_fold_f.php
@@ -0,0 +1 @@
+<?php return array('ß'=>'ss','İ'=>'i̇','ʼn'=>'ʼn','ǰ'=>'ǰ','ΐ'=>'ΐ','ΰ'=>'ΰ','և'=>'եւ','ẖ'=>'ẖ','ẗ'=>'ẗ','ẘ'=>'ẘ','ẙ'=>'ẙ','ẚ'=>'aʾ','ὐ'=>'ὐ','ὒ'=>'ὒ','ὔ'=>'ὔ','ὖ'=>'ὖ','ᾀ'=>'ἀι','ᾁ'=>'ἁι','ᾂ'=>'ἂι','ᾃ'=>'ἃι','ᾄ'=>'ἄι','ᾅ'=>'ἅι','ᾆ'=>'ἆι','ᾇ'=>'ἇι','ᾈ'=>'ἀι','ᾉ'=>'ἁι','ᾊ'=>'ἂι','ᾋ'=>'ἃι','ᾌ'=>'ἄι','ᾍ'=>'ἅι','ᾎ'=>'ἆι','ᾏ'=>'ἇι','ᾐ'=>'ἠι','ᾑ'=>'ἡι','ᾒ'=>'ἢι','ᾓ'=>'ἣι','ᾔ'=>'ἤι','ᾕ'=>'ἥι','ᾖ'=>'ἦι','ᾗ'=>'ἧι','ᾘ'=>'ἠι','ᾙ'=>'ἡι','ᾚ'=>'ἢι','ᾛ'=>'ἣι','ᾜ'=>'ἤι','ᾝ'=>'ἥι','ᾞ'=>'ἦι','ᾟ'=>'ἧι','ᾠ'=>'ὠι','ᾡ'=>'ὡι','ᾢ'=>'ὢι','ᾣ'=>'ὣι','ᾤ'=>'ὤι','ᾥ'=>'ὥι','ᾦ'=>'ὦι','ᾧ'=>'ὧι','ᾨ'=>'ὠι','ᾩ'=>'ὡι','ᾪ'=>'ὢι','ᾫ'=>'ὣι','ᾬ'=>'ὤι','ᾭ'=>'ὥι','ᾮ'=>'ὦι','ᾯ'=>'ὧι','ᾲ'=>'ὰι','ᾳ'=>'αι','ᾴ'=>'άι','ᾶ'=>'ᾶ','ᾷ'=>'ᾶι','ᾼ'=>'αι','ῂ'=>'ὴι','ῃ'=>'ηι','ῄ'=>'ήι','ῆ'=>'ῆ','ῇ'=>'ῆι','ῌ'=>'ηι','ῒ'=>'ῒ','ΐ'=>'ΐ','ῖ'=>'ῖ','ῗ'=>'ῗ','ῢ'=>'ῢ','ΰ'=>'ΰ','ῤ'=>'ῤ','ῦ'=>'ῦ','ῧ'=>'ῧ','ῲ'=>'ὼι','ῳ'=>'ωι','ῴ'=>'ώι','ῶ'=>'ῶ','ῷ'=>'ῶι','ῼ'=>'ωι','ff'=>'ff','fi'=>'fi','fl'=>'fl','ffi'=>'ffi','ffl'=>'ffl','ſt'=>'st','st'=>'st','ﬓ'=>'մն','ﬔ'=>'մե','ﬕ'=>'մի','ﬖ'=>'վն','ﬗ'=>'մխ'); \ No newline at end of file
diff --git a/phpBB/includes/utf/data/case_fold_s.php b/phpBB/includes/utf/data/case_fold_s.php
new file mode 100644
index 0000000000..5f09ffa1dd
--- /dev/null
+++ b/phpBB/includes/utf/data/case_fold_s.php
@@ -0,0 +1 @@
+<?php return array('ᾈ'=>'ᾀ','ᾉ'=>'ᾁ','ᾊ'=>'ᾂ','ᾋ'=>'ᾃ','ᾌ'=>'ᾄ','ᾍ'=>'ᾅ','ᾎ'=>'ᾆ','ᾏ'=>'ᾇ','ᾘ'=>'ᾐ','ᾙ'=>'ᾑ','ᾚ'=>'ᾒ','ᾛ'=>'ᾓ','ᾜ'=>'ᾔ','ᾝ'=>'ᾕ','ᾞ'=>'ᾖ','ᾟ'=>'ᾗ','ᾨ'=>'ᾠ','ᾩ'=>'ᾡ','ᾪ'=>'ᾢ','ᾫ'=>'ᾣ','ᾬ'=>'ᾤ','ᾭ'=>'ᾥ','ᾮ'=>'ᾦ','ᾯ'=>'ᾧ','ᾼ'=>'ᾳ','ῌ'=>'ῃ','ῼ'=>'ῳ'); \ No newline at end of file
diff --git a/phpBB/includes/utf/utf_normalizer.php b/phpBB/includes/utf/utf_normalizer.php
index 0b567fad6b..0d1d74539a 100644
--- a/phpBB/includes/utf/utf_normalizer.php
+++ b/phpBB/includes/utf/utf_normalizer.php
@@ -27,148 +27,20 @@ define('UTF8_CJK_LAST', "\xE9\xBE\xBB");
define('UTF8_CJK_B_FIRST', "\xF0\xA0\x80\x80");
define('UTF8_CJK_B_LAST', "\xF0\xAA\x9B\x96");
-
-if (function_exists('utf8_normalize'))
-{
-
-////////////////////////////////////////////////////////////////////////////////
-// Wrapper for the utfnormal extension, ICU wrapper //
-////////////////////////////////////////////////////////////////////////////////
-
-define('UNORM_NONE', 1);
-define('UNORM_NFD', 2);
-define('UNORM_NFKD', 3);
-define('UNORM_NFC', 4);
-define('UNORM_NFKC', 5);
-define('UNORM_FCD', 6);
-define('UNORM_DEFAULT', UNORM_NFC);
-
-/**
-* utf_normalizer class for the utfnormal extension
-*
-* @ignore
-*/
-class utf_normalizer
-{
- function cleanup($str)
- {
- /**
- * The string below is the list of all autorized characters, sorted by
- * frequency in latin text
- */
- $pos = strspn(
- $str,
- "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x0D"
- );
-
- if (!isset($str[$pos]))
- {
- /**
- * ASCII strings with no special chars return immediately
- */
- return $str;
- }
-
- /**
- * Check if there is potentially a U+FFFE or U+FFFF char (UTF sequence
- * 0xEFBFBE or 0xEFBFBF) and replace them
- *
- * Note: we start searching at position $pos
- */
- if (is_int(strpos($str, "\xEF\xBF", $pos)))
- {
- $str = str_replace(
- array("\xEF\xBF\xBE", "\xEF\xBF\xBF"),
- array(UTF8_REPLACEMENT, UTF8_REPLACEMENT),
- $str
- );
- }
-
- /**
- * Replace any byte in the range 0x00..0x1F, except for \r, \n and \t
- *
- * We replace those characters with a 0xFF byte, which is illegal in
- * UTF-8 and will in turn be replaced with a Unicode replacement char
- */
- $str = strtr(
- $str,
- "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F",
- "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
- );
-
- /**
- * As per the original implementation, "the UnicodeString constructor fails
- * if the string ends with a head byte". Therefore, if the string ends with
- * a leading byte we replace it with 0xFF, which is illegal too and will be
- * replaced with a Unicode replacement character
- */
- if (substr($str, -1) >= "\xC0")
- {
- $str[strlen($str) - 1] = "\xFF";
- }
-
- return utf8_normalize($str, UNORM_NFC);
- }
-
- function nfc($str)
- {
- return utf8_normalize($str, UNORM_NFC);
- }
-
- function nfkc($str)
- {
- return utf8_normalize($str, UNORM_NFKC);
- }
-
- function nfd($str)
- {
- return utf8_normalize($str, UNORM_NFD);
- }
-
- function nfkd($str)
- {
- return utf8_normalize($str, UNORM_NFKD);
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// End of the ICU wrapper //
-////////////////////////////////////////////////////////////////////////////////
-
-
-}
-else
-{
-
-
-////////////////////////////////////////////////////////////////////////////////
-// This block will NOT be loaded if the utfnormal extension is //
-////////////////////////////////////////////////////////////////////////////////
-
-/**
-* Unset global variables
-*/
+// Unset global variables
unset($GLOBALS['utf_jamo_index'], $GLOBALS['utf_jamo_type'], $GLOBALS['utf_nfc_qc'], $GLOBALS['utf_combining_class'], $GLOBALS['utf_canonical_comp'], $GLOBALS['utf_canonical_decomp'], $GLOBALS['utf_nfkc_qc'], $GLOBALS['utf_compatibility_decomp']);
-/**
-* NFC_QC and NFKC_QC values
-*/
+// NFC_QC and NFKC_QC values
define('UNICODE_QC_MAYBE', 0);
define('UNICODE_QC_NO', 1);
-/**
-* Contains all the ASCII characters appearing in UTF-8, sorted by frequency
-*/
+// Contains all the ASCII characters appearing in UTF-8, sorted by frequency
define('UTF8_ASCII_RANGE', "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F");
-/**
-* Contains all the tail bytes that can appear in the composition of a UTF-8 char
-*/
+// Contains all the tail bytes that can appear in the composition of a UTF-8 char
define('UTF8_TRAILING_BYTES', "\xA9\xA0\xA8\x80\xAA\x99\xA7\xBB\xAB\x89\x94\x82\xB4\xA2\xAE\x83\xB0\xB9\xB8\x93\xAF\xBC\xB3\x81\xA4\xB2\x9C\xA1\xB5\xBE\xBD\xBA\x98\xAD\xB1\x84\x95\xA6\xB6\x88\x8D\x90\xB7\xBF\x92\x85\xA5\x97\x8C\x86\xA3\x8E\x9F\x8F\x87\x91\x9D\xAC\x9E\x8B\x96\x9B\x8A\x9A");
-/**
-* Constants used by the Hangul [de]composition algorithms
-*/
+// Constants used by the Hangul [de]composition algorithms
define('UNICODE_HANGUL_SBASE', 0xAC00);
define('UNICODE_HANGUL_LBASE', 0x1100);
define('UNICODE_HANGUL_VBASE', 0x1161);
@@ -185,7 +57,7 @@ define('UNICODE_JAMO_T', 2);
/**
* Unicode normalization routines
*
-* @package phpBB3
+* @package phpBB3
*/
class utf_normalizer
{
@@ -200,37 +72,25 @@ class utf_normalizer
*/
function cleanup($str)
{
- /**
- * The string below is the list of all autorized characters, sorted by
- * frequency in latin text
- */
+ // The string below is the list of all autorized characters, sorted by frequency in latin text
$pos = strspn($str, "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x0D");
$len = strlen($str);
if ($pos == $len)
{
- /**
- * ASCII strings with no special chars return immediately
- */
+ // ASCII strings with no special chars return immediately
return $str;
}
- /**
- * Note: we do not check for $GLOBALS['utf_canonical_decomp']. It is assumed
- * they are always loaded together
- */
+ // Note: we do not check for $GLOBALS['utf_canonical_decomp']. It is assumed they are always loaded together
if (!isset($GLOBALS['utf_nfc_qc']))
{
global $phpbb_root_path, $phpEx;
include($phpbb_root_path . 'includes/utf/data/utf_nfc_qc.' . $phpEx);
}
- /**
- * Replace any byte in the range 0x00..0x1F, except for \r, \n and \t
- *
- * We replace those characters with a 0xFF byte, which is illegal in
- * UTF-8 and will in turn be replaced with a UTF replacement char
- */
+ // Replace any byte in the range 0x00..0x1F, except for \r, \n and \t
+ // We replace those characters with a 0xFF byte, which is illegal in UTF-8 and will in turn be replaced with a UTF replacement char
return utf_normalizer::recompose(
strtr(
$str,
@@ -254,9 +114,7 @@ class utf_normalizer
if ($pos == $len)
{
- /**
- * ASCII strings return immediately
- */
+ // ASCII strings return immediately
return $str;
}
@@ -282,9 +140,7 @@ class utf_normalizer
if ($pos == $len)
{
- /**
- * ASCII strings return immediately
- */
+ // ASCII strings return immediately
return $str;
}
@@ -293,6 +149,7 @@ class utf_normalizer
global $phpbb_root_path, $phpEx;
include($phpbb_root_path . 'includes/utf/data/utf_nfkc_qc.' . $phpEx);
}
+
if (!isset($GLOBALS['utf_canonical_comp']))
{
global $phpbb_root_path, $phpEx;
@@ -315,9 +172,7 @@ class utf_normalizer
if ($pos == $len)
{
- /**
- * ASCII strings return immediately
- */
+ // ASCII strings return immediately
return $str;
}
@@ -343,9 +198,7 @@ class utf_normalizer
if ($pos == $len)
{
- /**
- * ASCII strings return immediately
- */
+ // ASCII strings return immediately
return $str;
}
@@ -359,10 +212,6 @@ class utf_normalizer
}
- ////////////////////////////////////////////////////////////////////////////
- // Internal functions //
- ////////////////////////////////////////////////////////////////////////////
-
/**
* Recompose a UTF string
*
@@ -379,18 +228,14 @@ class utf_normalizer
{
global $utf_combining_class, $utf_canonical_comp, $utf_jamo_type, $utf_jamo_index;
- /**
- * Load some commonly-used tables
- */
+ // Load some commonly-used tables
if (!isset($utf_jamo_index, $utf_jamo_type, $utf_combining_class))
{
global $phpbb_root_path;
include($phpbb_root_path . 'includes/utf/data/utf_normalizer_common.php');
}
- /**
- * Buffer the last ASCII char before the UTF-8 stuff if applicable
- */
+ // Buffer the last ASCII char before the UTF-8 stuff if applicable
$tmp = '';
$i = $tmp_pos = $last_cc = 0;
@@ -403,96 +248,66 @@ class utf_normalizer
$buffer = array();
}
- /**
- * UTF char length array
- *
- * This array is used to determine the length of a UTF character. Be $c the
- * result of ($str[$pos] & "\xF0") --where $str is the string we're operating
- * on and $pos the position of the cursor--, if $utf_len_mask[$c] does not
- * exist, the byte is an ASCII char. Otherwise, if $utf_len_mask[$c] is greater
- * than 0, we have a the leading byte of a multibyte character whose length is
- * $utf_len_mask[$c] and if it is equal to 0, the byte is a trailing byte.
- */
+ // UTF char length array
+ // This array is used to determine the length of a UTF character.
+ // Be $c the result of ($str[$pos] & "\xF0") --where $str is the string we're operating on and $pos
+ // the position of the cursor--, if $utf_len_mask[$c] does not exist, the byte is an ASCII char.
+ // Otherwise, if $utf_len_mask[$c] is greater than 0, we have a the leading byte of a multibyte character
+ // whose length is $utf_len_mask[$c] and if it is equal to 0, the byte is a trailing byte.
$utf_len_mask = array(
- /**
- * Leading bytes masks
- */
+ // Leading bytes masks
"\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4,
-
- /**
- * Trailing bytes masks
- */
+ // Trailing bytes masks
"\x80" => 0, "\x90" => 0, "\xA0" => 0, "\xB0" => 0
);
$extra_check = array(
- "\xED"=>1, "\xEF"=>1, "\xC0"=>1, "\xC1"=>1, "\xE0"=>1, "\xF0"=>1,
- "\xF4"=>1, "\xF5"=>1, "\xF6"=>1, "\xF7"=>1, "\xF8"=>1, "\xF9"=>1,
- "\xFA"=>1, "\xFB"=>1, "\xFC"=>1, "\xFD"=>1, "\xFE"=>1, "\xFF"=>1
+ "\xED" => 1, "\xEF" => 1, "\xC0" => 1, "\xC1" => 1, "\xE0" => 1, "\xF0" => 1,
+ "\xF4" => 1, "\xF5" => 1, "\xF6" => 1, "\xF7" => 1, "\xF8" => 1, "\xF9" => 1,
+ "\xFA" => 1, "\xFB" => 1, "\xFC" => 1, "\xFD" => 1, "\xFE" => 1, "\xFF" => 1
);
$utf_validation_mask = array(
- 2 => "\xE0\xC0",
- 3 => "\xF0\xC0\xC0",
- 4 => "\xF8\xC0\xC0\xC0"
+ 2 => "\xE0\xC0",
+ 3 => "\xF0\xC0\xC0",
+ 4 => "\xF8\xC0\xC0\xC0"
);
$utf_validation_check = array(
- 2 => "\xC0\x80",
- 3 => "\xE0\x80\x80",
- 4 => "\xF0\x80\x80\x80"
+ 2 => "\xC0\x80",
+ 3 => "\xE0\x80\x80",
+ 4 => "\xF0\x80\x80\x80"
);
- ////////////////////////////////////////////////////////////////////////
- // Main loop //
- ////////////////////////////////////////////////////////////////////////
-
+ // Main loop
do
{
- ////////////////////////////////////////////////////////////////////
- // STEP 0: Capture the current char and buffer it //
- ////////////////////////////////////////////////////////////////////
-
+ // STEP 0: Capture the current char and buffer it
$c = $str[$pos];
$c_mask = $c & "\xF0";
if (isset($utf_len_mask[$c_mask]))
{
- /**
- * Byte at $pos is either a leading byte or a missplaced trailing byte
- */
+ // Byte at $pos is either a leading byte or a missplaced trailing byte
if ($utf_len = $utf_len_mask[$c_mask])
{
- /**
- * Capture the char
- */
+ // Capture the char
$buffer[++$i & 7] = $utf_char = substr($str, $pos, $utf_len);
- /**
- * Let's find out if a thorough check is needed
- */
+ // Let's find out if a thorough check is needed
if (isset($qc[$utf_char]))
{
- /**
- * If the UTF char is in the qc array then it may not be in normal
- * form. We do nothing here, the actual processing is below this
- * "if" block
- */
+ // If the UTF char is in the qc array then it may not be in normal form. We do nothing here, the actual processing is below this "if" block
}
- elseif (isset($utf_combining_class[$utf_char]))
+ else if (isset($utf_combining_class[$utf_char]))
{
if ($utf_combining_class[$utf_char] < $last_cc)
{
- /**
- * A combining character that is NOT canonically ordered
- */
+ // A combining character that is NOT canonically ordered
}
else
{
- /**
- * A combining character that IS canonically ordered, skip
- * to the next char
- */
+ // A combining character that IS canonically ordered, skip to the next char
$last_cc = $utf_combining_class[$utf_char];
$pos += $utf_len;
@@ -501,34 +316,26 @@ class utf_normalizer
}
else
{
- /**
- * At this point, $utf_char holds a UTF char that we know
- * is not a NF[K]C_QC and is not a combining character. It can
- * be a singleton, a canonical composite, a replacement char or
- * an even an ill-formed bunch of bytes. Let's find out
- */
+ // At this point, $utf_char holds a UTF char that we know is not a NF[K]C_QC and is not a combining character.
+ // It can be a singleton, a canonical composite, a replacement char or an even an ill-formed bunch of bytes. Let's find out
$last_cc = 0;
- /**
- * Check that we have the correct number of trailing bytes
- */
+ // Check that we have the correct number of trailing bytes
if (($utf_char & $utf_validation_mask[$utf_len]) != $utf_validation_check[$utf_len])
{
- /**
- * Current char isn't well-formed or legal: either one or
- * several trailing bytes are missing, or the Unicode char
- * has been encoded in a five- or six- byte sequence
- */
+ // Current char isn't well-formed or legal: either one or several trailing bytes are missing, or the Unicode char
+ // has been encoded in a five- or six- byte sequence
if ($utf_char[0] >= "\xF8")
{
if ($utf_char[0] < "\xF8")
{
$trailing_bytes = 3;
}
- elseif ($utf_char[0] < "\xFC")
+ else if ($utf_char[0] < "\xFC")
{
$trailing_bytes = 4;
}
+
if ($utf_char[0] > "\xFD")
{
$trailing_bytes = 0;
@@ -552,101 +359,80 @@ class utf_normalizer
if (isset($extra_check[$c]))
{
- switch($c)
+ switch ($c)
{
- /**
- * Note: 0xED is quite common in Korean
- */
+ // Note: 0xED is quite common in Korean
case "\xED":
if ($utf_char >= "\xED\xA0\x80")
{
- /**
- * Surrogates (U+D800..U+DFFF) are not allowed in UTF-8
- * (UTF sequence 0xEDA080..0xEDBFBF)
- */
+ // Surrogates (U+D800..U+DFFF) are not allowed in UTF-8 (UTF sequence 0xEDA080..0xEDBFBF)
$tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . UTF8_REPLACEMENT;
$pos += $utf_len;
$tmp_pos = $pos;
continue 2;
}
- break;
+ break;
- /**
- * Note: 0xEF is quite common in Japanese
- */
+ // Note: 0xEF is quite common in Japanese
case "\xEF":
if ($utf_char == "\xEF\xBF\xBE" || $utf_char == "\xEF\xBF\xBF")
{
- /**
- * U+FFFE and U+FFFF are explicitly disallowed
- * (UTF sequence 0xEFBFBE..0xEFBFBF)
- */
+ // U+FFFE and U+FFFF are explicitly disallowed (UTF sequence 0xEFBFBE..0xEFBFBF)
$tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . UTF8_REPLACEMENT;
$pos += $utf_len;
$tmp_pos = $pos;
continue 2;
}
- break;
+ break;
case "\xC0":
case "\xC1":
if ($utf_char <= "\xC1\xBF")
{
- /**
- * Overlong sequence: Unicode char U+0000..U+007F encoded as a
- * double-byte UTF char
- */
+ // Overlong sequence: Unicode char U+0000..U+007F encoded as a double-byte UTF char
$tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . UTF8_REPLACEMENT;
$pos += $utf_len;
$tmp_pos = $pos;
continue 2;
}
- break;
+ break;
case "\xE0":
if ($utf_char <= "\xE0\x9F\xBF")
{
- /**
- * Unicode char U+0000..U+07FF encoded in 3 bytes
- */
+ // Unicode char U+0000..U+07FF encoded in 3 bytes
$tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . UTF8_REPLACEMENT;
$pos += $utf_len;
$tmp_pos = $pos;
continue 2;
}
- break;
+ break;
case "\xF0":
if ($utf_char <= "\xF0\x8F\xBF\xBF")
{
- /**
- * Unicode char U+0000..U+FFFF encoded in 4 bytes
- */
+ // Unicode char U+0000..U+FFFF encoded in 4 bytes
$tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . UTF8_REPLACEMENT;
$pos += $utf_len;
$tmp_pos = $pos;
continue 2;
}
- break;
+ break;
default:
- /**
- * Five- and six- byte sequences do not need being checked for here anymore
- */
+ // Five- and six- byte sequences do not need being checked for here anymore
if ($utf_char > UTF8_MAX)
{
- /**
- * Out of the Unicode range
- */
+ // Out of the Unicode range
if ($utf_char[0] < "\xF8")
{
$trailing_bytes = 3;
}
- elseif ($utf_char[0] < "\xFC")
+ else if ($utf_char[0] < "\xFC")
{
$trailing_bytes = 4;
}
- elseif ($utf_char[0] > "\xFD")
+ else if ($utf_char[0] > "\xFD")
{
$trailing_bytes = 0;
}
@@ -660,23 +446,19 @@ class utf_normalizer
$tmp_pos = $pos;
continue 2;
}
+ break;
}
}
- /**
- * The char is a valid starter, move the cursor and go on
- */
+ // The char is a valid starter, move the cursor and go on
$pos += $utf_len;
continue;
}
}
else
{
- /**
- * A trailing byte came out of nowhere, we will advance the cursor
- * and treat the this byte and all following trailing bytes as if
- * each of them was a Unicode replacement char
- */
+ // A trailing byte came out of nowhere, we will advance the cursor and treat the this byte and all following trailing bytes as if
+ // each of them was a Unicode replacement char
$spn = strspn($str, UTF8_TRAILING_BYTES, $pos);
$tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . str_repeat(UTF8_REPLACEMENT, $spn);
@@ -686,26 +468,20 @@ class utf_normalizer
}
- ////////////////////////////////////////////////////////////////////
- // STEP 1: Decompose current char //
- ////////////////////////////////////////////////////////////////////
-
- /**
- * We have found a character that is either:
- * - in the NFC_QC/NFKC_QC list
- * - a non-starter char that is not canonically ordered
- *
- * We are going to capture the shortest UTF sequence that satisfies
- * these two conditions:
- *
- * 1 - If the sequence does not start at the begginning of the string,
- * it must begin with a starter, and that starter must not have the
- * NF[K]C_QC property equal to "MAYBE"
- *
- * 2 - If the sequence does not end at the end of the string, it must end
- * with a non-starter and be immediately followed by a starter that
- * is not on the QC list
- */
+ // STEP 1: Decompose current char
+
+ // We have found a character that is either:
+ // - in the NFC_QC/NFKC_QC list
+ // - a non-starter char that is not canonically ordered
+ //
+ // We are going to capture the shortest UTF sequence that satisfies these two conditions:
+ //
+ // 1 - If the sequence does not start at the begginning of the string, it must begin with a starter,
+ // and that starter must not have the NF[K]C_QC property equal to "MAYBE"
+ //
+ // 2 - If the sequence does not end at the end of the string, it must end with a non-starter and be
+ // immediately followed by a starter that is not on the QC list
+ //
$utf_seq = array();
$last_cc = 0;
$lpos = $pos;
@@ -715,6 +491,7 @@ class utf_normalizer
{
$_pos = 0;
$_len = strlen($decomp_map[$utf_char]);
+
do
{
$_utf_len =& $utf_len_mask[$decomp_map[$utf_char][$_pos] & "\xF0"];
@@ -730,59 +507,46 @@ class utf_normalizer
++$_pos;
}
}
- while($_pos < $_len);
+ while ($_pos < $_len);
}
else
{
- /**
- * The char is not decomposable
- */
+ // The char is not decomposable
$utf_seq = array($utf_char);
}
- ////////////////////////////////////////////////////////////////
- // STEP 2: Capture the starter //
- ////////////////////////////////////////////////////////////////
+ // STEP 2: Capture the starter
- /**
- * Check out the combining class of the first character of the UTF sequence
- */
+ // Check out the combining class of the first character of the UTF sequence
$k = 0;
if (isset($utf_combining_class[$utf_seq[0]]) || $qc[$utf_char] == UNICODE_QC_MAYBE)
{
- /**
- * Not a starter, inspect previous characters
- *
- * The last 8 characters are kept in a buffer so that we don't have
- * to capture them everytime. This is enough for all real-life strings
- * but even if it wasn't, we can capture characters in backward mode,
- * although it is slower than this method.
- *
- * In the following loop, $j starts at the previous buffered character
- * ($i - 1, because current character is at offset $i) and process them
- * in backward mode until we find a starter.
- *
- * $k is the index on each UTF character inside of our UTF sequence.
- * At this time, $utf_seq contains one or more characters numbered 0 to
- * n. $k starts at 0 and for each char we prepend we pre-decrement it
- * and for numbering
- */
+ // Not a starter, inspect previous characters
+ // The last 8 characters are kept in a buffer so that we don't have to capture them everytime.
+ // This is enough for all real-life strings but even if it wasn't, we can capture characters in backward mode,
+ // although it is slower than this method.
+ //
+ // In the following loop, $j starts at the previous buffered character ($i - 1, because current character is
+ // at offset $i) and process them in backward mode until we find a starter.
+ //
+ // $k is the index on each UTF character inside of our UTF sequence. At this time, $utf_seq contains one or more
+ // characters numbered 0 to n. $k starts at 0 and for each char we prepend we pre-decrement it and for numbering
$starter_found = 0;
$j_min = max(1, $i - 7);
- for($j = $i - 1; $j >= $j_min && $lpos > $tmp_pos; --$j)
+
+ for ($j = $i - 1; $j >= $j_min && $lpos > $tmp_pos; --$j)
{
$utf_char = $buffer[$j & 7];
$lpos -= strlen($utf_char);
if (isset($decomp_map[$utf_char]))
{
- /**
- * The char is a composite, decompose for storage
- */
+ // The char is a composite, decompose for storage
$decomp_seq = array();
$_pos = 0;
$_len = strlen($decomp_map[$utf_char]);
+
do
{
$c = $decomp_map[$utf_char][$_pos];
@@ -799,18 +563,15 @@ class utf_normalizer
++$_pos;
}
}
- while($_pos < $_len);
+ while ($_pos < $_len);
- /**
- * Prepend the UTF sequence with our decomposed sequence
- */
+ // Prepend the UTF sequence with our decomposed sequence
if (isset($decomp_seq[1]))
{
- /**
- * The char expanded into several chars
- */
- $decomp_cnt = count($decomp_seq);
- foreach($decomp_seq as $decomp_i => $decomp_char)
+ // The char expanded into several chars
+ $decomp_cnt = sizeof($decomp_seq);
+
+ foreach ($decomp_seq as $decomp_i => $decomp_char)
{
$utf_seq[$k + $decomp_i - $decomp_cnt] = $decomp_char;
}
@@ -818,9 +579,7 @@ class utf_normalizer
}
else
{
- /**
- * Decomposed to a single char, easier to prepend
- */
+ // Decomposed to a single char, easier to prepend
$utf_seq[--$k] = $decomp_seq[0];
}
}
@@ -831,9 +590,7 @@ class utf_normalizer
if (!isset($utf_combining_class[$utf_seq[$k]]))
{
- /**
- * We have found our starter
- */
+ // We have found our starter
$starter_found = 1;
break;
}
@@ -841,39 +598,28 @@ class utf_normalizer
if (!$starter_found && $lpos > $tmp_pos)
{
- /**
- * The starter was not found in the buffer, let's rewind some more
- */
+ // The starter was not found in the buffer, let's rewind some more
do
{
- /**
- * $utf_len_mask contains the masks of both leading bytes and
- * trailing bytes. If $utf_en > 0 then it's a leading byte,
- * otherwise it's a trailing byte.
- */
+ // $utf_len_mask contains the masks of both leading bytes and trailing bytes. If $utf_en > 0 then it's a leading byte, otherwise it's a trailing byte.
$c = $str[--$lpos];
$c_mask = $c & "\xF0";
if (isset($utf_len_mask[$c_mask]))
{
- /**
- * UTF byte
- */
+ // UTF byte
if ($utf_len = $utf_len_mask[$c_mask])
{
- /**
- * UTF *leading* byte
- */
+ // UTF *leading* byte
$utf_char = substr($str, $lpos, $utf_len);
if (isset($decomp_map[$utf_char]))
{
- /**
- * Decompose the character
- */
+ // Decompose the character
$decomp_seq = array();
$_pos = 0;
$_len = strlen($decomp_map[$utf_char]);
+
do
{
$c = $decomp_map[$utf_char][$_pos];
@@ -890,18 +636,14 @@ class utf_normalizer
++$_pos;
}
}
- while($_pos < $_len);
+ while ($_pos < $_len);
- /**
- * Prepend the UTF sequence with our decomposed sequence
- */
+ // Prepend the UTF sequence with our decomposed sequence
if (isset($decomp_seq[1]))
{
- /**
- * The char expanded into several chars
- */
- $decomp_cnt = count($decomp_seq);
- foreach($decomp_seq as $decomp_i => $utf_char)
+ // The char expanded into several chars
+ $decomp_cnt = sizeof($decomp_seq);
+ foreach ($decomp_seq as $decomp_i => $utf_char)
{
$utf_seq[$k + $decomp_i - $decomp_cnt] = $utf_char;
}
@@ -909,9 +651,7 @@ class utf_normalizer
}
else
{
- /**
- * Decomposed to a single char, easier to prepend
- */
+ // Decomposed to a single char, easier to prepend
$utf_seq[--$k] = $decomp_seq[0];
}
}
@@ -923,22 +663,18 @@ class utf_normalizer
}
else
{
- /**
- * ASCII char
- */
+ // ASCII char
$utf_seq[--$k] = $c;
}
}
- while($lpos > $tmp_pos);
+ while ($lpos > $tmp_pos);
}
}
- ////////////////////////////////////////////////////////////////
- // STEP 3: Capture following combining modifiers //
- ////////////////////////////////////////////////////////////////
+ // STEP 3: Capture following combining modifiers
- while($pos < $len)
+ while ($pos < $len)
{
$c_mask = $str[$pos] & "\xF0";
@@ -950,29 +686,21 @@ class utf_normalizer
}
else
{
- /**
- * A trailing byte came out of nowhere
- *
- * Trailing bytes are replaced with Unicode replacement chars,
- * we will just ignore it for now, break out of the loop
- * as if it was a starter (replacement chars ARE starters)
- * and let the next loop replace it
- */
+ // A trailing byte came out of nowhere
+ // Trailing bytes are replaced with Unicode replacement chars, we will just ignore it for now, break out of the loop
+ // as if it was a starter (replacement chars ARE starters) and let the next loop replace it
break;
}
if (isset($utf_combining_class[$utf_char]) || isset($qc[$utf_char]))
{
- /**
- * Combining character, add it to the sequence and move the cursor
- */
+ // Combining character, add it to the sequence and move the cursor
if (isset($decomp_map[$utf_char]))
{
- /**
- * Decompose the character
- */
+ // Decompose the character
$_pos = 0;
$_len = strlen($decomp_map[$utf_char]);
+
do
{
$c = $decomp_map[$utf_char][$_pos];
@@ -989,7 +717,7 @@ class utf_normalizer
++$_pos;
}
}
- while($_pos < $_len);
+ while ($_pos < $_len);
}
else
{
@@ -1000,54 +728,38 @@ class utf_normalizer
}
else
{
- /**
- * Combining class 0 and no QC, break out of the loop
- *
- * Note: we do not know if that character is valid. If
- * it's not, the next iteration will replace it
- */
+ // Combining class 0 and no QC, break out of the loop
+ // Note: we do not know if that character is valid. If it's not, the next iteration will replace it
break;
}
}
else
{
- /**
- * ASCII chars are starters
- */
+ // ASCII chars are starters
break;
}
}
- ////////////////////////////////////////////////////////////////
- // STEP 4: Sort and combine //
- ////////////////////////////////////////////////////////////////
+ // STEP 4: Sort and combine
+
+ // Here we sort...
+ $k_max = $k + sizeof($utf_seq);
- /**
- * Here we sort...
- */
- $k_max = $k + count($utf_seq);
if (!$k && $k_max == 1)
{
- /**
- * There is only one char in the UTF sequence, add it then
- * jump to the next iteration of main loop
- *
- * Note: the two commented lines below can be enabled under PHP5
- * for a very small performance gain in most cases
- */
-// if (substr_compare($str, $utf_seq[0], $lpos, $pos - $lpos))
-// {
+ // There is only one char in the UTF sequence, add it then jump to the next iteration of main loop
+ // Note: the two commented lines below can be enabled under PHP5 for a very small performance gain in most cases
+// if (substr_compare($str, $utf_seq[0], $lpos, $pos - $lpos))
+// {
$tmp .= substr($str, $tmp_pos, $lpos - $tmp_pos) . $utf_seq[0];
$tmp_pos = $pos;
-// }
+// }
continue;
}
- /**
- * ...there we combine
- */
+ // ...there we combine
if (isset($utf_combining_class[$utf_seq[$k]]))
{
$starter = $nf_seq = '';
@@ -1059,11 +771,8 @@ class utf_normalizer
}
$utf_sort = array();
- /**
- * We add an empty char at the end of the UTF char sequence.
- * It will act as a starter and trigger the sort/combine routine
- * at the end of the string without altering it
- */
+ // We add an empty char at the end of the UTF char sequence. It will act as a starter and trigger the sort/combine routine
+ // at the end of the string without altering it
$utf_seq[] = '';
do
@@ -1078,45 +787,27 @@ class utf_normalizer
{
if (empty($utf_sort))
{
- /**
- * No combining characters... check for a composite
- * of the two starters
- */
+ // No combining characters... check for a composite of the two starters
if (isset($utf_canonical_comp[$starter . $utf_char]))
{
- /**
- * Good ol' composite character
- */
+ // Good ol' composite character
$starter = $utf_canonical_comp[$starter . $utf_char];
}
- elseif (isset($utf_jamo_type[$utf_char]))
+ else if (isset($utf_jamo_type[$utf_char]))
{
- /**
- * Current char is a composable jamo
- */
- if (isset($utf_jamo_type[$starter])
- && $utf_jamo_type[$starter] == UNICODE_JAMO_L
- && $utf_jamo_type[$utf_char] == UNICODE_JAMO_V)
+ // Current char is a composable jamo
+ if (isset($utf_jamo_type[$starter]) && $utf_jamo_type[$starter] == UNICODE_JAMO_L && $utf_jamo_type[$utf_char] == UNICODE_JAMO_V)
{
- /**
- * We have a L jamo followed by a V jamo, we are going
- * to prefetch the next char to see if it's a T jamo
- */
+ // We have a L jamo followed by a V jamo, we are going to prefetch the next char to see if it's a T jamo
if (isset($utf_jamo_type[$utf_seq[$k]]) && $utf_jamo_type[$utf_seq[$k]] == UNICODE_JAMO_T)
{
- /**
- * L+V+T jamos, combine to a LVT Hangul syllable
- * ($k is incremented)
- */
+ // L+V+T jamos, combine to a LVT Hangul syllable ($k is incremented)
$cp = $utf_jamo_index[$starter] + $utf_jamo_index[$utf_char] + $utf_jamo_index[$utf_seq[$k]];
-
++$k;
}
else
{
- /**
- * L+V jamos, combine to a LV Hangul syllable
- */
+ // L+V jamos, combine to a LV Hangul syllable
$cp = $utf_jamo_index[$starter] + $utf_jamo_index[$utf_char];
}
@@ -1124,19 +815,14 @@ class utf_normalizer
}
else
{
- /**
- * Non-composable jamo, just add it to the sequence
- */
+ // Non-composable jamo, just add it to the sequence
$nf_seq .= $starter;
$starter = $utf_char;
}
}
else
{
- /**
- * No composite, just add the first starter to the sequence
- * then continue with the other one
- */
+ // No composite, just add the first starter to the sequence then continue with the other one
$nf_seq .= $starter;
$starter = $utf_char;
}
@@ -1145,44 +831,33 @@ class utf_normalizer
{
ksort($utf_sort);
- /**
- * For each class of combining characters
- */
- foreach($utf_sort as $cc => $utf_chars)
+ // For each class of combining characters
+ foreach ($utf_sort as $cc => $utf_chars)
{
$j = 0;
do
{
- /**
- * Look for a composite
- */
+ // Look for a composite
if (isset($utf_canonical_comp[$starter . $utf_chars[$j]]))
{
- /**
- * Found a composite, replace the starter
- */
+ // Found a composite, replace the starter
$starter = $utf_canonical_comp[$starter . $utf_chars[$j]];
unset($utf_sort[$cc][$j]);
}
else
{
- /**
- * No composite, all following characters in that
- * class are blocked
- */
+ // No composite, all following characters in that class are blocked
break;
}
}
- while(isset($utf_sort[$cc][++$j]));
+ while (isset($utf_sort[$cc][++$j]));
}
- /**
- * Add the starter to the normalized sequence, followed by
- * non-starters in canonical order
- */
+ // Add the starter to the normalized sequence, followed by non-starters in canonical order
$nf_seq .= $starter;
- foreach($utf_sort as $utf_chars)
+
+ foreach ($utf_sort as $utf_chars)
{
if (!empty($utf_chars))
{
@@ -1190,31 +865,25 @@ class utf_normalizer
}
}
- /**
- * Reset the array and go on
- */
+ // Reset the array and go on
$utf_sort = array();
$starter = $utf_char;
}
}
}
- while($k <= $k_max);
+ while ($k <= $k_max);
$tmp .= substr($str, $tmp_pos, $lpos - $tmp_pos) . $nf_seq;
$tmp_pos = $pos;
}
else
{
- /**
- * Only a ASCII char can make the program get here
- *
- * First we skip the current byte with ++$pos, then we quickly
- * skip following ASCII chars with strspn().
- *
- * The first two "if"'s here can be removed, with the consequences
- * of being faster on latin text (lots of ASCII) and slower on
- * multi-byte text (where the only ASCII chars are spaces and punctuation)
- */
+ // Only a ASCII char can make the program get here
+ //
+ // First we skip the current byte with ++$pos, then we quickly skip following ASCII chars with strspn().
+ //
+ // The first two "if"'s here can be removed, with the consequences of being faster on latin text (lots of ASCII) and slower on
+ // multi-byte text (where the only ASCII chars are spaces and punctuation)
if (++$pos != $len)
{
if ($str[$pos] < "\x80")
@@ -1229,37 +898,25 @@ class utf_normalizer
}
}
}
- while($pos < $len);
+ while ($pos < $len);
- /**
- * Now is time to return the string
- */
+ // Now is time to return the string
if ($tmp_pos)
{
- /**
- * If the $tmp_pos cursor is not at the beggining of the string then at least
- * one character was not in normal form. Replace $str with the fixed version
- */
+ // If the $tmp_pos cursor is not at the beggining of the string then at least one character was not in normal form. Replace $str with the fixed version
if ($tmp_pos == $len)
{
- /**
- * The $tmp_pos cursor is at the end of $str, therefore $tmp holds the
- * whole $str
- */
+ // The $tmp_pos cursor is at the end of $str, therefore $tmp holds the whole $str
return $tmp;
}
else
{
- /**
- * The rightmost chunk of $str has not been appended to $tmp yet
- */
+ // The rightmost chunk of $str has not been appended to $tmp yet
return $tmp . substr($str, $tmp_pos);
}
}
- /**
- * The string was already in normal form
- */
+ // The string was already in normal form
return $str;
}
@@ -1278,56 +935,42 @@ class utf_normalizer
{
global $utf_combining_class, $utf_canonical_decomp, $phpbb_root_path;
- /**
- * Load some commonly-used tables
- */
+ // Load some commonly-used tables
if (!isset($utf_combining_class))
{
include($phpbb_root_path . 'includes/utf/data/utf_normalizer_common.php');
}
- /**
- * UTF char length array
- */
+ // UTF char length array
$utf_len_mask = array(
- /**
- * Leading bytes masks
- */
+ // Leading bytes masks
"\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4,
-
- /**
- * Trailing bytes masks
- */
+ // Trailing bytes masks
"\x80" => 0, "\x90" => 0, "\xA0" => 0, "\xB0" => 0
);
- /**
- * Some extra checks are triggered on the first byte of a UTF sequence
- */
+ // Some extra checks are triggered on the first byte of a UTF sequence
$extra_check = array(
- "\xED"=>1, "\xEF"=>1, "\xC0"=>1, "\xC1"=>1, "\xE0"=>1, "\xF0"=>1,
- "\xF4"=>1, "\xF5"=>1, "\xF6"=>1, "\xF7"=>1, "\xF8"=>1, "\xF9"=>1,
- "\xFA"=>1, "\xFB"=>1, "\xFC"=>1, "\xFD"=>1, "\xFE"=>1, "\xFF"=>1
+ "\xED" => 1, "\xEF" => 1, "\xC0" => 1, "\xC1" => 1, "\xE0" => 1, "\xF0" => 1,
+ "\xF4" => 1, "\xF5" => 1, "\xF6" => 1, "\xF7" => 1, "\xF8" => 1, "\xF9" => 1,
+ "\xFA" => 1, "\xFB" => 1, "\xFC" => 1, "\xFD" => 1, "\xFE" => 1, "\xFF" => 1
);
- /**
- * These masks are used to check if a UTF sequence is well formed.
- * Here are the only 3 lengths we acknowledge:
- * - 2-byte: 110? ???? 10?? ????
- * - 3-byte: 1110 ???? 10?? ???? 10?? ????
- * - 4-byte: 1111 0??? 10?? ???? 10?? ???? 10?? ????
- *
- * Note that 5- and 6- byte sequences are automatically discarded
- */
+ // These masks are used to check if a UTF sequence is well formed. Here are the only 3 lengths we acknowledge:
+ // - 2-byte: 110? ???? 10?? ????
+ // - 3-byte: 1110 ???? 10?? ???? 10?? ????
+ // - 4-byte: 1111 0??? 10?? ???? 10?? ???? 10?? ????
+ // Note that 5- and 6- byte sequences are automatically discarded
$utf_validation_mask = array(
- 2 => "\xE0\xC0",
- 3 => "\xF0\xC0\xC0",
- 4 => "\xF8\xC0\xC0\xC0"
+ 2 => "\xE0\xC0",
+ 3 => "\xF0\xC0\xC0",
+ 4 => "\xF8\xC0\xC0\xC0"
);
+
$utf_validation_check = array(
- 2 => "\xC0\x80",
- 3 => "\xE0\x80\x80",
- 4 => "\xF0\x80\x80\x80"
+ 2 => "\xC0\x80",
+ 3 => "\xE0\x80\x80",
+ 4 => "\xF0\x80\x80\x80"
);
$tmp = '';
@@ -1336,43 +979,31 @@ class utf_normalizer
$utf_sort = array();
- ////////////////////////////////////////////////////////////////////////
- // Main loop //
- ////////////////////////////////////////////////////////////////////////
-
+ // Main loop
do
{
- ////////////////////////////////////////////////////////////////////
- // STEP 0: Capture the current char //
- ////////////////////////////////////////////////////////////////////
+ // STEP 0: Capture the current char
$cur_mask = $str[$pos] & "\xF0";
if (isset($utf_len_mask[$cur_mask]))
{
if ($utf_len = $utf_len_mask[$cur_mask])
{
- /**
- * Multibyte char
- */
+ // Multibyte char
$utf_char = substr($str, $pos, $utf_len);
$pos += $utf_len;
}
else
{
- /**
- * A trailing byte came out of nowhere, we will treat it and all
- * following trailing bytes as if each of them was a Unicode
- * replacement char and we will advance the cursor
- */
+ // A trailing byte came out of nowhere, we will treat it and all following trailing bytes as if each of them was a Unicode
+ // replacement char and we will advance the cursor
$spn = strspn($str, UTF8_TRAILING_BYTES, $pos);
if ($dump)
{
$tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos);
- /**
- * Dump combiners
- */
+ // Dump combiners
if (!empty($utf_sort))
{
if ($sort)
@@ -1404,21 +1035,15 @@ class utf_normalizer
}
- ////////////////////////////////////////////////////////////////////
- // STEP 1: Decide what to do with current char //
- ////////////////////////////////////////////////////////////////////
+ // STEP 1: Decide what to do with current char
- /**
- * Now, in that order:
- * - check if that character is decomposable
- * - check if that character is a non-starter
- * - check if that character requires extra checks to be performed
- */
+ // Now, in that order:
+ // - check if that character is decomposable
+ // - check if that character is a non-starter
+ // - check if that character requires extra checks to be performed
if (isset($decomp_map[$utf_char]))
{
- /**
- * Decompose the char
- */
+ // Decompose the char
$_pos = 0;
$_len = strlen($decomp_map[$utf_char]);
@@ -1434,16 +1059,12 @@ class utf_normalizer
if (isset($utf_combining_class[$_utf_char]))
{
- /**
- * The character decomposed to a non-starter, buffer it for sorting
- */
+ // The character decomposed to a non-starter, buffer it for sorting
$utf_sort[$utf_combining_class[$_utf_char]][] = $_utf_char;
if ($utf_combining_class[$_utf_char] < $last_cc)
{
- /**
- * Not canonically ordered, will require sorting
- */
+ // Not canonically ordered, will require sorting
$sort = $dump = 1;
}
else
@@ -1454,17 +1075,12 @@ class utf_normalizer
}
else
{
- /**
- * This character decomposition contains a starter,
- * dump the buffer and continue
- */
+ // This character decomposition contains a starter, dump the buffer and continue
if ($dump)
{
$tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos);
- /**
- * Dump combiners
- */
+ // Dump combiners
if (!empty($utf_sort))
{
if ($sort)
@@ -1472,7 +1088,7 @@ class utf_normalizer
ksort($utf_sort);
}
- foreach($utf_sort as $utf_chars)
+ foreach ($utf_sort as $utf_chars)
{
$tmp .= implode('', $utf_chars);
}
@@ -1493,18 +1109,14 @@ class utf_normalizer
}
else
{
- /**
- * This character decomposition contains an ASCII char,
- * which is a starter. Dump the buffer and continue
- */
+ // This character decomposition contains an ASCII char, which is a starter. Dump the buffer and continue
++$_pos;
+
if ($dump)
{
$tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos);
- /**
- * Dump combiners
- */
+ // Dump combiners
if (!empty($utf_sort))
{
if ($sort)
@@ -1512,7 +1124,7 @@ class utf_normalizer
ksort($utf_sort);
}
- foreach($utf_sort as $utf_chars)
+ foreach ($utf_sort as $utf_chars)
{
$tmp .= implode('', $utf_chars);
}
@@ -1531,18 +1143,14 @@ class utf_normalizer
$last_cc = 0;
}
}
- while($_pos < $_len);
+ while ($_pos < $_len);
}
- elseif (isset($utf_combining_class[$utf_char]))
+ else if (isset($utf_combining_class[$utf_char]))
{
- /**
- * Combining character
- */
+ // Combining character
if ($utf_combining_class[$utf_char] < $last_cc)
{
- /**
- * Not in canonical order
- */
+ // Not in canonical order
$sort = $dump = 1;
}
else
@@ -1554,24 +1162,15 @@ class utf_normalizer
}
else
{
- /**
- * Non-decomposable starter, check out if it's a Hangul syllable
- */
+ // Non-decomposable starter, check out if it's a Hangul syllable
if ($utf_char < UTF8_HANGUL_FIRST || $utf_char > UTF8_HANGUL_LAST)
{
- /**
- * Nope, regular UTF char, check that we have the correct number of trailing bytes
- */
+ // Nope, regular UTF char, check that we have the correct number of trailing bytes
if (($utf_char & $utf_validation_mask[$utf_len]) != $utf_validation_check[$utf_len])
{
- /**
- * Current char isn't well-formed or legal: either one or
- * several trailing bytes are missing, or the Unicode char
- * has been encoded in a five- or six- byte sequence.
- *
- * Move the cursor back to its original position then advance
- * it to the position it should really be at
- */
+ // Current char isn't well-formed or legal: either one or several trailing bytes are missing, or the Unicode char
+ // has been encoded in a five- or six- byte sequence.
+ // Move the cursor back to its original position then advance it to the position it should really be at
$pos -= $utf_len;
$tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos);
@@ -1579,20 +1178,16 @@ class utf_normalizer
{
ksort($utf_sort);
- foreach($utf_sort as $utf_chars)
+ foreach ($utf_sort as $utf_chars)
{
$tmp .= implode('', $utf_chars);
}
$utf_sort = array();
}
- /**
- * Add a replacement char then another replacement char for
- * every trailing byte.
- *
- * @todo I'm not entirely sure that's how we're supposed to
- * mark invalidated byte sequences, check this
- */
+ // Add a replacement char then another replacement char for every trailing byte.
+ //
+ // @todo I'm not entirely sure that's how we're supposed to mark invalidated byte sequences, check this
$spn = strspn($str, UTF8_TRAILING_BYTES, ++$pos);
$tmp .= str_repeat(UTF8_REPLACEMENT, $spn + 1);
@@ -1605,25 +1200,20 @@ class utf_normalizer
if (isset($extra_check[$utf_char[0]]))
{
- switch($utf_char[0])
+ switch ($utf_char[0])
{
- /**
- * Note: 0xED is quite common in Korean
- */
+ // Note: 0xED is quite common in Korean
case "\xED":
if ($utf_char >= "\xED\xA0\x80")
{
- /**
- * Surrogates (U+D800..U+DFFF) are not allowed in UTF-8
- * (UTF sequence 0xEDA080..0xEDBFBF)
- */
+ // Surrogates (U+D800..U+DFFF) are not allowed in UTF-8 (UTF sequence 0xEDA080..0xEDBFBF)
$tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos);
if (!empty($utf_sort))
{
ksort($utf_sort);
- foreach($utf_sort as $utf_chars)
+ foreach ($utf_sort as $utf_chars)
{
$tmp .= implode('', $utf_chars);
}
@@ -1636,25 +1226,20 @@ class utf_normalizer
$tmp_pos = $starter_pos = $pos;
continue 2;
}
- break;
+ break;
- /**
- * Note: 0xEF is quite common in Japanese
- */
+ // Note: 0xEF is quite common in Japanese
case "\xEF":
if ($utf_char == "\xEF\xBF\xBE" || $utf_char == "\xEF\xBF\xBF")
{
- /**
- * U+FFFE and U+FFFF are explicitly disallowed
- * (UTF sequence 0xEFBFBE..0xEFBFBF)
- */
+ // U+FFFE and U+FFFF are explicitly disallowed (UTF sequence 0xEFBFBE..0xEFBFBF)
$tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos);
if (!empty($utf_sort))
{
ksort($utf_sort);
- foreach($utf_sort as $utf_chars)
+ foreach ($utf_sort as $utf_chars)
{
$tmp .= implode('', $utf_chars);
}
@@ -1667,23 +1252,20 @@ class utf_normalizer
$tmp_pos = $starter_pos = $pos;
continue 2;
}
- break;
+ break;
case "\xC0":
case "\xC1":
if ($utf_char <= "\xC1\xBF")
{
- /**
- * Overlong sequence: Unicode char U+0000..U+007F encoded as a
- * double-byte UTF char
- */
+ // Overlong sequence: Unicode char U+0000..U+007F encoded as a double-byte UTF char
$tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos);
if (!empty($utf_sort))
{
ksort($utf_sort);
- foreach($utf_sort as $utf_chars)
+ foreach ($utf_sort as $utf_chars)
{
$tmp .= implode('', $utf_chars);
}
@@ -1696,21 +1278,19 @@ class utf_normalizer
$tmp_pos = $starter_pos = $pos;
continue 2;
}
- break;
+ break;
case "\xE0":
if ($utf_char <= "\xE0\x9F\xBF")
{
- /**
- * Unicode char U+0000..U+07FF encoded in 3 bytes
- */
+ // Unicode char U+0000..U+07FF encoded in 3 bytes
$tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos);
if (!empty($utf_sort))
{
ksort($utf_sort);
- foreach($utf_sort as $utf_chars)
+ foreach ($utf_sort as $utf_chars)
{
$tmp .= implode('', $utf_chars);
}
@@ -1723,21 +1303,19 @@ class utf_normalizer
$tmp_pos = $starter_pos = $pos;
continue 2;
}
- break;
+ break;
case "\xF0":
if ($utf_char <= "\xF0\x8F\xBF\xBF")
{
- /**
- * Unicode char U+0000..U+FFFF encoded in 4 bytes
- */
+ // Unicode char U+0000..U+FFFF encoded in 4 bytes
$tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos);
if (!empty($utf_sort))
{
ksort($utf_sort);
- foreach($utf_sort as $utf_chars)
+ foreach ($utf_sort as $utf_chars)
{
$tmp .= implode('', $utf_chars);
}
@@ -1750,21 +1328,19 @@ class utf_normalizer
$tmp_pos = $starter_pos = $pos;
continue 2;
}
- break;
+ break;
default:
if ($utf_char > UTF8_MAX)
{
- /**
- * Out of the Unicode range
- */
+ // Out of the Unicode range
$tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos);
if (!empty($utf_sort))
{
ksort($utf_sort);
- foreach($utf_sort as $utf_chars)
+ foreach ($utf_sort as $utf_chars)
{
$tmp .= implode('', $utf_chars);
}
@@ -1777,25 +1353,18 @@ class utf_normalizer
$tmp_pos = $starter_pos = $pos;
continue 2;
}
+ break;
}
}
}
else
{
- /**
- * Hangul syllable
- */
+ // Hangul syllable
$idx = (((ord($utf_char[0]) & 0x0F) << 12) | ((ord($utf_char[1]) & 0x3F) << 6) | (ord($utf_char[2]) & 0x3F)) - UNICODE_HANGUL_SBASE;
- /**
- * LIndex can only range from 0 to 18, therefore it cannot influence
- * the first two bytes of the L Jamo, which allows us to hardcode
- * them (based on LBase).
- *
- * The same goes for VIndex, but for TIndex there's a catch: the value
- * of the third byte could exceed 0xBF and we would have to increment
- * the second byte
- */
+ // LIndex can only range from 0 to 18, therefore it cannot influence the first two bytes of the L Jamo, which allows us to hardcode them (based on LBase).
+ //
+ // The same goes for VIndex, but for TIndex there's a catch: the value of the third byte could exceed 0xBF and we would have to increment the second byte
if ($tIndex = $idx % UNICODE_HANGUL_TCOUNT)
{
if ($tIndex < 25)
@@ -1817,24 +1386,16 @@ class utf_normalizer
$utf_char[2] = chr(0x80 + (int) ($idx / UNICODE_HANGUL_NCOUNT));
$utf_char[5] = chr(0xA1 + (int) (($idx % UNICODE_HANGUL_NCOUNT) / UNICODE_HANGUL_TCOUNT));
-
- /**
- * Just like other decompositions, the resulting Jamos must
- * be dumped to the tmp string
- */
+ // Just like other decompositions, the resulting Jamos must be dumped to the tmp string
$dump = 1;
}
- /**
- * Do we need to dump stuff to the tmp string?
- */
+ // Do we need to dump stuff to the tmp string?
if ($dump)
{
$tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos);
- /**
- * Dump combiners
- */
+ // Dump combiners
if (!empty($utf_sort))
{
if ($sort)
@@ -1842,7 +1403,7 @@ class utf_normalizer
ksort($utf_sort);
}
- foreach($utf_sort as $utf_chars)
+ foreach ($utf_sort as $utf_chars)
{
$tmp .= implode('', $utf_chars);
}
@@ -1860,16 +1421,12 @@ class utf_normalizer
}
else
{
- /**
- * ASCII char, which happens to be a starter (as any other ASCII char)
- */
+ // ASCII char, which happens to be a starter (as any other ASCII char)
if ($dump)
{
$tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos);
- /**
- * Dump combiners
- */
+ // Dump combiners
if (!empty($utf_sort))
{
if ($sort)
@@ -1877,7 +1434,7 @@ class utf_normalizer
ksort($utf_sort);
}
- foreach($utf_sort as $utf_chars)
+ foreach ($utf_sort as $utf_chars)
{
$tmp .= implode('', $utf_chars);
}
@@ -1899,18 +1456,14 @@ class utf_normalizer
$starter_pos = $pos;
}
}
- while($pos < $len);
+ while ($pos < $len);
- /**
- * Now is time to return the string
- */
+ // Now is time to return the string
if ($dump)
{
$tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos);
- /**
- * Dump combiners
- */
+ // Dump combiners
if (!empty($utf_sort))
{
if ($sort)
@@ -1918,7 +1471,7 @@ class utf_normalizer
ksort($utf_sort);
}
- foreach($utf_sort as $utf_chars)
+ foreach ($utf_sort as $utf_chars)
{
$tmp .= implode('', $utf_chars);
}
@@ -1927,34 +1480,24 @@ class utf_normalizer
return $tmp;
}
- elseif ($tmp_pos)
+ else if ($tmp_pos)
{
- /**
- * If the $tmp_pos cursor was moved then at least one character was not in
- * normal form. Replace $str with the fixed version
- */
+ // If the $tmp_pos cursor was moved then at least one character was not in normal form. Replace $str with the fixed version
if ($tmp_pos == $len)
{
- /**
- * The $tmp_pos cursor is at the end of $str, therefore $tmp holds
- * the whole $str
- */
+ // The $tmp_pos cursor is at the end of $str, therefore $tmp holds the whole $str
return $tmp;
}
else
{
- /**
- * The rightmost chunk of $str has not been appended to $tmp yet
- */
+ // The rightmost chunk of $str has not been appended to $tmp yet
return $tmp . substr($str, $tmp_pos);
}
}
- /**
- * The string was already in normal form
- */
+ // The string was already in normal form
return $str;
}
}
-} \ No newline at end of file
+?> \ No newline at end of file
diff --git a/phpBB/includes/utf/utf_tools.php b/phpBB/includes/utf/utf_tools.php
index b3c3c5ed5e..b91fd51c20 100644
--- a/phpBB/includes/utf/utf_tools.php
+++ b/phpBB/includes/utf/utf_tools.php
@@ -3,42 +3,700 @@
*
* @package phpBB3
* @version $Id$
-* @copyright (c) 2005 phpBB Group
+* @copyright (c) 2006 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
+* @todo make sure the replacements are called correctly
+* already done: strtolower, strtoupper, ucfirst, str_split, strrpos, strlen (hopefully!), strpos, substr
+* remaining: clean_username, htmlentities (no longer needed for internal data?), htmlspecialchars (using charset)
+* strspn, chr, ord
*/
/**
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
* UTF-8 tools
*
* Whenever possible, these functions will try to use PHP's built-in functions or
* extensions, otherwise they will default to custom routines.
*
-* If we go with UTF-8 in 3.2, we will also need a Unicode-aware replacement
-* to strtolower()
-*
* @package phpBB3
*/
+if (!extension_loaded('xml'))
+{
+ /**
+ * Implementation of PHP's native utf8_encode for people without XML support
+ * This function exploits some nice things that ISO-8859-1 and UTF-8 have in common
+ *
+ * @param string $str ISO-8859-1 encoded data
+ * @return string UTF-8 encoded data
+ */
+ function utf8_encode($str)
+ {
+ $out = '';
+ for ($i = 0, $len = strlen($str); $i < $len; $i++)
+ {
+ $letter = $str[$i];
+ $num = ord($letter);
+ if ($num < 0x80)
+ {
+ $out .= $letter;
+ }
+ else if ($num < 0xC0)
+ {
+ $out .= "\xC2" . $letter;
+ }
+ else
+ {
+ $out .= "\xC3" . chr($num - 64);
+ }
+ }
+ return $out;
+ }
+
+ /**
+ * Implementation of PHP's native utf8_decode for people without XML support
+ *
+ * @param string $string UTF-8 encoded data
+ * @return string ISO-8859-1 encoded data
+ */
+ function utf8_decode($str)
+ {
+ $pos = 0;
+ $len = strlen($str);
+ $ret = '';
+
+ while ($pos < $len)
+ {
+ $ord = ord($str[$pos]) & 0xF0;
+ if ($ord === 0xC0 || $ord === 0xD0)
+ {
+ $charval = ((ord($str[$pos]) & 0x1F) << 6) | (ord($str[$pos + 1]) & 0x3F);
+ $pos += 2;
+ $ret .= (($charval < 256) ? chr($charval) : '?');
+ }
+ else if ($ord === 0xE0)
+ {
+ $ret .= '?';
+ $pos += 3;
+ }
+ else if ($ord === 0xF0)
+ {
+ $ret .= '?';
+ $pos += 4;
+ }
+ else
+ {
+ $ret .= $str[$pos];
+ ++$pos;
+ }
+ }
+ return $ret;
+ }
+}
+
+// mbstring is old and has it's functions around for older versions of PHP.
+// if mbstring is not loaded, we go into native mode.
+if (extension_loaded('mbstring'))
+{
+ /**
+ * UTF-8 aware alternative to strrpos
+ * Find position of last occurrence of a char in a string
+ *
+ * Notes:
+ * - offset for mb_strrpos was added in 5.2.0, we emulate if it is lower
+ */
+ if (version_compare(phpversion(), '5.2.0', '>='))
+ {
+ /**
+ * UTF-8 aware alternative to strrpos
+ * @ignore
+ */
+ function utf8_strrpos($str, $needle, $offset = null)
+ {
+ // Emulate behaviour of strrpos rather than raising warning
+ if (empty($str))
+ {
+ return false;
+ }
+
+ return mb_strrpos($str, $search);
+ }
+ }
+ else
+ {
+ /**
+ * UTF-8 aware alternative to strrpos
+ * @ignore
+ */
+ function utf8_strrpos($str, $needle, $offset = null)
+ {
+ // offset for mb_strrpos was added in 5.2.0
+ if ($offset === false)
+ {
+ // Emulate behaviour of strrpos rather than raising warning
+ if (empty($str))
+ {
+ return false;
+ }
+
+ return mb_strrpos($str, $search);
+ }
+ else
+ {
+ if (!is_int($offset))
+ {
+ trigger_error('utf8_strrpos expects parameter 3 to be long', E_USER_WARNING);
+ return false;
+ }
+
+ $str = mb_substr($str, $offset);
+
+ if (false !== ($pos = mb_strrpos($str, $search)))
+ {
+ return $pos + $offset;
+ }
+
+ return false;
+ }
+ }
+ }
+
+ /**
+ * UTF-8 aware alternative to strpos
+ * @ignore
+ */
+ function utf8_strpos($str, $needle, $offset = null)
+ {
+ if ($offset === false)
+ {
+ return mb_strpos($str, $needle);
+ }
+ else
+ {
+ return mb_strpos($str, $needle, $offset);
+ }
+ }
+
+ /**
+ * UTF-8 aware alternative to strtolower
+ * @ignore
+ */
+ function utf8_strtolower($str)
+ {
+ return mb_strtolower($str);
+ }
+
+ /**
+ * UTF-8 aware alternative to strtoupper
+ * @ignore
+ */
+ function utf8_strtoupper($str)
+ {
+ return mb_strtoupper($str);
+ }
+
+ /**
+ * UTF-8 aware alternative to substr
+ * @ignore
+ */
+ function utf8_substr($str, $offset, $length = null)
+ {
+ if ($length === false)
+ {
+ return mb_substr($str, $offset);
+ }
+ else
+ {
+ return mb_substr($str, $offset, $length);
+ }
+ }
+
+ /**
+ * Return the length (in characters) of a UTF-8 string
+ * @ignore
+ */
+ function utf8_strlen($text)
+ {
+ return mb_strlen($text, 'utf-8');
+ }
+}
+else
+{
+ /**
+ * UTF-8 aware alternative to strrpos
+ * Find position of last occurrence of a char in a string
+ *
+ * @author Harry Fuecks
+ * @param string haystack
+ * @param string needle
+ * @param integer (optional) offset (from left)
+ * @return mixed integer position or FALSE on failure
+ */
+ function utf8_strrpos($str, $needle, $offset = null)
+ {
+ if (is_null($offset))
+ {
+ $ar = explode($needle, $str);
+
+ if (sizeof($ar) > 1)
+ {
+ // Pop off the end of the string where the last match was made
+ array_pop($ar);
+ $str = join($needle, $ar);
+
+ return utf8_strlen($str);
+ }
+ return false;
+ }
+ else
+ {
+ if (!is_int($offset))
+ {
+ trigger_error('utf8_strrpos expects parameter 3 to be long', E_USER_WARNING);
+ return false;
+ }
+
+ $str = utf8_substr($str, $offset);
+
+ if (false !== ($pos = utf8_strrpos($str, $needle)))
+ {
+ return $pos + $offset;
+ }
+
+ return false;
+ }
+ }
+
+ /**
+ * UTF-8 aware alternative to strpos
+ * Find position of first occurrence of a string
+ *
+ * @author Harry Fuecks
+ * @param string haystack
+ * @param string needle
+ * @param integer offset in characters (from left)
+ * @return mixed integer position or FALSE on failure
+ */
+ function utf8_strpos($str, $needle, $offset = null)
+ {
+ if (is_null($offset))
+ {
+ $ar = explode($needle, $str);
+ if (sizeof($ar) > 1)
+ {
+ return utf8_strlen($ar[0]);
+ }
+ return false;
+ }
+ else
+ {
+ if (!is_int($offset))
+ {
+ trigger_error('utf8_strpos: Offset must be an integer', E_USER_ERROR);
+ return false;
+ }
+
+ $str = utf8_substr($str, $offset);
+
+ if (false !== ($pos = utf8_strpos($str, $needle)))
+ {
+ return $pos + $offset;
+ }
+
+ return false;
+ }
+ }
+
+ $UTF8_UPPER_TO_LOWER = array(
+ "\x41" => "\x61", "\x42" => "\x62", "\x43" => "\x63", "\x44" => "\x64",
+ "\x45" => "\x65", "\x46" => "\x66", "\x47" => "\x67", "\x48" => "\x68",
+ "\x49" => "\x69", "\x4A" => "\x6A", "\x4B" => "\x6B", "\x4C" => "\x6C",
+ "\x4D" => "\x6D", "\x4E" => "\x6E", "\x4F" => "\x6F", "\x50" => "\x70",
+ "\x51" => "\x71", "\x52" => "\x72", "\x53" => "\x73", "\x54" => "\x74",
+ "\x55" => "\x75", "\x56" => "\x76", "\x57" => "\x77", "\x58" => "\x78",
+ "\x59" => "\x79", "\x5A" => "\x7A", "\xC3\x80" => "\xC3\xA0", "\xC3\x81" => "\xC3\xA1",
+ "\xC3\x82" => "\xC3\xA2", "\xC3\x83" => "\xC3\xA3", "\xC3\x84" => "\xC3\xA4", "\xC3\x85" => "\xC3\xA5",
+ "\xC3\x86" => "\xC3\xA6", "\xC3\x87" => "\xC3\xA7", "\xC3\x88" => "\xC3\xA8", "\xC3\x89" => "\xC3\xA9",
+ "\xC3\x8A" => "\xC3\xAA", "\xC3\x8B" => "\xC3\xAB", "\xC3\x8C" => "\xC3\xAC", "\xC3\x8D" => "\xC3\xAD",
+ "\xC3\x8E" => "\xC3\xAE", "\xC3\x8F" => "\xC3\xAF", "\xC3\x90" => "\xC3\xB0", "\xC3\x91" => "\xC3\xB1",
+ "\xC3\x92" => "\xC3\xB2", "\xC3\x93" => "\xC3\xB3", "\xC3\x94" => "\xC3\xB4", "\xC3\x95" => "\xC3\xB5",
+ "\xC3\x96" => "\xC3\xB6", "\xC3\x98" => "\xC3\xB8", "\xC3\x99" => "\xC3\xB9", "\xC3\x9A" => "\xC3\xBA",
+ "\xC3\x9B" => "\xC3\xBB", "\xC3\x9C" => "\xC3\xBC", "\xC3\x9D" => "\xC3\xBD", "\xC3\x9E" => "\xC3\xBE",
+ "\xC4\x80" => "\xC4\x81", "\xC4\x82" => "\xC4\x83", "\xC4\x84" => "\xC4\x85", "\xC4\x86" => "\xC4\x87",
+ "\xC4\x88" => "\xC4\x89", "\xC4\x8A" => "\xC4\x8B", "\xC4\x8C" => "\xC4\x8D", "\xC4\x8E" => "\xC4\x8F",
+ "\xC4\x90" => "\xC4\x91", "\xC4\x92" => "\xC4\x93", "\xC4\x96" => "\xC4\x97", "\xC4\x98" => "\xC4\x99",
+ "\xC4\x9A" => "\xC4\x9B", "\xC4\x9C" => "\xC4\x9D", "\xC4\x9E" => "\xC4\x9F", "\xC4\xA0" => "\xC4\xA1",
+ "\xC4\xA2" => "\xC4\xA3", "\xC4\xA4" => "\xC4\xA5", "\xC4\xA6" => "\xC4\xA7", "\xC4\xA8" => "\xC4\xA9",
+ "\xC4\xAA" => "\xC4\xAB", "\xC4\xAE" => "\xC4\xAF", "\xC4\xB4" => "\xC4\xB5", "\xC4\xB6" => "\xC4\xB7",
+ "\xC4\xB9" => "\xC4\xBA", "\xC4\xBB" => "\xC4\xBC", "\xC4\xBD" => "\xC4\xBE", "\xC5\x81" => "\xC5\x82",
+ "\xC5\x83" => "\xC5\x84", "\xC5\x85" => "\xC5\x86", "\xC5\x87" => "\xC5\x88", "\xC5\x8A" => "\xC5\x8B",
+ "\xC5\x8C" => "\xC5\x8D", "\xC5\x90" => "\xC5\x91", "\xC5\x94" => "\xC5\x95", "\xC5\x96" => "\xC5\x97",
+ "\xC5\x98" => "\xC5\x99", "\xC5\x9A" => "\xC5\x9B", "\xC5\x9C" => "\xC5\x9D", "\xC5\x9E" => "\xC5\x9F",
+ "\xC5\xA0" => "\xC5\xA1", "\xC5\xA2" => "\xC5\xA3", "\xC5\xA4" => "\xC5\xA5", "\xC5\xA6" => "\xC5\xA7",
+ "\xC5\xA8" => "\xC5\xA9", "\xC5\xAA" => "\xC5\xAB", "\xC5\xAC" => "\xC5\xAD", "\xC5\xAE" => "\xC5\xAF",
+ "\xC5\xB0" => "\xC5\xB1", "\xC5\xB2" => "\xC5\xB3", "\xC5\xB4" => "\xC5\xB5", "\xC5\xB6" => "\xC5\xB7",
+ "\xC5\xB8" => "\xC3\xBF", "\xC5\xB9" => "\xC5\xBA", "\xC5\xBB" => "\xC5\xBC", "\xC5\xBD" => "\xC5\xBE",
+ "\xC6\xA0" => "\xC6\xA1", "\xC6\xAF" => "\xC6\xB0", "\xC8\x98" => "\xC8\x99", "\xC8\x9A" => "\xC8\x9B",
+ "\xCE\x86" => "\xCE\xAC", "\xCE\x88" => "\xCE\xAD", "\xCE\x89" => "\xCE\xAE", "\xCE\x8A" => "\xCE\xAF",
+ "\xCE\x8C" => "\xCF\x8C", "\xCE\x8E" => "\xCF\x8D", "\xCE\x8F" => "\xCF\x8E", "\xCE\x91" => "\xCE\xB1",
+ "\xCE\x92" => "\xCE\xB2", "\xCE\x93" => "\xCE\xB3", "\xCE\x94" => "\xCE\xB4", "\xCE\x95" => "\xCE\xB5",
+ "\xCE\x96" => "\xCE\xB6", "\xCE\x97" => "\xCE\xB7", "\xCE\x98" => "\xCE\xB8", "\xCE\x99" => "\xCE\xB9",
+ "\xCE\x9A" => "\xCE\xBA", "\xCE\x9B" => "\xCE\xBB", "\xCE\x9C" => "\xCE\xBC", "\xCE\x9D" => "\xCE\xBD",
+ "\xCE\x9E" => "\xCE\xBE", "\xCE\x9F" => "\xCE\xBF", "\xCE\xA0" => "\xCF\x80", "\xCE\xA1" => "\xCF\x81",
+ "\xCE\xA3" => "\xCF\x83", "\xCE\xA4" => "\xCF\x84", "\xCE\xA5" => "\xCF\x85", "\xCE\xA6" => "\xCF\x86",
+ "\xCE\xA7" => "\xCF\x87", "\xCE\xA8" => "\xCF\x88", "\xCE\xA9" => "\xCF\x89", "\xCE\xAA" => "\xCF\x8A",
+ "\xCE\xAB" => "\xCF\x8B", "\xD0\x81" => "\xD1\x91", "\xD0\x82" => "\xD1\x92", "\xD0\x83" => "\xD1\x93",
+ "\xD0\x84" => "\xD1\x94", "\xD0\x85" => "\xD1\x95", "\xD0\x86" => "\xD1\x96", "\xD0\x87" => "\xD1\x97",
+ "\xD0\x88" => "\xD1\x98", "\xD0\x89" => "\xD1\x99", "\xD0\x8A" => "\xD1\x9A", "\xD0\x8B" => "\xD1\x9B",
+ "\xD0\x8C" => "\xD1\x9C", "\xD0\x8E" => "\xD1\x9E", "\xD0\x8F" => "\xD1\x9F", "\xD0\x90" => "\xD0\xB0",
+ "\xD0\x91" => "\xD0\xB1", "\xD0\x92" => "\xD0\xB2", "\xD0\x93" => "\xD0\xB3", "\xD0\x94" => "\xD0\xB4",
+ "\xD0\x95" => "\xD0\xB5", "\xD0\x96" => "\xD0\xB6", "\xD0\x97" => "\xD0\xB7", "\xD0\x98" => "\xD0\xB8",
+ "\xD0\x99" => "\xD0\xB9", "\xD0\x9A" => "\xD0\xBA", "\xD0\x9B" => "\xD0\xBB", "\xD0\x9C" => "\xD0\xBC",
+ "\xD0\x9D" => "\xD0\xBD", "\xD0\x9E" => "\xD0\xBE", "\xD0\x9F" => "\xD0\xBF", "\xD0\xA0" => "\xD1\x80",
+ "\xD0\xA1" => "\xD1\x81", "\xD0\xA2" => "\xD1\x82", "\xD0\xA3" => "\xD1\x83", "\xD0\xA4" => "\xD1\x84",
+ "\xD0\xA5" => "\xD1\x85", "\xD0\xA6" => "\xD1\x86", "\xD0\xA7" => "\xD1\x87", "\xD0\xA8" => "\xD1\x88",
+ "\xD0\xA9" => "\xD1\x89", "\xD0\xAA" => "\xD1\x8A", "\xD0\xAB" => "\xD1\x8B", "\xD0\xAC" => "\xD1\x8C",
+ "\xD0\xAD" => "\xD1\x8D", "\xD0\xAE" => "\xD1\x8E", "\xD0\xAF" => "\xD1\x8F", "\xD2\x90" => "\xD2\x91",
+ "\xE1\xB8\x82" => "\xE1\xB8\x83", "\xE1\xB8\x8A" => "\xE1\xB8\x8B", "\xE1\xB8\x9E" => "\xE1\xB8\x9F", "\xE1\xB9\x80" => "\xE1\xB9\x81",
+ "\xE1\xB9\x96" => "\xE1\xB9\x97", "\xE1\xB9\xA0" => "\xE1\xB9\xA1", "\xE1\xB9\xAA" => "\xE1\xB9\xAB", "\xE1\xBA\x80" => "\xE1\xBA\x81",
+ "\xE1\xBA\x82" => "\xE1\xBA\x83", "\xE1\xBA\x84" => "\xE1\xBA\x85", "\xE1\xBB\xB2" => "\xE1\xBB\xB3"
+ );
+
+ $UTF8_LOWER_TO_UPPER = array(
+ "\x61" => "\x41", "\x62" => "\x42", "\x63" => "\x43", "\x64" => "\x44",
+ "\x65" => "\x45", "\x66" => "\x46", "\x67" => "\x47", "\x68" => "\x48",
+ "\x69" => "\x49", "\x6A" => "\x4A", "\x6B" => "\x4B", "\x6C" => "\x4C",
+ "\x6D" => "\x4D", "\x6E" => "\x4E", "\x6F" => "\x4F", "\x70" => "\x50",
+ "\x71" => "\x51", "\x72" => "\x52", "\x73" => "\x53", "\x74" => "\x54",
+ "\x75" => "\x55", "\x76" => "\x56", "\x77" => "\x57", "\x78" => "\x58",
+ "\x79" => "\x59", "\x7A" => "\x5A", "\xC3\xA0" => "\xC3\x80", "\xC3\xA1" => "\xC3\x81",
+ "\xC3\xA2" => "\xC3\x82", "\xC3\xA3" => "\xC3\x83", "\xC3\xA4" => "\xC3\x84", "\xC3\xA5" => "\xC3\x85",
+ "\xC3\xA6" => "\xC3\x86", "\xC3\xA7" => "\xC3\x87", "\xC3\xA8" => "\xC3\x88", "\xC3\xA9" => "\xC3\x89",
+ "\xC3\xAA" => "\xC3\x8A", "\xC3\xAB" => "\xC3\x8B", "\xC3\xAC" => "\xC3\x8C", "\xC3\xAD" => "\xC3\x8D",
+ "\xC3\xAE" => "\xC3\x8E", "\xC3\xAF" => "\xC3\x8F", "\xC3\xB0" => "\xC3\x90", "\xC3\xB1" => "\xC3\x91",
+ "\xC3\xB2" => "\xC3\x92", "\xC3\xB3" => "\xC3\x93", "\xC3\xB4" => "\xC3\x94", "\xC3\xB5" => "\xC3\x95",
+ "\xC3\xB6" => "\xC3\x96", "\xC3\xB8" => "\xC3\x98", "\xC3\xB9" => "\xC3\x99", "\xC3\xBA" => "\xC3\x9A",
+ "\xC3\xBB" => "\xC3\x9B", "\xC3\xBC" => "\xC3\x9C", "\xC3\xBD" => "\xC3\x9D", "\xC3\xBE" => "\xC3\x9E",
+ "\xC3\xBF" => "\xC5\xB8", "\xC4\x81" => "\xC4\x80", "\xC4\x83" => "\xC4\x82", "\xC4\x85" => "\xC4\x84",
+ "\xC4\x87" => "\xC4\x86", "\xC4\x89" => "\xC4\x88", "\xC4\x8B" => "\xC4\x8A", "\xC4\x8D" => "\xC4\x8C",
+ "\xC4\x8F" => "\xC4\x8E", "\xC4\x91" => "\xC4\x90", "\xC4\x93" => "\xC4\x92", "\xC4\x97" => "\xC4\x96",
+ "\xC4\x99" => "\xC4\x98", "\xC4\x9B" => "\xC4\x9A", "\xC4\x9D" => "\xC4\x9C", "\xC4\x9F" => "\xC4\x9E",
+ "\xC4\xA1" => "\xC4\xA0", "\xC4\xA3" => "\xC4\xA2", "\xC4\xA5" => "\xC4\xA4", "\xC4\xA7" => "\xC4\xA6",
+ "\xC4\xA9" => "\xC4\xA8", "\xC4\xAB" => "\xC4\xAA", "\xC4\xAF" => "\xC4\xAE", "\xC4\xB5" => "\xC4\xB4",
+ "\xC4\xB7" => "\xC4\xB6", "\xC4\xBA" => "\xC4\xB9", "\xC4\xBC" => "\xC4\xBB", "\xC4\xBE" => "\xC4\xBD",
+ "\xC5\x82" => "\xC5\x81", "\xC5\x84" => "\xC5\x83", "\xC5\x86" => "\xC5\x85", "\xC5\x88" => "\xC5\x87",
+ "\xC5\x8B" => "\xC5\x8A", "\xC5\x8D" => "\xC5\x8C", "\xC5\x91" => "\xC5\x90", "\xC5\x95" => "\xC5\x94",
+ "\xC5\x97" => "\xC5\x96", "\xC5\x99" => "\xC5\x98", "\xC5\x9B" => "\xC5\x9A", "\xC5\x9D" => "\xC5\x9C",
+ "\xC5\x9F" => "\xC5\x9E", "\xC5\xA1" => "\xC5\xA0", "\xC5\xA3" => "\xC5\xA2", "\xC5\xA5" => "\xC5\xA4",
+ "\xC5\xA7" => "\xC5\xA6", "\xC5\xA9" => "\xC5\xA8", "\xC5\xAB" => "\xC5\xAA", "\xC5\xAD" => "\xC5\xAC",
+ "\xC5\xAF" => "\xC5\xAE", "\xC5\xB1" => "\xC5\xB0", "\xC5\xB3" => "\xC5\xB2", "\xC5\xB5" => "\xC5\xB4",
+ "\xC5\xB7" => "\xC5\xB6", "\xC5\xBA" => "\xC5\xB9", "\xC5\xBC" => "\xC5\xBB", "\xC5\xBE" => "\xC5\xBD",
+ "\xC6\xA1" => "\xC6\xA0", "\xC6\xB0" => "\xC6\xAF", "\xC8\x99" => "\xC8\x98", "\xC8\x9B" => "\xC8\x9A",
+ "\xCE\xAC" => "\xCE\x86", "\xCE\xAD" => "\xCE\x88", "\xCE\xAE" => "\xCE\x89", "\xCE\xAF" => "\xCE\x8A",
+ "\xCE\xB1" => "\xCE\x91", "\xCE\xB2" => "\xCE\x92", "\xCE\xB3" => "\xCE\x93", "\xCE\xB4" => "\xCE\x94",
+ "\xCE\xB5" => "\xCE\x95", "\xCE\xB6" => "\xCE\x96", "\xCE\xB7" => "\xCE\x97", "\xCE\xB8" => "\xCE\x98",
+ "\xCE\xB9" => "\xCE\x99", "\xCE\xBA" => "\xCE\x9A", "\xCE\xBB" => "\xCE\x9B", "\xCE\xBC" => "\xCE\x9C",
+ "\xCE\xBD" => "\xCE\x9D", "\xCE\xBE" => "\xCE\x9E", "\xCE\xBF" => "\xCE\x9F", "\xCF\x80" => "\xCE\xA0",
+ "\xCF\x81" => "\xCE\xA1", "\xCF\x83" => "\xCE\xA3", "\xCF\x84" => "\xCE\xA4", "\xCF\x85" => "\xCE\xA5",
+ "\xCF\x86" => "\xCE\xA6", "\xCF\x87" => "\xCE\xA7", "\xCF\x88" => "\xCE\xA8", "\xCF\x89" => "\xCE\xA9",
+ "\xCF\x8A" => "\xCE\xAA", "\xCF\x8B" => "\xCE\xAB", "\xCF\x8C" => "\xCE\x8C", "\xCF\x8D" => "\xCE\x8E",
+ "\xCF\x8E" => "\xCE\x8F", "\xD0\xB0" => "\xD0\x90", "\xD0\xB1" => "\xD0\x91", "\xD0\xB2" => "\xD0\x92",
+ "\xD0\xB3" => "\xD0\x93", "\xD0\xB4" => "\xD0\x94", "\xD0\xB5" => "\xD0\x95", "\xD0\xB6" => "\xD0\x96",
+ "\xD0\xB7" => "\xD0\x97", "\xD0\xB8" => "\xD0\x98", "\xD0\xB9" => "\xD0\x99", "\xD0\xBA" => "\xD0\x9A",
+ "\xD0\xBB" => "\xD0\x9B", "\xD0\xBC" => "\xD0\x9C", "\xD0\xBD" => "\xD0\x9D", "\xD0\xBE" => "\xD0\x9E",
+ "\xD0\xBF" => "\xD0\x9F", "\xD1\x80" => "\xD0\xA0", "\xD1\x81" => "\xD0\xA1", "\xD1\x82" => "\xD0\xA2",
+ "\xD1\x83" => "\xD0\xA3", "\xD1\x84" => "\xD0\xA4", "\xD1\x85" => "\xD0\xA5", "\xD1\x86" => "\xD0\xA6",
+ "\xD1\x87" => "\xD0\xA7", "\xD1\x88" => "\xD0\xA8", "\xD1\x89" => "\xD0\xA9", "\xD1\x8A" => "\xD0\xAA",
+ "\xD1\x8B" => "\xD0\xAB", "\xD1\x8C" => "\xD0\xAC", "\xD1\x8D" => "\xD0\xAD", "\xD1\x8E" => "\xD0\xAE",
+ "\xD1\x8F" => "\xD0\xAF", "\xD1\x91" => "\xD0\x81", "\xD1\x92" => "\xD0\x82", "\xD1\x93" => "\xD0\x83",
+ "\xD1\x94" => "\xD0\x84", "\xD1\x95" => "\xD0\x85", "\xD1\x96" => "\xD0\x86", "\xD1\x97" => "\xD0\x87",
+ "\xD1\x98" => "\xD0\x88", "\xD1\x99" => "\xD0\x89", "\xD1\x9A" => "\xD0\x8A", "\xD1\x9B" => "\xD0\x8B",
+ "\xD1\x9C" => "\xD0\x8C", "\xD1\x9E" => "\xD0\x8E", "\xD1\x9F" => "\xD0\x8F", "\xD2\x91" => "\xD2\x90",
+ "\xE1\xB8\x83" => "\xE1\xB8\x82", "\xE1\xB8\x8B" => "\xE1\xB8\x8A", "\xE1\xB8\x9F" => "\xE1\xB8\x9E", "\xE1\xB9\x81" => "\xE1\xB9\x80",
+ "\xE1\xB9\x97" => "\xE1\xB9\x96", "\xE1\xB9\xA1" => "\xE1\xB9\xA0", "\xE1\xB9\xAB" => "\xE1\xB9\xAA", "\xE1\xBA\x81" => "\xE1\xBA\x80",
+ "\xE1\xBA\x83" => "\xE1\xBA\x82", "\xE1\xBA\x85" => "\xE1\xBA\x84", "\xE1\xBB\xB3" => "\xE1\xBB\xB2"
+ );
+
+ /**
+ * UTF-8 aware alternative to strtolower
+ * Make a string lowercase
+ * Note: The concept of a characters "case" only exists is some alphabets
+ * such as Latin, Greek, Cyrillic, Armenian and archaic Georgian - it does
+ * not exist in the Chinese alphabet, for example. See Unicode Standard
+ * Annex #21: Case Mappings
+ *
+ * @param string
+ * @return string string in lowercase
+ */
+ function utf8_strtolower($string)
+ {
+ global $UTF8_UPPER_TO_LOWER;
+
+ return strtr($string, $UTF8_UPPER_TO_LOWER);
+ }
+
+ /**
+ * UTF-8 aware alternative to strtoupper
+ * Make a string uppercase
+ * Note: The concept of a characters "case" only exists is some alphabets
+ * such as Latin, Greek, Cyrillic, Armenian and archaic Georgian - it does
+ * not exist in the Chinese alphabet, for example. See Unicode Standard
+ * Annex #21: Case Mappings
+ *
+ * @param string
+ * @return string string in uppercase
+ */
+ function utf8_strtoupper($string)
+ {
+ global $UTF8_LOWER_TO_UPPER;
+
+ return strtr($string, $UTF8_LOWER_TO_UPPER);
+ }
+
+ /**
+ * UTF-8 aware alternative to substr
+ * Return part of a string given character offset (and optionally length)
+ *
+ * Note arguments: comparied to substr - if offset or length are
+ * not integers, this version will not complain but rather massages them
+ * into an integer.
+ *
+ * Note on returned values: substr documentation states false can be
+ * returned in some cases (e.g. offset > string length)
+ * mb_substr never returns false, it will return an empty string instead.
+ * This adopts the mb_substr approach
+ *
+ * Note on implementation: PCRE only supports repetitions of less than
+ * 65536, in order to accept up to MAXINT values for offset and length,
+ * we'll repeat a group of 65535 characters when needed.
+ *
+ * Note on implementation: calculating the number of characters in the
+ * string is a relatively expensive operation, so we only carry it out when
+ * necessary. It isn't necessary for +ve offsets and no specified length
+ *
+ * @author Chris Smith<chris@jalakai.co.uk>
+ * @param string
+ * @param integer number of UTF-8 characters offset (from left)
+ * @param integer (optional) length in UTF-8 characters from offset
+ * @return mixed string or FALSE if failure
+ */
+ function utf8_substr($str, $offset, $length = NULL)
+ {
+ // generates E_NOTICE
+ // for PHP4 objects, but not PHP5 objects
+ $str = (string) $str;
+ $offset = (int) $offset;
+ if (!is_null($length))
+ {
+ $length = (int) $length;
+ }
+
+ // handle trivial cases
+ if ($length === 0 || ($offset < 0 && $length < 0 && $length < $offset))
+ {
+ return '';
+ }
+
+ // normalise negative offsets (we could use a tail
+ // anchored pattern, but they are horribly slow!)
+ if ($offset < 0)
+ {
+ // see notes
+ $strlen = utf8_strlen($str);
+ $offset = $strlen + $offset;
+ if ($offset < 0)
+ {
+ $offset = 0;
+ }
+ }
+
+ $op = '';
+ $lp = '';
+
+ // establish a pattern for offset, a
+ // non-captured group equal in length to offset
+ if ($offset > 0)
+ {
+ $ox = (int) ($offset / 65535);
+ $oy = $offset % 65535;
+
+ if ($ox)
+ {
+ $op = '(?:.{65535}){' . $ox . '}';
+ }
+
+ $op = '^(?:' . $op . '.{' . $oy . '})';
+ }
+ else
+ {
+ // offset == 0; just anchor the pattern
+ $op = '^';
+ }
+
+ // establish a pattern for length
+ if (is_null($length))
+ {
+ // the rest of the string
+ $lp = '(.*)$';
+ }
+ else
+ {
+ if (!isset($strlen))
+ {
+ // see notes
+ $strlen = utf8_strlen($str);
+ }
+
+ // another trivial case
+ if ($offset > $strlen)
+ {
+ return '';
+ }
+
+ if ($length > 0)
+ {
+ // reduce any length that would
+ // go passed the end of the string
+ $length = min($strlen - $offset, $length);
+
+ $lx = (int) ($length / 65535);
+ $ly = $length % 65535;
+
+ // negative length requires a captured group
+ // of length characters
+ if ($lx)
+ {
+ $lp = '(?:.{65535}){' . $lx . '}';
+ }
+ $lp = '(' . $lp . '.{'. $ly . '})';
+ }
+ else if ($length < 0)
+ {
+ if ($length < ($offset - $strlen))
+ {
+ return '';
+ }
+
+ $lx = (int)((-$length) / 65535);
+ $ly = (-$length) % 65535;
+
+ // negative length requires ... capture everything
+ // except a group of -length characters
+ // anchored at the tail-end of the string
+ if ($lx)
+ {
+ $lp = '(?:.{65535}){' . $lx . '}';
+ }
+ $lp = '(.*)(?:' . $lp . '.{' . $ly . '})$';
+ }
+ }
+
+ if (!preg_match('#' . $op . $lp . '#us', $str, $match))
+ {
+ return '';
+ }
+
+ return $match[1];
+ }
+
+ /**
+ * Return the length (in characters) of a UTF-8 string
+ *
+ * @param string $text UTF-8 string
+ * @return integer Length (in chars) of given string
+ */
+ function utf8_strlen($text)
+ {
+ // Since utf8_decode is replacing multibyte characters to ? strlen works fine
+ return strlen(utf8_decode($text));
+ }
+}
+
/**
-* Return the length (in characters) of a UTF-8 string
-*
-* @param string $text UTF-8 string
-* @return integer Length (in chars) of given string
+* UTF-8 aware alternative to str_split
+* Convert a string to an array
+*
+* @author Harry Fuecks
+* @param string UTF-8 encoded
+* @param int number to characters to split string by
+* @return string characters in string reverses
*/
-function utf8_strlen($text)
+function utf8_str_split($str, $split_len = 1)
{
- if (function_exists('iconv_strlen'))
+ if (!preg_match('/^[0-9]+$/', $split_len) || $split_len < 1)
{
- return iconv_strlen($text, 'utf-8');
+ return false;
}
- if (function_exists('mb_strlen'))
+ $len = utf8_strlen($str);
+ if ($len <= $split_len)
{
- return mb_strlen($text, 'utf-8');
+ return array($str);
+ }
+
+ preg_match_all('/.{' . $split_len . '}|[^\x00]{1,' . $split_len . '}$/us', $str, $ar);
+ return $ar[0];
+}
+
+/**
+* UTF-8 aware alternative to strcspn
+* Find length of initial segment not matching mask
+*
+* @author Harry Fuecks
+* @param string
+* @return int
+*/
+function utf8_strspn($str, $mask, $start = null, $length = null)
+{
+ $mask = preg_replace('!([\\\\\\-\\]\\[/^])!', '\\\${1}', $mask);
+
+ if ($start !== null || $length !== null)
+ {
+ $str = utf8_substr($str, $start, $length);
}
- return strlen(utf8_decode($text));
+ preg_match('/^[' . $mask . ']+/u', $str, $matches);
+
+ if (isset($matches[0]))
+ {
+ return utf8_strlen($matches[0]);
+ }
+
+ return 0;
+}
+
+/**
+* UTF-8 aware alternative to ucfirst
+* Make a string's first character uppercase
+*
+* @author Harry Fuecks
+* @param string
+* @return string with first character as upper case (if applicable)
+*/
+function utf8_ucfirst($str)
+{
+ switch (utf8_strlen($str))
+ {
+ case 0:
+ return '';
+ break;
+
+ case 1:
+ return utf8_strtoupper($str);
+ break;
+
+ default:
+ preg_match('/^(.{1})(.*)$/us', $str, $matches);
+ return utf8_strtoupper($matches[1]) . $matches[2];
+ break;
+ }
}
/**
@@ -47,7 +705,7 @@ function utf8_strlen($text)
* If the encoding is not supported, the string is returned as-is
*
* @param string $string Original string
-* @param string $encoding Original encoding
+* @param string $encoding Original encoding (lowered)
* @return string The string, encoded in UTF-8
*/
function utf8_recode($string, $encoding)
@@ -59,17 +717,13 @@ function utf8_recode($string, $encoding)
return $string;
}
- /**
- * PHP has a built-in function for encoding from iso-8859-1, let's use that
- */
+ // start with something simple
if ($encoding == 'iso-8859-1')
{
return utf8_encode($string);
}
- /**
- * First, try iconv()
- */
+ // First, try iconv()
if (function_exists('iconv'))
{
$ret = @iconv($encoding, 'utf-8', $string);
@@ -80,9 +734,7 @@ function utf8_recode($string, $encoding)
}
}
- /**
- * Try the mb_string extension
- */
+ // Try the mb_string extension
if (function_exists('mb_convert_encoding'))
{
$ret = @mb_convert_encoding($string, 'utf-8', $encoding);
@@ -93,9 +745,7 @@ function utf8_recode($string, $encoding)
}
}
- /**
- * Try the recode extension
- */
+ // Try the recode extension
if (function_exists('recode_string'))
{
$ret = @recode_string($encoding . '..utf-8', $string);
@@ -106,25 +756,21 @@ function utf8_recode($string, $encoding)
}
}
- /**
- * If nothing works, check if we have a custom transcoder available
- */
+ // If nothing works, check if we have a custom transcoder available
if (!preg_match('#^[a-z0-9\\-]+$#', $encoding))
{
- /**
- * Make sure the encoding name is alphanumeric, we don't want it
- * to be abused into loading arbitrary files
- */
- trigger_error('Unknown encoding: ' . $encoding);
+ // Make sure the encoding name is alphanumeric, we don't want it to be abused into loading arbitrary files
+ trigger_error('Unknown encoding: ' . $encoding, E_USER_ERROR);
}
global $phpbb_root_path;
+
if (!file_exists($phpbb_root_path . 'includes/utf/data/'))
{
return $string;
}
- die('Finish me!! '.basename(__FILE__).' at line '.__LINE__);
+ die('Finish me!! ' . basename(__FILE__) . ' at line ' . __LINE__);
}
/**
@@ -135,7 +781,7 @@ function utf8_recode($string, $encoding)
*/
function utf8_encode_ncr($text)
{
- return preg_replace_callback('#[\\xC2-\\xF4][\\x80-\\xBF]+#', 'utf8_encode_ncr_callback', $text);
+ return preg_replace_callback('#[\\xC2-\\xF4][\\x80-\\xBF]{1,3}#', 'utf8_encode_ncr_callback', $text);
}
/**
@@ -148,23 +794,64 @@ function utf8_encode_ncr($text)
*/
function utf8_encode_ncr_callback($m)
{
- switch (strlen($m[0]))
+ return '&#' . utf8_ord($m[0]) . ';';
+}
+
+/**
+* Enter description here...
+*
+* @param string $chr UTF-8 char
+* @return integer UNICODE code point
+*/
+function utf8_ord($chr)
+{
+ switch (strlen($chr))
{
case 1:
- return '&#' . ord($m[0]) . ';';
+ return ord($chr);
+ break;
case 2:
- return '&#' . (((ord($m[0][0]) & 0x1F) << 6) | (ord($m[0][1]) & 0x3F)) . ';';
+ return ((ord($chr[0]) & 0x1F) << 6) | (ord($chr[1]) & 0x3F);
+ break;
case 3:
- return '&#' . (((ord($m[0][0]) & 0x0F) << 12) | ((ord($m[0][1]) & 0x3F) << 6) | (ord($m[0][2]) & 0x3F)) . ';';
+ return ((ord($chr[0]) & 0x0F) << 12) | ((ord($chr[1]) & 0x3F) << 6) | (ord($chr[2]) & 0x3F);
+ break;
case 4:
- return '&#' . (((ord($m[0][0]) & 0x07) << 18) | ((ord($m[0][1]) & 0x3F) << 12) | ((ord($m[0][2]) & 0x3F) << 6) | (ord($m[0][3]) & 0x3F)) . ';';
+ return ((ord($chr[0]) & 0x07) << 18) | ((ord($chr[1]) & 0x3F) << 12) | ((ord($chr[2]) & 0x3F) << 6) | (ord($chr[3]) & 0x3F);
+ break;
default:
- return $m[0];
- }
+ return $chr;
+ }
+}
+
+/**
+* Converts an NCR to a UTF-8 char
+*
+* @param integer $cp UNICODE code point
+* @return string UTF-8 char
+*/
+function utf8_chr($cp)
+{
+ if ($cp > 0xFFFF)
+ {
+ return chr(0xF0 | ($cp >> 18)) . chr(0x80 | (($cp >> 12) & 0x3F)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F));
+ }
+ else if ($cp > 0x7FF)
+ {
+ return chr(0xE0 | ($cp >> 12)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F));
+ }
+ else if ($cp > 0x7F)
+ {
+ return chr(0xC0 | ($cp >> 6)) . chr(0x80 | ($cp & 0x3F));
+ }
+ else
+ {
+ return chr($cp);
+ }
}
/**
@@ -196,22 +883,130 @@ function utf8_decode_ncr_callback($m)
{
$cp = (strncasecmp($m[1], 'x', 1)) ? $m[1] : hexdec(substr($m[1], 1));
- if ($cp > 0xFFFF)
+ return utf8_chr($cp);
+}
+
+/**
+* Takes an array of ints representing the Unicode characters and returns
+* a UTF-8 string.
+*
+* @param string $text text to be case folded
+* @param string $option determines how we will fold the cases
+* @return string case folded text
+*/
+function utf8_case_fold($text, $option = 'full')
+{
+ static $uniarray = array();
+ global $phpbb_root_path, $phpEx;
+
+ // common is always set
+ if (!isset($uniarray['c']))
{
- return chr(0xF0 | ($cp >> 18)) . chr(0x80 | (($cp >> 12) & 0x3F)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F));
+ $uniarray['c'] = include($phpbb_root_path . 'includes/utf/data/case_fold_c.' . $phpEx);
}
- elseif ($cp > 0x7FF)
+
+ // only set full if we need to
+ if ($option === 'full' && !isset($uniarray['f']))
{
- return chr(0xE0 | ($cp >> 12)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F));
+ $uniarray['f'] = include($phpbb_root_path . 'includes/utf/data/case_fold_f.' . $phpEx);
}
- elseif ($cp > 0x7F)
+
+ // only set simple if we need to
+ if ($option !== 'full' && !isset($uniarray['s']))
{
- return chr(0xC0 | ($cp >> 6)) . chr(0x80 | ($cp & 0x3F));
+ $uniarray['s'] = include($phpbb_root_path . 'includes/utf/data/case_fold_s.' . $phpEx);
+ }
+
+ $text = strtr($text, $uniarray['c']);
+ if ($option === 'full')
+ {
+ $text = strtr($text, $uniarray['f']);
}
else
{
- return chr($cp);
+ $text = strtr($text, $uniarray['s']);
}
+ return $text;
+}
+
+/**
+* A wrapper function for the normalizer which takes care of including the class if required and modifies the passed strings
+* to be in NFC (Normalization Form Composition).
+*
+* @param mixed $strings Either an array of references to strings, a reference to an array of strings or a reference to a single string
+*/
+function utf8_normalize_nfc($strings)
+{
+ if (!is_array($strings) || (sizeof($strings) > 0))
+ {
+ if (!class_exists('utf_normalizer'))
+ {
+ global $phpbb_root_path, $phpEx;
+ include($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx);
+ }
+
+ if (is_array($strings))
+ {
+ foreach ($strings as $key => $string)
+ {
+ $strings[$key] = utf_normalizer::nfc($strings[$key]);
+ }
+ }
+ else
+ {
+ $strings = utf_normalizer::nfc($strings);
+ }
+ }
+}
+
+/**
+* This function is used to generate a "clean" version of a string.
+* Clean means that it is a case insensitive form (case folding) and that it is normalized (NFC).
+* Additionally a homographs of one character are transformed into one specific character (preferably ASCII
+* if it is an ASCII character).
+*
+* Please be aware that if you change something within this function or within
+* functions used here you need to rebuild/update the username_clean column in the users table. And all other
+* columns that store a clean string otherwise you will break this functionality.
+*
+* @param $text An unclean string, mabye user input (has to be valid UTF-8!)
+* @return Cleaned up version of the input string
+*/
+function utf8_clean_string($text)
+{
+ $text = utf8_case_fold($text);
+
+ if (!class_exists('utf_normalizer'))
+ {
+ global $phpbb_root_path, $phpEx;
+ include($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx);
+ }
+
+ $text = utf_normalizer::nfc($text);
+
+ static $homographs = array(
+ // cyrllic
+ "\xD0\xB0" => "\x61",
+ "\xD0\xB5" => "\x65",
+ "\xD0\xBE" => "\x6F",
+ "\xD1\x80" => "\x70",
+ "\xD1\x81" => "\x63",
+ "\xD1\x83" => "\x79",
+ "\xD1\x85" => "\x78",
+ "\xD1\x95" => "\x73",
+ "\xD1\x96" => "\x69",
+ "\xD1\x98" => "\x6A",
+ "\xD2\xBB" => "\x68",
+ // greek
+ "\xCE\xB1" => "\x61",
+ "\xCE\xBF" => "\x6F",
+ // other
+ "\xC2\xA1" => "\x69",
+ );
+
+ $text = strtr($text, $homographs);
+
+ return $text;
}
?> \ No newline at end of file