aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB/includes
diff options
context:
space:
mode:
Diffstat (limited to 'phpBB/includes')
-rw-r--r--phpBB/includes/acp/acp_attachments.php19
-rw-r--r--phpBB/includes/acp/acp_bbcodes.php14
-rw-r--r--phpBB/includes/acp/acp_board.php235
-rw-r--r--phpBB/includes/acp/acp_captcha.php2
-rw-r--r--phpBB/includes/acp/acp_extensions.php34
-rw-r--r--phpBB/includes/acp/acp_groups.php40
-rw-r--r--phpBB/includes/acp/acp_modules.php73
-rw-r--r--phpBB/includes/acp/acp_permission_roles.php25
-rw-r--r--phpBB/includes/acp/acp_update.php2
-rw-r--r--phpBB/includes/auth/auth.php9
-rw-r--r--phpBB/includes/auth/auth_apache.php247
-rw-r--r--phpBB/includes/auth/auth_db.php289
-rw-r--r--phpBB/includes/auth/auth_ldap.php350
-rw-r--r--phpBB/includes/auth/provider/apache.php275
-rw-r--r--phpBB/includes/auth/provider/db.php337
-rw-r--r--phpBB/includes/auth/provider/index.htm10
-rw-r--r--phpBB/includes/auth/provider/interface.php93
-rw-r--r--phpBB/includes/auth/provider/ldap.php386
-rw-r--r--phpBB/includes/avatar/driver/upload.php2
-rw-r--r--phpBB/includes/constants.php1
-rw-r--r--phpBB/includes/db/driver/mssql_odbc.php2
-rw-r--r--phpBB/includes/db/driver/mssqlnative.php10
-rw-r--r--phpBB/includes/db/migration/data/30x/local_url_bbcode.php57
-rw-r--r--phpBB/includes/db/migration/data/310/notifications_schema_fix.php92
-rw-r--r--phpBB/includes/db/migration/data/310/signature_module_auth.php51
-rw-r--r--phpBB/includes/db/migration/tool/module.php5
-rw-r--r--phpBB/includes/extension/base.php71
-rw-r--r--phpBB/includes/extension/finder.php28
-rw-r--r--phpBB/includes/extension/manager.php108
-rw-r--r--phpBB/includes/feed/base.php259
-rw-r--r--phpBB/includes/feed/factory.php129
-rw-r--r--phpBB/includes/feed/forum.php147
-rw-r--r--phpBB/includes/feed/forums.php72
-rw-r--r--phpBB/includes/feed/helper.php159
-rw-r--r--phpBB/includes/feed/news.php112
-rw-r--r--phpBB/includes/feed/overall.php97
-rw-r--r--phpBB/includes/feed/post_base.php57
-rw-r--r--phpBB/includes/feed/topic.php116
-rw-r--r--phpBB/includes/feed/topic_base.php59
-rw-r--r--phpBB/includes/feed/topics.php91
-rw-r--r--phpBB/includes/feed/topics_active.php136
-rw-r--r--phpBB/includes/functions.php9
-rw-r--r--phpBB/includes/functions_acp.php38
-rw-r--r--phpBB/includes/functions_admin.php45
-rw-r--r--phpBB/includes/functions_download.php33
-rw-r--r--phpBB/includes/functions_posting.php57
-rw-r--r--phpBB/includes/functions_profile_fields.php18
-rw-r--r--phpBB/includes/functions_user.php44
-rw-r--r--phpBB/includes/notification/exception.php29
-rw-r--r--phpBB/includes/notification/manager.php242
-rw-r--r--phpBB/includes/notification/method/base.php2
-rw-r--r--phpBB/includes/notification/method/email.php2
-rw-r--r--phpBB/includes/notification/type/base.php22
-rw-r--r--phpBB/includes/notification/type/bookmark.php8
-rw-r--r--phpBB/includes/notification/type/post.php8
-rw-r--r--phpBB/includes/notification/type/quote.php22
-rw-r--r--phpBB/includes/search/fulltext_mysql.php11
-rw-r--r--phpBB/includes/search/fulltext_native.php4
-rw-r--r--phpBB/includes/search/fulltext_postgres.php4
-rw-r--r--phpBB/includes/search/fulltext_sphinx.php6
-rw-r--r--phpBB/includes/session.php41
-rw-r--r--phpBB/includes/template/compile.php39
-rw-r--r--phpBB/includes/template/filter.php98
-rw-r--r--phpBB/includes/ucp/ucp_groups.php34
-rw-r--r--phpBB/includes/ucp/ucp_notifications.php4
65 files changed, 3608 insertions, 1513 deletions
diff --git a/phpBB/includes/acp/acp_attachments.php b/phpBB/includes/acp/acp_attachments.php
index 9d6c2d5de1..d0e8ff3882 100644
--- a/phpBB/includes/acp/acp_attachments.php
+++ b/phpBB/includes/acp/acp_attachments.php
@@ -117,8 +117,8 @@ class acp_attachments
'attachment_quota' => array('lang' => 'ATTACH_QUOTA', 'validate' => 'string', 'type' => 'custom', 'method' => 'max_filesize', 'explain' => true),
'max_filesize' => array('lang' => 'ATTACH_MAX_FILESIZE', 'validate' => 'string', 'type' => 'custom', 'method' => 'max_filesize', 'explain' => true),
'max_filesize_pm' => array('lang' => 'ATTACH_MAX_PM_FILESIZE','validate' => 'string', '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),
+ 'max_attachments' => array('lang' => 'MAX_ATTACHMENTS', 'validate' => 'int:0:999', 'type' => 'number:0:999', 'explain' => false),
+ 'max_attachments_pm' => array('lang' => 'MAX_ATTACHMENTS_PM', 'validate' => 'int:0:999', 'type' => 'number:0:999', '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),
@@ -128,11 +128,11 @@ class acp_attachments
'legend2' => $l_legend_cat_images,
'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' => ' ' . $user->lang['PIXEL']),
- 'img_min_thumb_filesize' => array('lang' => 'MIN_THUMB_FILESIZE', 'validate' => 'int', 'type' => 'text:7:15', 'explain' => true, 'append' => ' ' . $user->lang['BYTES']),
+ 'img_max_thumb_width' => array('lang' => 'MAX_THUMB_WIDTH', 'validate' => 'int:0:999999999999999', 'type' => 'number:0:999999999999999', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
+ 'img_min_thumb_filesize' => array('lang' => 'MIN_THUMB_FILESIZE', 'validate' => 'int:0:999999999999999', 'type' => 'number:0:999999999999999', '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, 'append' => ' ' . $user->lang['PIXEL']),
- 'img_link' => array('lang' => 'IMAGE_LINK_SIZE', 'validate' => 'int', 'type' => 'dimension:3:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
+ 'img_max' => array('lang' => 'MAX_IMAGE_SIZE', 'validate' => 'int:0:9999', 'type' => 'dimension:0:9999', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
+ 'img_link' => array('lang' => 'IMAGE_LINK_SIZE', 'validate' => 'int:0:9999', 'type' => 'dimension:0:9999', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
)
);
@@ -1203,8 +1203,8 @@ class acp_attachments
// Just get the files
$sql = 'SELECT a.*, u.username, u.user_colour, t.topic_title
- FROM ' . ATTACHMENTS_TABLE . ' a
- LEFT JOIN ' . USERS_TABLE . ' u ON (u.user_id = a.poster_id)
+ FROM ' . ATTACHMENTS_TABLE . ' a
+ LEFT JOIN ' . USERS_TABLE . ' u ON (u.user_id = a.poster_id)
LEFT JOIN ' . TOPICS_TABLE . " t ON (a.topic_id = t.topic_id)
WHERE a.is_orphan = 0
$limit_filetime
@@ -1670,7 +1670,8 @@ class acp_attachments
$size_var = $filesize['si_identifier'];
$value = $filesize['value'];
- return '<input type="text" id="' . $key . '" size="8" maxlength="15" name="config[' . $key . ']" value="' . $value . '" /> <select name="' . $key . '">' . size_select_options($size_var) . '</select>';
+ // size="8" and maxlength="15" attributes as a fallback for browsers that do not support type="number" yet.
+ return '<input type="number" id="' . $key . '" size="8" maxlength="15" min="0" name="config[' . $key . ']" value="' . $value . '" /> <select name="' . $key . '">' . size_select_options($size_var) . '</select>';
}
/**
diff --git a/phpBB/includes/acp/acp_bbcodes.php b/phpBB/includes/acp/acp_bbcodes.php
index e537d7a8b9..9c430b5a0b 100644
--- a/phpBB/includes/acp/acp_bbcodes.php
+++ b/phpBB/includes/acp/acp_bbcodes.php
@@ -112,8 +112,8 @@ class acp_bbcodes
{
$template->assign_block_vars('token', array(
'TOKEN' => '{' . $token . '}',
- 'EXPLAIN' => $token_explain)
- );
+ 'EXPLAIN' => ($token === 'LOCAL_URL') ? sprintf($token_explain, generate_board_url() . '/') : $token_explain,
+ ));
}
return;
@@ -347,6 +347,9 @@ class acp_bbcodes
'LOCAL_URL' => array(
'!(' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('relative_url')) . ')!e' => "\$this->bbcode_specialchars('$1')"
),
+ 'RELATIVE_URL' => array(
+ '!(' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('relative_url')) . ')!e' => "\$this->bbcode_specialchars('$1')"
+ ),
'EMAIL' => array(
'!(' . get_preg_expression('email') . ')!ie' => "\$this->bbcode_specialchars('$1')"
),
@@ -373,6 +376,7 @@ class acp_bbcodes
$sp_tokens = array(
'URL' => '(?i)((?:' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('url')) . ')|(?:' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('www_url')) . '))(?-i)',
'LOCAL_URL' => '(?i)(' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('relative_url')) . ')(?-i)',
+ 'RELATIVE_URL' => '(?i)(' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('relative_url')) . ')(?-i)',
'EMAIL' => '(' . get_preg_expression('email') . ')',
'TEXT' => '(.*?)',
'SIMPLETEXT' => '([a-zA-Z0-9-+.,_ ]+)',
@@ -429,7 +433,11 @@ class acp_bbcodes
$fp_replace = str_replace($token, $replace, $fp_replace);
$sp_match = str_replace(preg_quote($token, '!'), $sp_tokens[$token_type], $sp_match);
- $sp_replace = str_replace($token, '${' . ($n + 1) . '}', $sp_replace);
+
+ // Prepend the board url to local relative links
+ $replace_prepend = ($token_type === 'LOCAL_URL') ? generate_board_url() . '/' : '';
+
+ $sp_replace = str_replace($token, $replace_prepend . '${' . ($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 ab44920f0a..24b913260b 100644
--- a/phpBB/includes/acp/acp_board.php
+++ b/phpBB/includes/acp/acp_board.php
@@ -53,7 +53,7 @@ class acp_board
'legend1' => 'ACP_BOARD_SETTINGS',
'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),
- 'site_home_url' => array('lang' => 'SITE_HOME_URL', 'validate' => 'string', 'type' => 'text:40:255', 'explain' => true),
+ 'site_home_url' => array('lang' => 'SITE_HOME_URL', 'validate' => 'string', 'type' => 'url:40:255', 'explain' => true),
'site_home_text' => array('lang' => 'SITE_HOME_TEXT', 'validate' => 'string', 'type' => 'text:40:255', 'explain' => true),
'board_index_text' => array('lang' => 'BOARD_INDEX_TEXT', 'validate' => 'string', 'type' => 'text:40:255', 'explain' => true),
'board_disable' => array('lang' => 'DISABLE_BOARD', 'validate' => 'bool', 'type' => 'custom', 'method' => 'board_disable', 'explain' => true),
@@ -65,7 +65,7 @@ class acp_board
'override_user_style' => array('lang' => 'OVERRIDE_STYLE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'legend2' => 'WARNINGS',
- 'warnings_expire_days' => array('lang' => 'WARNINGS_EXPIRE', 'validate' => 'int', 'type' => 'text:3:4', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']),
+ 'warnings_expire_days' => array('lang' => 'WARNINGS_EXPIRE', 'validate' => 'int:0:9999', 'type' => 'number:0:9999', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']),
'legend3' => 'ACP_SUBMIT_CHANGES',
)
@@ -136,8 +136,8 @@ class acp_board
'avatar_max_height' => array('lang' => 'MAX_AVATAR_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false),
'allow_avatar' => array('lang' => 'ALLOW_AVATARS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
- 'avatar_min' => array('lang' => 'MIN_AVATAR_SIZE', 'validate' => 'int:0', 'type' => 'dimension:3:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
- 'avatar_max' => array('lang' => 'MAX_AVATAR_SIZE', 'validate' => 'int:0', 'type' => 'dimension:3:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
+ 'avatar_min' => array('lang' => 'MIN_AVATAR_SIZE', 'validate' => 'int:0', 'type' => 'dimension:0', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
+ 'avatar_max' => array('lang' => 'MAX_AVATAR_SIZE', 'validate' => 'int:0', 'type' => 'dimension:0', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
)
);
@@ -154,11 +154,11 @@ class acp_board
'vars' => array(
'legend1' => 'GENERAL_SETTINGS',
'allow_privmsg' => array('lang' => 'BOARD_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
- 'pm_max_boxes' => array('lang' => 'BOXES_MAX', 'validate' => 'int:0', 'type' => 'text:4:4', 'explain' => true),
- 'pm_max_msgs' => array('lang' => 'BOXES_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:4', 'explain' => true),
+ 'pm_max_boxes' => array('lang' => 'BOXES_MAX', 'validate' => 'int:0:9999', 'type' => 'number:0:9999', 'explain' => true),
+ 'pm_max_msgs' => array('lang' => 'BOXES_LIMIT', 'validate' => 'int:0:9999', 'type' => 'number:0:9999', '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:0', 'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']),
- 'pm_max_recipients' => array('lang' => 'PM_MAX_RECIPIENTS', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true),
+ 'pm_edit_time' => array('lang' => 'PM_EDIT_TIME', 'validate' => 'int:0:99999', 'type' => 'number:0:99999', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']),
+ 'pm_max_recipients' => array('lang' => 'PM_MAX_RECIPIENTS', 'validate' => 'int:0:99999', 'type' => 'number:0:99999', 'explain' => true),
'legend2' => 'GENERAL_OPTIONS',
'allow_mass_pm' => array('lang' => 'ALLOW_MASS_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false),
@@ -195,24 +195,24 @@ class acp_board
'legend2' => 'POSTING',
'bump_type' => false,
- 'edit_time' => array('lang' => 'EDIT_TIME', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']),
- 'delete_time' => array('lang' => 'DELETE_TIME', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']),
+ 'edit_time' => array('lang' => 'EDIT_TIME', 'validate' => 'int:0:99999', 'type' => 'number:0:99999', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']),
+ 'delete_time' => array('lang' => 'DELETE_TIME', 'validate' => 'int:0:99999', 'type' => 'number:0:99999', '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:0', 'type' => 'text:3:10', 'explain' => true, 'append' => ' ' . $user->lang['SECONDS']),
+ 'flood_interval' => array('lang' => 'FLOOD_INTERVAL', 'validate' => 'int:0:9999999999', 'type' => 'number:0:9999999999', 'explain' => true, 'append' => ' ' . $user->lang['SECONDS']),
'bump_interval' => array('lang' => 'BUMP_INTERVAL', 'validate' => 'int:0', 'type' => 'custom', 'method' => 'bump_interval', 'explain' => true),
- 'topics_per_page' => array('lang' => 'TOPICS_PER_PAGE', 'validate' => 'int:1', 'type' => 'text:3:4', 'explain' => false),
- 'posts_per_page' => array('lang' => 'POSTS_PER_PAGE', 'validate' => 'int:1', 'type' => 'text:3:4', 'explain' => false),
- 'smilies_per_page' => array('lang' => 'SMILIES_PER_PAGE', 'validate' => 'int:1', 'type' => 'text:3:4', 'explain' => false),
- 'hot_threshold' => array('lang' => 'HOT_THRESHOLD', 'validate' => 'int:0', 'type' => 'text:3:4', 'explain' => true),
- 'max_poll_options' => array('lang' => 'MAX_POLL_OPTIONS', 'validate' => 'int:2:127', 'type' => 'text:4:4', 'explain' => false),
- 'max_post_chars' => array('lang' => 'CHAR_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:6', 'explain' => true),
- 'min_post_chars' => array('lang' => 'MIN_CHAR_LIMIT', 'validate' => 'int:1', 'type' => 'text:4:6', 'explain' => true),
- 'max_post_smilies' => array('lang' => 'SMILIES_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:4', 'explain' => true),
- 'max_post_urls' => array('lang' => 'MAX_POST_URLS', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true),
- 'max_post_font_size' => array('lang' => 'MAX_POST_FONT_SIZE', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' %'),
- 'max_quote_depth' => array('lang' => 'QUOTE_DEPTH_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:4', 'explain' => true),
- 'max_post_img_width' => array('lang' => 'MAX_POST_IMG_WIDTH', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
- 'max_post_img_height' => array('lang' => 'MAX_POST_IMG_HEIGHT', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
+ 'topics_per_page' => array('lang' => 'TOPICS_PER_PAGE', 'validate' => 'int:1:9999', 'type' => 'number:1:9999', 'explain' => false),
+ 'posts_per_page' => array('lang' => 'POSTS_PER_PAGE', 'validate' => 'int:1:9999', 'type' => 'number:1:9999', 'explain' => false),
+ 'smilies_per_page' => array('lang' => 'SMILIES_PER_PAGE', 'validate' => 'int:1:9999', 'type' => 'number:1:9999', 'explain' => false),
+ 'hot_threshold' => array('lang' => 'HOT_THRESHOLD', 'validate' => 'int:0:9999', 'type' => 'number:0:9999', 'explain' => true),
+ 'max_poll_options' => array('lang' => 'MAX_POLL_OPTIONS', 'validate' => 'int:2:127', 'type' => 'number:2:127', 'explain' => false),
+ 'max_post_chars' => array('lang' => 'CHAR_LIMIT', 'validate' => 'int:0:999999', 'type' => 'number:0:999999', 'explain' => true),
+ 'min_post_chars' => array('lang' => 'MIN_CHAR_LIMIT', 'validate' => 'int:1:999999', 'type' => 'number:1:999999', 'explain' => true),
+ 'max_post_smilies' => array('lang' => 'SMILIES_LIMIT', 'validate' => 'int:0:9999', 'type' => 'number:0:9999', 'explain' => true),
+ 'max_post_urls' => array('lang' => 'MAX_POST_URLS', 'validate' => 'int:0:9999', 'type' => 'number:0:9999', 'explain' => true),
+ 'max_post_font_size' => array('lang' => 'MAX_POST_FONT_SIZE', 'validate' => 'int:0:9999', 'type' => 'number:0:9999', 'explain' => true, 'append' => ' %'),
+ 'max_quote_depth' => array('lang' => 'QUOTE_DEPTH_LIMIT', 'validate' => 'int:0:9999', 'type' => 'number:0:9999', 'explain' => true),
+ 'max_post_img_width' => array('lang' => 'MAX_POST_IMG_WIDTH', 'validate' => 'int:0:9999', 'type' => 'number:0:9999', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
+ 'max_post_img_height' => array('lang' => 'MAX_POST_IMG_HEIGHT', 'validate' => 'int:0:9999', 'type' => 'number:0:9999', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
'legend3' => 'ACP_SUBMIT_CHANGES',
)
@@ -232,12 +232,12 @@ class acp_board
'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', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true),
- 'max_sig_urls' => array('lang' => 'MAX_SIG_URLS', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true),
- 'max_sig_font_size' => array('lang' => 'MAX_SIG_FONT_SIZE', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' %'),
- 'max_sig_smilies' => array('lang' => 'MAX_SIG_SMILIES', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true),
- 'max_sig_img_width' => array('lang' => 'MAX_SIG_IMG_WIDTH', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
- 'max_sig_img_height' => array('lang' => 'MAX_SIG_IMG_HEIGHT', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
+ 'max_sig_chars' => array('lang' => 'MAX_SIG_LENGTH', 'validate' => 'int:0:9999', 'type' => 'number:0:9999', 'explain' => true),
+ 'max_sig_urls' => array('lang' => 'MAX_SIG_URLS', 'validate' => 'int:0:9999', 'type' => 'number:0:9999', 'explain' => true),
+ 'max_sig_font_size' => array('lang' => 'MAX_SIG_FONT_SIZE', 'validate' => 'int:0:9999', 'type' => 'number:0:9999', 'explain' => true, 'append' => ' %'),
+ 'max_sig_smilies' => array('lang' => 'MAX_SIG_SMILIES', 'validate' => 'int:0:9999', 'type' => 'number:0:9999', 'explain' => true),
+ 'max_sig_img_width' => array('lang' => 'MAX_SIG_IMG_WIDTH', 'validate' => 'int:0:9999', 'type' => 'number:0:9999', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
+ 'max_sig_img_height' => array('lang' => 'MAX_SIG_IMG_HEIGHT', 'validate' => 'int:0:9999', 'type' => 'number:0:9999', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),
'legend3' => 'ACP_SUBMIT_CHANGES',
)
@@ -253,20 +253,20 @@ class acp_board
'max_pass_chars' => array('lang' => 'PASSWORD_LENGTH', 'validate' => 'int:8:255', 'type' => false, 'method' => false, 'explain' => false,),
'require_activation' => array('lang' => 'ACC_ACTIVATION', 'validate' => 'int', 'type' => 'select', 'method' => 'select_acc_activation', 'explain' => true),
- 'new_member_post_limit' => array('lang' => 'NEW_MEMBER_POST_LIMIT', 'validate' => 'int:0:255', 'type' => 'text:4:4', 'explain' => true, 'append' => ' ' . $user->lang['POSTS']),
+ 'new_member_post_limit' => array('lang' => 'NEW_MEMBER_POST_LIMIT', 'validate' => 'int:0:255', 'type' => 'number:0:255', 'explain' => true, 'append' => ' ' . $user->lang['POSTS']),
'new_member_group_default'=> array('lang' => 'NEW_MEMBER_GROUP_DEFAULT', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'min_name_chars' => array('lang' => 'USERNAME_LENGTH', 'validate' => 'int:1', 'type' => 'custom:5:180', 'method' => 'username_length', 'explain' => true),
'min_pass_chars' => array('lang' => 'PASSWORD_LENGTH', 'validate' => 'int:1', '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:0', 'type' => 'text:3:3', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']),
+ 'chg_passforce' => array('lang' => 'FORCE_PASS_CHANGE', 'validate' => 'int:0:999', 'type' => 'number:0:999', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']),
'legend2' => 'GENERAL_OPTIONS',
'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:0', 'type' => 'text:3:3', 'explain' => true),
- 'max_reg_attempts' => array('lang' => 'REG_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:4', 'explain' => true),
+ 'max_login_attempts' => array('lang' => 'MAX_LOGIN_ATTEMPTS', 'validate' => 'int:0:999', 'type' => 'number:0:999', 'explain' => true),
+ 'max_reg_attempts' => array('lang' => 'REG_LIMIT', 'validate' => 'int:0:9999', 'type' => 'number:0:9999', 'explain' => true),
'legend3' => 'COPPA',
'coppa_enable' => array('lang' => 'ENABLE_COPPA', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
@@ -288,13 +288,13 @@ class acp_board
'feed_http_auth' => array('lang' => 'ACP_FEED_HTTP_AUTH', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true),
'legend2' => 'ACP_FEED_POST_BASED',
- 'feed_limit_post' => array('lang' => 'ACP_FEED_LIMIT', 'validate' => 'int:5', 'type' => 'text:3:4', 'explain' => true),
+ 'feed_limit_post' => array('lang' => 'ACP_FEED_LIMIT', 'validate' => 'int:5:9999', 'type' => 'number:5:9999', 'explain' => true),
'feed_overall' => array('lang' => 'ACP_FEED_OVERALL', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true ),
'feed_forum' => array('lang' => 'ACP_FEED_FORUM', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true ),
'feed_topic' => array('lang' => 'ACP_FEED_TOPIC', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true ),
'legend3' => 'ACP_FEED_TOPIC_BASED',
- 'feed_limit_topic' => array('lang' => 'ACP_FEED_LIMIT', 'validate' => 'int:5', 'type' => 'text:3:4', 'explain' => true),
+ 'feed_limit_topic' => array('lang' => 'ACP_FEED_LIMIT', 'validate' => 'int:5:9999', 'type' => 'number:5:9999', 'explain' => true),
'feed_topics_new' => array('lang' => 'ACP_FEED_TOPICS_NEW', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true ),
'feed_topics_active' => array('lang' => 'ACP_FEED_TOPICS_ACTIVE', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true ),
'feed_news_id' => array('lang' => 'ACP_FEED_NEWS', 'validate' => 'string', 'type' => 'custom', 'method' => 'select_news_forums', 'explain' => true),
@@ -324,10 +324,10 @@ class acp_board
'title' => 'ACP_LOAD_SETTINGS',
'vars' => array(
'legend1' => 'GENERAL_SETTINGS',
- 'limit_load' => array('lang' => 'LIMIT_LOAD', 'validate' => 'string', 'type' => 'text:4:4', 'explain' => true),
- 'session_length' => array('lang' => 'SESSION_LENGTH', 'validate' => 'int:60', 'type' => 'text:5:10', 'explain' => true, 'append' => ' ' . $user->lang['SECONDS']),
- 'active_sessions' => array('lang' => 'LIMIT_SESSIONS', 'validate' => 'int:0', 'type' => 'text:4:4', 'explain' => true),
- 'load_online_time' => array('lang' => 'ONLINE_LENGTH', 'validate' => 'int:0', 'type' => 'text:4:3', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']),
+ 'limit_load' => array('lang' => 'LIMIT_LOAD', 'validate' => 'int:0:9999', 'type' => 'number:0:9999', 'explain' => true),
+ 'session_length' => array('lang' => 'SESSION_LENGTH', 'validate' => 'int:60:9999999999', 'type' => 'number:60:9999999999', 'explain' => true, 'append' => ' ' . $user->lang['SECONDS']),
+ 'active_sessions' => array('lang' => 'LIMIT_SESSIONS', 'validate' => 'int:0:9999', 'type' => 'number:0:9999', 'explain' => true),
+ 'load_online_time' => array('lang' => 'ONLINE_LENGTH', 'validate' => 'int:0:999', 'type' => 'number:0:999', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']),
'legend2' => 'GENERAL_OPTIONS',
'load_notifications' => array('lang' => 'LOAD_NOTIFICATIONS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
@@ -384,7 +384,7 @@ class acp_board
'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:0', 'type' => 'text:5:5', 'explain' => true),
+ 'server_port' => array('lang' => 'SERVER_PORT', 'validate' => 'int:0:99999', 'type' => 'number:0:99999', 'explain' => true),
'script_path' => array('lang' => 'SCRIPT_PATH', 'validate' => 'script_path', 'type' => 'text::255', 'explain' => true),
'legend4' => 'ACP_SUBMIT_CHANGES',
@@ -399,7 +399,7 @@ class acp_board
'legend1' => 'ACP_SECURITY_SETTINGS',
'allow_autologin' => array('lang' => 'ALLOW_AUTOLOGIN', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'allow_password_reset' => array('lang' => 'ALLOW_PASSWORD_RESET', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
- 'max_autologin_time' => array('lang' => 'AUTOLOGIN_LENGTH', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']),
+ 'max_autologin_time' => array('lang' => 'AUTOLOGIN_LENGTH', 'validate' => 'int:0:99999', 'type' => 'number:0:99999', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']),
'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),
'forwarded_for_check' => array('lang' => 'FORWARDED_FOR_VALID', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
@@ -409,13 +409,13 @@ class acp_board
'max_pass_chars' => array('lang' => 'PASSWORD_LENGTH', 'validate' => 'int:8:255', 'type' => false, 'method' => false, 'explain' => false,),
'min_pass_chars' => array('lang' => 'PASSWORD_LENGTH', 'validate' => 'int:1', 'type' => 'custom', 'method' => 'password_length', '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:0', 'type' => 'text:3:3', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']),
- 'max_login_attempts' => array('lang' => 'MAX_LOGIN_ATTEMPTS', 'validate' => 'int:0', 'type' => 'text:3:3', 'explain' => true),
- 'ip_login_limit_max' => array('lang' => 'IP_LOGIN_LIMIT_MAX', 'validate' => 'int:0', 'type' => 'text:3:3', 'explain' => true),
- 'ip_login_limit_time' => array('lang' => 'IP_LOGIN_LIMIT_TIME', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['SECONDS']),
+ 'chg_passforce' => array('lang' => 'FORCE_PASS_CHANGE', 'validate' => 'int:0:999', 'type' => 'number:0:999', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']),
+ 'max_login_attempts' => array('lang' => 'MAX_LOGIN_ATTEMPTS', 'validate' => 'int:0:999', 'type' => 'number:0:999', 'explain' => true),
+ 'ip_login_limit_max' => array('lang' => 'IP_LOGIN_LIMIT_MAX', 'validate' => 'int:0:999', 'type' => 'number:0:999', 'explain' => true),
+ 'ip_login_limit_time' => array('lang' => 'IP_LOGIN_LIMIT_TIME', 'validate' => 'int:0:99999', 'type' => 'number:0:99999', 'explain' => true, 'append' => ' ' . $user->lang['SECONDS']),
'ip_login_limit_use_forwarded' => array('lang' => 'IP_LOGIN_LIMIT_USE_FORWARDED', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
'tpl_allow_php' => array('lang' => 'TPL_ALLOW_PHP', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
- 'form_token_lifetime' => array('lang' => 'FORM_TIME_MAX', 'validate' => 'int:-1', 'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['SECONDS']),
+ 'form_token_lifetime' => array('lang' => 'FORM_TIME_MAX', 'validate' => 'int:-1:99999', 'type' => 'number:-1:99999', 'explain' => true, 'append' => ' ' . $user->lang['SECONDS']),
'form_token_sid_guests' => array('lang' => 'FORM_SID_GUESTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
)
@@ -430,16 +430,16 @@ class acp_board
'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:0', 'type' => 'text:5:5', 'explain' => true),
- 'board_contact' => array('lang' => 'CONTACT_EMAIL', 'validate' => 'email', 'type' => 'text:25:100', 'explain' => true),
- 'board_email' => array('lang' => 'ADMIN_EMAIL', 'validate' => 'email', 'type' => 'text:25:100', 'explain' => true),
+ 'email_package_size' => array('lang' => 'EMAIL_PACKAGE_SIZE', 'validate' => 'int:0', 'type' => 'number:0:99999', 'explain' => true),
+ 'board_contact' => array('lang' => 'CONTACT_EMAIL', 'validate' => 'email', 'type' => 'email:25:100', 'explain' => true),
+ 'board_email' => array('lang' => 'ADMIN_EMAIL', 'validate' => 'email', 'type' => 'email: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', '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:0', 'type' => 'text:4:5', 'explain' => true),
+ 'smtp_port' => array('lang' => 'SMTP_PORT', 'validate' => 'int:0:99999', 'type' => 'number:0:99999', '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),
@@ -522,84 +522,54 @@ class acp_board
if ($mode == 'auth')
{
// Retrieve a list of auth plugins and check their config values
- $auth_plugins = array();
+ $auth_providers = $phpbb_container->get('auth.provider_collection');
- $dp = @opendir($phpbb_root_path . 'includes/auth');
-
- if ($dp)
+ $updated_auth_settings = false;
+ $old_auth_config = array();
+ foreach ($auth_providers as $provider)
{
- while (($file = readdir($dp)) !== false)
+ if ($fields = $provider->acp($this->new_config))
{
- if (preg_match('#^auth_(.*?)\.' . $phpEx . '$#', $file))
+ // Check if we need to create config fields for this plugin and save config when submit was pressed
+ foreach ($fields['config'] as $field)
{
- $auth_plugins[] = basename(preg_replace('#^auth_(.*?)\.' . $phpEx . '$#', '\1', $file));
- }
- }
- closedir($dp);
+ if (!isset($config[$field]))
+ {
+ set_config($field, '');
+ }
- sort($auth_plugins);
- }
+ if (!isset($cfg_array[$field]) || strpos($field, 'legend') !== false)
+ {
+ continue;
+ }
- $updated_auth_settings = false;
- $old_auth_config = array();
- foreach ($auth_plugins as $method)
- {
- if ($method && file_exists($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx))
- {
- include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx);
+ $old_auth_config[$field] = $this->new_config[$field];
+ $config_value = $cfg_array[$field];
+ $this->new_config[$field] = $config_value;
- $method = 'acp_' . $method;
- if (function_exists($method))
- {
- if ($fields = $method($this->new_config))
+ if ($submit)
{
- // Check if we need to create config fields for this plugin and save config when submit was pressed
- foreach ($fields['config'] as $field)
- {
- if (!isset($config[$field]))
- {
- set_config($field, '');
- }
-
- if (!isset($cfg_array[$field]) || strpos($field, 'legend') !== false)
- {
- continue;
- }
-
- $old_auth_config[$field] = $this->new_config[$field];
- $config_value = $cfg_array[$field];
- $this->new_config[$field] = $config_value;
-
- if ($submit)
- {
- $updated_auth_settings = true;
- set_config($field, $config_value);
- }
- }
+ $updated_auth_settings = true;
+ set_config($field, $config_value);
}
- unset($fields);
}
}
+ unset($fields);
}
if ($submit && (($cfg_array['auth_method'] != $this->new_config['auth_method']) || $updated_auth_settings))
{
$method = basename($cfg_array['auth_method']);
- if ($method && in_array($method, $auth_plugins))
+ if (array_key_exists('auth.provider.' . $method, $auth_providers))
{
- include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx);
-
- $method = 'init_' . $method;
- if (function_exists($method))
+ $provider = $auth_providers['auth.provider.' . $method];
+ if ($error = $provider->init())
{
- if ($error = $method())
+ foreach ($old_auth_config as $config_name => $config_value)
{
- foreach ($old_auth_config as $config_name => $config_value)
- {
- set_config($config_name, $config_value);
- }
- trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING);
+ set_config($config_name, $config_value);
}
+ trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING);
}
set_config('auth_method', basename($cfg_array['auth_method']));
}
@@ -683,24 +653,17 @@ class acp_board
{
$template->assign_var('S_AUTH', true);
- foreach ($auth_plugins as $method)
+ foreach ($auth_providers as $provider)
{
- if ($method && file_exists($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx))
- {
- $method = 'acp_' . $method;
- if (function_exists($method))
- {
- $fields = $method($this->new_config);
+ $fields = $provider->acp($this->new_config);
- if ($fields['tpl'])
- {
- $template->assign_block_vars('auth_tpl', array(
- 'TPL' => $fields['tpl'])
- );
- }
- unset($fields);
- }
+ if ($fields['tpl'])
+ {
+ $template->assign_block_vars('auth_tpl', array(
+ 'TPL' => $fields['tpl'],
+ ));
}
+ unset($fields);
}
}
}
@@ -710,26 +673,16 @@ class acp_board
*/
function select_auth_method($selected_method, $key = '')
{
- global $phpbb_root_path, $phpEx;
+ global $phpbb_root_path, $phpEx, $phpbb_container;
$auth_plugins = array();
+ $auth_providers = $phpbb_container->get('auth.provider_collection');
- $dp = @opendir($phpbb_root_path . 'includes/auth');
-
- if (!$dp)
+ foreach($auth_providers as $key => $value)
{
- return '';
+ $auth_plugins[] = str_replace('auth.provider.', '', $key);
}
- while (($file = readdir($dp)) !== false)
- {
- if (preg_match('#^auth_(.*?)\.' . $phpEx . '$#', $file))
- {
- $auth_plugins[] = preg_replace('#^auth_(.*?)\.' . $phpEx . '$#', '\1', $file);
- }
- }
- closedir($dp);
-
sort($auth_plugins);
$auth_select = '';
@@ -805,7 +758,7 @@ class acp_board
{
$act_ary['ACC_USER'] = USER_ACTIVATION_SELF;
$act_ary['ACC_ADMIN'] = USER_ACTIVATION_ADMIN;
- }
+ }
$act_options = '';
foreach ($act_ary as $key => $value)
@@ -824,7 +777,7 @@ class acp_board
{
global $user;
- return '<input id="' . $key . '" type="text" size="3" maxlength="3" name="config[min_name_chars]" value="' . $value . '" /> ' . $user->lang['MIN_CHARS'] . '&nbsp;&nbsp;<input type="text" size="3" maxlength="3" name="config[max_name_chars]" value="' . $this->new_config['max_name_chars'] . '" /> ' . $user->lang['MAX_CHARS'];
+ return '<input id="' . $key . '" type="number" size="3" maxlength="3" min="1" max="999" name="config[min_name_chars]" value="' . $value . '" /> ' . $user->lang['MIN_CHARS'] . '&nbsp;&nbsp;<input type="number" size="3" maxlength="3" min="8" max="180" name="config[max_name_chars]" value="' . $this->new_config['max_name_chars'] . '" /> ' . $user->lang['MAX_CHARS'];
}
/**
@@ -852,7 +805,7 @@ class acp_board
{
global $user;
- return '<input id="' . $key . '" type="text" size="3" maxlength="3" name="config[min_pass_chars]" value="' . $value . '" /> ' . $user->lang['MIN_CHARS'] . '&nbsp;&nbsp;<input type="text" size="3" maxlength="3" name="config[max_pass_chars]" value="' . $this->new_config['max_pass_chars'] . '" /> ' . $user->lang['MAX_CHARS'];
+ return '<input id="' . $key . '" type="number" size="3" maxlength="3" min="1" max="999" name="config[min_pass_chars]" value="' . $value . '" /> ' . $user->lang['MIN_CHARS'] . '&nbsp;&nbsp;<input type="number" size="3" maxlength="3" min="8" max="255" name="config[max_pass_chars]" value="' . $this->new_config['max_pass_chars'] . '" /> ' . $user->lang['MAX_CHARS'];
}
/**
diff --git a/phpBB/includes/acp/acp_captcha.php b/phpBB/includes/acp/acp_captcha.php
index c7c64ae56b..1a083c20ac 100644
--- a/phpBB/includes/acp/acp_captcha.php
+++ b/phpBB/includes/acp/acp_captcha.php
@@ -124,6 +124,8 @@ class acp_captcha
'CAPTCHA_PREVIEW_TPL' => $demo_captcha->get_demo_template($id),
'S_CAPTCHA_HAS_CONFIG' => $demo_captcha->has_config(),
'CAPTCHA_SELECT' => $captcha_select,
+
+ 'U_ACTION' => $this->u_action,
));
}
}
diff --git a/phpBB/includes/acp/acp_extensions.php b/phpBB/includes/acp/acp_extensions.php
index c52e4e0473..379e779c2c 100644
--- a/phpBB/includes/acp/acp_extensions.php
+++ b/phpBB/includes/acp/acp_extensions.php
@@ -44,6 +44,10 @@ class acp_extensions
$action = $request->variable('action', 'list');
$ext_name = $request->variable('ext_name', '');
+ // What is a safe limit of execution time? Half the max execution time should be safe.
+ $safe_time_limit = (ini_get('max_execution_time') / 2);
+ $start_time = time();
+
// Cancel action
if ($request->is_set_post('cancel'))
{
@@ -105,11 +109,15 @@ class acp_extensions
try
{
- if ($phpbb_extension_manager->enable_step($ext_name))
+ while ($phpbb_extension_manager->enable_step($ext_name))
{
- $template->assign_var('S_NEXT_STEP', true);
+ // Are we approaching the time limit? If so we want to pause the update and continue after refreshing
+ if ((time() - $start_time) >= $safe_time_limit)
+ {
+ $template->assign_var('S_NEXT_STEP', true);
- meta_refresh(0, $this->u_action . '&amp;action=enable&amp;ext_name=' . urlencode($ext_name));
+ meta_refresh(0, $this->u_action . '&amp;action=enable&amp;ext_name=' . urlencode($ext_name));
+ }
}
}
catch (phpbb_db_migration_exception $e)
@@ -139,11 +147,15 @@ class acp_extensions
break;
case 'disable':
- if ($phpbb_extension_manager->disable_step($ext_name))
+ while ($phpbb_extension_manager->disable_step($ext_name))
{
- $template->assign_var('S_NEXT_STEP', true);
+ // Are we approaching the time limit? If so we want to pause the update and continue after refreshing
+ if ((time() - $start_time) >= $safe_time_limit)
+ {
+ $template->assign_var('S_NEXT_STEP', true);
- meta_refresh(0, $this->u_action . '&amp;action=disable&amp;ext_name=' . urlencode($ext_name));
+ meta_refresh(0, $this->u_action . '&amp;action=disable&amp;ext_name=' . urlencode($ext_name));
+ }
}
$this->tpl_name = 'acp_ext_disable';
@@ -165,11 +177,15 @@ class acp_extensions
case 'purge':
try
{
- if ($phpbb_extension_manager->purge_step($ext_name))
+ while ($phpbb_extension_manager->purge_step($ext_name))
{
- $template->assign_var('S_NEXT_STEP', true);
+ // Are we approaching the time limit? If so we want to pause the update and continue after refreshing
+ if ((time() - $start_time) >= $safe_time_limit)
+ {
+ $template->assign_var('S_NEXT_STEP', true);
- meta_refresh(0, $this->u_action . '&amp;action=purge&amp;ext_name=' . urlencode($ext_name));
+ meta_refresh(0, $this->u_action . '&amp;action=purge&amp;ext_name=' . urlencode($ext_name));
+ }
}
}
catch (phpbb_db_migration_exception $e)
diff --git a/phpBB/includes/acp/acp_groups.php b/phpBB/includes/acp/acp_groups.php
index 865810687b..c79699d465 100644
--- a/phpBB/includes/acp/acp_groups.php
+++ b/phpBB/includes/acp/acp_groups.php
@@ -87,6 +87,11 @@ class acp_groups
case 'approve':
case 'demote':
case 'promote':
+ if (!check_form_key($form_key))
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
+ }
+
if (!$group_id)
{
trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING);
@@ -259,6 +264,11 @@ class acp_groups
break;
case 'addusers':
+ if (!check_form_key($form_key))
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
+ }
+
if (!$group_id)
{
trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING);
@@ -381,15 +391,26 @@ class acp_groups
$submit_ary['avatar_width'] = 0;
$submit_ary['avatar_height'] = 0;
}
+
+ // Merge any avatar errors into the primary error array
+ $error = array_merge($error, $phpbb_avatar_manager->localize_errors($user, $avatar_error));
}
- // Validate the length of "Maximum number of allowed recipients per private message" setting.
- // We use 16777215 as a maximum because it matches MySQL unsigned mediumint maximum value
- // which is the lowest amongst DBMSes supported by phpBB3
- if ($max_recipients_error = validate_data($submit_ary, array('max_recipients' => array('num', false, 0, 16777215))))
+ /*
+ * Validate the length of "Maximum number of allowed recipients per
+ * private message" setting. We use 16777215 as a maximum because it matches
+ * MySQL unsigned mediumint maximum value which is the lowest amongst DBMSes
+ * supported by phpBB3. Also validate the submitted colour value.
+ */
+ $validation_checks = array(
+ 'max_recipients' => array('num', false, 0, 16777215),
+ 'colour' => array('hex_colour', true),
+ );
+
+ if ($validation_error = validate_data($submit_ary, $validation_checks))
{
// Replace "error" string with its real, localised form
- $error = array_merge($error, array_map(array(&$user, 'lang'), $max_recipients_error));
+ $error = array_merge($error, array_map(array(&$user, 'lang'), $validation_error));
}
if (!sizeof($error))
@@ -570,8 +591,11 @@ class acp_groups
$avatar = phpbb_get_group_avatar($group_row, 'GROUP_AVATAR', true);
- // Merge any avatar errors into the primary error array
- $error = array_merge($error, $phpbb_avatar_manager->localize_errors($user, $avatar_error));
+ if (isset($phpbb_avatar_manager) && !$update)
+ {
+ // Merge any avatar errors into the primary error array
+ $error = array_merge($error, $phpbb_avatar_manager->localize_errors($user, $avatar_error));
+ }
$back_link = request_var('back_link', '');
@@ -906,10 +930,12 @@ class acp_groups
case 'set_config_teampage':
$config->set('teampage_forums', $request->variable('teampage_forums', 0));
$config->set('teampage_memberships', $request->variable('teampage_memberships', 0));
+ trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action));
break;
case 'set_config_legend':
$config->set('legend_sort_groupname', $request->variable('legend_sort_groupname', 0));
+ trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action));
break;
}
}
diff --git a/phpBB/includes/acp/acp_modules.php b/phpBB/includes/acp/acp_modules.php
index 7c2ea86122..ab416fb406 100644
--- a/phpBB/includes/acp/acp_modules.php
+++ b/phpBB/includes/acp/acp_modules.php
@@ -544,81 +544,60 @@ class acp_modules
*/
function get_module_infos($module = '', $module_class = false, $use_all_available = false)
{
- global $phpbb_root_path, $phpEx;
+ global $phpbb_extension_manager, $phpbb_root_path, $phpEx;
$module_class = ($module_class === false) ? $this->module_class : $module_class;
$directory = $phpbb_root_path . 'includes/' . $module_class . '/info/';
$fileinfo = array();
- if (!$module)
- {
- global $phpbb_extension_manager;
-
- $finder = $phpbb_extension_manager->get_finder();
+ $finder = $phpbb_extension_manager->get_finder();
- $modules = $finder
- ->extension_suffix('_module')
- ->extension_directory("/$module_class")
- ->core_path("includes/$module_class/info/")
- ->core_prefix($module_class . '_')
- ->get_classes(true, $use_all_available);
+ $modules = $finder
+ ->extension_suffix('_module')
+ ->extension_directory("/$module_class")
+ ->core_path("includes/$module_class/info/")
+ ->core_prefix($module_class . '_')
+ ->get_classes(true, $use_all_available);
- foreach ($modules as $module)
+ foreach ($modules as $cur_module)
+ {
+ // Skip entries we do not need if we know the module we are
+ // looking for
+ if ($module && strpos($cur_module, $module) === false)
{
- $info_class = preg_replace('/_module$/', '_info', $module);
-
- // If the class does not exist it might be following the old
- // format. phpbb_acp_info_acp_foo needs to be turned into
- // acp_foo_info and the respective file has to be included
- // manually because it does not support auto loading
- if (!class_exists($info_class))
- {
- $info_class = str_replace("phpbb_{$module_class}_info_", '', $module) . '_info';
- if (file_exists($directory . $info_class . '.' . $phpEx))
- {
- include($directory . $info_class . '.' . $phpEx);
- }
- }
-
- if (class_exists($info_class))
- {
- $info = new $info_class();
- $module_info = $info->module();
-
- $main_class = (isset($module_info['filename'])) ? $module_info['filename'] : $module;
-
- $fileinfo[$main_class] = $module_info;
- }
+ continue;
}
- ksort($fileinfo);
- }
- else
- {
- $info_class = preg_replace('/_module$/', '_info', $module);
+ $info_class = preg_replace('/_module$/', '_info', $cur_module);
+ // If the class does not exist it might be following the old
+ // format. phpbb_acp_info_acp_foo needs to be turned into
+ // acp_foo_info and the respective file has to be included
+ // manually because it does not support auto loading
if (!class_exists($info_class))
{
- $info_class = $module . '_info';
- if (!class_exists($info_class) && file_exists($directory . $module . '.' . $phpEx))
+ $info_class_file = str_replace("phpbb_{$module_class}_info_", '', $cur_module);
+ $info_class = $info_class_file . '_info';
+ if (!class_exists($info_class) && file_exists($directory . $info_class_file . '.' . $phpEx))
{
- include($directory . $module . '.' . $phpEx);
+ include($directory . $info_class_file . '.' . $phpEx);
}
}
- // Get module title tag
if (class_exists($info_class))
{
$info = new $info_class();
$module_info = $info->module();
- $main_class = (isset($module_info['filename'])) ? $module_info['filename'] : $module;
+ $main_class = (isset($module_info['filename'])) ? $module_info['filename'] : $cur_module;
$fileinfo[$main_class] = $module_info;
}
}
+ ksort($fileinfo);
+
return $fileinfo;
}
diff --git a/phpBB/includes/acp/acp_permission_roles.php b/phpBB/includes/acp/acp_permission_roles.php
index 004187af84..e830479389 100644
--- a/phpBB/includes/acp/acp_permission_roles.php
+++ b/phpBB/includes/acp/acp_permission_roles.php
@@ -21,6 +21,7 @@ if (!defined('IN_PHPBB'))
class acp_permission_roles
{
var $u_action;
+ protected $auth_admin;
function main($id, $mode)
{
@@ -30,7 +31,7 @@ class acp_permission_roles
include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx);
include_once($phpbb_root_path . 'includes/acp/auth.' . $phpEx);
- $auth_admin = new auth_admin();
+ $this->auth_admin = new auth_admin();
$user->add_lang('acp/permissions');
add_permission_language();
@@ -210,7 +211,7 @@ class acp_permission_roles
}
// Now add the auth settings
- $auth_admin->acl_set_role($role_id, $auth_settings);
+ $this->auth_admin->acl_set_role($role_id, $auth_settings);
$role_name = (!empty($user->lang[$role_name])) ? $user->lang[$role_name] : $role_name;
add_log('admin', 'LOG_' . strtoupper($permission_type) . 'ROLE_' . strtoupper($action), $role_name);
@@ -343,7 +344,7 @@ class acp_permission_roles
// Get users/groups/forums using this preset...
if ($action == 'edit')
{
- $hold_ary = $auth_admin->get_role_mask($role_id);
+ $hold_ary = $this->auth_admin->get_role_mask($role_id);
if (sizeof($hold_ary))
{
@@ -354,7 +355,7 @@ class acp_permission_roles
'L_ROLE_ASSIGNED_TO' => sprintf($user->lang['ROLE_ASSIGNED_TO'], $role_name))
);
- $auth_admin->display_role_mask($hold_ary);
+ $this->auth_admin->display_role_mask($hold_ary);
}
}
@@ -445,8 +446,8 @@ class acp_permission_roles
'S_DISPLAY_ROLE_MASK' => true)
);
- $hold_ary = $auth_admin->get_role_mask($display_item);
- $auth_admin->display_role_mask($hold_ary);
+ $hold_ary = $this->auth_admin->get_role_mask($display_item);
+ $this->auth_admin->display_role_mask($hold_ary);
}
}
@@ -462,7 +463,7 @@ class acp_permission_roles
$auth_options = array(0 => $auth_options);
// Making use of auth_admin method here (we do not really want to change two similar code fragments)
- auth_admin::build_permission_array($auth_options, $content_array, $categories, $key_sort_array);
+ $this->auth_admin->build_permission_array($auth_options, $content_array, $categories, $key_sort_array);
$content_array = $content_array[0];
@@ -500,8 +501,6 @@ class acp_permission_roles
{
global $db;
- $auth_admin = new auth_admin();
-
// Get complete auth array
$sql = 'SELECT auth_option, auth_option_id
FROM ' . ACL_OPTIONS_TABLE . "
@@ -529,19 +528,19 @@ class acp_permission_roles
$db->sql_freeresult($result);
// Get role assignments
- $hold_ary = $auth_admin->get_role_mask($role_id);
+ $hold_ary = $this->auth_admin->get_role_mask($role_id);
// Re-assign permissions
foreach ($hold_ary as $forum_id => $forum_ary)
{
if (isset($forum_ary['users']))
{
- $auth_admin->acl_set('user', $forum_id, $forum_ary['users'], $auth_settings, 0, false);
+ $this->auth_admin->acl_set('user', $forum_id, $forum_ary['users'], $auth_settings, 0, false);
}
if (isset($forum_ary['groups']))
{
- $auth_admin->acl_set('group', $forum_id, $forum_ary['groups'], $auth_settings, 0, false);
+ $this->auth_admin->acl_set('group', $forum_id, $forum_ary['groups'], $auth_settings, 0, false);
}
}
@@ -563,6 +562,6 @@ class acp_permission_roles
WHERE role_id = ' . $role_id;
$db->sql_query($sql);
- $auth_admin->acl_clear_prefetch();
+ $this->auth_admin->acl_clear_prefetch();
}
}
diff --git a/phpBB/includes/acp/acp_update.php b/phpBB/includes/acp/acp_update.php
index f7f003781d..6b5407067d 100644
--- a/phpBB/includes/acp/acp_update.php
+++ b/phpBB/includes/acp/acp_update.php
@@ -38,7 +38,7 @@ class acp_update
$info = obtain_latest_version_info(request_var('versioncheck_force', false));
- if ($info === false)
+ if (empty($info))
{
trigger_error('VERSIONCHECK_FAIL', E_USER_WARNING);
}
diff --git a/phpBB/includes/auth/auth.php b/phpBB/includes/auth/auth.php
index 2535247571..279959974d 100644
--- a/phpBB/includes/auth/auth.php
+++ b/phpBB/includes/auth/auth.php
@@ -927,15 +927,14 @@ class phpbb_auth
*/
function login($username, $password, $autologin = false, $viewonline = 1, $admin = 0)
{
- global $config, $db, $user, $phpbb_root_path, $phpEx;
+ global $config, $db, $user, $phpbb_root_path, $phpEx, $phpbb_container;
$method = trim(basename($config['auth_method']));
- include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx);
- $method = 'login_' . $method;
- if (function_exists($method))
+ $provider = $phpbb_container->get('auth.provider.' . $method);
+ if ($provider)
{
- $login = $method($username, $password, $user->ip, $user->browser, $user->forwarded_for);
+ $login = $provider->login($username, $password);
// If the auth module wants us to create an empty profile do so and then treat the status as LOGIN_SUCCESS
if ($login['status'] == LOGIN_SUCCESS_CREATE_PROFILE)
diff --git a/phpBB/includes/auth/auth_apache.php b/phpBB/includes/auth/auth_apache.php
deleted file mode 100644
index 10b288aa09..0000000000
--- a/phpBB/includes/auth/auth_apache.php
+++ /dev/null
@@ -1,247 +0,0 @@
-<?php
-/**
-* Apache auth plug-in for phpBB3
-*
-* Authentication plug-ins is largely down to Sergey Kanareykin, our thanks to him.
-*
-* @package login
-* @copyright (c) 2005 phpBB Group
-* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
-*
-*/
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Checks whether the user is identified to apache
-* Only allow changing authentication to apache if the user is identified
-* Called in acp_board while setting authentication plugins
-*
-* @return boolean|string false if the user is identified and else an error message
-*/
-function init_apache()
-{
- global $user, $request;
-
- if (!$request->is_set('PHP_AUTH_USER', phpbb_request_interface::SERVER) || $user->data['username'] !== htmlspecialchars_decode($request->server('PHP_AUTH_USER')))
- {
- return $user->lang['APACHE_SETUP_BEFORE_USE'];
- }
- return false;
-}
-
-/**
-* Login function
-*/
-function login_apache(&$username, &$password)
-{
- global $db, $request;
-
- // do not allow empty password
- if (!$password)
- {
- return array(
- 'status' => LOGIN_ERROR_PASSWORD,
- 'error_msg' => 'NO_PASSWORD_SUPPLIED',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
-
- if (!$username)
- {
- return array(
- 'status' => LOGIN_ERROR_USERNAME,
- 'error_msg' => 'LOGIN_ERROR_USERNAME',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
-
- if (!$request->is_set('PHP_AUTH_USER', phpbb_request_interface::SERVER))
- {
- return array(
- 'status' => LOGIN_ERROR_EXTERNAL_AUTH,
- 'error_msg' => 'LOGIN_ERROR_EXTERNAL_AUTH_APACHE',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
-
- $php_auth_user = htmlspecialchars_decode($request->server('PHP_AUTH_USER'));
- $php_auth_pw = htmlspecialchars_decode($request->server('PHP_AUTH_PW'));
-
- if (!empty($php_auth_user) && !empty($php_auth_pw))
- {
- if ($php_auth_user !== $username)
- {
- return array(
- 'status' => LOGIN_ERROR_USERNAME,
- 'error_msg' => 'LOGIN_ERROR_USERNAME',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
-
- $sql = 'SELECT user_id, username, user_password, user_passchg, user_email, user_type
- FROM ' . USERS_TABLE . "
- WHERE username = '" . $db->sql_escape($php_auth_user) . "'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if ($row)
- {
- // User inactive...
- if ($row['user_type'] == USER_INACTIVE || $row['user_type'] == USER_IGNORE)
- {
- return array(
- 'status' => LOGIN_ERROR_ACTIVE,
- 'error_msg' => 'ACTIVE_ERROR',
- 'user_row' => $row,
- );
- }
-
- // Successful login...
- return array(
- 'status' => LOGIN_SUCCESS,
- 'error_msg' => false,
- 'user_row' => $row,
- );
- }
-
- // this is the user's first login so create an empty profile
- return array(
- 'status' => LOGIN_SUCCESS_CREATE_PROFILE,
- 'error_msg' => false,
- 'user_row' => user_row_apache($php_auth_user, $php_auth_pw),
- );
- }
-
- // Not logged into apache
- return array(
- 'status' => LOGIN_ERROR_EXTERNAL_AUTH,
- 'error_msg' => 'LOGIN_ERROR_EXTERNAL_AUTH_APACHE',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
-}
-
-/**
-* Autologin function
-*
-* @return array containing the user row or empty if no auto login should take place
-*/
-function autologin_apache()
-{
- global $db, $request;
-
- if (!$request->is_set('PHP_AUTH_USER', phpbb_request_interface::SERVER))
- {
- return array();
- }
-
- $php_auth_user = htmlspecialchars_decode($request->server('PHP_AUTH_USER'));
- $php_auth_pw = htmlspecialchars_decode($request->server('PHP_AUTH_PW'));
-
- if (!empty($php_auth_user) && !empty($php_auth_pw))
- {
- set_var($php_auth_user, $php_auth_user, 'string', true);
- set_var($php_auth_pw, $php_auth_pw, 'string', true);
-
- $sql = 'SELECT *
- FROM ' . USERS_TABLE . "
- WHERE username = '" . $db->sql_escape($php_auth_user) . "'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if ($row)
- {
- 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_clean = '" . $db->sql_escape(utf8_clean_string($php_auth_user)) . "'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if ($row)
- {
- return $row;
- }
- }
-
- return array();
-}
-
-/**
-* This function generates an array which can be passed to the user_add function in order to create a user
-*/
-function user_row_apache($username, $password)
-{
- global $db, $config, $user;
- // first retrieve default group id
- $sql = 'SELECT group_id
- FROM ' . GROUPS_TABLE . "
- WHERE group_name = '" . $db->sql_escape('REGISTERED') . "'
- AND group_type = " . GROUP_SPECIAL;
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if (!$row)
- {
- trigger_error('NO_GROUP');
- }
-
- // generate user account data
- return array(
- 'username' => $username,
- 'user_password' => phpbb_hash($password),
- 'user_email' => '',
- 'group_id' => (int) $row['group_id'],
- 'user_type' => USER_NORMAL,
- 'user_ip' => $user->ip,
- 'user_new' => ($config['new_member_post_limit']) ? 1 : 0,
- );
-}
-
-/**
-* The session validation function checks whether the user is still logged in
-*
-* @return boolean true if the given user is authenticated or false if the session should be closed
-*/
-function validate_session_apache(&$user)
-{
- global $request;
-
- // Check if PHP_AUTH_USER is set and handle this case
- if ($request->is_set('PHP_AUTH_USER', phpbb_request_interface::SERVER))
- {
- $php_auth_user = $request->server('PHP_AUTH_USER');
-
- return ($php_auth_user === $user['username']) ? true : false;
- }
-
- // PHP_AUTH_USER is not set. A valid session is now determined by the user type (anonymous/bot or not)
- if ($user['user_type'] == USER_IGNORE)
- {
- return true;
- }
-
- return false;
-}
diff --git a/phpBB/includes/auth/auth_db.php b/phpBB/includes/auth/auth_db.php
deleted file mode 100644
index ac944532a5..0000000000
--- a/phpBB/includes/auth/auth_db.php
+++ /dev/null
@@ -1,289 +0,0 @@
-<?php
-/**
-* Database auth plug-in for phpBB3
-*
-* Authentication plug-ins is largely down to Sergey Kanareykin, our thanks to him.
-*
-* This is for authentication via the integrated user table
-*
-* @package login
-* @copyright (c) 2005 phpBB Group
-* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
-*
-*/
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Login function
-*
-* @param string $username
-* @param string $password
-* @param string $ip IP address the login is taking place from. Used to
-* limit the number of login attempts per IP address.
-* @param string $browser The user agent used to login
-* @param string $forwarded_for X_FORWARDED_FOR header sent with login request
-* @return array A associative array of the format
-* array(
-* 'status' => status constant
-* 'error_msg' => string
-* 'user_row' => array
-* )
-*/
-function login_db($username, $password, $ip = '', $browser = '', $forwarded_for = '')
-{
- global $db, $config;
- global $request;
-
- // Auth plugins get the password untrimmed.
- // For compatibility we trim() here.
- $password = trim($password);
-
- // do not allow empty password
- if (!$password)
- {
- return array(
- 'status' => LOGIN_ERROR_PASSWORD,
- 'error_msg' => 'NO_PASSWORD_SUPPLIED',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
-
- if (!$username)
- {
- return array(
- 'status' => LOGIN_ERROR_USERNAME,
- 'error_msg' => 'LOGIN_ERROR_USERNAME',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
-
- $username_clean = utf8_clean_string($username);
-
- $sql = 'SELECT user_id, username, user_password, user_passchg, user_pass_convert, user_email, user_type, user_login_attempts
- FROM ' . USERS_TABLE . "
- WHERE username_clean = '" . $db->sql_escape($username_clean) . "'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if (($ip && !$config['ip_login_limit_use_forwarded']) ||
- ($forwarded_for && $config['ip_login_limit_use_forwarded']))
- {
- $sql = 'SELECT COUNT(*) AS attempts
- FROM ' . LOGIN_ATTEMPT_TABLE . '
- WHERE attempt_time > ' . (time() - (int) $config['ip_login_limit_time']);
- if ($config['ip_login_limit_use_forwarded'])
- {
- $sql .= " AND attempt_forwarded_for = '" . $db->sql_escape($forwarded_for) . "'";
- }
- else
- {
- $sql .= " AND attempt_ip = '" . $db->sql_escape($ip) . "' ";
- }
-
- $result = $db->sql_query($sql);
- $attempts = (int) $db->sql_fetchfield('attempts');
- $db->sql_freeresult($result);
-
- $attempt_data = array(
- 'attempt_ip' => $ip,
- 'attempt_browser' => trim(substr($browser, 0, 149)),
- 'attempt_forwarded_for' => $forwarded_for,
- 'attempt_time' => time(),
- 'user_id' => ($row) ? (int) $row['user_id'] : 0,
- 'username' => $username,
- 'username_clean' => $username_clean,
- );
- $sql = 'INSERT INTO ' . LOGIN_ATTEMPT_TABLE . $db->sql_build_array('INSERT', $attempt_data);
- $result = $db->sql_query($sql);
- }
- else
- {
- $attempts = 0;
- }
-
- if (!$row)
- {
- if ($config['ip_login_limit_max'] && $attempts >= $config['ip_login_limit_max'])
- {
- return array(
- 'status' => LOGIN_ERROR_ATTEMPTS,
- 'error_msg' => 'LOGIN_ERROR_ATTEMPTS',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
-
- return array(
- 'status' => LOGIN_ERROR_USERNAME,
- 'error_msg' => 'LOGIN_ERROR_USERNAME',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
-
- $show_captcha = ($config['max_login_attempts'] && $row['user_login_attempts'] >= $config['max_login_attempts']) ||
- ($config['ip_login_limit_max'] && $attempts >= $config['ip_login_limit_max']);
-
- // If there are too much login attempts, we need to check for an confirm image
- // Every auth module is able to define what to do by itself...
- if ($show_captcha)
- {
- // Visual Confirmation handling
- if (!class_exists('phpbb_captcha_factory', false))
- {
- global $phpbb_root_path, $phpEx;
- include ($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx);
- }
-
- $captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']);
- $captcha->init(CONFIRM_LOGIN);
- $vc_response = $captcha->validate($row);
- if ($vc_response)
- {
- return array(
- 'status' => LOGIN_ERROR_ATTEMPTS,
- 'error_msg' => 'LOGIN_ERROR_ATTEMPTS',
- 'user_row' => $row,
- );
- }
- else
- {
- $captcha->reset();
- }
-
- }
-
- // If the password convert flag is set we need to convert it
- if ($row['user_pass_convert'])
- {
- // enable super globals to get literal value
- // this is needed to prevent unicode normalization
- $super_globals_disabled = $request->super_globals_disabled();
- if ($super_globals_disabled)
- {
- $request->enable_super_globals();
- }
-
- // in phpBB2 passwords were used exactly as they were sent, with addslashes applied
- $password_old_format = isset($_REQUEST['password']) ? (string) $_REQUEST['password'] : '';
- $password_old_format = (!STRIP) ? addslashes($password_old_format) : $password_old_format;
- $password_new_format = $request->variable('password', '', true);
-
- if ($super_globals_disabled)
- {
- $request->disable_super_globals();
- }
-
- if ($password == $password_new_format)
- {
- if (!function_exists('utf8_to_cp1252'))
- {
- global $phpbb_root_path, $phpEx;
- include($phpbb_root_path . 'includes/utf/data/recode_basic.' . $phpEx);
- }
-
- // cp1252 is phpBB2's default encoding, characters outside ASCII range might work when converted into that encoding
- // plain md5 support left in for conversions from other systems.
- if ((strlen($row['user_password']) == 34 && (phpbb_check_hash(md5($password_old_format), $row['user_password']) || phpbb_check_hash(md5(utf8_to_cp1252($password_old_format)), $row['user_password'])))
- || (strlen($row['user_password']) == 32 && (md5($password_old_format) == $row['user_password'] || md5(utf8_to_cp1252($password_old_format)) == $row['user_password'])))
- {
- $hash = phpbb_hash($password_new_format);
-
- // Update the password in the users table to the new format and remove user_pass_convert flag
- $sql = 'UPDATE ' . USERS_TABLE . '
- SET user_password = \'' . $db->sql_escape($hash) . '\',
- user_pass_convert = 0
- WHERE user_id = ' . $row['user_id'];
- $db->sql_query($sql);
-
- $row['user_pass_convert'] = 0;
- $row['user_password'] = $hash;
- }
- else
- {
- // Although we weren't able to convert this password we have to
- // increase login attempt count to make sure this cannot be exploited
- $sql = 'UPDATE ' . USERS_TABLE . '
- SET user_login_attempts = user_login_attempts + 1
- WHERE user_id = ' . (int) $row['user_id'] . '
- AND user_login_attempts < ' . LOGIN_ATTEMPTS_MAX;
- $db->sql_query($sql);
-
- return array(
- 'status' => LOGIN_ERROR_PASSWORD_CONVERT,
- 'error_msg' => 'LOGIN_ERROR_PASSWORD_CONVERT',
- 'user_row' => $row,
- );
- }
- }
- }
-
- // Check password ...
- if (!$row['user_pass_convert'] && phpbb_check_hash($password, $row['user_password']))
- {
- // Check for old password hash...
- if (strlen($row['user_password']) == 32)
- {
- $hash = phpbb_hash($password);
-
- // Update the password in the users table to the new format
- $sql = 'UPDATE ' . USERS_TABLE . "
- SET user_password = '" . $db->sql_escape($hash) . "',
- user_pass_convert = 0
- WHERE user_id = {$row['user_id']}";
- $db->sql_query($sql);
-
- $row['user_password'] = $hash;
- }
-
- $sql = 'DELETE FROM ' . LOGIN_ATTEMPT_TABLE . '
- WHERE user_id = ' . $row['user_id'];
- $db->sql_query($sql);
-
- if ($row['user_login_attempts'] != 0)
- {
- // Successful, reset login attempts (the user passed all stages)
- $sql = 'UPDATE ' . USERS_TABLE . '
- SET user_login_attempts = 0
- WHERE user_id = ' . $row['user_id'];
- $db->sql_query($sql);
- }
-
- // User inactive...
- if ($row['user_type'] == USER_INACTIVE || $row['user_type'] == USER_IGNORE)
- {
- return array(
- 'status' => LOGIN_ERROR_ACTIVE,
- 'error_msg' => 'ACTIVE_ERROR',
- 'user_row' => $row,
- );
- }
-
- // Successful login... set user_login_attempts to zero...
- return array(
- 'status' => LOGIN_SUCCESS,
- 'error_msg' => false,
- 'user_row' => $row,
- );
- }
-
- // Password incorrect - increase login attempts
- $sql = 'UPDATE ' . USERS_TABLE . '
- SET user_login_attempts = user_login_attempts + 1
- WHERE user_id = ' . (int) $row['user_id'] . '
- AND user_login_attempts < ' . LOGIN_ATTEMPTS_MAX;
- $db->sql_query($sql);
-
- // Give status about wrong password...
- return array(
- 'status' => ($show_captcha) ? LOGIN_ERROR_ATTEMPTS : LOGIN_ERROR_PASSWORD,
- 'error_msg' => ($show_captcha) ? 'LOGIN_ERROR_ATTEMPTS' : 'LOGIN_ERROR_PASSWORD',
- 'user_row' => $row,
- );
-}
diff --git a/phpBB/includes/auth/auth_ldap.php b/phpBB/includes/auth/auth_ldap.php
deleted file mode 100644
index 24823f9ce7..0000000000
--- a/phpBB/includes/auth/auth_ldap.php
+++ /dev/null
@@ -1,350 +0,0 @@
-<?php
-/**
-*
-* LDAP auth plug-in for phpBB3
-*
-* Authentication plug-ins is largely down to Sergey Kanareykin, our thanks to him.
-*
-* @package login
-* @copyright (c) 2005 phpBB Group
-* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
-*
-*/
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Connect to ldap server
-* Only allow changing authentication to ldap if we can connect to the ldap server
-* Called in acp_board while setting authentication plugins
-*/
-function init_ldap()
-{
- global $config, $user;
-
- if (!@extension_loaded('ldap'))
- {
- return $user->lang['LDAP_NO_LDAP_EXTENSION'];
- }
-
- $config['ldap_port'] = (int) $config['ldap_port'];
- if ($config['ldap_port'])
- {
- $ldap = @ldap_connect($config['ldap_server'], $config['ldap_port']);
- }
- else
- {
- $ldap = @ldap_connect($config['ldap_server']);
- }
-
- if (!$ldap)
- {
- return $user->lang['LDAP_NO_SERVER_CONNECTION'];
- }
-
- @ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
- @ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
-
- if ($config['ldap_user'] || $config['ldap_password'])
- {
- if (!@ldap_bind($ldap, htmlspecialchars_decode($config['ldap_user']), htmlspecialchars_decode($config['ldap_password'])))
- {
- return $user->lang['LDAP_INCORRECT_USER_PASSWORD'];
- }
- }
-
- // ldap_connect only checks whether the specified server is valid, so the connection might still fail
- $search = @ldap_search(
- $ldap,
- htmlspecialchars_decode($config['ldap_base_dn']),
- ldap_user_filter($user->data['username']),
- (empty($config['ldap_email'])) ?
- array(htmlspecialchars_decode($config['ldap_uid'])) :
- array(htmlspecialchars_decode($config['ldap_uid']), htmlspecialchars_decode($config['ldap_email'])),
- 0,
- 1
- );
-
- if ($search === false)
- {
- return $user->lang['LDAP_SEARCH_FAILED'];
- }
-
- $result = @ldap_get_entries($ldap, $search);
-
- @ldap_close($ldap);
-
-
- if (!is_array($result) || sizeof($result) < 2)
- {
- return sprintf($user->lang['LDAP_NO_IDENTITY'], $user->data['username']);
- }
-
- if (!empty($config['ldap_email']) && !isset($result[0][htmlspecialchars_decode($config['ldap_email'])]))
- {
- return $user->lang['LDAP_NO_EMAIL'];
- }
-
- return false;
-}
-
-/**
-* Login function
-*/
-function login_ldap(&$username, &$password)
-{
- global $db, $config, $user;
-
- // do not allow empty password
- if (!$password)
- {
- return array(
- 'status' => LOGIN_ERROR_PASSWORD,
- 'error_msg' => 'NO_PASSWORD_SUPPLIED',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
-
- if (!$username)
- {
- return array(
- 'status' => LOGIN_ERROR_USERNAME,
- 'error_msg' => 'LOGIN_ERROR_USERNAME',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
-
- if (!@extension_loaded('ldap'))
- {
- return array(
- 'status' => LOGIN_ERROR_EXTERNAL_AUTH,
- 'error_msg' => 'LDAP_NO_LDAP_EXTENSION',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
-
- $config['ldap_port'] = (int) $config['ldap_port'];
- if ($config['ldap_port'])
- {
- $ldap = @ldap_connect($config['ldap_server'], $config['ldap_port']);
- }
- else
- {
- $ldap = @ldap_connect($config['ldap_server']);
- }
-
- if (!$ldap)
- {
- return array(
- 'status' => LOGIN_ERROR_EXTERNAL_AUTH,
- 'error_msg' => 'LDAP_NO_SERVER_CONNECTION',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
-
- @ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
- @ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
-
- if ($config['ldap_user'] || $config['ldap_password'])
- {
- if (!@ldap_bind($ldap, htmlspecialchars_decode($config['ldap_user']), htmlspecialchars_decode($config['ldap_password'])))
- {
- return array(
- 'status' => LOGIN_ERROR_EXTERNAL_AUTH,
- 'error_msg' => 'LDAP_NO_SERVER_CONNECTION',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
- }
-
- $search = @ldap_search(
- $ldap,
- htmlspecialchars_decode($config['ldap_base_dn']),
- ldap_user_filter($username),
- (empty($config['ldap_email'])) ?
- array(htmlspecialchars_decode($config['ldap_uid'])) :
- array(htmlspecialchars_decode($config['ldap_uid']), htmlspecialchars_decode($config['ldap_email'])),
- 0,
- 1
- );
-
- $ldap_result = @ldap_get_entries($ldap, $search);
-
- if (is_array($ldap_result) && sizeof($ldap_result) > 1)
- {
- 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_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if ($row)
- {
- unset($ldap_result);
-
- // User inactive...
- if ($row['user_type'] == USER_INACTIVE || $row['user_type'] == USER_IGNORE)
- {
- return array(
- 'status' => LOGIN_ERROR_ACTIVE,
- 'error_msg' => 'ACTIVE_ERROR',
- 'user_row' => $row,
- );
- }
-
- // Successful login... set user_login_attempts to zero...
- return array(
- 'status' => LOGIN_SUCCESS,
- 'error_msg' => false,
- 'user_row' => $row,
- );
- }
- else
- {
- // retrieve default group id
- $sql = 'SELECT group_id
- FROM ' . GROUPS_TABLE . "
- WHERE group_name = '" . $db->sql_escape('REGISTERED') . "'
- AND group_type = " . GROUP_SPECIAL;
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if (!$row)
- {
- trigger_error('NO_GROUP');
- }
-
- // generate user account data
- $ldap_user_row = array(
- 'username' => $username,
- 'user_password' => phpbb_hash($password),
- 'user_email' => (!empty($config['ldap_email'])) ? utf8_htmlspecialchars($ldap_result[0][htmlspecialchars_decode($config['ldap_email'])][0]) : '',
- 'group_id' => (int) $row['group_id'],
- 'user_type' => USER_NORMAL,
- 'user_ip' => $user->ip,
- 'user_new' => ($config['new_member_post_limit']) ? 1 : 0,
- );
-
- unset($ldap_result);
-
- // this is the user's first login so create an empty profile
- return array(
- 'status' => LOGIN_SUCCESS_CREATE_PROFILE,
- 'error_msg' => false,
- 'user_row' => $ldap_user_row,
- );
- }
- }
- else
- {
- unset($ldap_result);
- @ldap_close($ldap);
-
- // Give status about wrong password...
- return array(
- 'status' => LOGIN_ERROR_PASSWORD,
- 'error_msg' => 'LOGIN_ERROR_PASSWORD',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
- }
-
- @ldap_close($ldap);
-
- return array(
- 'status' => LOGIN_ERROR_USERNAME,
- 'error_msg' => 'LOGIN_ERROR_USERNAME',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
-}
-
-/**
-* Generates a filter string for ldap_search to find a user
-*
-* @param $username string Username identifying the searched user
-*
-* @return string A filter string for ldap_search
-*/
-function ldap_user_filter($username)
-{
- global $config;
-
- $filter = '(' . $config['ldap_uid'] . '=' . ldap_escape(htmlspecialchars_decode($username)) . ')';
- if ($config['ldap_user_filter'])
- {
- $_filter = ($config['ldap_user_filter'][0] == '(' && substr($config['ldap_user_filter'], -1) == ')') ? $config['ldap_user_filter'] : "({$config['ldap_user_filter']})";
- $filter = "(&{$filter}{$_filter})";
- }
- return $filter;
-}
-
-/**
-* Escapes an LDAP AttributeValue
-*/
-function ldap_escape($string)
-{
- return str_replace(array('*', '\\', '(', ')'), array('\\*', '\\\\', '\\(', '\\)'), $string);
-}
-
-/**
-* This function is used to output any required fields in the authentication
-* admin panel. It also defines any required configuration table fields.
-*/
-function acp_ldap(&$new)
-{
- global $user;
-
- $tpl = '
-
- <dl>
- <dt><label for="ldap_server">' . $user->lang['LDAP_SERVER'] . $user->lang['COLON'] . '</label><br /><span>' . $user->lang['LDAP_SERVER_EXPLAIN'] . '</span></dt>
- <dd><input type="text" id="ldap_server" size="40" name="config[ldap_server]" value="' . $new['ldap_server'] . '" /></dd>
- </dl>
- <dl>
- <dt><label for="ldap_port">' . $user->lang['LDAP_PORT'] . $user->lang['COLON'] . '</label><br /><span>' . $user->lang['LDAP_PORT_EXPLAIN'] . '</span></dt>
- <dd><input type="text" id="ldap_port" size="40" name="config[ldap_port]" value="' . $new['ldap_port'] . '" /></dd>
- </dl>
- <dl>
- <dt><label for="ldap_dn">' . $user->lang['LDAP_DN'] . $user->lang['COLON'] . '</label><br /><span>' . $user->lang['LDAP_DN_EXPLAIN'] . '</span></dt>
- <dd><input type="text" id="ldap_dn" size="40" name="config[ldap_base_dn]" value="' . $new['ldap_base_dn'] . '" /></dd>
- </dl>
- <dl>
- <dt><label for="ldap_uid">' . $user->lang['LDAP_UID'] . $user->lang['COLON'] . '</label><br /><span>' . $user->lang['LDAP_UID_EXPLAIN'] . '</span></dt>
- <dd><input type="text" id="ldap_uid" size="40" name="config[ldap_uid]" value="' . $new['ldap_uid'] . '" /></dd>
- </dl>
- <dl>
- <dt><label for="ldap_user_filter">' . $user->lang['LDAP_USER_FILTER'] . $user->lang['COLON'] . '</label><br /><span>' . $user->lang['LDAP_USER_FILTER_EXPLAIN'] . '</span></dt>
- <dd><input type="text" id="ldap_user_filter" size="40" name="config[ldap_user_filter]" value="' . $new['ldap_user_filter'] . '" /></dd>
- </dl>
- <dl>
- <dt><label for="ldap_email">' . $user->lang['LDAP_EMAIL'] . $user->lang['COLON'] . '</label><br /><span>' . $user->lang['LDAP_EMAIL_EXPLAIN'] . '</span></dt>
- <dd><input type="text" id="ldap_email" size="40" name="config[ldap_email]" value="' . $new['ldap_email'] . '" /></dd>
- </dl>
- <dl>
- <dt><label for="ldap_user">' . $user->lang['LDAP_USER'] . $user->lang['COLON'] . '</label><br /><span>' . $user->lang['LDAP_USER_EXPLAIN'] . '</span></dt>
- <dd><input type="text" id="ldap_user" size="40" name="config[ldap_user]" value="' . $new['ldap_user'] . '" /></dd>
- </dl>
- <dl>
- <dt><label for="ldap_password">' . $user->lang['LDAP_PASSWORD'] . $user->lang['COLON'] . '</label><br /><span>' . $user->lang['LDAP_PASSWORD_EXPLAIN'] . '</span></dt>
- <dd><input type="password" id="ldap_password" size="40" name="config[ldap_password]" value="' . $new['ldap_password'] . '" autocomplete="off" /></dd>
- </dl>
- ';
-
- // These are fields required in the config table
- return array(
- 'tpl' => $tpl,
- 'config' => array('ldap_server', 'ldap_port', 'ldap_base_dn', 'ldap_uid', 'ldap_user_filter', 'ldap_email', 'ldap_user', 'ldap_password')
- );
-}
diff --git a/phpBB/includes/auth/provider/apache.php b/phpBB/includes/auth/provider/apache.php
new file mode 100644
index 0000000000..5f6f2862b6
--- /dev/null
+++ b/phpBB/includes/auth/provider/apache.php
@@ -0,0 +1,275 @@
+<?php
+/**
+*
+* @package auth
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+ * Apache authentication provider for phpBB3
+ *
+ * @package auth
+ */
+class phpbb_auth_provider_apache implements phpbb_auth_provider_interface
+{
+ /**
+ * Apache Authentication Constructor
+ *
+ * @param phpbb_db_driver $db
+ * @param phpbb_config $config
+ * @param phpbb_request $request
+ * @param phpbb_user $user
+ * @param string $phpbb_root_path
+ * @param string $php_ext
+ */
+ public function __construct(phpbb_db_driver $db, phpbb_config $config, phpbb_request $request, phpbb_user $user, $phpbb_root_path, $php_ext)
+ {
+ $this->db = $db;
+ $this->config = $config;
+ $this->request = $request;
+ $this->user = $user;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function init()
+ {
+ if (!$this->request->is_set('PHP_AUTH_USER', phpbb_request_interface::SERVER) || $this->user->data['username'] !== htmlspecialchars_decode($this->request->server('PHP_AUTH_USER')))
+ {
+ return $this->user->lang['APACHE_SETUP_BEFORE_USE'];
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function login($username, $password)
+ {
+ // do not allow empty password
+ if (!$password)
+ {
+ return array(
+ 'status' => LOGIN_ERROR_PASSWORD,
+ 'error_msg' => 'NO_PASSWORD_SUPPLIED',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ if (!$username)
+ {
+ return array(
+ 'status' => LOGIN_ERROR_USERNAME,
+ 'error_msg' => 'LOGIN_ERROR_USERNAME',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ if (!$this->request->is_set('PHP_AUTH_USER', phpbb_request_interface::SERVER))
+ {
+ return array(
+ 'status' => LOGIN_ERROR_EXTERNAL_AUTH,
+ 'error_msg' => 'LOGIN_ERROR_EXTERNAL_AUTH_APACHE',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ $php_auth_user = htmlspecialchars_decode($this->request->server('PHP_AUTH_USER'));
+ $php_auth_pw = htmlspecialchars_decode($this->request->server('PHP_AUTH_PW'));
+
+ if (!empty($php_auth_user) && !empty($php_auth_pw))
+ {
+ if ($php_auth_user !== $username)
+ {
+ return array(
+ 'status' => LOGIN_ERROR_USERNAME,
+ 'error_msg' => 'LOGIN_ERROR_USERNAME',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ $sql = 'SELECT user_id, username, user_password, user_passchg, user_email, user_type
+ FROM ' . USERS_TABLE . "
+ WHERE username = '" . $this->db->sql_escape($php_auth_user) . "'";
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if ($row)
+ {
+ // User inactive...
+ if ($row['user_type'] == USER_INACTIVE || $row['user_type'] == USER_IGNORE)
+ {
+ return array(
+ 'status' => LOGIN_ERROR_ACTIVE,
+ 'error_msg' => 'ACTIVE_ERROR',
+ 'user_row' => $row,
+ );
+ }
+
+ // Successful login...
+ return array(
+ 'status' => LOGIN_SUCCESS,
+ 'error_msg' => false,
+ 'user_row' => $row,
+ );
+ }
+
+ // this is the user's first login so create an empty profile
+ return array(
+ 'status' => LOGIN_SUCCESS_CREATE_PROFILE,
+ 'error_msg' => false,
+ 'user_row' => user_row_apache($php_auth_user, $php_auth_pw),
+ );
+ }
+
+ // Not logged into apache
+ return array(
+ 'status' => LOGIN_ERROR_EXTERNAL_AUTH,
+ 'error_msg' => 'LOGIN_ERROR_EXTERNAL_AUTH_APACHE',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function autologin()
+ {
+ if (!$this->request->is_set('PHP_AUTH_USER', phpbb_request_interface::SERVER))
+ {
+ return array();
+ }
+
+ $php_auth_user = htmlspecialchars_decode($this->request->server('PHP_AUTH_USER'));
+ $php_auth_pw = htmlspecialchars_decode($this->request->server('PHP_AUTH_PW'));
+
+ if (!empty($php_auth_user) && !empty($php_auth_pw))
+ {
+ set_var($php_auth_user, $php_auth_user, 'string', true);
+ set_var($php_auth_pw, $php_auth_pw, 'string', true);
+
+ $sql = 'SELECT *
+ FROM ' . USERS_TABLE . "
+ WHERE username = '" . $this->db->sql_escape($php_auth_user) . "'";
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if ($row)
+ {
+ return ($row['user_type'] == USER_INACTIVE || $row['user_type'] == USER_IGNORE) ? array() : $row;
+ }
+
+ if (!function_exists('user_add'))
+ {
+ include($this->phpbb_root_path . 'includes/functions_user.' . $this->php_ext);
+ }
+
+ // 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_clean = '" . $this->db->sql_escape(utf8_clean_string($php_auth_user)) . "'";
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if ($row)
+ {
+ return $row;
+ }
+ }
+
+ return array();
+ }
+
+ /**
+ * This function generates an array which can be passed to the user_add
+ * function in order to create a user
+ *
+ * @param string $username The username of the new user.
+ * @param string $password The password of the new user.
+ * @return array Contains data that can be passed directly to
+ * the user_add function.
+ */
+ private function user_row($username, $password)
+ {
+ // first retrieve default group id
+ $sql = 'SELECT group_id
+ FROM ' . GROUPS_TABLE . "
+ WHERE group_name = '" . $this->db->sql_escape('REGISTERED') . "'
+ AND group_type = " . GROUP_SPECIAL;
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if (!$row)
+ {
+ trigger_error('NO_GROUP');
+ }
+
+ // generate user account data
+ return array(
+ 'username' => $username,
+ 'user_password' => phpbb_hash($password),
+ 'user_email' => '',
+ 'group_id' => (int) $row['group_id'],
+ 'user_type' => USER_NORMAL,
+ 'user_ip' => $this->user->ip,
+ 'user_new' => ($this->config['new_member_post_limit']) ? 1 : 0,
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validate_session($user)
+ {
+ // Check if PHP_AUTH_USER is set and handle this case
+ if ($this->request->is_set('PHP_AUTH_USER', phpbb_request_interface::SERVER))
+ {
+ $php_auth_user = $this->request->server('PHP_AUTH_USER');
+
+ return ($php_auth_user === $user['username']) ? true : false;
+ }
+
+ // PHP_AUTH_USER is not set. A valid session is now determined by the user type (anonymous/bot or not)
+ if ($user['user_type'] == USER_IGNORE)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function acp($new)
+ {
+ return;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function logout($data, $new_session)
+ {
+ return;
+ }
+}
diff --git a/phpBB/includes/auth/provider/db.php b/phpBB/includes/auth/provider/db.php
new file mode 100644
index 0000000000..894041c9cf
--- /dev/null
+++ b/phpBB/includes/auth/provider/db.php
@@ -0,0 +1,337 @@
+<?php
+/**
+*
+* @package auth
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+ * Database authentication provider for phpBB3
+ *
+ * This is for authentication via the integrated user table
+ *
+ * @package auth
+ */
+class phpbb_auth_provider_db implements phpbb_auth_provider_interface
+{
+
+ /**
+ * Database Authentication Constructor
+ *
+ * @param phpbb_db_driver $db
+ * @param phpbb_config $config
+ * @param phpbb_request $request
+ * @param phpbb_user $user
+ * @param string $phpbb_root_path
+ * @param string $php_ext
+ */
+ public function __construct(phpbb_db_driver $db, phpbb_config $config, phpbb_request $request, phpbb_user $user, $phpbb_root_path, $php_ext)
+ {
+ $this->db = $db;
+ $this->config = $config;
+ $this->request = $request;
+ $this->user = $user;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function init()
+ {
+ return;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function login($username, $password)
+ {
+ // Auth plugins get the password untrimmed.
+ // For compatibility we trim() here.
+ $password = trim($password);
+
+ // do not allow empty password
+ if (!$password)
+ {
+ return array(
+ 'status' => LOGIN_ERROR_PASSWORD,
+ 'error_msg' => 'NO_PASSWORD_SUPPLIED',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ if (!$username)
+ {
+ return array(
+ 'status' => LOGIN_ERROR_USERNAME,
+ 'error_msg' => 'LOGIN_ERROR_USERNAME',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ $username_clean = utf8_clean_string($username);
+
+ $sql = 'SELECT user_id, username, user_password, user_passchg, user_pass_convert, user_email, user_type, user_login_attempts
+ FROM ' . USERS_TABLE . "
+ WHERE username_clean = '" . $this->db->sql_escape($username_clean) . "'";
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if (($this->user->ip && !$this->config['ip_login_limit_use_forwarded']) ||
+ ($this->user->forwarded_for && $this->config['ip_login_limit_use_forwarded']))
+ {
+ $sql = 'SELECT COUNT(*) AS attempts
+ FROM ' . LOGIN_ATTEMPT_TABLE . '
+ WHERE attempt_time > ' . (time() - (int) $this->config['ip_login_limit_time']);
+ if ($this->config['ip_login_limit_use_forwarded'])
+ {
+ $sql .= " AND attempt_forwarded_for = '" . $this->db->sql_escape($this->user->forwarded_for) . "'";
+ }
+ else
+ {
+ $sql .= " AND attempt_ip = '" . $this->db->sql_escape($this->user->ip) . "' ";
+ }
+
+ $result = $this->db->sql_query($sql);
+ $attempts = (int) $this->db->sql_fetchfield('attempts');
+ $this->db->sql_freeresult($result);
+
+ $attempt_data = array(
+ 'attempt_ip' => $this->user->ip,
+ 'attempt_browser' => trim(substr($this->user->browser, 0, 149)),
+ 'attempt_forwarded_for' => $this->user->forwarded_for,
+ 'attempt_time' => time(),
+ 'user_id' => ($row) ? (int) $row['user_id'] : 0,
+ 'username' => $username,
+ 'username_clean' => $username_clean,
+ );
+ $sql = 'INSERT INTO ' . LOGIN_ATTEMPT_TABLE . $this->db->sql_build_array('INSERT', $attempt_data);
+ $result = $this->db->sql_query($sql);
+ }
+ else
+ {
+ $attempts = 0;
+ }
+
+ if (!$row)
+ {
+ if ($this->config['ip_login_limit_max'] && $attempts >= $this->config['ip_login_limit_max'])
+ {
+ return array(
+ 'status' => LOGIN_ERROR_ATTEMPTS,
+ 'error_msg' => 'LOGIN_ERROR_ATTEMPTS',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ return array(
+ 'status' => LOGIN_ERROR_USERNAME,
+ 'error_msg' => 'LOGIN_ERROR_USERNAME',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ $show_captcha = ($this->config['max_login_attempts'] && $row['user_login_attempts'] >= $this->config['max_login_attempts']) ||
+ ($this->config['ip_login_limit_max'] && $attempts >= $this->config['ip_login_limit_max']);
+
+ // If there are too many login attempts, we need to check for a confirm image
+ // Every auth module is able to define what to do by itself...
+ if ($show_captcha)
+ {
+ // Visual Confirmation handling
+ if (!class_exists('phpbb_captcha_factory', false))
+ {
+ include ($this->phpbb_root_path . 'includes/captcha/captcha_factory.' . $this->php_ext);
+ }
+
+ $captcha = phpbb_captcha_factory::get_instance($this->config['captcha_plugin']);
+ $captcha->init(CONFIRM_LOGIN);
+ $vc_response = $captcha->validate($row);
+ if ($vc_response)
+ {
+ return array(
+ 'status' => LOGIN_ERROR_ATTEMPTS,
+ 'error_msg' => 'LOGIN_ERROR_ATTEMPTS',
+ 'user_row' => $row,
+ );
+ }
+ else
+ {
+ $captcha->reset();
+ }
+
+ }
+
+ // If the password convert flag is set we need to convert it
+ if ($row['user_pass_convert'])
+ {
+ // enable super globals to get literal value
+ // this is needed to prevent unicode normalization
+ $super_globals_disabled = $this->request->super_globals_disabled();
+ if ($super_globals_disabled)
+ {
+ $this->request->enable_super_globals();
+ }
+
+ // in phpBB2 passwords were used exactly as they were sent, with addslashes applied
+ $password_old_format = isset($_REQUEST['password']) ? (string) $_REQUEST['password'] : '';
+ $password_old_format = (!STRIP) ? addslashes($password_old_format) : $password_old_format;
+ $password_new_format = $this->request->variable('password', '', true);
+
+ if ($super_globals_disabled)
+ {
+ $this->request->disable_super_globals();
+ }
+
+ if ($password == $password_new_format)
+ {
+ if (!function_exists('utf8_to_cp1252'))
+ {
+ include($this->phpbb_root_path . 'includes/utf/data/recode_basic.' . $this->php_ext);
+ }
+
+ // cp1252 is phpBB2's default encoding, characters outside ASCII range might work when converted into that encoding
+ // plain md5 support left in for conversions from other systems.
+ if ((strlen($row['user_password']) == 34 && (phpbb_check_hash(md5($password_old_format), $row['user_password']) || phpbb_check_hash(md5(utf8_to_cp1252($password_old_format)), $row['user_password'])))
+ || (strlen($row['user_password']) == 32 && (md5($password_old_format) == $row['user_password'] || md5(utf8_to_cp1252($password_old_format)) == $row['user_password'])))
+ {
+ $hash = phpbb_hash($password_new_format);
+
+ // Update the password in the users table to the new format and remove user_pass_convert flag
+ $sql = 'UPDATE ' . USERS_TABLE . '
+ SET user_password = \'' . $this->db->sql_escape($hash) . '\',
+ user_pass_convert = 0
+ WHERE user_id = ' . $row['user_id'];
+ $this->db->sql_query($sql);
+
+ $row['user_pass_convert'] = 0;
+ $row['user_password'] = $hash;
+ }
+ else
+ {
+ // Although we weren't able to convert this password we have to
+ // increase login attempt count to make sure this cannot be exploited
+ $sql = 'UPDATE ' . USERS_TABLE . '
+ SET user_login_attempts = user_login_attempts + 1
+ WHERE user_id = ' . (int) $row['user_id'] . '
+ AND user_login_attempts < ' . LOGIN_ATTEMPTS_MAX;
+ $this->db->sql_query($sql);
+
+ return array(
+ 'status' => LOGIN_ERROR_PASSWORD_CONVERT,
+ 'error_msg' => 'LOGIN_ERROR_PASSWORD_CONVERT',
+ 'user_row' => $row,
+ );
+ }
+ }
+ }
+
+ // Check password ...
+ if (!$row['user_pass_convert'] && phpbb_check_hash($password, $row['user_password']))
+ {
+ // Check for old password hash...
+ if (strlen($row['user_password']) == 32)
+ {
+ $hash = phpbb_hash($password);
+
+ // Update the password in the users table to the new format
+ $sql = 'UPDATE ' . USERS_TABLE . "
+ SET user_password = '" . $this->db->sql_escape($hash) . "',
+ user_pass_convert = 0
+ WHERE user_id = {$row['user_id']}";
+ $this->db->sql_query($sql);
+
+ $row['user_password'] = $hash;
+ }
+
+ $sql = 'DELETE FROM ' . LOGIN_ATTEMPT_TABLE . '
+ WHERE user_id = ' . $row['user_id'];
+ $this->db->sql_query($sql);
+
+ if ($row['user_login_attempts'] != 0)
+ {
+ // Successful, reset login attempts (the user passed all stages)
+ $sql = 'UPDATE ' . USERS_TABLE . '
+ SET user_login_attempts = 0
+ WHERE user_id = ' . $row['user_id'];
+ $this->db->sql_query($sql);
+ }
+
+ // User inactive...
+ if ($row['user_type'] == USER_INACTIVE || $row['user_type'] == USER_IGNORE)
+ {
+ return array(
+ 'status' => LOGIN_ERROR_ACTIVE,
+ 'error_msg' => 'ACTIVE_ERROR',
+ 'user_row' => $row,
+ );
+ }
+
+ // Successful login... set user_login_attempts to zero...
+ return array(
+ 'status' => LOGIN_SUCCESS,
+ 'error_msg' => false,
+ 'user_row' => $row,
+ );
+ }
+
+ // Password incorrect - increase login attempts
+ $sql = 'UPDATE ' . USERS_TABLE . '
+ SET user_login_attempts = user_login_attempts + 1
+ WHERE user_id = ' . (int) $row['user_id'] . '
+ AND user_login_attempts < ' . LOGIN_ATTEMPTS_MAX;
+ $this->db->sql_query($sql);
+
+ // Give status about wrong password...
+ return array(
+ 'status' => ($show_captcha) ? LOGIN_ERROR_ATTEMPTS : LOGIN_ERROR_PASSWORD,
+ 'error_msg' => ($show_captcha) ? 'LOGIN_ERROR_ATTEMPTS' : 'LOGIN_ERROR_PASSWORD',
+ 'user_row' => $row,
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function autologin()
+ {
+ return;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function acp($new)
+ {
+ return;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function logout($data, $new_session)
+ {
+ return;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validate_session($user)
+ {
+ return;
+ }
+}
diff --git a/phpBB/includes/auth/provider/index.htm b/phpBB/includes/auth/provider/index.htm
new file mode 100644
index 0000000000..ee1f723a7d
--- /dev/null
+++ b/phpBB/includes/auth/provider/index.htm
@@ -0,0 +1,10 @@
+<html>
+<head>
+<title></title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</head>
+
+<body bgcolor="#FFFFFF" text="#000000">
+
+</body>
+</html>
diff --git a/phpBB/includes/auth/provider/interface.php b/phpBB/includes/auth/provider/interface.php
new file mode 100644
index 0000000000..2d1935f8f0
--- /dev/null
+++ b/phpBB/includes/auth/provider/interface.php
@@ -0,0 +1,93 @@
+<?php
+/**
+*
+* @package auth
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+ * The interface authentication provider classes have to implement.
+ *
+ * @package auth
+ */
+interface phpbb_auth_provider_interface
+{
+ /**
+ * Checks whether the user is currently identified to the authentication
+ * provider.
+ * Called in acp_board while setting authentication plugins.
+ * Changing to an authentication provider will not be permitted in acp_board
+ * if there is an error.
+ *
+ * @return boolean|string False if the user is identified, otherwise an
+ * error message, or null if not implemented.
+ */
+ public function init();
+
+ /**
+ * Performs login.
+ *
+ * @param string $username The name of the user being authenticated.
+ * @param string $password The password of the user.
+ * @return array An associative array of the format:
+ * array(
+ * 'status' => status constant
+ * 'error_msg' => string
+ * 'user_row' => array
+ * )
+ */
+ public function login($username, $password);
+
+ /**
+ * Autologin function
+ *
+ * @return array|null containing the user row, empty if no auto login
+ * should take place, or null if not impletmented.
+ */
+ public function autologin();
+
+ /**
+ * This function is used to output any required fields in the authentication
+ * admin panel. It also defines any required configuration table fields.
+ *
+ * @param array $new Contains the new configuration values that have
+ * been set in acp_board.
+ * @return array|null Returns null if not implemented or an array of the
+ * form:
+ * array(
+ * 'tpl' => string
+ * 'config' => array
+ * )
+ */
+ public function acp($new);
+
+ /**
+ * Performs additional actions during logout.
+ *
+ * @param array $data An array corresponding to
+ * phpbb_session::data
+ * @param boolean $new_session True for a new session, false for no new
+ * session.
+ */
+ public function logout($data, $new_session);
+
+ /**
+ * The session validation function checks whether the user is still logged
+ * into phpBB.
+ *
+ * @param array $user
+ * @return boolean true if the given user is authenticated, false if the
+ * session should be closed, or null if not implemented.
+ */
+ public function validate_session($user);
+}
diff --git a/phpBB/includes/auth/provider/ldap.php b/phpBB/includes/auth/provider/ldap.php
new file mode 100644
index 0000000000..f67c1e9247
--- /dev/null
+++ b/phpBB/includes/auth/provider/ldap.php
@@ -0,0 +1,386 @@
+<?php
+/**
+*
+* @package auth
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+ * Database authentication provider for phpBB3
+ *
+ * This is for authentication via the integrated user table
+ *
+ * @package auth
+ */
+class phpbb_auth_provider_ldap implements phpbb_auth_provider_interface
+{
+ /**
+ * LDAP Authentication Constructor
+ *
+ * @param phpbb_db_driver $db
+ * @param phpbb_config $config
+ * @param phpbb_user $user
+ */
+ public function __construct(phpbb_db_driver $db, phpbb_config $config, phpbb_user $user)
+ {
+ $this->db = $db;
+ $this->config = $config;
+ $this->user = $user;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function init()
+ {
+ if (!@extension_loaded('ldap'))
+ {
+ return $this->user->lang['LDAP_NO_LDAP_EXTENSION'];
+ }
+
+ $this->config['ldap_port'] = (int) $this->config['ldap_port'];
+ if ($this->config['ldap_port'])
+ {
+ $ldap = @ldap_connect($this->config['ldap_server'], $this->config['ldap_port']);
+ }
+ else
+ {
+ $ldap = @ldap_connect($this->config['ldap_server']);
+ }
+
+ if (!$ldap)
+ {
+ return $this->user->lang['LDAP_NO_SERVER_CONNECTION'];
+ }
+
+ @ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
+ @ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
+
+ if ($this->config['ldap_user'] || $this->config['ldap_password'])
+ {
+ if (!@ldap_bind($ldap, htmlspecialchars_decode($this->config['ldap_user']), htmlspecialchars_decode($this->config['ldap_password'])))
+ {
+ return $this->user->lang['LDAP_INCORRECT_USER_PASSWORD'];
+ }
+ }
+
+ // ldap_connect only checks whether the specified server is valid, so the connection might still fail
+ $search = @ldap_search(
+ $ldap,
+ htmlspecialchars_decode($this->config['ldap_base_dn']),
+ $this->ldap_user_filter($this->user->data['username']),
+ (empty($this->config['ldap_email'])) ?
+ array(htmlspecialchars_decode($this->config['ldap_uid'])) :
+ array(htmlspecialchars_decode($this->config['ldap_uid']), htmlspecialchars_decode($this->config['ldap_email'])),
+ 0,
+ 1
+ );
+
+ if ($search === false)
+ {
+ return $this->user->lang['LDAP_SEARCH_FAILED'];
+ }
+
+ $result = @ldap_get_entries($ldap, $search);
+
+ @ldap_close($ldap);
+
+
+ if (!is_array($result) || sizeof($result) < 2)
+ {
+ return sprintf($this->user->lang['LDAP_NO_IDENTITY'], $this->user->data['username']);
+ }
+
+ if (!empty($this->config['ldap_email']) && !isset($result[0][htmlspecialchars_decode($this->config['ldap_email'])]))
+ {
+ return $this->user->lang['LDAP_NO_EMAIL'];
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function login($username, $password)
+ {
+ // do not allow empty password
+ if (!$password)
+ {
+ return array(
+ 'status' => LOGIN_ERROR_PASSWORD,
+ 'error_msg' => 'NO_PASSWORD_SUPPLIED',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ if (!$username)
+ {
+ return array(
+ 'status' => LOGIN_ERROR_USERNAME,
+ 'error_msg' => 'LOGIN_ERROR_USERNAME',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ if (!@extension_loaded('ldap'))
+ {
+ return array(
+ 'status' => LOGIN_ERROR_EXTERNAL_AUTH,
+ 'error_msg' => 'LDAP_NO_LDAP_EXTENSION',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ $this->config['ldap_port'] = (int) $this->config['ldap_port'];
+ if ($this->config['ldap_port'])
+ {
+ $ldap = @ldap_connect($this->config['ldap_server'], $this->config['ldap_port']);
+ }
+ else
+ {
+ $ldap = @ldap_connect($this->config['ldap_server']);
+ }
+
+ if (!$ldap)
+ {
+ return array(
+ 'status' => LOGIN_ERROR_EXTERNAL_AUTH,
+ 'error_msg' => 'LDAP_NO_SERVER_CONNECTION',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ @ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
+ @ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
+
+ if ($this->config['ldap_user'] || $this->config['ldap_password'])
+ {
+ if (!@ldap_bind($ldap, htmlspecialchars_decode($this->config['ldap_user']), htmlspecialchars_decode($this->config['ldap_password'])))
+ {
+ return array(
+ 'status' => LOGIN_ERROR_EXTERNAL_AUTH,
+ 'error_msg' => 'LDAP_NO_SERVER_CONNECTION',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+ }
+
+ $search = @ldap_search(
+ $ldap,
+ htmlspecialchars_decode($this->config['ldap_base_dn']),
+ $this->ldap_user_filter($username),
+ (empty($this->config['ldap_email'])) ?
+ array(htmlspecialchars_decode($this->config['ldap_uid'])) :
+ array(htmlspecialchars_decode($this->config['ldap_uid']), htmlspecialchars_decode($this->config['ldap_email'])),
+ 0,
+ 1
+ );
+
+ $ldap_result = @ldap_get_entries($ldap, $search);
+
+ if (is_array($ldap_result) && sizeof($ldap_result) > 1)
+ {
+ 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_clean = '" . $this->db->sql_escape(utf8_clean_string($username)) . "'";
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if ($row)
+ {
+ unset($ldap_result);
+
+ // User inactive...
+ if ($row['user_type'] == USER_INACTIVE || $row['user_type'] == USER_IGNORE)
+ {
+ return array(
+ 'status' => LOGIN_ERROR_ACTIVE,
+ 'error_msg' => 'ACTIVE_ERROR',
+ 'user_row' => $row,
+ );
+ }
+
+ // Successful login... set user_login_attempts to zero...
+ return array(
+ 'status' => LOGIN_SUCCESS,
+ 'error_msg' => false,
+ 'user_row' => $row,
+ );
+ }
+ else
+ {
+ // retrieve default group id
+ $sql = 'SELECT group_id
+ FROM ' . GROUPS_TABLE . "
+ WHERE group_name = '" . $this->db->sql_escape('REGISTERED') . "'
+ AND group_type = " . GROUP_SPECIAL;
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if (!$row)
+ {
+ trigger_error('NO_GROUP');
+ }
+
+ // generate user account data
+ $ldap_user_row = array(
+ 'username' => $username,
+ 'user_password' => phpbb_hash($password),
+ 'user_email' => (!empty($this->config['ldap_email'])) ? utf8_htmlspecialchars($ldap_result[0][htmlspecialchars_decode($this->config['ldap_email'])][0]) : '',
+ 'group_id' => (int) $row['group_id'],
+ 'user_type' => USER_NORMAL,
+ 'user_ip' => $this->user->ip,
+ 'user_new' => ($this->config['new_member_post_limit']) ? 1 : 0,
+ );
+
+ unset($ldap_result);
+
+ // this is the user's first login so create an empty profile
+ return array(
+ 'status' => LOGIN_SUCCESS_CREATE_PROFILE,
+ 'error_msg' => false,
+ 'user_row' => $ldap_user_row,
+ );
+ }
+ }
+ else
+ {
+ unset($ldap_result);
+ @ldap_close($ldap);
+
+ // Give status about wrong password...
+ return array(
+ 'status' => LOGIN_ERROR_PASSWORD,
+ 'error_msg' => 'LOGIN_ERROR_PASSWORD',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+ }
+
+ @ldap_close($ldap);
+
+ return array(
+ 'status' => LOGIN_ERROR_USERNAME,
+ 'error_msg' => 'LOGIN_ERROR_USERNAME',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function autologin()
+ {
+ return;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function acp($new)
+ {
+ $tpl = '
+
+ <dl>
+ <dt><label for="ldap_server">' . $this->user->lang['LDAP_SERVER'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['LDAP_SERVER_EXPLAIN'] . '</span></dt>
+ <dd><input type="text" id="ldap_server" size="40" name="config[ldap_server]" value="' . $new['ldap_server'] . '" /></dd>
+ </dl>
+ <dl>
+ <dt><label for="ldap_port">' . $this->user->lang['LDAP_PORT'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['LDAP_PORT_EXPLAIN'] . '</span></dt>
+ <dd><input type="text" id="ldap_port" size="40" name="config[ldap_port]" value="' . $new['ldap_port'] . '" /></dd>
+ </dl>
+ <dl>
+ <dt><label for="ldap_dn">' . $this->user->lang['LDAP_DN'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['LDAP_DN_EXPLAIN'] . '</span></dt>
+ <dd><input type="text" id="ldap_dn" size="40" name="config[ldap_base_dn]" value="' . $new['ldap_base_dn'] . '" /></dd>
+ </dl>
+ <dl>
+ <dt><label for="ldap_uid">' . $this->user->lang['LDAP_UID'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['LDAP_UID_EXPLAIN'] . '</span></dt>
+ <dd><input type="text" id="ldap_uid" size="40" name="config[ldap_uid]" value="' . $new['ldap_uid'] . '" /></dd>
+ </dl>
+ <dl>
+ <dt><label for="ldap_user_filter">' . $this->user->lang['LDAP_USER_FILTER'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['LDAP_USER_FILTER_EXPLAIN'] . '</span></dt>
+ <dd><input type="text" id="ldap_user_filter" size="40" name="config[ldap_user_filter]" value="' . $new['ldap_user_filter'] . '" /></dd>
+ </dl>
+ <dl>
+ <dt><label for="ldap_email">' . $this->user->lang['LDAP_EMAIL'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['LDAP_EMAIL_EXPLAIN'] . '</span></dt>
+ <dd><input type="email" id="ldap_email" size="40" name="config[ldap_email]" value="' . $new['ldap_email'] . '" /></dd>
+ </dl>
+ <dl>
+ <dt><label for="ldap_user">' . $this->user->lang['LDAP_USER'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['LDAP_USER_EXPLAIN'] . '</span></dt>
+ <dd><input type="text" id="ldap_user" size="40" name="config[ldap_user]" value="' . $new['ldap_user'] . '" /></dd>
+ </dl>
+ <dl>
+ <dt><label for="ldap_password">' . $this->user->lang['LDAP_PASSWORD'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['LDAP_PASSWORD_EXPLAIN'] . '</span></dt>
+ <dd><input type="password" id="ldap_password" size="40" name="config[ldap_password]" value="' . $new['ldap_password'] . '" autocomplete="off" /></dd>
+ </dl>
+ ';
+
+ // These are fields required in the config table
+ return array(
+ 'tpl' => $tpl,
+ 'config' => array('ldap_server', 'ldap_port', 'ldap_base_dn', 'ldap_uid', 'ldap_user_filter', 'ldap_email', 'ldap_user', 'ldap_password')
+ );
+ }
+
+ /**
+ * Generates a filter string for ldap_search to find a user
+ *
+ * @param $username string Username identifying the searched user
+ *
+ * @return string A filter string for ldap_search
+ */
+ private function ldap_user_filter($username)
+ {
+ $filter = '(' . $this->config['ldap_uid'] . '=' . $this->ldap_escape(htmlspecialchars_decode($username)) . ')';
+ if ($this->config['ldap_user_filter'])
+ {
+ $_filter = ($this->config['ldap_user_filter'][0] == '(' && substr($this->config['ldap_user_filter'], -1) == ')') ? $this->config['ldap_user_filter'] : "({$this->config['ldap_user_filter']})";
+ $filter = "(&{$filter}{$_filter})";
+ }
+ return $filter;
+ }
+
+ /**
+ * Escapes an LDAP AttributeValue
+ *
+ * @param string $string The string to be escaped
+ * @return string The escaped string
+ */
+ private function ldap_escape($string)
+ {
+ return str_replace(array('*', '\\', '(', ')'), array('\\*', '\\\\', '\\(', '\\)'), $string);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function logout($data, $new_session)
+ {
+ return;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validate_session($user)
+ {
+ return;
+ }
+}
diff --git a/phpBB/includes/avatar/driver/upload.php b/phpBB/includes/avatar/driver/upload.php
index 19737693fd..baf51f61c1 100644
--- a/phpBB/includes/avatar/driver/upload.php
+++ b/phpBB/includes/avatar/driver/upload.php
@@ -126,7 +126,7 @@ class phpbb_avatar_driver_upload extends phpbb_avatar_driver
{
return array(
'allow_avatar_remote_upload'=> array('lang' => 'ALLOW_REMOTE_UPLOAD', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),
- 'avatar_filesize' => array('lang' => 'MAX_FILESIZE', 'validate' => 'int:0', 'type' => 'text:4:10', 'explain' => true, 'append' => ' ' . $user->lang['BYTES']),
+ 'avatar_filesize' => array('lang' => 'MAX_FILESIZE', 'validate' => 'int:0', 'type' => 'number:0', 'explain' => true, 'append' => ' ' . $user->lang['BYTES']),
'avatar_path' => array('lang' => 'AVATAR_STORAGE_PATH', 'validate' => 'rwpath', 'type' => 'text:20:255', 'explain' => true),
);
}
diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php
index 8c27d3fd0c..96011f4ec5 100644
--- a/phpBB/includes/constants.php
+++ b/phpBB/includes/constants.php
@@ -156,6 +156,7 @@ define('PHYSICAL_LINK', 2);
define('CONFIRM_REG', 1);
define('CONFIRM_LOGIN', 2);
define('CONFIRM_POST', 3);
+define('CONFIRM_REPORT', 4);
// Categories - Attachments
define('ATTACHMENT_CATEGORY_NONE', 0);
diff --git a/phpBB/includes/db/driver/mssql_odbc.php b/phpBB/includes/db/driver/mssql_odbc.php
index cde9d332ba..a1d1a5d5dd 100644
--- a/phpBB/includes/db/driver/mssql_odbc.php
+++ b/phpBB/includes/db/driver/mssql_odbc.php
@@ -253,7 +253,7 @@ class phpbb_db_driver_mssql_odbc extends phpbb_db_driver_mssql_base
* Fetch current row
* @note number of bytes returned depends on odbc.defaultlrl php.ini setting. If it is limited to 4K for example only 4K of data is returned max.
*/
- function sql_fetchrow($query_id = false, $debug = false)
+ function sql_fetchrow($query_id = false)
{
global $cache;
diff --git a/phpBB/includes/db/driver/mssqlnative.php b/phpBB/includes/db/driver/mssqlnative.php
index 6f433e10cf..28fc88298a 100644
--- a/phpBB/includes/db/driver/mssqlnative.php
+++ b/phpBB/includes/db/driver/mssqlnative.php
@@ -326,7 +326,7 @@ class phpbb_db_driver_mssqlnative extends phpbb_db_driver_mssql_base
$this->sql_report('stop', $query);
}
- if ($cache_ttl)
+ if ($cache && $cache_ttl)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
$this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
@@ -394,7 +394,7 @@ class phpbb_db_driver_mssqlnative extends phpbb_db_driver_mssql_base
*/
function sql_affectedrows()
{
- return (!empty($this->query_result)) ? @sqlsrv_rows_affected($this->query_result) : false;
+ return ($this->db_connect_id) ? @sqlsrv_rows_affected($this->query_result) : false;
}
/**
@@ -409,7 +409,7 @@ class phpbb_db_driver_mssqlnative extends phpbb_db_driver_mssql_base
$query_id = $this->query_result;
}
- if ($cache->sql_exists($query_id))
+ if ($cache && $cache->sql_exists($query_id))
{
return $cache->sql_fetchrow($query_id);
}
@@ -474,9 +474,9 @@ class phpbb_db_driver_mssqlnative extends phpbb_db_driver_mssql_base
return $cache->sql_freeresult($query_id);
}
- if (isset($this->open_queries[$query_id]))
+ if (isset($this->open_queries[(int) $query_id]))
{
- unset($this->open_queries[$query_id]);
+ unset($this->open_queries[(int) $query_id]);
return @sqlsrv_free_stmt($query_id);
}
return false;
diff --git a/phpBB/includes/db/migration/data/30x/local_url_bbcode.php b/phpBB/includes/db/migration/data/30x/local_url_bbcode.php
new file mode 100644
index 0000000000..f324b8880d
--- /dev/null
+++ b/phpBB/includes/db/migration/data/30x/local_url_bbcode.php
@@ -0,0 +1,57 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+class phpbb_db_migration_data_30x_local_url_bbcode extends phpbb_db_migration
+{
+ static public function depends_on()
+ {
+ return array('phpbb_db_migration_data_30x_3_0_12_rc1');
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('custom', array(array($this, 'update_local_url_bbcode'))),
+ );
+ }
+
+ /**
+ * Update BBCodes that currently use the LOCAL_URL tag
+ *
+ * To fix http://tracker.phpbb.com/browse/PHPBB3-8319 we changed
+ * the second_pass_replace value, so that needs updating for existing ones
+ */
+ public function update_local_url_bbcode()
+ {
+ $sql = 'SELECT *
+ FROM ' . BBCODES_TABLE . '
+ WHERE bbcode_match ' . $this->db->sql_like_expression($this->db->any_char . 'LOCAL_URL' . $this->db->any_char);
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ if (!class_exists('acp_bbcodes'))
+ {
+ global $phpEx;
+ phpbb_require_updated('includes/acp/acp_bbcodes.' . $phpEx);
+ }
+ $bbcode_match = $row['bbcode_match'];
+ $bbcode_tpl = $row['bbcode_tpl'];
+
+ $acp_bbcodes = new acp_bbcodes();
+ $sql_ary = $acp_bbcodes->build_regexp($bbcode_match, $bbcode_tpl);
+
+ $sql = 'UPDATE ' . BBCODES_TABLE . '
+ SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . '
+ WHERE bbcode_id = ' . (int) $row['bbcode_id'];
+ $this->sql_query($sql);
+ }
+ $this->db->sql_freeresult($result);
+ }
+}
diff --git a/phpBB/includes/db/migration/data/310/notifications_schema_fix.php b/phpBB/includes/db/migration/data/310/notifications_schema_fix.php
new file mode 100644
index 0000000000..27e63e10d0
--- /dev/null
+++ b/phpBB/includes/db/migration/data/310/notifications_schema_fix.php
@@ -0,0 +1,92 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+*
+*/
+
+class phpbb_db_migration_data_310_notifications_schema_fix extends phpbb_db_migration
+{
+ static public function depends_on()
+ {
+ return array('phpbb_db_migration_data_310_notifications');
+ }
+
+ public function update_schema()
+ {
+ return array(
+ 'drop_tables' => array(
+ $this->table_prefix . 'notification_types',
+ $this->table_prefix . 'notifications',
+ ),
+ 'add_tables' => array(
+ $this->table_prefix . 'notification_types' => array(
+ 'COLUMNS' => array(
+ 'notification_type_id' => array('USINT', NULL, 'auto_increment'),
+ 'notification_type_name' => array('VCHAR:255', ''),
+ 'notification_type_enabled' => array('BOOL', 1),
+ ),
+ 'PRIMARY_KEY' => array('notification_type_id'),
+ 'KEYS' => array(
+ 'type' => array('UNIQUE', array('notification_type_name')),
+ ),
+ ),
+ $this->table_prefix . 'notifications' => array(
+ 'COLUMNS' => array(
+ 'notification_id' => array('UINT:10', NULL, 'auto_increment'),
+ 'notification_type_id' => array('USINT', 0),
+ 'item_id' => array('UINT', 0),
+ 'item_parent_id' => array('UINT', 0),
+ 'user_id' => array('UINT', 0),
+ 'notification_read' => array('BOOL', 0),
+ 'notification_time' => array('TIMESTAMP', 1),
+ 'notification_data' => array('TEXT_UNI', ''),
+ ),
+ 'PRIMARY_KEY' => 'notification_id',
+ 'KEYS' => array(
+ 'item_ident' => array('INDEX', array('notification_type_id', 'item_id')),
+ 'user' => array('INDEX', array('user_id', 'notification_read')),
+ ),
+ ),
+ ),
+ );
+ }
+
+ public function revert_schema()
+ {
+ return array(
+ 'drop_tables' => array(
+ $this->table_prefix . 'notification_types',
+ $this->table_prefix . 'notifications',
+ ),
+ 'add_tables' => array(
+ $this->table_prefix . 'notification_types' => array(
+ 'COLUMNS' => array(
+ 'notification_type' => array('VCHAR:255', ''),
+ 'notification_type_enabled' => array('BOOL', 1),
+ ),
+ 'PRIMARY_KEY' => array('notification_type', 'notification_type_enabled'),
+ ),
+ $this->table_prefix . 'notifications' => array(
+ 'COLUMNS' => array(
+ 'notification_id' => array('UINT', NULL, 'auto_increment'),
+ 'item_type' => array('VCHAR:255', ''),
+ 'item_id' => array('UINT', 0),
+ 'item_parent_id' => array('UINT', 0),
+ 'user_id' => array('UINT', 0),
+ 'notification_read' => array('BOOL', 0),
+ 'notification_time' => array('TIMESTAMP', 1),
+ 'notification_data' => array('TEXT_UNI', ''),
+ ),
+ 'PRIMARY_KEY' => 'notification_id',
+ 'KEYS' => array(
+ 'item_ident' => array('INDEX', array('item_type', 'item_id')),
+ 'user' => array('INDEX', array('user_id', 'notification_read')),
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/phpBB/includes/db/migration/data/310/signature_module_auth.php b/phpBB/includes/db/migration/data/310/signature_module_auth.php
new file mode 100644
index 0000000000..e4fbb27bcb
--- /dev/null
+++ b/phpBB/includes/db/migration/data/310/signature_module_auth.php
@@ -0,0 +1,51 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License v2
+*
+*/
+
+class phpbb_db_migration_data_310_signature_module_auth extends phpbb_db_migration
+{
+ public function effectively_installed()
+ {
+ $sql = 'SELECT module_auth
+ FROM ' . MODULES_TABLE . "
+ WHERE module_class = 'ucp'
+ AND module_basename = 'ucp_profile'
+ AND module_mode = 'signature'";
+ $result = $this->db->sql_query($sql);
+ $module_auth = $this->db_sql_fetchfield('module_auth');
+ $this->db->sql_freeresult($result);
+
+ return $module_auth === 'acl_u_sig' || $module_auth === false;
+ }
+
+ static public function depends_on()
+ {
+ return array('phpbb_db_migration_data_31x_dev');
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('custom', array(
+ array($this, 'update_signature_module_auth'),
+ ),
+ ),
+ );
+ }
+
+ public function update_signature_module_auth()
+ {
+ $sql = 'UPDATE ' . MODULES_TABLE . "
+ SET module_auth = 'acl_u_sig'
+ WHERE module_class = 'ucp'
+ AND module_basename = 'ucp_profile'
+ AND module_mode = 'signature'
+ AND module_auth = ''";
+ $this->db->sql_query($sql);
+ }
+}
diff --git a/phpBB/includes/db/migration/tool/module.php b/phpBB/includes/db/migration/tool/module.php
index ec683d36af..ac4d2c9bd7 100644
--- a/phpBB/includes/db/migration/tool/module.php
+++ b/phpBB/includes/db/migration/tool/module.php
@@ -209,9 +209,6 @@ class phpbb_db_migration_tool_module implements phpbb_db_migration_tool_interfac
}
// The "manual" way
- $module_log_name = ((isset($this->user->lang[$data['module_langname']])) ? $this->user->lang[$data['module_langname']] : $data['module_langname']);
- add_log('admin', 'LOG_MODULE_ADD', $module_log_name);
-
if (!is_numeric($parent))
{
$sql = 'SELECT module_id
@@ -267,6 +264,8 @@ class phpbb_db_migration_tool_module implements phpbb_db_migration_tool_interfac
else
{
// Success
+ $module_log_name = ((isset($this->user->lang[$data['module_langname']])) ? $this->user->lang[$data['module_langname']] : $data['module_langname']);
+ add_log('admin', 'LOG_MODULE_ADD', $module_log_name);
// Move the module if requested above/below an existing one
if (isset($data['before']) && $data['before'])
diff --git a/phpBB/includes/extension/base.php b/phpBB/includes/extension/base.php
index d51589d719..c4462b64d8 100644
--- a/phpBB/includes/extension/base.php
+++ b/phpBB/includes/extension/base.php
@@ -27,25 +27,51 @@ class phpbb_extension_base implements phpbb_extension_interface
/** @var ContainerInterface */
protected $container;
+ /** @var phpbb_extension_finder */
+ protected $finder;
+
+ /** @var phpbb_db_migrator */
+ protected $migrator;
+
+ /** @var string */
+ protected $extension_name;
+
+ /** @var string */
+ protected $extension_path;
+
/**
* Constructor
*
* @param ContainerInterface $container Container object
+ * @param phpbb_extension_finder $extension_finder
+ * @param string $extension_name Name of this extension (from ext.manager)
+ * @param string $extension_path Relative path to this extension
*/
- public function __construct(ContainerInterface $container)
+ public function __construct(ContainerInterface $container, phpbb_extension_finder $extension_finder, phpbb_db_migrator $migrator, $extension_name, $extension_path)
{
$this->container = $container;
+ $this->extension_finder = $extension_finder;
+ $this->migrator = $migrator;
+
+ $this->extension_name = $extension_name;
+ $this->extension_path = $extension_path;
}
/**
- * Single enable step that does nothing
+ * Single enable step that installs any included migrations
*
* @param mixed $old_state State returned by previous call of this method
* @return false Indicates no further steps are required
*/
public function enable_step($old_state)
{
- return false;
+ $migrations = $this->get_migration_file_list();
+
+ $this->migrator->set_migrations($migrations);
+
+ $this->migrator->update();
+
+ return !$this->migrator->finished();
}
/**
@@ -60,13 +86,50 @@ class phpbb_extension_base implements phpbb_extension_interface
}
/**
- * Single purge step that does nothing
+ * Single purge step that reverts any included and installed migrations
*
* @param mixed $old_state State returned by previous call of this method
* @return false Indicates no further steps are required
*/
public function purge_step($old_state)
{
+ $migrations = $this->get_migration_file_list();
+
+ $this->migrator->set_migrations($migrations);
+
+ foreach ($migrations as $migration)
+ {
+ while ($this->migrator->migration_state($migration) !== false)
+ {
+ $this->migrator->revert($migration);
+
+ return true;
+ }
+ }
+
return false;
}
+
+ /**
+ * Get the list of migration files from this extension
+ *
+ * @return array
+ */
+ protected function get_migration_file_list()
+ {
+ static $migrations = false;
+
+ if ($migrations !== false)
+ {
+ return $migrations;
+ }
+
+ // Only have the finder search in this extension path directory
+ $migrations = $this->extension_finder
+ ->extension_directory('/migrations')
+ ->find_from_extension($this->extension_name, $this->extension_path);
+ $migrations = $this->extension_finder->get_classes_from_files($migrations);
+
+ return $migrations;
+ }
}
diff --git a/phpBB/includes/extension/finder.php b/phpBB/includes/extension/finder.php
index 766b9e9b63..49bb2a514f 100644
--- a/phpBB/includes/extension/finder.php
+++ b/phpBB/includes/extension/finder.php
@@ -377,6 +377,34 @@ class phpbb_extension_finder
return $files;
}
+
+ /**
+ * Finds all file system entries matching the configured options for one
+ * specific extension
+ *
+ * @param string $extension_name Name of the extension
+ * @param string $extension_path Relative path to the extension root directory
+ * @param bool $cache Whether the result should be cached
+ * @param bool $is_dir Directories will be returned when true, only files
+ * otherwise
+ * @return array An array of paths to found items
+ */
+ public function find_from_extension($extension_name, $extension_path, $cache = true, $is_dir = false)
+ {
+ $extensions = array(
+ $extension_name => $extension_path,
+ );
+
+ $files = array();
+ $file_list = $this->find_from_paths($extensions, $cache, $is_dir);
+
+ foreach ($file_list as $file)
+ {
+ $files[$file['named_path']] = $file['ext_name'];
+ }
+
+ return $files;
+ }
/**
* Finds all file system entries matching the configured options from
diff --git a/phpBB/includes/extension/manager.php b/phpBB/includes/extension/manager.php
index 653117adfa..4451049d04 100644
--- a/phpBB/includes/extension/manager.php
+++ b/phpBB/includes/extension/manager.php
@@ -29,7 +29,6 @@ class phpbb_extension_manager
protected $db;
protected $config;
- protected $migrator;
protected $cache;
protected $php_ext;
protected $extensions;
@@ -43,7 +42,6 @@ class phpbb_extension_manager
* @param ContainerInterface $container A container
* @param phpbb_db_driver $db A database connection
* @param phpbb_config $config phpbb_config
- * @param phpbb_db_migrator $migrator
* @param phpbb_filesystem $filesystem
* @param string $extension_table The name of the table holding extensions
* @param string $phpbb_root_path Path to the phpbb includes directory.
@@ -51,13 +49,12 @@ class phpbb_extension_manager
* @param phpbb_cache_driver_interface $cache A cache instance or null
* @param string $cache_name The name of the cache variable, defaults to _ext
*/
- public function __construct(ContainerInterface $container, phpbb_db_driver $db, phpbb_config $config, phpbb_db_migrator $migrator, phpbb_filesystem $filesystem, $extension_table, $phpbb_root_path, $php_ext = 'php', phpbb_cache_driver_interface $cache = null, $cache_name = '_ext')
+ public function __construct(ContainerInterface $container, phpbb_db_driver $db, phpbb_config $config, phpbb_filesystem $filesystem, $extension_table, $phpbb_root_path, $php_ext = 'php', phpbb_cache_driver_interface $cache = null, $cache_name = '_ext')
{
$this->container = $container;
$this->phpbb_root_path = $phpbb_root_path;
$this->db = $db;
$this->config = $config;
- $this->migrator = $migrator;
$this->cache = $cache;
$this->filesystem = $filesystem;
$this->php_ext = $php_ext;
@@ -136,13 +133,15 @@ class phpbb_extension_manager
{
$extension_class_name = 'phpbb_ext_' . str_replace('/', '_', $name) . '_ext';
+ $migrator = $this->container->get('migrator');
+
if (class_exists($extension_class_name))
{
- return new $extension_class_name($this->container);
+ return new $extension_class_name($this->container, $this->get_finder(), $migrator, $name, $this->get_extension_path($name, true));
}
else
{
- return new phpbb_extension_base($this->container);
+ return new phpbb_extension_base($this->container, $this->get_finder(), $migrator, $name, $this->get_extension_path($name, true));
}
}
@@ -178,12 +177,6 @@ class phpbb_extension_manager
$old_state = (isset($this->extensions[$name]['ext_state'])) ? unserialize($this->extensions[$name]['ext_state']) : false;
- // Returns false if not completed
- if (!$this->handle_migrations($name, 'enable'))
- {
- return true;
- }
-
$extension = $this->get_extension($name);
$state = $extension->enable_step($old_state);
@@ -199,12 +192,21 @@ class phpbb_extension_manager
$this->extensions[$name]['ext_path'] = $this->get_extension_path($extension_data['ext_name']);
ksort($this->extensions);
- $sql = 'UPDATE ' . $this->extension_table . '
- SET ' . $this->db->sql_build_array('UPDATE', $extension_data) . "
+ $sql = 'SELECT COUNT(ext_name) as row_count
+ FROM ' . $this->extension_table . "
WHERE ext_name = '" . $this->db->sql_escape($name) . "'";
- $this->db->sql_query($sql);
+ $result = $this->db->sql_query($sql);
+ $count = $this->db->sql_fetchfield('row_count');
+ $this->db->sql_freeresult($result);
- if (!$this->db->sql_affectedrows())
+ if ($count)
+ {
+ $sql = 'UPDATE ' . $this->extension_table . '
+ SET ' . $this->db->sql_build_array('UPDATE', $extension_data) . "
+ WHERE ext_name = '" . $this->db->sql_escape($name) . "'";
+ $this->db->sql_query($sql);
+ }
+ else
{
$sql = 'INSERT INTO ' . $this->extension_table . '
' . $this->db->sql_build_array('INSERT', $extension_data);
@@ -335,12 +337,6 @@ class phpbb_extension_manager
$old_state = unserialize($this->extensions[$name]['ext_state']);
- // Returns false if not completed
- if (!$this->handle_migrations($name, 'purge'))
- {
- return true;
- }
-
$extension = $this->get_extension($name);
$state = $extension->purge_step($old_state);
@@ -514,72 +510,4 @@ class phpbb_extension_manager
{
return new phpbb_extension_finder($this, $this->filesystem, $this->phpbb_root_path, $this->cache, $this->php_ext, $this->cache_name . '_finder');
}
-
- /**
- * Handle installing/reverting migrations
- *
- * @param string $extension_name Name of the extension
- * @param string $mode enable or purge
- * @return bool True if completed, False if not completed
- */
- protected function handle_migrations($extension_name, $mode)
- {
- $extensions = array(
- $extension_name => $this->phpbb_root_path . $this->get_extension_path($extension_name),
- );
-
- $finder = $this->get_finder();
- $migrations = array();
- $file_list = $finder
- ->extension_directory('/migrations')
- ->find_from_paths($extensions);
-
- if (empty($file_list))
- {
- return true;
- }
-
- foreach ($file_list as $file)
- {
- $migrations[$file['named_path']] = $file['ext_name'];
- }
- $migrations = $finder->get_classes_from_files($migrations);
- $this->migrator->set_migrations($migrations);
-
- // What is a safe limit of execution time? Half the max execution time should be safe.
- $safe_time_limit = (ini_get('max_execution_time') / 2);
- $start_time = time();
-
- if ($mode == 'enable')
- {
- while (!$this->migrator->finished())
- {
- $this->migrator->update();
-
- // Are we approaching the time limit? If so we want to pause the update and continue after refreshing
- if ((time() - $start_time) >= $safe_time_limit)
- {
- return false;
- }
- }
- }
- else if ($mode == 'purge')
- {
- foreach ($migrations as $migration)
- {
- while ($this->migrator->migration_state($migration) !== false)
- {
- $this->migrator->revert($migration);
-
- // Are we approaching the time limit? If so we want to pause the update and continue after refreshing
- if ((time() - $start_time) >= $safe_time_limit)
- {
- return false;
- }
- }
- }
- }
-
- return true;
- }
}
diff --git a/phpBB/includes/feed/base.php b/phpBB/includes/feed/base.php
new file mode 100644
index 0000000000..af28ee8dc8
--- /dev/null
+++ b/phpBB/includes/feed/base.php
@@ -0,0 +1,259 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Base class with some generic functions and settings.
+*
+* @package phpBB3
+*/
+abstract class phpbb_feed_base
+{
+ /**
+ * Feed helper object
+ * @var phpbb_feed_helper
+ */
+ protected $helper;
+
+ /** @var phpbb_config */
+ protected $config;
+
+ /** @var phpbb_db_driver */
+ protected $db;
+
+ /** @var phpbb_cache_driver_interface */
+ protected $cache;
+
+ /** @var phpbb_user */
+ protected $user;
+
+ /** @var phpbb_auth */
+ protected $auth;
+
+ /** @var string */
+ protected $phpEx;
+
+ /**
+ * SQL Query to be executed to get feed items
+ */
+ var $sql = array();
+
+ /**
+ * Keys specified for retrieval of title, content, etc.
+ */
+ var $keys = array();
+
+ /**
+ * Number of items to fetch. Usually overwritten by $config['feed_something']
+ */
+ var $num_items = 15;
+
+ /**
+ * Separator for title elements to separate items (for example forum / topic)
+ */
+ var $separator = "\xE2\x80\xA2"; // &bull;
+
+ /**
+ * Separator for the statistics row (Posted by, post date, replies, etc.)
+ */
+ var $separator_stats = "\xE2\x80\x94"; // &mdash;
+
+ /**
+ * Constructor
+ *
+ * @param phpbb_feed_helper $helper Feed helper
+ * @param phpbb_config $config Config object
+ * @param phpbb_db_driver $db Database connection
+ * @param phpbb_cache_driver_interface $cache Cache object
+ * @param phpbb_user $user User object
+ * @param phpbb_auth $auth Auth object
+ * @param string $phpEx php file extension
+ * @return null
+ */
+ function __construct(phpbb_feed_helper $helper, phpbb_config $config, phpbb_db_driver $db, phpbb_cache_driver_interface $cache, phpbb_user $user, phpbb_auth $auth, $phpEx)
+ {
+ $this->config = $config;
+ $this->helper = $helper;
+ $this->db = $db;
+ $this->cache = $cache;
+ $this->user = $user;
+ $this->auth = $auth;
+ $this->phpEx = $phpEx;
+
+ $this->set_keys();
+
+ // Allow num_items to be string
+ if (is_string($this->num_items))
+ {
+ $this->num_items = (int) $this->config[$this->num_items];
+
+ // A precaution
+ if (!$this->num_items)
+ {
+ $this->num_items = 10;
+ }
+ }
+ }
+
+ /**
+ * Set keys.
+ */
+ function set_keys()
+ {
+ }
+
+ /**
+ * Open feed
+ */
+ function open()
+ {
+ }
+
+ /**
+ * Close feed
+ */
+ function close()
+ {
+ if (!empty($this->result))
+ {
+ $this->db->sql_freeresult($this->result);
+ }
+ }
+
+ /**
+ * Set key
+ */
+ function set($key, $value)
+ {
+ $this->keys[$key] = $value;
+ }
+
+ /**
+ * Get key
+ */
+ function get($key)
+ {
+ return (isset($this->keys[$key])) ? $this->keys[$key] : NULL;
+ }
+
+ function get_readable_forums()
+ {
+ static $forum_ids;
+
+ if (!isset($forum_ids))
+ {
+ $forum_ids = array_keys($this->auth->acl_getf('f_read', true));
+ }
+
+ return $forum_ids;
+ }
+
+ function get_moderator_approve_forums()
+ {
+ static $forum_ids;
+
+ if (!isset($forum_ids))
+ {
+ $forum_ids = array_keys($this->auth->acl_getf('m_approve', true));
+ }
+
+ return $forum_ids;
+ }
+
+ function is_moderator_approve_forum($forum_id)
+ {
+ static $forum_ids;
+
+ if (!isset($forum_ids))
+ {
+ $forum_ids = array_flip($this->get_moderator_approve_forums());
+ }
+
+ return (isset($forum_ids[$forum_id])) ? true : false;
+ }
+
+ function get_excluded_forums()
+ {
+ static $forum_ids;
+
+ // Matches acp/acp_board.php
+ $cache_name = 'feed_excluded_forum_ids';
+
+ if (!isset($forum_ids) && ($forum_ids = $this->cache->get('_' . $cache_name)) === false)
+ {
+ $sql = 'SELECT forum_id
+ FROM ' . FORUMS_TABLE . '
+ WHERE ' . $this->db->sql_bit_and('forum_options', FORUM_OPTION_FEED_EXCLUDE, '<> 0');
+ $result = $this->db->sql_query($sql);
+
+ $forum_ids = array();
+ while ($forum_id = (int) $this->db->sql_fetchfield('forum_id'))
+ {
+ $forum_ids[$forum_id] = $forum_id;
+ }
+ $this->db->sql_freeresult($result);
+
+ $this->cache->put('_' . $cache_name, $forum_ids);
+ }
+
+ return $forum_ids;
+ }
+
+ function is_excluded_forum($forum_id)
+ {
+ $forum_ids = $this->get_excluded_forums();
+
+ return isset($forum_ids[$forum_id]) ? true : false;
+ }
+
+ function get_passworded_forums()
+ {
+ return $this->user->get_passworded_forums();
+ }
+
+ function get_item()
+ {
+ static $result;
+
+ if (!isset($result))
+ {
+ if (!$this->get_sql())
+ {
+ return false;
+ }
+
+ // Query database
+ $sql = $this->db->sql_build_query('SELECT', $this->sql);
+ $result = $this->db->sql_query_limit($sql, $this->num_items);
+ }
+
+ return $this->db->sql_fetchrow($result);
+ }
+
+ function user_viewprofile($row)
+ {
+ $author_id = (int) $row[$this->get('author_id')];
+
+ if ($author_id == ANONYMOUS)
+ {
+ // Since we cannot link to a profile, we just return GUEST
+ // instead of $row['username']
+ return $this->user->lang['GUEST'];
+ }
+
+ return '<a href="' . $this->helper->append_sid('memberlist.' . $this->phpEx, 'mode=viewprofile&amp;u=' . $author_id) . '">' . $row[$this->get('creator')] . '</a>';
+ }
+}
diff --git a/phpBB/includes/feed/factory.php b/phpBB/includes/feed/factory.php
new file mode 100644
index 0000000000..63a1eb8ef0
--- /dev/null
+++ b/phpBB/includes/feed/factory.php
@@ -0,0 +1,129 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Factory class to return correct object
+* @package phpBB3
+*/
+class phpbb_feed_factory
+{
+ /**
+ * Service container object
+ * @var object
+ */
+ protected $container;
+
+ /** @var phpbb_config */
+ protected $config;
+
+ /** @var phpbb_db_driver */
+ protected $db;
+
+ /**
+ * Constructor
+ *
+ * @param objec $container Container object
+ * @param phpbb_config $config Config object
+ * @param phpbb_db_driver $db Database connection
+ * @return null
+ */
+ public function __construct($container, phpbb_config $config, phpbb_db_driver $db)
+ {
+ $this->container = $container;
+ $this->config = $config;
+ $this->db = $db;
+ }
+
+ /**
+ * Return correct object for specified mode
+ *
+ * @param string $mode The feeds mode.
+ * @param int $forum_id Forum id specified by the script if forum feed provided.
+ * @param int $topic_id Topic id specified by the script if topic feed provided.
+ *
+ * @return object Returns correct feeds object for specified mode.
+ */
+ function get_feed($mode, $forum_id, $topic_id)
+ {
+ switch ($mode)
+ {
+ case 'forums':
+ if (!$this->config['feed_overall_forums'])
+ {
+ return false;
+ }
+
+ return $this->container->get('feed.forums');
+ break;
+
+ case 'topics':
+ case 'topics_new':
+ if (!$this->config['feed_topics_new'])
+ {
+ return false;
+ }
+
+ return $this->container->get('feed.topics');
+ break;
+
+ case 'topics_active':
+ if (!$this->config['feed_topics_active'])
+ {
+ return false;
+ }
+
+ return $this->container->get('feed.topics_active');
+ break;
+
+ case 'news':
+ // Get at least one news forum
+ $sql = 'SELECT forum_id
+ FROM ' . FORUMS_TABLE . '
+ WHERE ' . $this->db->sql_bit_and('forum_options', FORUM_OPTION_FEED_NEWS, '<> 0');
+ $result = $this->db->sql_query_limit($sql, 1, 0, 600);
+ $s_feed_news = (int) $this->db->sql_fetchfield('forum_id');
+ $this->db->sql_freeresult($result);
+
+ if (!$s_feed_news)
+ {
+ return false;
+ }
+
+ return $this->container->get('feed.news');
+ break;
+
+ default:
+ if ($topic_id && $this->config['feed_topic'])
+ {
+ return $this->container->get('feed.topic')
+ ->set_topic_id($topic_id);
+ }
+ else if ($forum_id && $this->config['feed_forum'])
+ {
+ return $this->container->get('feed.forum')
+ ->set_forum_id($forum_id);
+ }
+ else if ($this->config['feed_overall'])
+ {
+ return $this->container->get('feed.overall');
+ }
+
+ return false;
+ break;
+ }
+ }
+}
diff --git a/phpBB/includes/feed/forum.php b/phpBB/includes/feed/forum.php
new file mode 100644
index 0000000000..7670fbeaaa
--- /dev/null
+++ b/phpBB/includes/feed/forum.php
@@ -0,0 +1,147 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Forum feed
+*
+* This will give you the last {$this->num_items} posts made
+* within a specific forum.
+*
+* @package phpBB3
+*/
+class phpbb_feed_forum extends phpbb_feed_post_base
+{
+ var $forum_id = 0;
+ var $forum_data = array();
+
+ /**
+ * Set the Forum ID
+ *
+ * @param int $forum_id Forum ID
+ * @return phpbb_feed_forum
+ */
+ public function set_forum_id($topic_id)
+ {
+ $this->forum_id = (int) $forum_id;
+
+ return $this;
+ }
+
+ function open()
+ {
+ // Check if forum exists
+ $sql = 'SELECT forum_id, forum_name, forum_password, forum_type, forum_options
+ FROM ' . FORUMS_TABLE . '
+ WHERE forum_id = ' . $this->forum_id;
+ $result = $this->db->sql_query($sql);
+ $this->forum_data = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if (empty($this->forum_data))
+ {
+ trigger_error('NO_FORUM');
+ }
+
+ // Forum needs to be postable
+ if ($this->forum_data['forum_type'] != FORUM_POST)
+ {
+ trigger_error('NO_FEED');
+ }
+
+ // Make sure forum is not excluded from feed
+ if (phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $this->forum_data['forum_options']))
+ {
+ trigger_error('NO_FEED');
+ }
+
+ // Make sure we can read this forum
+ if (!$this->auth->acl_get('f_read', $this->forum_id))
+ {
+ trigger_error('SORRY_AUTH_READ');
+ }
+
+ // Make sure forum is not passworded or user is authed
+ if ($this->forum_data['forum_password'])
+ {
+ $forum_ids_passworded = $this->get_passworded_forums();
+
+ if (isset($forum_ids_passworded[$this->forum_id]))
+ {
+ trigger_error('SORRY_AUTH_READ');
+ }
+
+ unset($forum_ids_passworded);
+ }
+ }
+
+ function get_sql()
+ {
+ $m_approve = ($this->auth->acl_get('m_approve', $this->forum_id)) ? true : false;
+
+ // Determine topics with recent activity
+ $sql = 'SELECT topic_id, topic_last_post_time
+ FROM ' . TOPICS_TABLE . '
+ WHERE forum_id = ' . $this->forum_id . '
+ AND topic_moved_id = 0
+ ' . ((!$m_approve) ? 'AND topic_approved = 1' : '') . '
+ ORDER BY topic_last_post_time DESC';
+ $result = $this->db->sql_query_limit($sql, $this->num_items);
+
+ $topic_ids = array();
+ $min_post_time = 0;
+ while ($row = $this->db->sql_fetchrow())
+ {
+ $topic_ids[] = (int) $row['topic_id'];
+
+ $min_post_time = (int) $row['topic_last_post_time'];
+ }
+ $this->db->sql_freeresult($result);
+
+ if (empty($topic_ids))
+ {
+ return false;
+ }
+
+ $this->sql = array(
+ 'SELECT' => 'p.post_id, p.topic_id, p.post_time, p.post_edit_time, p.post_approved, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, ' .
+ 'u.username, u.user_id',
+ 'FROM' => array(
+ POSTS_TABLE => 'p',
+ USERS_TABLE => 'u',
+ ),
+ 'WHERE' => $this->db->sql_in_set('p.topic_id', $topic_ids) . '
+ ' . ((!$m_approve) ? 'AND p.post_approved = 1' : '') . '
+ AND p.post_time >= ' . $min_post_time . '
+ AND p.poster_id = u.user_id',
+ 'ORDER_BY' => 'p.post_time DESC',
+ );
+
+ return true;
+ }
+
+ function adjust_item(&$item_row, &$row)
+ {
+ parent::adjust_item($item_row, $row);
+
+ $item_row['title'] = (isset($row['forum_name']) && $row['forum_name'] !== '') ? $row['forum_name'] . ' ' . $this->separator . ' ' . $item_row['title'] : $item_row['title'];
+ }
+
+ function get_item()
+ {
+ return ($row = parent::get_item()) ? array_merge($this->forum_data, $row) : $row;
+ }
+}
diff --git a/phpBB/includes/feed/forums.php b/phpBB/includes/feed/forums.php
new file mode 100644
index 0000000000..72f786aa6a
--- /dev/null
+++ b/phpBB/includes/feed/forums.php
@@ -0,0 +1,72 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* 'All Forums' feed
+*
+* This will give you a list of all postable forums where feeds are enabled
+* including forum description, topic stats and post stats
+*
+* @package phpBB3
+*/
+class phpbb_feed_forums extends phpbb_feed_base
+{
+ var $num_items = 0;
+
+ function set_keys()
+ {
+ $this->set('title', 'forum_name');
+ $this->set('text', 'forum_desc');
+ $this->set('bitfield', 'forum_desc_bitfield');
+ $this->set('bbcode_uid','forum_desc_uid');
+ $this->set('updated', 'forum_last_post_time');
+ $this->set('options', 'forum_desc_options');
+ }
+
+ function get_sql()
+ {
+ $in_fid_ary = array_diff($this->get_readable_forums(), $this->get_excluded_forums());
+ if (empty($in_fid_ary))
+ {
+ return false;
+ }
+
+ // Build SQL Query
+ $this->sql = array(
+ 'SELECT' => 'f.forum_id, f.left_id, f.forum_name, f.forum_last_post_time,
+ f.forum_desc, f.forum_desc_bitfield, f.forum_desc_uid, f.forum_desc_options,
+ f.forum_topics, f.forum_posts',
+ 'FROM' => array(FORUMS_TABLE => 'f'),
+ 'WHERE' => 'f.forum_type = ' . FORUM_POST . '
+ AND ' . $this->db->sql_in_set('f.forum_id', $in_fid_ary),
+ 'ORDER_BY' => 'f.left_id ASC',
+ );
+
+ return true;
+ }
+
+ function adjust_item(&$item_row, &$row)
+ {
+ $item_row['link'] = $this->helper->append_sid('viewforum.' . $this->phpEx, 'f=' . $row['forum_id']);
+
+ if ($this->config['feed_item_statistics'])
+ {
+ $item_row['statistics'] = $this->user->lang('TOTAL_TOPICS', (int) $row['forum_topics'])
+ . ' ' . $this->separator_stats . ' ' . $this->user->lang('TOTAL_POSTS_COUNT', (int) $row['forum_posts']);
+ }
+ }
+}
diff --git a/phpBB/includes/feed/helper.php b/phpBB/includes/feed/helper.php
new file mode 100644
index 0000000000..93330aa2ad
--- /dev/null
+++ b/phpBB/includes/feed/helper.php
@@ -0,0 +1,159 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Class with some helpful functions used in feeds
+* @package phpBB3
+*/
+class phpbb_feed_helper
+{
+ /** @var phpbb_config */
+ protected $config;
+
+ /** @var phpbb_user */
+ protected $user;
+
+ /** @var string */
+ protected $phpbb_root_path;
+
+ /**
+ * Constructor
+ *
+ * @param phpbb_config $config Config object
+ * @param phpbb_user $user User object
+ * @param string $phpbb_root_path Root path
+ * @return null
+ */
+ public function __construct(phpbb_config $config, phpbb_user $user, $phpbb_root_path)
+ {
+ $this->config = $config;
+ $this->user = $user;
+ $this->phpbb_root_path = $phpbb_root_path;
+ }
+
+ /**
+ * Run links through append_sid(), prepend generate_board_url() and remove session id
+ */
+ public function get_board_url()
+ {
+ static $board_url;
+
+ if (empty($board_url))
+ {
+ $board_url = generate_board_url();
+ }
+
+ return $board_url;
+ }
+
+ /**
+ * Run links through append_sid(), prepend generate_board_url() and remove session id
+ */
+ public function append_sid($url, $params)
+ {
+ return append_sid($this->get_board_url() . '/' . $url, $params, true, '');
+ }
+
+ /**
+ * Generate ISO 8601 date string (RFC 3339)
+ */
+ public function format_date($time)
+ {
+ static $zone_offset;
+ static $offset_string;
+
+ if (empty($offset_string))
+ {
+ $zone_offset = $this->user->create_datetime()->getOffset();
+ $offset_string = phpbb_format_timezone_offset($zone_offset);
+ }
+
+ return gmdate("Y-m-d\TH:i:s", $time + $zone_offset) . $offset_string;
+ }
+
+ /**
+ * Generate text content
+ */
+ public function generate_content($content, $uid, $bitfield, $options)
+ {
+ if (empty($content))
+ {
+ return '';
+ }
+
+ // Prepare some bbcodes for better parsing
+ $content = preg_replace("#\[quote(=&quot;.*?&quot;)?:$uid\]\s*(.*?)\s*\[/quote:$uid\]#si", "[quote$1:$uid]<br />$2<br />[/quote:$uid]", $content);
+
+ $content = generate_text_for_display($content, $uid, $bitfield, $options);
+
+ // Add newlines
+ $content = str_replace('<br />', '<br />' . "\n", $content);
+
+ // Convert smiley Relative paths to Absolute path, Windows style
+ $content = str_replace($this->phpbb_root_path . $this->config['smilies_path'], $this->get_board_url() . '/' . $this->config['smilies_path'], $content);
+
+ // Remove "Select all" link and mouse events
+ $content = str_replace('<a href="#" onclick="selectCode(this); return false;">' . $this->user->lang['SELECT_ALL_CODE'] . '</a>', '', $content);
+ $content = preg_replace('#(onkeypress|onclick)="(.*?)"#si', '', $content);
+
+ // Firefox does not support CSS for feeds, though
+
+ // Remove font sizes
+ // $content = preg_replace('#<span style="font-size: [0-9]+%; line-height: [0-9]+%;">([^>]+)</span>#iU', '\1', $content);
+
+ // Make text strong :P
+ // $content = preg_replace('#<span style="font-weight: bold?">(.*?)</span>#iU', '<strong>\1</strong>', $content);
+
+ // Italic
+ // $content = preg_replace('#<span style="font-style: italic?">([^<]+)</span>#iU', '<em>\1</em>', $content);
+
+ // Underline
+ // $content = preg_replace('#<span style="text-decoration: underline?">([^<]+)</span>#iU', '<u>\1</u>', $content);
+
+ // Remove embed Windows Media Streams
+ $content = preg_replace( '#<\!--\[if \!IE\]>-->([^[]+)<\!--<!\[endif\]-->#si', '', $content);
+
+ // Do not use &lt; and &gt;, because we want to retain code contained in [code][/code]
+
+ // Remove embed and objects
+ $content = preg_replace( '#<(object|embed)(.*?) (value|src)=(.*?) ([^[]+)(object|embed)>#si',' <a href=$4 target="_blank"><strong>$1</strong></a> ',$content);
+
+ // Remove some specials html tag, because somewhere there are a mod to allow html tags ;)
+ $content = preg_replace( '#<(script|iframe)([^[]+)\1>#siU', ' <strong>$1</strong> ', $content);
+
+ // Remove Comments from inline attachments [ia]
+ $content = preg_replace('#<div class="(inline-attachment|attachtitle)">(.*?)<!-- ia(.*?) -->(.*?)<!-- ia(.*?) -->(.*?)</div>#si','$4',$content);
+
+ // Replace some entities with their unicode counterpart
+ $entities = array(
+ '&nbsp;' => "\xC2\xA0",
+ '&bull;' => "\xE2\x80\xA2",
+ '&middot;' => "\xC2\xB7",
+ '&copy;' => "\xC2\xA9",
+ );
+
+ $content = str_replace(array_keys($entities), array_values($entities), $content);
+
+ // Remove CDATA blocks. ;)
+ $content = preg_replace('#\<\!\[CDATA\[(.*?)\]\]\>#s', '', $content);
+
+ // Other control characters
+ $content = preg_replace('#(?:[\x00-\x1F\x7F]+|(?:\xC2[\x80-\x9F])+)#', '', $content);
+
+ return $content;
+ }
+}
diff --git a/phpBB/includes/feed/news.php b/phpBB/includes/feed/news.php
new file mode 100644
index 0000000000..92cc18a3ab
--- /dev/null
+++ b/phpBB/includes/feed/news.php
@@ -0,0 +1,112 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* News feed
+*
+* This will give you {$this->num_items} first posts
+* of all topics in the selected news forums.
+*
+* @package phpBB3
+*/
+class phpbb_feed_news extends phpbb_feed_topic_base
+{
+ function get_news_forums()
+ {
+ static $forum_ids;
+
+ // Matches acp/acp_board.php
+ $cache_name = 'feed_news_forum_ids';
+
+ if (!isset($forum_ids) && ($forum_ids = $this->cache->get('_' . $cache_name)) === false)
+ {
+ $sql = 'SELECT forum_id
+ FROM ' . FORUMS_TABLE . '
+ WHERE ' . $this->db->sql_bit_and('forum_options', FORUM_OPTION_FEED_NEWS, '<> 0');
+ $result = $this->db->sql_query($sql);
+
+ $forum_ids = array();
+ while ($forum_id = (int) $this->db->sql_fetchfield('forum_id'))
+ {
+ $forum_ids[$forum_id] = $forum_id;
+ }
+ $this->db->sql_freeresult($result);
+
+ $this->cache->put('_' . $cache_name, $forum_ids);
+ }
+
+ return $forum_ids;
+ }
+
+ function get_sql()
+ {
+ // Determine forum ids
+ $in_fid_ary = array_intersect($this->get_news_forums(), $this->get_readable_forums());
+ if (empty($in_fid_ary))
+ {
+ return false;
+ }
+
+ $in_fid_ary = array_diff($in_fid_ary, $this->get_passworded_forums());
+ if (empty($in_fid_ary))
+ {
+ return false;
+ }
+
+ // We really have to get the post ids first!
+ $sql = 'SELECT topic_first_post_id, topic_time
+ FROM ' . TOPICS_TABLE . '
+ WHERE ' . $this->db->sql_in_set('forum_id', $in_fid_ary) . '
+ AND topic_moved_id = 0
+ AND topic_approved = 1
+ ORDER BY topic_time DESC';
+ $result = $this->db->sql_query_limit($sql, $this->num_items);
+
+ $post_ids = array();
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $post_ids[] = (int) $row['topic_first_post_id'];
+ }
+ $this->db->sql_freeresult($result);
+
+ if (empty($post_ids))
+ {
+ return false;
+ }
+
+ $this->sql = array(
+ 'SELECT' => 'f.forum_id, f.forum_name,
+ t.topic_id, t.topic_title, t.topic_poster, t.topic_first_poster_name, t.topic_replies, t.topic_replies_real, t.topic_views, t.topic_time, t.topic_last_post_time,
+ p.post_id, p.post_time, p.post_edit_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url',
+ 'FROM' => array(
+ TOPICS_TABLE => 't',
+ POSTS_TABLE => 'p',
+ ),
+ 'LEFT_JOIN' => array(
+ array(
+ 'FROM' => array(FORUMS_TABLE => 'f'),
+ 'ON' => 'p.forum_id = f.forum_id',
+ ),
+ ),
+ 'WHERE' => 'p.topic_id = t.topic_id
+ AND ' . $this->db->sql_in_set('p.post_id', $post_ids),
+ 'ORDER_BY' => 'p.post_time DESC',
+ );
+
+ return true;
+ }
+}
diff --git a/phpBB/includes/feed/overall.php b/phpBB/includes/feed/overall.php
new file mode 100644
index 0000000000..5fb922f6bb
--- /dev/null
+++ b/phpBB/includes/feed/overall.php
@@ -0,0 +1,97 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Board wide feed (aka overall feed)
+*
+* This will give you the newest {$this->num_items} posts
+* from the whole board.
+*
+* @package phpBB3
+*/
+class phpbb_feed_overall extends phpbb_feed_post_base
+{
+ function get_sql()
+ {
+ $forum_ids = array_diff($this->get_readable_forums(), $this->get_excluded_forums(), $this->get_passworded_forums());
+ if (empty($forum_ids))
+ {
+ return false;
+ }
+
+ // m_approve forums
+ $fid_m_approve = $this->get_moderator_approve_forums();
+ $sql_m_approve = (!empty($fid_m_approve)) ? 'OR ' . $this->db->sql_in_set('forum_id', $fid_m_approve) : '';
+
+ // Determine topics with recent activity
+ $sql = 'SELECT topic_id, topic_last_post_time
+ FROM ' . TOPICS_TABLE . '
+ WHERE ' . $this->db->sql_in_set('forum_id', $forum_ids) . '
+ AND topic_moved_id = 0
+ AND (topic_approved = 1
+ ' . $sql_m_approve . ')
+ ORDER BY topic_last_post_time DESC';
+ $result = $this->db->sql_query_limit($sql, $this->num_items);
+
+ $topic_ids = array();
+ $min_post_time = 0;
+ while ($row = $this->db->sql_fetchrow())
+ {
+ $topic_ids[] = (int) $row['topic_id'];
+
+ $min_post_time = (int) $row['topic_last_post_time'];
+ }
+ $this->db->sql_freeresult($result);
+
+ if (empty($topic_ids))
+ {
+ return false;
+ }
+
+ // Get the actual data
+ $this->sql = array(
+ 'SELECT' => 'f.forum_id, f.forum_name, ' .
+ 'p.post_id, p.topic_id, p.post_time, p.post_edit_time, p.post_approved, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, ' .
+ 'u.username, u.user_id',
+ 'FROM' => array(
+ USERS_TABLE => 'u',
+ POSTS_TABLE => 'p',
+ ),
+ 'LEFT_JOIN' => array(
+ array(
+ 'FROM' => array(FORUMS_TABLE => 'f'),
+ 'ON' => 'f.forum_id = p.forum_id',
+ ),
+ ),
+ 'WHERE' => $this->db->sql_in_set('p.topic_id', $topic_ids) . '
+ AND (p.post_approved = 1
+ ' . str_replace('forum_id', 'p.forum_id', $sql_m_approve) . ')
+ AND p.post_time >= ' . $min_post_time . '
+ AND u.user_id = p.poster_id',
+ 'ORDER_BY' => 'p.post_time DESC',
+ );
+
+ return true;
+ }
+
+ function adjust_item(&$item_row, &$row)
+ {
+ parent::adjust_item($item_row, $row);
+
+ $item_row['title'] = (isset($row['forum_name']) && $row['forum_name'] !== '') ? $row['forum_name'] . ' ' . $this->separator . ' ' . $item_row['title'] : $item_row['title'];
+ }
+}
diff --git a/phpBB/includes/feed/post_base.php b/phpBB/includes/feed/post_base.php
new file mode 100644
index 0000000000..a25ed50263
--- /dev/null
+++ b/phpBB/includes/feed/post_base.php
@@ -0,0 +1,57 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Abstract class for post based feeds
+*
+* @package phpBB3
+*/
+abstract class phpbb_feed_post_base extends phpbb_feed_base
+{
+ var $num_items = 'feed_limit_post';
+
+ function set_keys()
+ {
+ $this->set('title', 'post_subject');
+ $this->set('title2', 'topic_title');
+
+ $this->set('author_id', 'user_id');
+ $this->set('creator', 'username');
+ $this->set('published', 'post_time');
+ $this->set('updated', 'post_edit_time');
+ $this->set('text', 'post_text');
+
+ $this->set('bitfield', 'bbcode_bitfield');
+ $this->set('bbcode_uid','bbcode_uid');
+
+ $this->set('enable_bbcode', 'enable_bbcode');
+ $this->set('enable_smilies', 'enable_smilies');
+ $this->set('enable_magic_url', 'enable_magic_url');
+ }
+
+ function adjust_item(&$item_row, &$row)
+ {
+ $item_row['link'] = $this->helper->append_sid('viewtopic.' . $this->phpEx, "t={$row['topic_id']}&amp;p={$row['post_id']}#p{$row['post_id']}");
+
+ if ($this->config['feed_item_statistics'])
+ {
+ $item_row['statistics'] = $this->user->lang['POSTED'] . ' ' . $this->user->lang['POST_BY_AUTHOR'] . ' ' . $this->user_viewprofile($row)
+ . ' ' . $this->separator_stats . ' ' . $this->user->format_date($row[$this->get('published')])
+ . (($this->is_moderator_approve_forum($row['forum_id']) && !$row['post_approved']) ? ' ' . $this->separator_stats . ' ' . $this->user->lang['POST_UNAPPROVED'] : '');
+ }
+ }
+}
diff --git a/phpBB/includes/feed/topic.php b/phpBB/includes/feed/topic.php
new file mode 100644
index 0000000000..7d9a344982
--- /dev/null
+++ b/phpBB/includes/feed/topic.php
@@ -0,0 +1,116 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Topic feed for a specific topic
+*
+* This will give you the last {$this->num_items} posts made within this topic.
+*
+* @package phpBB3
+*/
+class phpbb_feed_topic extends phpbb_feed_post_base
+{
+ var $topic_id = 0;
+ var $forum_id = 0;
+ var $topic_data = array();
+
+ /**
+ * Set the Topic ID
+ *
+ * @param int $topic_id Topic ID
+ * @return phpbb_feed_topic
+ */
+ public function set_topic_id($topic_id)
+ {
+ $this->topic_id = (int) $topic_id;
+
+ return $this;
+ }
+
+ function open()
+ {
+ $sql = 'SELECT f.forum_options, f.forum_password, t.topic_id, t.forum_id, t.topic_approved, t.topic_title, t.topic_time, t.topic_views, t.topic_replies, t.topic_type
+ FROM ' . TOPICS_TABLE . ' t
+ LEFT JOIN ' . FORUMS_TABLE . ' f
+ ON (f.forum_id = t.forum_id)
+ WHERE t.topic_id = ' . $this->topic_id;
+ $result = $this->db->sql_query($sql);
+ $this->topic_data = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if (empty($this->topic_data))
+ {
+ trigger_error('NO_TOPIC');
+ }
+
+ $this->forum_id = (int) $this->topic_data['forum_id'];
+
+ // Make sure topic is either approved or user authed
+ if (!$this->topic_data['topic_approved'] && !$this->auth->acl_get('m_approve', $this->forum_id))
+ {
+ trigger_error('SORRY_AUTH_READ');
+ }
+
+ // Make sure forum is not excluded from feed
+ if (phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $this->topic_data['forum_options']))
+ {
+ trigger_error('NO_FEED');
+ }
+
+ // Make sure we can read this forum
+ if (!$this->auth->acl_get('f_read', $this->forum_id))
+ {
+ trigger_error('SORRY_AUTH_READ');
+ }
+
+ // Make sure forum is not passworded or user is authed
+ if ($this->topic_data['forum_password'])
+ {
+ $forum_ids_passworded = $this->get_passworded_forums();
+
+ if (isset($forum_ids_passworded[$this->forum_id]))
+ {
+ trigger_error('SORRY_AUTH_READ');
+ }
+
+ unset($forum_ids_passworded);
+ }
+ }
+
+ function get_sql()
+ {
+ $this->sql = array(
+ 'SELECT' => 'p.post_id, p.post_time, p.post_edit_time, p.post_approved, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, ' .
+ 'u.username, u.user_id',
+ 'FROM' => array(
+ POSTS_TABLE => 'p',
+ USERS_TABLE => 'u',
+ ),
+ 'WHERE' => 'p.topic_id = ' . $this->topic_id . '
+ ' . ($this->forum_id && !$this->auth->acl_get('m_approve', $this->forum_id) ? 'AND p.post_approved = 1' : '') . '
+ AND p.poster_id = u.user_id',
+ 'ORDER_BY' => 'p.post_time DESC',
+ );
+
+ return true;
+ }
+
+ function get_item()
+ {
+ return ($row = parent::get_item()) ? array_merge($this->topic_data, $row) : $row;
+ }
+}
diff --git a/phpBB/includes/feed/topic_base.php b/phpBB/includes/feed/topic_base.php
new file mode 100644
index 0000000000..e6a47b4c86
--- /dev/null
+++ b/phpBB/includes/feed/topic_base.php
@@ -0,0 +1,59 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Abstract class for topic based feeds
+*
+* @package phpBB3
+*/
+abstract class phpbb_feed_topic_base extends phpbb_feed_base
+{
+ var $num_items = 'feed_limit_topic';
+
+ function set_keys()
+ {
+ $this->set('title', 'topic_title');
+ $this->set('title2', 'forum_name');
+
+ $this->set('author_id', 'topic_poster');
+ $this->set('creator', 'topic_first_poster_name');
+ $this->set('published', 'post_time');
+ $this->set('updated', 'post_edit_time');
+ $this->set('text', 'post_text');
+
+ $this->set('bitfield', 'bbcode_bitfield');
+ $this->set('bbcode_uid','bbcode_uid');
+
+ $this->set('enable_bbcode', 'enable_bbcode');
+ $this->set('enable_smilies', 'enable_smilies');
+ $this->set('enable_magic_url', 'enable_magic_url');
+ }
+
+ function adjust_item(&$item_row, &$row)
+ {
+ $item_row['link'] = $this->helper->append_sid('viewtopic.' . $this->phpEx, 't=' . $row['topic_id'] . '&amp;p=' . $row['post_id'] . '#p' . $row['post_id']);
+
+ if ($this->config['feed_item_statistics'])
+ {
+ $item_row['statistics'] = $this->user->lang['POSTED'] . ' ' . $this->user->lang['POST_BY_AUTHOR'] . ' ' . $this->user_viewprofile($row)
+ . ' ' . $this->separator_stats . ' ' . $this->user->format_date($row[$this->get('published')])
+ . ' ' . $this->separator_stats . ' ' . $this->user->lang['REPLIES'] . ' ' . (($this->is_moderator_approve_forum($row['forum_id'])) ? $row['topic_replies_real'] : $row['topic_replies'])
+ . ' ' . $this->separator_stats . ' ' . $this->user->lang['VIEWS'] . ' ' . $row['topic_views']
+ . (($this->is_moderator_approve_forum($row['forum_id']) && ($row['topic_replies_real'] != $row['topic_replies'])) ? ' ' . $this->separator_stats . ' ' . $this->user->lang['POSTS_UNAPPROVED'] : '');
+ }
+ }
+}
diff --git a/phpBB/includes/feed/topics.php b/phpBB/includes/feed/topics.php
new file mode 100644
index 0000000000..c8761d7176
--- /dev/null
+++ b/phpBB/includes/feed/topics.php
@@ -0,0 +1,91 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* New Topics feed
+*
+* This will give you the last {$this->num_items} created topics
+* including the first post.
+*
+* @package phpBB3
+*/
+class phpbb_feed_topics extends phpbb_feed_topic_base
+{
+ function get_sql()
+ {
+ $forum_ids_read = $this->get_readable_forums();
+ if (empty($forum_ids_read))
+ {
+ return false;
+ }
+
+ $in_fid_ary = array_diff($forum_ids_read, $this->get_excluded_forums(), $this->get_passworded_forums());
+ if (empty($in_fid_ary))
+ {
+ return false;
+ }
+
+ // We really have to get the post ids first!
+ $sql = 'SELECT topic_first_post_id, topic_time
+ FROM ' . TOPICS_TABLE . '
+ WHERE ' . $this->db->sql_in_set('forum_id', $in_fid_ary) . '
+ AND topic_moved_id = 0
+ AND topic_approved = 1
+ ORDER BY topic_time DESC';
+ $result = $this->db->sql_query_limit($sql, $this->num_items);
+
+ $post_ids = array();
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $post_ids[] = (int) $row['topic_first_post_id'];
+ }
+ $this->db->sql_freeresult($result);
+
+ if (empty($post_ids))
+ {
+ return false;
+ }
+
+ $this->sql = array(
+ 'SELECT' => 'f.forum_id, f.forum_name,
+ t.topic_id, t.topic_title, t.topic_poster, t.topic_first_poster_name, t.topic_replies, t.topic_replies_real, t.topic_views, t.topic_time, t.topic_last_post_time,
+ p.post_id, p.post_time, p.post_edit_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url',
+ 'FROM' => array(
+ TOPICS_TABLE => 't',
+ POSTS_TABLE => 'p',
+ ),
+ 'LEFT_JOIN' => array(
+ array(
+ 'FROM' => array(FORUMS_TABLE => 'f'),
+ 'ON' => 'p.forum_id = f.forum_id',
+ ),
+ ),
+ 'WHERE' => 'p.topic_id = t.topic_id
+ AND ' . $this->db->sql_in_set('p.post_id', $post_ids),
+ 'ORDER_BY' => 'p.post_time DESC',
+ );
+
+ return true;
+ }
+
+ function adjust_item(&$item_row, &$row)
+ {
+ parent::adjust_item($item_row, $row);
+
+ $item_row['title'] = (isset($row['forum_name']) && $row['forum_name'] !== '') ? $row['forum_name'] . ' ' . $this->separator . ' ' . $item_row['title'] : $item_row['title'];
+ }
+}
diff --git a/phpBB/includes/feed/topics_active.php b/phpBB/includes/feed/topics_active.php
new file mode 100644
index 0000000000..d1c920c136
--- /dev/null
+++ b/phpBB/includes/feed/topics_active.php
@@ -0,0 +1,136 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Active Topics feed
+*
+* This will give you the last {$this->num_items} topics
+* with replies made withing the last {$this->sort_days} days
+* including the last post.
+*
+* @package phpBB3
+*/
+class phpbb_feed_topics_active extends phpbb_feed_topic_base
+{
+ var $sort_days = 7;
+
+ function set_keys()
+ {
+ parent::set_keys();
+
+ $this->set('author_id', 'topic_last_poster_id');
+ $this->set('creator', 'topic_last_poster_name');
+ }
+
+ function get_sql()
+ {
+ $forum_ids_read = $this->get_readable_forums();
+ if (empty($forum_ids_read))
+ {
+ return false;
+ }
+
+ $in_fid_ary = array_intersect($forum_ids_read, $this->get_forum_ids());
+ $in_fid_ary = array_diff($in_fid_ary, $this->get_passworded_forums());
+ if (empty($in_fid_ary))
+ {
+ return false;
+ }
+
+ // Search for topics in last X days
+ $last_post_time_sql = ($this->sort_days) ? ' AND topic_last_post_time > ' . (time() - ($this->sort_days * 24 * 3600)) : '';
+
+ // We really have to get the post ids first!
+ $sql = 'SELECT topic_last_post_id, topic_last_post_time
+ FROM ' . TOPICS_TABLE . '
+ WHERE ' . $this->db->sql_in_set('forum_id', $in_fid_ary) . '
+ AND topic_moved_id = 0
+ AND topic_approved = 1
+ ' . $last_post_time_sql . '
+ ORDER BY topic_last_post_time DESC';
+ $result = $this->db->sql_query_limit($sql, $this->num_items);
+
+ $post_ids = array();
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $post_ids[] = (int) $row['topic_last_post_id'];
+ }
+ $this->db->sql_freeresult($result);
+
+ if (empty($post_ids))
+ {
+ return false;
+ }
+
+ $this->sql = array(
+ 'SELECT' => 'f.forum_id, f.forum_name,
+ t.topic_id, t.topic_title, t.topic_replies, t.topic_replies_real, t.topic_views,
+ t.topic_last_poster_id, t.topic_last_poster_name, t.topic_last_post_time,
+ p.post_id, p.post_time, p.post_edit_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url',
+ 'FROM' => array(
+ TOPICS_TABLE => 't',
+ POSTS_TABLE => 'p',
+ ),
+ 'LEFT_JOIN' => array(
+ array(
+ 'FROM' => array(FORUMS_TABLE => 'f'),
+ 'ON' => 'p.forum_id = f.forum_id',
+ ),
+ ),
+ 'WHERE' => 'p.topic_id = t.topic_id
+ AND ' . $this->db->sql_in_set('p.post_id', $post_ids),
+ 'ORDER_BY' => 'p.post_time DESC',
+ );
+
+ return true;
+ }
+
+ function get_forum_ids()
+ {
+ static $forum_ids;
+
+ $cache_name = 'feed_topic_active_forum_ids';
+
+ if (!isset($forum_ids) && ($forum_ids = $this->cache->get('_' . $cache_name)) === false)
+ {
+ $sql = 'SELECT forum_id
+ FROM ' . FORUMS_TABLE . '
+ WHERE forum_type = ' . FORUM_POST . '
+ AND ' . $this->db->sql_bit_and('forum_options', FORUM_OPTION_FEED_EXCLUDE, '= 0') . '
+ AND ' . $this->db->sql_bit_and('forum_flags', log(FORUM_FLAG_ACTIVE_TOPICS, 2), '<> 0');
+ $result = $this->db->sql_query($sql);
+
+ $forum_ids = array();
+ while ($forum_id = (int) $this->db->sql_fetchfield('forum_id'))
+ {
+ $forum_ids[$forum_id] = $forum_id;
+ }
+ $this->db->sql_freeresult($result);
+
+ $this->cache->put('_' . $cache_name, $forum_ids, 180);
+ }
+
+ return $forum_ids;
+ }
+
+ function adjust_item(&$item_row, &$row)
+ {
+ parent::adjust_item($item_row, $row);
+
+ $item_row['title'] = (isset($row['forum_name']) && $row['forum_name'] !== '') ? $row['forum_name'] . ' ' . $this->separator . ' ' . $item_row['title'] : $item_row['title'];
+ }
+}
diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php
index 0dc2f314f1..6a1b3fd4f8 100644
--- a/phpBB/includes/functions.php
+++ b/phpBB/includes/functions.php
@@ -846,7 +846,7 @@ function phpbb_is_writable($file)
*/
function phpbb_is_absolute($path)
{
- return ($path[0] == '/' || (DIRECTORY_SEPARATOR == '\\' && preg_match('#^[a-z]:[/\\\]#i', $path))) ? true : false;
+ return (isset($path[0]) && $path[0] == '/' || preg_match('#^[a-z]:[/\\\]#i', $path)) ? true : false;
}
/**
@@ -2345,9 +2345,8 @@ function phpbb_generate_template_pagination($template, $base_url, $block_var_nam
$tpl_prefix . 'BASE_URL' => $base_url,
'A_' . $tpl_prefix . 'BASE_URL' => addslashes($base_url),
$tpl_prefix . 'PER_PAGE' => $per_page,
- $tpl_prefix . 'PREVIOUS_PAGE' => $previous_page,
- $tpl_prefix . 'PREV_PAGE' => $previous_page,
- $tpl_prefix . 'NEXT_PAGE' => ($on_page != $total_pages) ? $base_url . $url_delim . $start_name . '=' . ($on_page * $per_page) : '',
+ 'U_' . $tpl_prefix . 'PREVIOUS_PAGE' => $previous_page,
+ 'U_' . $tpl_prefix . 'NEXT_PAGE' => ($on_page != $total_pages) ? $base_url . $url_delim . $start_name . '=' . ($on_page * $per_page) : '',
$tpl_prefix . 'TOTAL_PAGES' => $total_pages,
$tpl_prefix . 'CURRENT_PAGE' => $on_page,
);
@@ -2907,7 +2906,7 @@ function meta_refresh($time, $url, $disable_cd_check = false)
// For XHTML compatibility we change back & to &amp;
$template->assign_vars(array(
- 'META' => '<meta http-equiv="refresh" content="' . $time . ';url=' . $url . '" />')
+ 'META' => '<meta http-equiv="refresh" content="' . $time . '; url=' . $url . '" />')
);
}
diff --git a/phpBB/includes/functions_acp.php b/phpBB/includes/functions_acp.php
index d6bd9e35dd..ff0e2a1ac1 100644
--- a/phpBB/includes/functions_acp.php
+++ b/phpBB/includes/functions_acp.php
@@ -249,17 +249,49 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
{
case 'text':
case 'password':
+ case 'url':
+ case 'email':
+ case 'color':
+ case 'date':
+ case 'time':
+ case 'datetime':
+ case 'datetime-local':
+ case 'month':
+ case 'range':
+ case 'search':
+ case 'tel':
+ case 'url':
+ case 'week':
$size = (int) $tpl_type[1];
$maxlength = (int) $tpl_type[2];
$tpl = '<input id="' . $key . '" type="' . $tpl_type[0] . '"' . (($size) ? ' size="' . $size . '"' : '') . ' maxlength="' . (($maxlength) ? $maxlength : 255) . '" name="' . $name . '" value="' . $new[$config_key] . '"' . (($tpl_type[0] === 'password') ? ' autocomplete="off"' : '') . ' />';
break;
+ case 'number':
+ $min = $max = $maxlength = '';
+ $min = ( isset($tpl_type[1]) ) ? (int) $tpl_type[1] : false;
+ if ( isset($tpl_type[2]) )
+ {
+ $max = (int) $tpl_type[2];
+ $maxlength = strlen( (string) $max );
+ }
+
+ $tpl = '<input id="' . $key . '" type="number" maxlength="' . (( $maxlength != '' ) ? $maxlength : 255) . '"' . (( $min != '' ) ? ' min="' . $min . '"' : '') . (( $max != '' ) ? ' max="' . $max . '"' : '') . ' name="' . $name . '" value="' . $new[$config_key] . '" />';
+ break;
+
case 'dimension':
- $size = (int) $tpl_type[1];
- $maxlength = (int) $tpl_type[2];
+ $min = $max = $maxlength = $size = '';
+
+ $min = (int) $tpl_type[1];
+
+ if ( isset($tpl_type[2]) )
+ {
+ $max = (int) $tpl_type[2];
+ $size = $maxlength = strlen( (string) $max );
+ }
- $tpl = '<input id="' . $key . '" type="text"' . (($size) ? ' size="' . $size . '"' : '') . ' maxlength="' . (($maxlength) ? $maxlength : 255) . '" name="config[' . $config_key . '_width]" value="' . $new[$config_key . '_width'] . '" /> x <input type="text"' . (($size) ? ' size="' . $size . '"' : '') . ' maxlength="' . (($maxlength) ? $maxlength : 255) . '" name="config[' . $config_key . '_height]" value="' . $new[$config_key . '_height'] . '" />';
+ $tpl = '<input id="' . $key . '" type="number"' . (( $size != '' ) ? ' size="' . $size . '"' : '') . ' maxlength="' . (($maxlength != '') ? $maxlength : 255) . '"' . (( $min !== '' ) ? ' min="' . $min . '"' : '') . (( $max != '' ) ? ' max="' . $max . '"' : '') . ' name="config[' . $config_key . '_width]" value="' . $new[$config_key . '_width'] . '" /> x <input type="number"' . (( $size != '' ) ? ' size="' . $size . '"' : '') . ' maxlength="' . (($maxlength != '') ? $maxlength : 255) . '"' . (( $min !== '' ) ? ' min="' . $min . '"' : '') . (( $max != '' ) ? ' max="' . $max . '"' : '') . ' name="config[' . $config_key . '_height]" value="' . $new[$config_key . '_height'] . '" />';
break;
case 'textarea':
diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php
index d273b9fb3a..21662eb493 100644
--- a/phpBB/includes/functions_admin.php
+++ b/phpBB/includes/functions_admin.php
@@ -2899,7 +2899,7 @@ function get_remote_file($host, $directory, $filename, &$errstr, &$errno, $port
if ($fsock = @fsockopen($host, $port, $errno, $errstr, $timeout))
{
- @fputs($fsock, "GET $directory/$filename HTTP/1.1\r\n");
+ @fputs($fsock, "GET $directory/$filename HTTP/1.0\r\n");
@fputs($fsock, "HOST: $host\r\n");
@fputs($fsock, "Connection: close\r\n\r\n");
@@ -3040,38 +3040,29 @@ function tidy_database()
*/
function add_permission_language()
{
- global $user, $phpEx;
+ global $user, $phpEx, $phpbb_extension_manager;
- // First of all, our own file. We need to include it as the first file because it presets all relevant variables.
- $user->add_lang('acp/permissions_phpbb');
+ // add permission language files from extensions
+ $finder = $phpbb_extension_manager->get_finder();
- $files_to_add = array();
+ $lang_files = $finder
+ ->prefix('permissions_')
+ ->suffix(".$phpEx")
+ ->core_path('language/' . $user->lang_name . '/')
+ ->extension_directory('/language/' . $user->lang_name)
+ ->find();
- // Now search in acp and mods folder for permissions_ files.
- foreach (array('acp/', 'mods/') as $path)
+ foreach ($lang_files as $lang_file => $ext_name)
{
- $dh = @opendir($user->lang_path . $user->lang_name . '/' . $path);
-
- if ($dh)
+ if ($ext_name === '/')
{
- while (($file = readdir($dh)) !== false)
- {
- if ($file !== 'permissions_phpbb.' . $phpEx && strpos($file, 'permissions_') === 0 && substr($file, -(strlen($phpEx) + 1)) === '.' . $phpEx)
- {
- $files_to_add[] = $path . substr($file, 0, -(strlen($phpEx) + 1));
- }
- }
- closedir($dh);
+ $user->add_lang($lang_file);
+ }
+ else
+ {
+ $user->add_lang_ext($ext_name, $lang_file);
}
}
-
- if (!sizeof($files_to_add))
- {
- return false;
- }
-
- $user->add_lang($files_to_add);
- return true;
}
/**
@@ -3097,7 +3088,7 @@ function obtain_latest_version_info($force_update = false, $warn_fail = false, $
$info = get_remote_file('version.phpbb.com', '/phpbb',
((defined('PHPBB_QA')) ? '30x_qa.txt' : '30x.txt'), $errstr, $errno);
- if ($info === false)
+ if (empty($info))
{
$cache->destroy('versioncheck');
if ($warn_fail)
diff --git a/phpBB/includes/functions_download.php b/phpBB/includes/functions_download.php
index ee4e2f5135..0a8000ea3d 100644
--- a/phpBB/includes/functions_download.php
+++ b/phpBB/includes/functions_download.php
@@ -46,7 +46,7 @@ function send_avatar_to_browser($file, $browser)
$image_data = @getimagesize($file_path);
header('Content-Type: ' . image_type_to_mime_type($image_data[2]));
- if (strpos(strtolower($browser), 'msie') !== false && strpos(strtolower($browser), 'msie 8.0') === false)
+ if ((strpos(strtolower($user->browser), 'msie') !== false) && !phpbb_is_greater_ie_version($browser, 7))
{
header('Content-Disposition: attachment; ' . header_filename($file));
@@ -174,10 +174,9 @@ function send_file_to_browser($attachment, $upload_dir, $category)
header('Pragma: public');
// Send out the Headers. Do not set Content-Disposition to inline please, it is a security measure for users using the Internet Explorer.
- $is_ie8 = (strpos(strtolower($user->browser), 'msie 8.0') !== false);
header('Content-Type: ' . $attachment['mimetype']);
- if ($is_ie8)
+ if (phpbb_is_greater_ie_version($user->browser, 7))
{
header('X-Content-Type-Options: nosniff');
}
@@ -189,7 +188,7 @@ function send_file_to_browser($attachment, $upload_dir, $category)
}
else
{
- if (empty($user->browser) || (!$is_ie8 && (strpos(strtolower($user->browser), 'msie') !== false)))
+ if (empty($user->browser) || ((strpos(strtolower($user->browser), 'msie') !== false) && !phpbb_is_greater_ie_version($user->browser, 7)))
{
header('Content-Disposition: attachment; ' . header_filename(htmlspecialchars_decode($attachment['real_filename'])));
if (empty($user->browser) || (strpos(strtolower($user->browser), 'msie 6.0') !== false))
@@ -200,7 +199,7 @@ function send_file_to_browser($attachment, $upload_dir, $category)
else
{
header('Content-Disposition: ' . ((strpos($attachment['mimetype'], 'image') === 0) ? 'inline' : 'attachment') . '; ' . header_filename(htmlspecialchars_decode($attachment['real_filename'])));
- if ($is_ie8 && (strpos($attachment['mimetype'], 'image') !== 0))
+ if (phpbb_is_greater_ie_version($user->browser, 7) && (strpos($attachment['mimetype'], 'image') !== 0))
{
header('X-Download-Options: noopen');
}
@@ -410,7 +409,8 @@ function set_modified_headers($stamp, $browser)
// let's see if we have to send the file at all
$last_load = $request->header('Modified-Since') ? strtotime(trim($request->header('Modified-Since'))) : false;
- if ((strpos(strtolower($browser), 'msie 6.0') === false) && (strpos(strtolower($browser), 'msie 8.0') === false))
+
+ if (strpos(strtolower($browser), 'msie 6.0') === false && !phpbb_is_greater_ie_version($browser, 7))
{
if ($last_load !== false && $last_load >= $stamp)
{
@@ -721,3 +721,24 @@ function phpbb_download_clean_filename($filename)
return $filename;
}
+
+/**
+* Check if the browser is internet explorer version 7+
+*
+* @param string $user_agent User agent HTTP header
+* @param int $version IE version to check against
+*
+* @return bool true if internet explorer version is greater than $version
+*/
+function phpbb_is_greater_ie_version($user_agent, $version)
+{
+ if (preg_match('/msie (\d+)/', strtolower($user_agent), $matches))
+ {
+ $ie_version = (int) $matches[1];
+ return ($ie_version > $version);
+ }
+ else
+ {
+ return false;
+ }
+}
diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php
index baef7bcda5..b9b518ad32 100644
--- a/phpBB/includes/functions_posting.php
+++ b/phpBB/includes/functions_posting.php
@@ -403,14 +403,7 @@ function upload_attachment($form_name, $forum_id, $local = false, $local_storage
$upload->set_disallowed_content(explode('|', $config['mime_triggers']));
}
- if (!$local)
- {
- $filedata['post_attach'] = ($upload->is_valid($form_name)) ? true : false;
- }
- else
- {
- $filedata['post_attach'] = true;
- }
+ $filedata['post_attach'] = $local || $upload->is_valid($form_name);
if (!$filedata['post_attach'])
{
@@ -429,30 +422,18 @@ function upload_attachment($form_name, $forum_id, $local = false, $local_storage
return $filedata;
}
- $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['ATTACHED_IMAGE_NOT_IMAGE']);
- }
-
- // Do we have to create a thumbnail?
- $filedata['thumbnail'] = ($cat_id == ATTACHMENT_CATEGORY_IMAGE && $config['img_create_thumbnail']) ? 1 : 0;
-
- // Check Image Size, if it is an image
- if (!$auth->acl_get('a_') && !$auth->acl_get('m_', $forum_id) && $cat_id == ATTACHMENT_CATEGORY_IMAGE)
- {
- $file->upload->set_allowed_dimensions(0, 0, $config['img_max_width'], $config['img_max_height']);
- }
+ // Whether the uploaded file is in the image category
+ $is_image = (isset($extensions[$file->get('extension')]['display_cat'])) ? $extensions[$file->get('extension')]['display_cat'] == ATTACHMENT_CATEGORY_IMAGE : false;
- // Admins and mods are allowed to exceed the allowed filesize
if (!$auth->acl_get('a_') && !$auth->acl_get('m_', $forum_id))
{
+ // Check Image Size, if it is an image
+ if ($is_image)
+ {
+ $file->upload->set_allowed_dimensions(0, 0, $config['img_max_width'], $config['img_max_height']);
+ }
+
+ // Admins and mods are allowed to exceed the allowed filesize
if (!empty($extensions[$file->get('extension')]['max_filesize']))
{
$allowed_filesize = $extensions[$file->get('extension')]['max_filesize'];
@@ -467,10 +448,12 @@ function upload_attachment($form_name, $forum_id, $local = false, $local_storage
$file->clean_filename('unique', $user->data['user_id'] . '_');
- // Are we uploading an image *and* this image being within the image category? Only then perform additional image checks.
- $no_image = ($cat_id == ATTACHMENT_CATEGORY_IMAGE) ? false : true;
+ // Are we uploading an image *and* this image being within the image category?
+ // Only then perform additional image checks.
+ $file->move_file($config['upload_path'], false, !$is_image);
- $file->move_file($config['upload_path'], false, $no_image);
+ // Do we have to create a thumbnail?
+ $filedata['thumbnail'] = ($is_image && $config['img_create_thumbnail']) ? 1 : 0;
if (sizeof($file->error))
{
@@ -481,6 +464,16 @@ function upload_attachment($form_name, $forum_id, $local = false, $local_storage
return $filedata;
}
+ // Make sure the image category only holds valid images...
+ if ($is_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['ATTACHED_IMAGE_NOT_IMAGE']);
+ }
+
$filedata['filesize'] = $file->get('filesize');
$filedata['mimetype'] = $file->get('mimetype');
$filedata['extension'] = $file->get('extension');
diff --git a/phpBB/includes/functions_profile_fields.php b/phpBB/includes/functions_profile_fields.php
index 10af997bff..7dd0b0e87d 100644
--- a/phpBB/includes/functions_profile_fields.php
+++ b/phpBB/includes/functions_profile_fields.php
@@ -1040,9 +1040,9 @@ class custom_profile_admin extends custom_profile
global $user;
$options = array(
- 0 => array('TITLE' => $user->lang['FIELD_LENGTH'], 'FIELD' => '<input type="text" name="field_length" size="5" value="' . $this->vars['field_length'] . '" />'),
- 1 => array('TITLE' => $user->lang['MIN_FIELD_CHARS'], 'FIELD' => '<input type="text" name="field_minlen" size="5" value="' . $this->vars['field_minlen'] . '" />'),
- 2 => array('TITLE' => $user->lang['MAX_FIELD_CHARS'], 'FIELD' => '<input type="text" name="field_maxlen" size="5" value="' . $this->vars['field_maxlen'] . '" />'),
+ 0 => array('TITLE' => $user->lang['FIELD_LENGTH'], 'FIELD' => '<input type="number" min="0" name="field_length" size="5" value="' . $this->vars['field_length'] . '" />'),
+ 1 => array('TITLE' => $user->lang['MIN_FIELD_CHARS'], 'FIELD' => '<input type="number" min="0" name="field_minlen" size="5" value="' . $this->vars['field_minlen'] . '" />'),
+ 2 => array('TITLE' => $user->lang['MAX_FIELD_CHARS'], 'FIELD' => '<input type="number" min="0" size="5" value="' . $this->vars['field_maxlen'] . '" />'),
3 => array('TITLE' => $user->lang['FIELD_VALIDATION'], 'FIELD' => '<select name="field_validation">' . $this->validate_options() . '</select>')
);
@@ -1057,9 +1057,9 @@ class custom_profile_admin extends custom_profile
global $user;
$options = array(
- 0 => array('TITLE' => $user->lang['FIELD_LENGTH'], 'FIELD' => '<input name="rows" size="5" value="' . $this->vars['rows'] . '" /> ' . $user->lang['ROWS'] . '</dd><dd><input name="columns" size="5" value="' . $this->vars['columns'] . '" /> ' . $user->lang['COLUMNS'] . ' <input type="hidden" name="field_length" value="' . $this->vars['field_length'] . '" />'),
- 1 => array('TITLE' => $user->lang['MIN_FIELD_CHARS'], 'FIELD' => '<input type="text" name="field_minlen" size="10" value="' . $this->vars['field_minlen'] . '" />'),
- 2 => array('TITLE' => $user->lang['MAX_FIELD_CHARS'], 'FIELD' => '<input type="text" name="field_maxlen" size="10" value="' . $this->vars['field_maxlen'] . '" />'),
+ 0 => array('TITLE' => $user->lang['FIELD_LENGTH'], 'FIELD' => '<input type="number" min="0" max="99999" name="rows" size="5" value="' . $this->vars['rows'] . '" /> ' . $user->lang['ROWS'] . '</dd><dd><input type="number" min="0" max="99999" name="columns" size="5" value="' . $this->vars['columns'] . '" /> ' . $user->lang['COLUMNS'] . ' <input type="hidden" name="field_length" value="' . $this->vars['field_length'] . '" />'),
+ 1 => array('TITLE' => $user->lang['MIN_FIELD_CHARS'], 'FIELD' => '<input type="number" min="0" max="9999999999" name="field_minlen" size="10" value="' . $this->vars['field_minlen'] . '" />'),
+ 2 => array('TITLE' => $user->lang['MAX_FIELD_CHARS'], 'FIELD' => '<input type="number" min="0" max="9999999999" name="field_maxlen" size="10" value="' . $this->vars['field_maxlen'] . '" />'),
3 => array('TITLE' => $user->lang['FIELD_VALIDATION'], 'FIELD' => '<select name="field_validation">' . $this->validate_options() . '</select>')
);
@@ -1074,9 +1074,9 @@ class custom_profile_admin extends custom_profile
global $user;
$options = array(
- 0 => array('TITLE' => $user->lang['FIELD_LENGTH'], 'FIELD' => '<input type="text" name="field_length" size="5" value="' . $this->vars['field_length'] . '" />'),
- 1 => array('TITLE' => $user->lang['MIN_FIELD_NUMBER'], 'FIELD' => '<input type="text" name="field_minlen" size="5" value="' . $this->vars['field_minlen'] . '" />'),
- 2 => array('TITLE' => $user->lang['MAX_FIELD_NUMBER'], 'FIELD' => '<input type="text" name="field_maxlen" size="5" value="' . $this->vars['field_maxlen'] . '" />'),
+ 0 => array('TITLE' => $user->lang['FIELD_LENGTH'], 'FIELD' => '<input type="number" min="0" max="99999" name="field_length" size="5" value="' . $this->vars['field_length'] . '" />'),
+ 1 => array('TITLE' => $user->lang['MIN_FIELD_NUMBER'], 'FIELD' => '<input type="number" min="0" max="99999" name="field_minlen" size="5" value="' . $this->vars['field_minlen'] . '" />'),
+ 2 => array('TITLE' => $user->lang['MAX_FIELD_NUMBER'], 'FIELD' => '<input type="number" min="0" max="99999" name="field_maxlen" size="5" value="' . $this->vars['field_maxlen'] . '" />'),
3 => array('TITLE' => $user->lang['DEFAULT_VALUE'], 'FIELD' => '<input type="post" name="field_default_value" value="' . $this->vars['field_default_value'] . '" />')
);
diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php
index 599cb24f75..1b598f7bf7 100644
--- a/phpBB/includes/functions_user.php
+++ b/phpBB/includes/functions_user.php
@@ -1330,22 +1330,12 @@ function validate_data($data, $val_ary)
{
$function = array_shift($validate);
array_unshift($validate, $data[$var]);
+ $function_prefix = (function_exists('phpbb_validate_' . $function)) ? 'phpbb_validate_' : 'validate_';
- if (function_exists('phpbb_validate_' . $function))
+ if ($result = call_user_func_array($function_prefix . $function, $validate))
{
- if ($result = call_user_func_array('phpbb_validate_' . $function, $validate))
- {
- // Since errors are checked later for their language file existence, we need to make sure custom errors are not adjusted.
- $error[] = (empty($user->lang[$result . '_' . strtoupper($var)])) ? $result : $result . '_' . strtoupper($var);
- }
- }
- else
- {
- if ($result = call_user_func_array('validate_' . $function, $validate))
- {
- // Since errors are checked later for their language file existence, we need to make sure custom errors are not adjusted.
- $error[] = (empty($user->lang[$result . '_' . strtoupper($var)])) ? $result : $result . '_' . strtoupper($var);
- }
+ // Since errors are checked later for their language file existence, we need to make sure custom errors are not adjusted.
+ $error[] = (empty($user->lang[$result . '_' . strtoupper($var)])) ? $result : $result . '_' . strtoupper($var);
}
}
}
@@ -1663,7 +1653,7 @@ function validate_username($username, $allowed_username = false)
*/
function validate_password($password)
{
- global $config, $db, $user;
+ global $config;
if ($password === '' || $config['pass_complex'] === 'PASS_TYPE_ANY')
{
@@ -2009,6 +1999,30 @@ function validate_jabber($jid)
}
/**
+* Validate hex colour value
+*
+* @param string $colour The hex colour value
+* @param bool $optional Whether the colour value is optional. True if an empty
+* string will be accepted as correct input, false if not.
+* @return bool|string Error message if colour value is incorrect, false if it
+* fits the hex colour code
+*/
+function phpbb_validate_hex_colour($colour, $optional = false)
+{
+ if ($colour === '')
+ {
+ return (($optional) ? false : 'WRONG_DATA');
+ }
+
+ if (!preg_match('/^([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/', $colour))
+ {
+ return 'WRONG_DATA';
+ }
+
+ return false;
+}
+
+/**
* Verifies whether a style ID corresponds to an active style.
*
* @param int $style_id The style_id of a style which should be checked if activated or not.
diff --git a/phpBB/includes/notification/exception.php b/phpBB/includes/notification/exception.php
new file mode 100644
index 0000000000..a52d6fdc57
--- /dev/null
+++ b/phpBB/includes/notification/exception.php
@@ -0,0 +1,29 @@
+<?php
+/**
+*
+* @package notifications
+* @copyright (c) 2013 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Notifications exception
+*
+* @package notifications
+*/
+class phpbb_notification_exception extends \Exception
+{
+ public function __toString()
+ {
+ return $this->getMessage();
+ }
+}
diff --git a/phpBB/includes/notification/manager.php b/phpBB/includes/notification/manager.php
index 9eceeb753a..97833710c0 100644
--- a/phpBB/includes/notification/manager.php
+++ b/phpBB/includes/notification/manager.php
@@ -36,6 +36,9 @@ class phpbb_notification_manager
/** @var phpbb_db_driver */
protected $db;
+ /** @var phpbb_cache_service */
+ protected $cache;
+
/** @var phpbb_user */
protected $user;
@@ -70,7 +73,7 @@ class phpbb_notification_manager
* @param string $user_notifications_table
* @return phpbb_notification_manager
*/
- public function __construct($notification_types, $notification_methods, $phpbb_container, phpbb_user_loader $user_loader, phpbb_db_driver $db, $user, $phpbb_root_path, $php_ext, $notification_types_table, $notifications_table, $user_notifications_table)
+ public function __construct($notification_types, $notification_methods, $phpbb_container, phpbb_user_loader $user_loader, phpbb_db_driver $db, phpbb_cache_service $cache, $user, $phpbb_root_path, $php_ext, $notification_types_table, $notifications_table, $user_notifications_table)
{
$this->notification_types = $notification_types;
$this->notification_methods = $notification_methods;
@@ -78,6 +81,7 @@ class phpbb_notification_manager
$this->user_loader = $user_loader;
$this->db = $db;
+ $this->cache = $cache;
$this->user = $user;
$this->phpbb_root_path = $phpbb_root_path;
@@ -145,7 +149,7 @@ class phpbb_notification_manager
FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
WHERE n.user_id = ' . (int) $options['user_id'] . '
AND n.notification_read = 0
- AND nt.notification_type = n.item_type
+ AND nt.notification_type_id = n.notification_type_id
AND nt.notification_type_enabled = 1';
$result = $this->db->sql_query($sql);
$unread_count = (int) $this->db->sql_fetchfield('unread_count', $result);
@@ -158,7 +162,7 @@ class phpbb_notification_manager
$sql = 'SELECT COUNT(n.notification_id) AS total_count
FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
WHERE n.user_id = ' . (int) $options['user_id'] . '
- AND nt.notification_type = n.item_type
+ AND nt.notification_type_id = n.notification_type_id
AND nt.notification_type_enabled = 1';
$result = $this->db->sql_query($sql);
$total_count = (int) $this->db->sql_fetchfield('total_count', $result);
@@ -170,11 +174,11 @@ class phpbb_notification_manager
$rowset = array();
// Get the main notifications
- $sql = 'SELECT n.*
+ $sql = 'SELECT n.*, nt.notification_type_name
FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
WHERE n.user_id = ' . (int) $options['user_id'] .
(($options['notification_id']) ? ((is_array($options['notification_id'])) ? ' AND ' . $this->db->sql_in_set('n.notification_id', $options['notification_id']) : ' AND n.notification_id = ' . (int) $options['notification_id']) : '') . '
- AND nt.notification_type = n.item_type
+ AND nt.notification_type_id = n.notification_type_id
AND nt.notification_type_enabled = 1
ORDER BY n.' . $this->db->sql_escape($options['order_by']) . ' ' . $this->db->sql_escape($options['order_dir']);
$result = $this->db->sql_query_limit($sql, $options['limit'], $options['start']);
@@ -188,12 +192,12 @@ class phpbb_notification_manager
// Get all unread notifications
if ($unread_count && $options['all_unread'] && !empty($rowset))
{
- $sql = 'SELECT n.*
+ $sql = 'SELECT n.*, nt.notification_type_name
FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
WHERE n.user_id = ' . (int) $options['user_id'] . '
AND n.notification_read = 0
AND ' . $this->db->sql_in_set('n.notification_id', array_keys($rowset), true) . '
- AND nt.notification_type = n.item_type
+ AND nt.notification_type_id = n.notification_type_id
AND nt.notification_type_enabled = 1
ORDER BY n.' . $this->db->sql_escape($options['order_by']) . ' ' . $this->db->sql_escape($options['order_dir']);
$result = $this->db->sql_query_limit($sql, $options['limit'], $options['start']);
@@ -207,17 +211,17 @@ class phpbb_notification_manager
foreach ($rowset as $row)
{
- $notification = $this->get_item_type_class($row['item_type'], $row);
+ $notification = $this->get_item_type_class($row['notification_type_name'], $row);
// Array of user_ids to query all at once
$user_ids = array_merge($user_ids, $notification->users_to_query());
// Some notification types also require querying additional tables themselves
- if (!isset($load_special[$row['item_type']]))
+ if (!isset($load_special[$row['notification_type_name']]))
{
- $load_special[$row['item_type']] = array();
+ $load_special[$row['notification_type_name']] = array();
}
- $load_special[$row['item_type']] = array_merge($load_special[$row['item_type']], $notification->get_load_special());
+ $load_special[$row['notification_type_name']] = array_merge($load_special[$row['notification_type_name']], $notification->get_load_special());
$notifications[$row['notification_id']] = $notification;
}
@@ -243,19 +247,21 @@ class phpbb_notification_manager
/**
* Mark notifications read
*
- * @param bool|string|array $item_type Type identifier or array of item types (only acceptable if the $data is identical for the specified types). False to mark read for all item types
+ * @param bool|string|array $notification_type_name Type identifier or array of item types (only acceptable if the $data is identical for the specified types). False to mark read for all item types
* @param bool|int|array $item_id Item id or array of item ids. False to mark read for all item ids
* @param bool|int|array $user_id User id or array of user ids. False to mark read for all user ids
* @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False)
*/
- public function mark_notifications_read($item_type, $item_id, $user_id, $time = false)
+ public function mark_notifications_read($notification_type_name, $item_id, $user_id, $time = false)
{
$time = ($time !== false) ? $time : time();
$sql = 'UPDATE ' . $this->notifications_table . "
SET notification_read = 1
WHERE notification_time <= " . (int) $time .
- (($item_type !== false) ? ' AND ' . (is_array($item_type) ? $this->db->sql_in_set('item_type', $item_type) : " item_type = '" . $this->db->sql_escape($item_type) . "'") : '') .
+ (($notification_type_name !== false) ? ' AND ' .
+ (is_array($notification_type_name) ? $this->db->sql_in_set('notification_type_id', $this->get_notification_type_ids($notification_type_name)) : 'notification_type_id = ' . $this->get_notification_type_id($notification_type_name))
+ : '') .
(($user_id !== false) ? ' AND ' . (is_array($user_id) ? $this->db->sql_in_set('user_id', $user_id) : 'user_id = ' . (int) $user_id) : '') .
(($item_id !== false) ? ' AND ' . (is_array($item_id) ? $this->db->sql_in_set('item_id', $item_id) : 'item_id = ' . (int) $item_id) : '');
$this->db->sql_query($sql);
@@ -264,29 +270,21 @@ class phpbb_notification_manager
/**
* Mark notifications read from a parent identifier
*
- * @param string|array $item_type Type identifier or array of item types (only acceptable if the $data is identical for the specified types)
+ * @param string|array $notification_type_name Type identifier or array of item types (only acceptable if the $data is identical for the specified types)
* @param bool|int|array $item_parent_id Item parent id or array of item parent ids. False to mark read for all item parent ids
* @param bool|int|array $user_id User id or array of user ids. False to mark read for all user ids
* @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False)
*/
- public function mark_notifications_read_by_parent($item_type, $item_parent_id, $user_id, $time = false)
+ public function mark_notifications_read_by_parent($notification_type_name, $item_parent_id, $user_id, $time = false)
{
- if (is_array($item_type))
- {
- foreach ($item_type as $type)
- {
- $this->mark_notifications_read_by_parent($type, $item_parent_id, $user_id, $time);
- }
-
- return;
- }
-
$time = ($time !== false) ? $time : time();
$sql = 'UPDATE ' . $this->notifications_table . "
SET notification_read = 1
- WHERE item_type = '" . $this->db->sql_escape($item_type) . "'
- AND notification_time <= " . (int) $time .
+ WHERE notification_time <= " . (int) $time .
+ (($notification_type_name !== false) ? ' AND ' .
+ (is_array($notification_type_name) ? $this->db->sql_in_set('notification_type_id', $this->get_notification_type_ids($notification_type_name)) : 'notification_type_id = ' . $this->get_notification_type_id($notification_type_name))
+ : '') .
(($item_parent_id !== false) ? ' AND ' . (is_array($item_parent_id) ? $this->db->sql_in_set('item_parent_id', $item_parent_id) : 'item_parent_id = ' . (int) $item_parent_id) : '') .
(($user_id !== false) ? ' AND ' . (is_array($user_id) ? $this->db->sql_in_set('user_id', $user_id) : 'user_id = ' . (int) $user_id) : '');
$this->db->sql_query($sql);
@@ -312,7 +310,7 @@ class phpbb_notification_manager
/**
* Add a notification
*
- * @param string|array $item_type Type identifier or array of item types (only acceptable if the $data is identical for the specified types)
+ * @param string|array $notification_type_name Type identifier or array of item types (only acceptable if the $data is identical for the specified types)
* Note: If you send an array of types, any user who could receive multiple notifications from this single item will only receive
* a single notification. If they MUST receive multiple notifications, call this function multiple times instead of sending an array
* @param array $data Data specific for this type that will be inserted
@@ -320,18 +318,18 @@ class phpbb_notification_manager
* ignore_users array of data to specify which users should not receive certain types of notifications
* @return array Information about what users were notified and how they were notified
*/
- public function add_notifications($item_type, $data, array $options = array())
+ public function add_notifications($notification_type_name, $data, array $options = array())
{
$options = array_merge(array(
'ignore_users' => array(),
), $options);
- if (is_array($item_type))
+ if (is_array($notification_type_name))
{
$notified_users = array();
$temp_options = $options;
- foreach ($item_type as $type)
+ foreach ($notification_type_name as $type)
{
$temp_options['ignore_users'] = $options['ignore_users'] + $notified_users;
$notified_users += $this->add_notifications($type, $data, $temp_options);
@@ -340,12 +338,12 @@ class phpbb_notification_manager
return $notified_users;
}
- $item_id = $this->get_item_type_class($item_type)->get_item_id($data);
+ $item_id = $this->get_item_type_class($notification_type_name)->get_item_id($data);
// find out which users want to receive this type of notification
- $notify_users = $this->get_item_type_class($item_type)->find_users_for_notification($data, $options);
+ $notify_users = $this->get_item_type_class($notification_type_name)->find_users_for_notification($data, $options);
- $this->add_notifications_for_users($item_type, $data, $notify_users);
+ $this->add_notifications_for_users($notification_type_name, $data, $notify_users);
return $notify_users;
}
@@ -353,15 +351,15 @@ class phpbb_notification_manager
/**
* Add a notification for specific users
*
- * @param string|array $item_type Type identifier or array of item types (only acceptable if the $data is identical for the specified types)
+ * @param string|array $notification_type_name Type identifier or array of item types (only acceptable if the $data is identical for the specified types)
* @param array $data Data specific for this type that will be inserted
* @param array $notify_users User list to notify
*/
- public function add_notifications_for_users($item_type, $data, $notify_users)
+ public function add_notifications_for_users($notification_type_name, $data, $notify_users)
{
- if (is_array($item_type))
+ if (is_array($notification_type_name))
{
- foreach ($item_type as $type)
+ foreach ($notification_type_name as $type)
{
$this->add_notifications_for_users($type, $data, $notify_users);
}
@@ -369,24 +367,9 @@ class phpbb_notification_manager
return;
}
- $sql = 'SELECT notification_type
- FROM ' . $this->notification_types_table . "
- WHERE notification_type = '" . $this->db->sql_escape($item_type) . "'";
- $result = $this->db->sql_query($sql);
+ $notification_type_id = $this->get_notification_type_id($notification_type_name);
- if ($this->db->sql_fetchrow($result) === false)
- {
- // Does not exist in the database, must add the item type
- $sql = 'INSERT INTO ' . $this->notification_types_table . ' ' . $this->db->sql_build_array('INSERT', array(
- 'notification_type' => $item_type,
- 'notification_type_enabled' => 1,
- ));
- $this->db->sql_query($sql);
- }
-
- $this->db->sql_freeresult($result);
-
- $item_id = $this->get_item_type_class($item_type)->get_item_id($data);
+ $item_id = $this->get_item_type_class($notification_type_name)->get_item_id($data);
$user_ids = array();
$notification_objects = $notification_methods = array();
@@ -397,10 +380,10 @@ class phpbb_notification_manager
// Make sure not to send new notifications to users who've already been notified about this item
// This may happen when an item was added, but now new users are able to see the item
$sql = 'SELECT n.user_id
- FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . " nt
- WHERE n.item_type = '" . $this->db->sql_escape($item_type) . "'
- AND n.item_id = " . (int) $item_id . '
- AND nt.notification_type = n.item_type
+ FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
+ WHERE n.notification_type_id = ' . (int) $notification_type_id . '
+ AND n.item_id = ' . (int) $item_id . '
+ AND nt.notification_type_id = n.notification_type_id
AND nt.notification_type_enabled = 1';
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
@@ -415,7 +398,7 @@ class phpbb_notification_manager
}
// Allow notifications to perform actions before creating the insert array (such as run a query to cache some data needed for all notifications)
- $notification = $this->get_item_type_class($item_type);
+ $notification = $this->get_item_type_class($notification_type_name);
$pre_create_data = $notification->pre_create_insert_array($data, $notify_users);
unset($notification);
@@ -424,7 +407,7 @@ class phpbb_notification_manager
// Go through each user so we can insert a row in the DB and then notify them by their desired means
foreach ($notify_users as $user => $methods)
{
- $notification = $this->get_item_type_class($item_type);
+ $notification = $this->get_item_type_class($notification_type_name);
$notification->user_id = (int) $user;
@@ -464,14 +447,14 @@ class phpbb_notification_manager
/**
* Update a notification
*
- * @param string|array $item_type Type identifier or array of item types (only acceptable if the $data is identical for the specified types)
+ * @param string|array $notification_type_name Type identifier or array of item types (only acceptable if the $data is identical for the specified types)
* @param array $data Data specific for this type that will be updated
*/
- public function update_notifications($item_type, $data)
+ public function update_notifications($notification_type_name, $data)
{
- if (is_array($item_type))
+ if (is_array($notification_type_name))
{
- foreach ($item_type as $type)
+ foreach ($notification_type_name as $type)
{
$this->update_notifications($type, $data);
}
@@ -479,7 +462,7 @@ class phpbb_notification_manager
return;
}
- $notification = $this->get_item_type_class($item_type);
+ $notification = $this->get_item_type_class($notification_type_name);
// Allow the notifications class to over-ride the update_notifications functionality
if (method_exists($notification, 'update_notifications'))
@@ -491,28 +474,29 @@ class phpbb_notification_manager
}
}
+ $notification_type_id = $this->get_notification_type_id($notification_type_name);
$item_id = $notification->get_item_id($data);
$update_array = $notification->create_update_array($data);
$sql = 'UPDATE ' . $this->notifications_table . '
- SET ' . $this->db->sql_build_array('UPDATE', $update_array) . "
- WHERE item_type = '" . $this->db->sql_escape($item_type) . "'
- AND item_id = " . (int) $item_id;
+ SET ' . $this->db->sql_build_array('UPDATE', $update_array) . '
+ WHERE notification_type_id = ' . (int) $notification_type_id . '
+ AND item_id = ' . (int) $item_id;
$this->db->sql_query($sql);
}
/**
* Delete a notification
*
- * @param string|array $item_type Type identifier or array of item types (only acceptable if the $item_id is identical for the specified types)
+ * @param string|array $notification_type_name Type identifier or array of item types (only acceptable if the $item_id is identical for the specified types)
* @param int|array $item_id Identifier within the type (or array of ids)
* @param array $data Data specific for this type that will be updated
*/
- public function delete_notifications($item_type, $item_id)
+ public function delete_notifications($notification_type_name, $item_id)
{
- if (is_array($item_type))
+ if (is_array($notification_type_name))
{
- foreach ($item_type as $type)
+ foreach ($notification_type_name as $type)
{
$this->delete_notifications($type, $item_id);
}
@@ -520,9 +504,11 @@ class phpbb_notification_manager
return;
}
- $sql = 'DELETE FROM ' . $this->notifications_table . "
- WHERE item_type = '" . $this->db->sql_escape($item_type) . "'
- AND " . (is_array($item_id) ? $this->db->sql_in_set('item_id', $item_id) : 'item_id = ' . (int) $item_id);
+ $notification_type_id = $this->get_notification_type_id($notification_type_name);
+
+ $sql = 'DELETE FROM ' . $this->notifications_table . '
+ WHERE notification_type_id = ' . (int) $notification_type_id . '
+ AND ' . (is_array($item_id) ? $this->db->sql_in_set('item_id', $item_id) : 'item_id = ' . (int) $item_id);
$this->db->sql_query($sql);
}
@@ -655,7 +641,8 @@ class phpbb_notification_manager
{
if ($method !== '')
{
- $this->add_subscription($item_type, $item_type, '', $user_id);
+ // Make sure to subscribe them to the base subscription
+ $this->add_subscription($item_type, $item_id, '', $user_id);
}
$user_id = ($user_id === false) ? $this->user->data['user_id'] : $user_id;
@@ -755,13 +742,13 @@ class phpbb_notification_manager
* is disabled so that all those notifications are hidden and do not
* cause errors
*
- * @param string $item_type Type identifier of the subscription
+ * @param string $notification_type_name Type identifier of the subscription
*/
- public function disable_notifications($item_type)
+ public function disable_notifications($notification_type_name)
{
$sql = 'UPDATE ' . $this->notification_types_table . "
SET notification_type_enabled = 0
- WHERE notification_type = '" . $this->db->sql_escape($item_type) . "'";
+ WHERE notification_type_name = '" . $this->db->sql_escape($notification_type_name) . "'";
$this->db->sql_query($sql);
}
@@ -771,17 +758,21 @@ class phpbb_notification_manager
* This should be called when an extension which has notification types
* is purged so that all those notifications are removed
*
- * @param string $item_type Type identifier of the subscription
+ * @param string $notification_type_name Type identifier of the subscription
*/
- public function purge_notifications($item_type)
+ public function purge_notifications($notification_type_name)
{
- $sql = 'DELETE FROM ' . $this->notifications_table . "
- WHERE item_type = '" . $this->db->sql_escape($item_type) . "'";
+ $notification_type_id = $this->get_notification_type_id($notification_type_name);
+
+ $sql = 'DELETE FROM ' . $this->notifications_table . '
+ WHERE notification_type_id = ' . (int) $notification_type_id;
$this->db->sql_query($sql);
- $sql = 'DELETE FROM ' . $this->notification_types_table . "
- WHERE notification_type = '" . $this->db->sql_escape($item_type) . "'";
+ $sql = 'DELETE FROM ' . $this->notification_types_table . '
+ WHERE notification_type_id = ' . (int) $notification_type_id;
$this->db->sql_query($sql);
+
+ $this->cache->destroy('notification_type_ids');
}
/**
@@ -791,13 +782,13 @@ class phpbb_notification_manager
* that was disabled is re-enabled so that all those notifications that
* were hidden are shown again
*
- * @param string $item_type Type identifier of the subscription
+ * @param string $notification_type_name Type identifier of the subscription
*/
- public function enable_notifications($item_type)
+ public function enable_notifications($notification_type_name)
{
$sql = 'UPDATE ' . $this->notification_types_table . "
SET notification_type_enabled = 1
- WHERE notification_type = '" . $this->db->sql_escape($item_type) . "'";
+ WHERE notification_type_name = '" . $this->db->sql_escape($notification_type_name) . "'";
$this->db->sql_query($sql);
}
@@ -816,11 +807,11 @@ class phpbb_notification_manager
/**
* Helper to get the notifications item type class and set it up
*/
- public function get_item_type_class($item_type, $data = array())
+ public function get_item_type_class($notification_type_name, $data = array())
{
- $item_type = (strpos($item_type, 'notification.type.') === 0) ? $item_type : 'notification.type.' . $item_type;
+ $notification_type_name = (strpos($notification_type_name, 'notification.type.') === 0) ? $notification_type_name : 'notification.type.' . $notification_type_name;
- $item = $this->load_object($item_type);
+ $item = $this->load_object($notification_type_name);
$item->set_initial_data($data);
@@ -851,4 +842,69 @@ class phpbb_notification_manager
return $object;
}
+
+ /**
+ * Get the notification type id from the name
+ *
+ * @param string $notification_type_name The name
+ * @return int the notification_type_id
+ */
+ public function get_notification_type_id($notification_type_name)
+ {
+ $notification_type_ids = $this->cache->get('notification_type_ids');
+
+ if ($notification_type_ids === false)
+ {
+ $notification_type_ids = array();
+
+ $sql = 'SELECT notification_type_id, notification_type_name
+ FROM ' . $this->notification_types_table;
+ $result = $this->db->sql_query($sql);
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $notification_type_ids[$row['notification_type_name']] = (int) $row['notification_type_id'];
+ }
+ $this->db->sql_freeresult($result);
+
+ $this->cache->put('notification_type_ids', $notification_type_ids);
+ }
+
+ if (!isset($notification_type_ids[$notification_type_name]))
+ {
+ if (!isset($this->notification_types[$notification_type_name]) && !isset($this->notification_types['notification.type.' . $notification_type_name]))
+ {
+ throw new phpbb_notification_exception($this->user->lang('NOTIFICATION_TYPE_NOT_EXIST', $notification_type_name));
+ }
+
+ $sql = 'INSERT INTO ' . $this->notification_types_table . ' ' . $this->db->sql_build_array('INSERT', array(
+ 'notification_type_name' => $notification_type_name,
+ 'notification_type_enabled' => 1,
+ ));
+ $this->db->sql_query($sql);
+
+ $notification_type_ids[$notification_type_name] = (int) $this->db->sql_nextid();
+
+ $this->cache->put('notification_type_ids', $notification_type_ids);
+ }
+
+ return $notification_type_ids[$notification_type_name];
+ }
+
+ /**
+ * Get notification type ids (as an array)
+ *
+ * @param array $notification_type_names Array of strings
+ * @return array Array of integers
+ */
+ public function get_notification_type_ids(array $notification_type_names)
+ {
+ $notification_type_ids = array();
+
+ foreach ($notification_type_names as $name)
+ {
+ $notification_type_ids[$name] = $this->get_notification_type_id($name);
+ }
+
+ return $notification_type_ids;
+ }
}
diff --git a/phpBB/includes/notification/method/base.php b/phpBB/includes/notification/method/base.php
index 22418c9be8..b633956d01 100644
--- a/phpBB/includes/notification/method/base.php
+++ b/phpBB/includes/notification/method/base.php
@@ -30,7 +30,7 @@ abstract class phpbb_notification_method_base implements phpbb_notification_meth
/** @var phpbb_db_driver */
protected $db;
- /** @var phpbb_cache_service */
+ /** @var phpbb_cache_driver_interface */
protected $cache;
/** @var phpbb_template */
diff --git a/phpBB/includes/notification/method/email.php b/phpBB/includes/notification/method/email.php
index 44666b1422..571b0ec656 100644
--- a/phpBB/includes/notification/method/email.php
+++ b/phpBB/includes/notification/method/email.php
@@ -39,7 +39,7 @@ class phpbb_notification_method_email extends phpbb_notification_method_messenge
*/
public function is_available()
{
- return (bool) $this->config['email_enable'];
+ return $this->config['email_enable'] && $this->user->data['user_email'];
}
/**
diff --git a/phpBB/includes/notification/type/base.php b/phpBB/includes/notification/type/base.php
index 600ef7c965..46517f1c9b 100644
--- a/phpBB/includes/notification/type/base.php
+++ b/phpBB/includes/notification/type/base.php
@@ -30,7 +30,7 @@ abstract class phpbb_notification_type_base implements phpbb_notification_type_i
/** @var phpbb_db_driver */
protected $db;
- /** @var phpbb_cache_service */
+ /** @var phpbb_cache_driver_interface */
protected $cache;
/** @var phpbb_template */
@@ -69,10 +69,18 @@ abstract class phpbb_notification_type_base implements phpbb_notification_type_i
public static $notification_option = false;
/**
+ * The notification_type_id, set upon creation of the class
+ * This is the notification_type_id from the notification_types table
+ *
+ * @var int
+ */
+ protected $notification_type_id;
+
+ /**
* Indentification data
- * item_type - Type of the item (translates to the notification type)
- * item_id - ID of the item (e.g. post_id, msg_id)
- * item_parent_id - Parent item id (ex: for topic => forum_id, for post => topic_id, etc)
+ * notification_type_id - ID of the item type (auto generated, from notification types table)
+ * item_id - ID of the item (e.g. post_id, msg_id)
+ * item_parent_id - Parent item id (ex: for topic => forum_id, for post => topic_id, etc)
* user_id
* notification_read
* notification_time
@@ -124,6 +132,8 @@ abstract class phpbb_notification_type_base implements phpbb_notification_type_i
public function set_notification_manager(phpbb_notification_manager $notification_manager)
{
$this->notification_manager = $notification_manager;
+
+ $this->notification_type_id = $this->notification_manager->get_notification_type_id($this->get_type());
}
/**
@@ -211,7 +221,7 @@ abstract class phpbb_notification_type_base implements phpbb_notification_type_i
// Defaults
$this->data = array_merge(array(
'item_id' => static::get_item_id($type_data),
- 'item_type' => $this->get_type(),
+ 'notification_type_id' => $this->notification_type_id,
'item_parent_id' => static::get_item_parent_id($type_data),
'notification_time' => time(),
@@ -460,7 +470,7 @@ abstract class phpbb_notification_type_base implements phpbb_notification_type_i
$this->notification_read = (bool) !$unread;
$where = array(
- "item_type = '" . $this->db->sql_escape($this->item_type) . "'",
+ 'notification_type_id = ' . (int) $this->notification_type_id,
'item_id = ' . (int) $this->item_id,
'user_id = ' . (int) $this->user_id,
);
diff --git a/phpBB/includes/notification/type/bookmark.php b/phpBB/includes/notification/type/bookmark.php
index 946cb9b4ed..ae2e75d3eb 100644
--- a/phpBB/includes/notification/type/bookmark.php
+++ b/phpBB/includes/notification/type/bookmark.php
@@ -103,11 +103,11 @@ class phpbb_notification_type_bookmark extends phpbb_notification_type_post
// Try to find the users who already have been notified about replies and have not read the topic since and just update their notifications
$update_notifications = array();
$sql = 'SELECT n.*
- FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . " nt
- WHERE n.item_type = '" . $this->get_type() . "'
- AND n.item_parent_id = " . (int) self::get_item_parent_id($post) . '
+ FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
+ WHERE n.notification_type_id = ' . (int) $this->notification_type_id . '
+ AND n.item_parent_id = ' . (int) self::get_item_parent_id($post) . '
AND n.notification_read = 0
- AND nt.notification_type = n.item_type
+ AND nt.notification_type_id = n.notification_type_id
AND nt.notification_type_enabled = 1';
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
diff --git a/phpBB/includes/notification/type/post.php b/phpBB/includes/notification/type/post.php
index 626c13b7fd..9207fd866e 100644
--- a/phpBB/includes/notification/type/post.php
+++ b/phpBB/includes/notification/type/post.php
@@ -138,11 +138,11 @@ class phpbb_notification_type_post extends phpbb_notification_type_base
// Try to find the users who already have been notified about replies and have not read the topic since and just update their notifications
$update_notifications = array();
$sql = 'SELECT n.*
- FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . " nt
- WHERE n.item_type = '" . $this->get_type() . "'
- AND n.item_parent_id = " . (int) self::get_item_parent_id($post) . '
+ FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
+ WHERE n.notification_type_id = ' . (int) $this->notification_type_id . '
+ AND n.item_parent_id = ' . (int) self::get_item_parent_id($post) . '
AND n.notification_read = 0
- AND nt.notification_type = n.item_type
+ AND nt.notification_type_id = n.notification_type_id
AND nt.notification_type_enabled = 1';
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
diff --git a/phpBB/includes/notification/type/quote.php b/phpBB/includes/notification/type/quote.php
index e9eb7bea21..0ed13f36fb 100644
--- a/phpBB/includes/notification/type/quote.php
+++ b/phpBB/includes/notification/type/quote.php
@@ -122,11 +122,11 @@ class phpbb_notification_type_quote extends phpbb_notification_type_post
// Try to find the users who already have been notified about replies and have not read the topic since and just update their notifications
$update_notifications = array();
$sql = 'SELECT n.*
- FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . " nt
- WHERE n.item_type = '" . $this->get_type() . "'
- AND n.item_parent_id = " . (int) self::get_item_parent_id($post) . '
+ FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
+ WHERE n.notification_type_id = ' . (int) $this->notification_type_id . '
+ AND n.item_parent_id = ' . (int) self::get_item_parent_id($post) . '
AND n.notification_read = 0
- AND nt.notification_type = n.item_type
+ AND nt.notification_type_id = n.notification_type_id
AND nt.notification_type_enabled = 1';
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
@@ -154,10 +154,10 @@ class phpbb_notification_type_quote extends phpbb_notification_type_post
{
$old_notifications = array();
$sql = 'SELECT n.user_id
- FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . " nt
- WHERE n.item_type = '" . $this->get_type() . "'
- AND n.item_id = " . self::get_item_id($post) . '
- AND nt.notification_type = n.item_type
+ FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
+ WHERE n.notification_type_id = ' . (int) $this->notification_type_id . '
+ AND n.item_id = ' . self::get_item_id($post) . '
+ AND nt.notification_type_id = n.notification_type_id
AND nt.notification_type_enabled = 1';
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
@@ -185,9 +185,9 @@ class phpbb_notification_type_quote extends phpbb_notification_type_post
// Remove the necessary notifications
if (!empty($remove_notifications))
{
- $sql = 'DELETE FROM ' . $this->notifications_table . "
- WHERE item_type = '" . $this->get_type() . "'
- AND item_id = " . self::get_item_id($post) . '
+ $sql = 'DELETE FROM ' . $this->notifications_table . '
+ WHERE notification_type_id = ' . (int) $this->notification_type_id . '
+ AND item_id = ' . self::get_item_id($post) . '
AND ' . $this->db->sql_in_set('user_id', $remove_notifications);
$this->db->sql_query($sql);
}
diff --git a/phpBB/includes/search/fulltext_mysql.php b/phpBB/includes/search/fulltext_mysql.php
index adaf025730..aa493c3281 100644
--- a/phpBB/includes/search/fulltext_mysql.php
+++ b/phpBB/includes/search/fulltext_mysql.php
@@ -163,9 +163,16 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
$engine = $info['Type'];
}
- if ($engine != 'MyISAM')
+ $fulltext_supported =
+ $engine === 'MyISAM' ||
+ // FULLTEXT is supported on InnoDB since MySQL 5.6.4 according to
+ // http://dev.mysql.com/doc/refman/5.6/en/innodb-storage-engine.html
+ $engine === 'InnoDB' &&
+ phpbb_version_compare($this->db->sql_server_info(true), '5.6.4', '>=');
+
+ if (!$fulltext_supported)
{
- return $this->user->lang['FULLTEXT_MYSQL_NOT_MYISAM'];
+ return $this->user->lang['FULLTEXT_MYSQL_NOT_SUPPORTED'];
}
$sql = 'SHOW VARIABLES
diff --git a/phpBB/includes/search/fulltext_native.php b/phpBB/includes/search/fulltext_native.php
index c9f33054fc..b9c784ea67 100644
--- a/phpBB/includes/search/fulltext_native.php
+++ b/phpBB/includes/search/fulltext_native.php
@@ -1819,11 +1819,11 @@ class phpbb_search_fulltext_native extends phpbb_search_base
</dl>
<dl>
<dt><label for="fulltext_native_min_chars">' . $this->user->lang['MIN_SEARCH_CHARS'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['MIN_SEARCH_CHARS_EXPLAIN'] . '</span></dt>
- <dd><input id="fulltext_native_min_chars" type="text" size="3" maxlength="3" name="config[fulltext_native_min_chars]" value="' . (int) $this->config['fulltext_native_min_chars'] . '" /></dd>
+ <dd><input id="fulltext_native_min_chars" type="number" size="3" maxlength="3" min="0" max="255" name="config[fulltext_native_min_chars]" value="' . (int) $this->config['fulltext_native_min_chars'] . '" /></dd>
</dl>
<dl>
<dt><label for="fulltext_native_max_chars">' . $this->user->lang['MAX_SEARCH_CHARS'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['MAX_SEARCH_CHARS_EXPLAIN'] . '</span></dt>
- <dd><input id="fulltext_native_max_chars" type="text" size="3" maxlength="3" name="config[fulltext_native_max_chars]" value="' . (int) $this->config['fulltext_native_max_chars'] . '" /></dd>
+ <dd><input id="fulltext_native_max_chars" type="number" size="3" maxlength="3" min="0" max="255" name="config[fulltext_native_max_chars]" value="' . (int) $this->config['fulltext_native_max_chars'] . '" /></dd>
</dl>
<dl>
<dt><label for="fulltext_native_common_thres">' . $this->user->lang['COMMON_WORD_THRESHOLD'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['COMMON_WORD_THRESHOLD_EXPLAIN'] . '</span></dt>
diff --git a/phpBB/includes/search/fulltext_postgres.php b/phpBB/includes/search/fulltext_postgres.php
index 5080587681..496a29f5a3 100644
--- a/phpBB/includes/search/fulltext_postgres.php
+++ b/phpBB/includes/search/fulltext_postgres.php
@@ -970,11 +970,11 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base
</dl>
<dl>
<dt><label for="fulltext_postgres_min_word_len">' . $this->user->lang['FULLTEXT_POSTGRES_MIN_WORD_LEN'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['FULLTEXT_POSTGRES_MIN_WORD_LEN_EXPLAIN'] . '</span></dt>
- <dd><input id="fulltext_postgres_min_word_len" type="text" size="3" maxlength="3" name="config[fulltext_postgres_min_word_len]" value="' . (int) $this->config['fulltext_postgres_min_word_len'] . '" /></dd>
+ <dd><input id="fulltext_postgres_min_word_len" type="number" size="3" maxlength="3" min="0" max="255" name="config[fulltext_postgres_min_word_len]" value="' . (int) $this->config['fulltext_postgres_min_word_len'] . '" /></dd>
</dl>
<dl>
<dt><label for="fulltext_postgres_max_word_len">' . $this->user->lang['FULLTEXT_POSTGRES_MAX_WORD_LEN'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['FULLTEXT_POSTGRES_MAX_WORD_LEN_EXPLAIN'] . '</span></dt>
- <dd><input id="fulltext_postgres_max_word_len" type="text" size="3" maxlength="3" name="config[fulltext_postgres_max_word_len]" value="' . (int) $this->config['fulltext_postgres_max_word_len'] . '" /></dd>
+ <dd><input id="fulltext_postgres_max_word_len" type="number" size="3" maxlength="3" min="0" max="255" name="config[fulltext_postgres_max_word_len]" value="' . (int) $this->config['fulltext_postgres_max_word_len'] . '" /></dd>
</dl>
';
diff --git a/phpBB/includes/search/fulltext_sphinx.php b/phpBB/includes/search/fulltext_sphinx.php
index 28761792ec..889324bbda 100644
--- a/phpBB/includes/search/fulltext_sphinx.php
+++ b/phpBB/includes/search/fulltext_sphinx.php
@@ -611,7 +611,7 @@ class phpbb_search_fulltext_sphinx
$result_count = $result['total_found'];
- if ($start >= $result_count)
+ if ($result_count && $start >= $result_count)
{
$start = floor(($result_count - 1) / $per_page) * $per_page;
@@ -888,11 +888,11 @@ class phpbb_search_fulltext_sphinx
</dl>
<dl>
<dt><label for="fulltext_sphinx_port">' . $this->user->lang['FULLTEXT_SPHINX_PORT'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['FULLTEXT_SPHINX_PORT_EXPLAIN'] . '</span></dt>
- <dd><input id="fulltext_sphinx_port" type="text" size="4" maxlength="10" name="config[fulltext_sphinx_port]" value="' . $this->config['fulltext_sphinx_port'] . '" /></dd>
+ <dd><input id="fulltext_sphinx_port" type="number" size="4" maxlength="10" name="config[fulltext_sphinx_port]" value="' . $this->config['fulltext_sphinx_port'] . '" /></dd>
</dl>
<dl>
<dt><label for="fulltext_sphinx_indexer_mem_limit">' . $this->user->lang['FULLTEXT_SPHINX_INDEXER_MEM_LIMIT'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['FULLTEXT_SPHINX_INDEXER_MEM_LIMIT_EXPLAIN'] . '</span></dt>
- <dd><input id="fulltext_sphinx_indexer_mem_limit" type="text" size="4" maxlength="10" name="config[fulltext_sphinx_indexer_mem_limit]" value="' . $this->config['fulltext_sphinx_indexer_mem_limit'] . '" /> ' . $this->user->lang['MIB'] . '</dd>
+ <dd><input id="fulltext_sphinx_indexer_mem_limit" type="number" size="4" maxlength="10" name="config[fulltext_sphinx_indexer_mem_limit]" value="' . $this->config['fulltext_sphinx_indexer_mem_limit'] . '" /> ' . $this->user->lang['MIB'] . '</dd>
</dl>
<dl>
<dt><label for="fulltext_sphinx_config_file">' . $this->user->lang['FULLTEXT_SPHINX_CONFIG_FILE'] . $this->user->lang['COLON'] . '</label><br /><span>' . $this->user->lang['FULLTEXT_SPHINX_CONFIG_FILE_EXPLAIN'] . '</span></dt>
diff --git a/phpBB/includes/session.php b/phpBB/includes/session.php
index 6bc71da0c1..66bf053f7d 100644
--- a/phpBB/includes/session.php
+++ b/phpBB/includes/session.php
@@ -207,7 +207,7 @@ class phpbb_session
function session_begin($update_session_page = true)
{
global $phpEx, $SID, $_SID, $_EXTRA_URL, $db, $config, $phpbb_root_path;
- global $request;
+ global $request, $phpbb_container;
// Give us some basic information
$this->time_now = time();
@@ -402,15 +402,12 @@ class phpbb_session
// Check whether the session is still valid if we have one
$method = basename(trim($config['auth_method']));
- include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx);
- $method = 'validate_session_' . $method;
- if (function_exists($method))
+ $provider = $phpbb_container->get('auth.provider.' . $method);
+ $ret = $provider->validate_session($this->data);
+ if ($ret !== null && !$ret)
{
- if (!$method($this->data))
- {
- $session_expired = true;
- }
+ $session_expired = true;
}
if (!$session_expired)
@@ -504,7 +501,7 @@ class phpbb_session
*/
function session_create($user_id = false, $set_admin = false, $persist_login = false, $viewonline = true)
{
- global $SID, $_SID, $db, $config, $cache, $phpbb_root_path, $phpEx;
+ global $SID, $_SID, $db, $config, $cache, $phpbb_root_path, $phpEx, $phpbb_container;
$this->data = array();
@@ -568,18 +565,14 @@ class phpbb_session
}
$method = basename(trim($config['auth_method']));
- include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx);
- $method = 'autologin_' . $method;
- if (function_exists($method))
- {
- $this->data = $method();
+ $provider = $phpbb_container->get('auth.provider.' . $method);
+ $this->data = $provider->autologin();
- if (sizeof($this->data))
- {
- $this->cookie_data['k'] = '';
- $this->cookie_data['u'] = $this->data['user_id'];
- }
+ if (sizeof($this->data))
+ {
+ $this->cookie_data['k'] = '';
+ $this->cookie_data['u'] = $this->data['user_id'];
}
// If we're presented with an autologin key we'll join against it.
@@ -884,7 +877,7 @@ class phpbb_session
*/
function session_kill($new_session = true)
{
- global $SID, $_SID, $db, $config, $phpbb_root_path, $phpEx;
+ global $SID, $_SID, $db, $config, $phpbb_root_path, $phpEx, $phpbb_container;
$sql = 'DELETE FROM ' . SESSIONS_TABLE . "
WHERE session_id = '" . $db->sql_escape($this->session_id) . "'
@@ -893,13 +886,9 @@ class phpbb_session
// Allow connecting logout with external auth method logout
$method = basename(trim($config['auth_method']));
- include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx);
- $method = 'logout_' . $method;
- if (function_exists($method))
- {
- $method($this->data, $new_session);
- }
+ $provider = $phpbb_container->get('auth.provider.' . $method);
+ $provider->logout($this->data, $new_session);
if ($this->data['user_id'] != ANONYMOUS)
{
diff --git a/phpBB/includes/template/compile.php b/phpBB/includes/template/compile.php
index fcdaf7abda..76cb3011df 100644
--- a/phpBB/includes/template/compile.php
+++ b/phpBB/includes/template/compile.php
@@ -33,6 +33,13 @@ class phpbb_template_compile
private $filter_params;
/**
+ * Array of default parameters
+ *
+ * @var array
+ */
+ private $default_filter_params;
+
+ /**
* Constructor.
*
* @param bool $allow_php Whether PHP code will be allowed in templates (inline PHP code, PHP tag and INCLUDEPHP tag)
@@ -44,18 +51,40 @@ class phpbb_template_compile
*/
public function __construct($allow_php, $style_names, $locator, $phpbb_root_path, $extension_manager = null, $user = null)
{
- $this->filter_params = array(
- 'allow_php' => $allow_php,
- 'style_names' => $style_names,
- 'locator' => $locator,
+ $this->filter_params = $this->default_filter_params = array(
+ 'allow_php' => $allow_php,
+ 'style_names' => $style_names,
+ 'locator' => $locator,
'phpbb_root_path' => $phpbb_root_path,
'extension_manager' => $extension_manager,
- 'user' => $user,
+ 'user' => $user,
'template_compile' => $this,
+ 'cleanup' => true,
);
}
/**
+ * Set filter parameters
+ *
+ * @param array $params Array of parameters (will be merged onto $this->filter_params)
+ */
+ public function set_filter_params($params)
+ {
+ $this->filter_params = array_merge(
+ $this->filter_params,
+ $params
+ );
+ }
+
+ /**
+ * Reset filter parameters to their default settings
+ */
+ public function reset_filter_params()
+ {
+ $this->filter_params = $this->default_filter_params;
+ }
+
+ /**
* Compiles template in $source_file and writes compiled template to
* cache directory
*
diff --git a/phpBB/includes/template/filter.php b/phpBB/includes/template/filter.php
index c2c100e93e..1c0a56c9f5 100644
--- a/phpBB/includes/template/filter.php
+++ b/phpBB/includes/template/filter.php
@@ -76,6 +76,14 @@ class phpbb_template_filter extends php_user_filter
private $allow_php;
/**
+ * Whether cleanup will be performed on resulting code, see compile()
+ * (Preserve whitespace)
+ *
+ * @var bool
+ */
+ private $cleanup = true;
+
+ /**
* Resource locator.
*
* @var phpbb_template_locator
@@ -183,6 +191,7 @@ class phpbb_template_filter extends php_user_filter
$this->phpbb_root_path = $this->params['phpbb_root_path'];
$this->style_names = $this->params['style_names'];
$this->extension_manager = $this->params['extension_manager'];
+ $this->cleanup = $this->params['cleanup'];
if (isset($this->params['user']))
{
$this->user = $this->params['user'];
@@ -223,41 +232,45 @@ class phpbb_template_filter extends php_user_filter
$data = preg_replace('~<!-- ENDPHP -->.*?$~', '', $data);
}
- /*
+ if ($this->cleanup)
+ {
+ /*
- Preserve whitespace.
- PHP removes a newline after the closing tag (if it's there).
- This is by design:
+ Preserve whitespace.
+ PHP removes a newline after the closing tag (if it's there).
+ This is by design:
- http://www.php.net/manual/en/language.basic-syntax.phpmode.php
- http://www.php.net/manual/en/language.basic-syntax.instruction-separation.php
+ http://www.php.net/manual/en/language.basic-syntax.phpmode.php
+ http://www.php.net/manual/en/language.basic-syntax.instruction-separation.php
- Consider the following template:
+ Consider the following template:
- <!-- IF condition -->
- some content
- <!-- ENDIF -->
+ <!-- IF condition -->
+ some content
+ <!-- ENDIF -->
- If we were to simply preserve all whitespace, we could simply
- replace all "?>" tags with "?>\n".
- Doing that, would add additional newlines to the compiled
- template in place of the IF and ENDIF statements. These
- newlines are unwanted (and one is conditional). The IF and
- ENDIF are usually on their own line for ease of reading.
+ If we were to simply preserve all whitespace, we could simply
+ replace all "?>" tags with "?>\n".
+ Doing that, would add additional newlines to the compiled
+ template in place of the IF and ENDIF statements. These
+ newlines are unwanted (and one is conditional). The IF and
+ ENDIF are usually on their own line for ease of reading.
- This replacement preserves newlines only for statements that
- are not the only statement on a line. It will NOT preserve
- newlines at the end of statements in the above example.
- It will preserve newlines in situations like:
+ This replacement preserves newlines only for statements that
+ are not the only statement on a line. It will NOT preserve
+ newlines at the end of statements in the above example.
+ It will preserve newlines in situations like:
- <!-- IF condition -->inline content<!-- ENDIF -->
+ <!-- IF condition -->inline content<!-- ENDIF -->
- */
+ */
+
+ $data = preg_replace('~(?<!^)(<\?php.+(?<!/\*\*/)\?>)$~m', "$1\n", $data);
+ $data = str_replace('/**/?>', "?>\n", $data);
+ $data = str_replace('?><?php', '', $data);
+ }
- $data = preg_replace('~(?<!^)(<\?php.+(?<!/\*\*/)\?>)$~m', "$1\n", $data);
- $data = str_replace('/**/?>', "?>\n", $data);
- $data = str_replace('?><?php', '', $data);
return $data;
}
@@ -335,6 +348,10 @@ class phpbb_template_filter extends php_user_filter
return '<?php ' . $this->compile_tag_define($matches[2], false) . ' ?>';
break;
+ case 'ENDDEFINE':
+ return '<?php ' . $this->compile_tag_enddefine() . ' ?>';
+ break;
+
case 'INCLUDE':
return '<?php ' . $this->compile_tag_include($matches[2]) . ' ?>';
break;
@@ -458,6 +475,7 @@ class phpbb_template_filter extends php_user_filter
*/
private function compile_var_tags(&$text_blocks)
{
+ $is_expr = null;
$text_blocks = $this->get_varref($text_blocks, $is_expr);
$lang_replaced = $this->compile_language_tags($text_blocks);
@@ -839,6 +857,16 @@ class phpbb_template_filter extends php_user_filter
$match = array();
preg_match('#^((?:' . self::REGEX_NS . '\.)+)?\$(?=[A-Z])([A-Z0-9_\-]*)(?: = (.*?))?$#', $tag_args, $match);
+ if (!empty($match[2]) && !isset($match[3]) && $op)
+ {
+ // DEFINE tag with ENDDEFINE
+ $array = "\$_tpldata['DEFINE']['.vars']";
+ $code = 'ob_start(); ';
+ $code .= "if (!isset($array)) { $array = array(); } ";
+ $code .= "{$array}[] = '{$match[2]}'";
+ return $code;
+ }
+
if (empty($match[2]) || (!isset($match[3]) && $op))
{
return '';
@@ -866,6 +894,20 @@ class phpbb_template_filter extends php_user_filter
}
/**
+ * Compile ENDDEFINE tag
+ *
+ * @return string compiled template code
+ */
+ private function compile_tag_enddefine()
+ {
+ $array = "\$_tpldata['DEFINE']['.vars']";
+ $code = "if (!isset($array) || !sizeof($array)) { trigger_error('ENDDEFINE tag without DEFINE in ' . basename(__FILE__), E_USER_ERROR); }";
+ $code .= "\$define_var = array_pop($array); ";
+ $code .= "\$_tpldata['DEFINE']['.'][\$define_var] = ob_get_clean();";
+ return $code;
+ }
+
+ /**
* Compile INCLUDE tag
*
* @param string $tag_args Expression given with INCLUDE in source template
@@ -967,8 +1009,14 @@ class phpbb_template_filter extends php_user_filter
$all_compiled = '';
foreach ($files as $file)
{
+ $this->template_compile->set_filter_params(array(
+ 'cleanup' => false,
+ ));
+
$compiled = $this->template_compile->compile_file($file);
+ $this->template_compile->reset_filter_params();
+
if ($compiled === false)
{
if ($this->user)
diff --git a/phpBB/includes/ucp/ucp_groups.php b/phpBB/includes/ucp/ucp_groups.php
index 50d13e00b1..aada0525a8 100644
--- a/phpBB/includes/ucp/ucp_groups.php
+++ b/phpBB/includes/ucp/ucp_groups.php
@@ -416,9 +416,11 @@ class ucp_groups
if ($group_id)
{
- $sql = 'SELECT *
- FROM ' . GROUPS_TABLE . "
- WHERE group_id = $group_id";
+ $sql = 'SELECT g.*, t.teampage_position AS group_teampage
+ FROM ' . GROUPS_TABLE . ' g
+ LEFT JOIN ' . TEAMPAGE_TABLE . ' t
+ ON (t.group_id = g.group_id)
+ WHERE g.group_id = ' . $group_id;
$result = $db->sql_query($sql);
$group_row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
@@ -514,6 +516,8 @@ class ucp_groups
'receive_pm' => isset($_REQUEST['group_receive_pm']) ? 1 : 0,
'message_limit' => request_var('group_message_limit', 0),
'max_recipients'=> request_var('group_max_recipients', 0),
+ 'legend' => $group_row['group_legend'],
+ 'teampage' => $group_row['group_teampage'],
);
if ($config['allow_avatar'])
@@ -547,6 +551,9 @@ class ucp_groups
$submit_ary['avatar_width'] = 0;
$submit_ary['avatar_height'] = 0;
}
+
+ // Merge any avatars errors into the primary error array
+ $error = array_merge($error, $phpbb_avatar_manager->localize_errors($user, $avatar_error));
}
if (!check_form_key('ucp_groups'))
@@ -554,11 +561,21 @@ class ucp_groups
$error[] = $user->lang['FORM_INVALID'];
}
+ // Validate submitted colour value
+ if ($colour_error = validate_data($submit_ary, array('colour' => array('hex_colour', true))))
+ {
+ // Replace "error" string with its real, localised form
+ $error = array_merge($error, array_map(array(&$user, 'lang'), $colour_error));
+ }
+
if (!sizeof($error))
{
// Only set the rank, colour, etc. if it's changed or if we're adding a new
// group. This prevents existing group members being updated if no changes
// were made.
+ // However there are some attributes that need to be set everytime,
+ // otherwise the group gets removed from the feature.
+ $set_attributes = array('legend', 'teampage');
$group_attributes = array();
$test_variables = array(
@@ -570,13 +587,14 @@ class ucp_groups
'avatar_height' => 'int',
'receive_pm' => 'int',
'legend' => 'int',
+ 'teampage' => 'int',
'message_limit' => 'int',
'max_recipients'=> 'int',
);
foreach ($test_variables as $test => $type)
{
- if (isset($submit_ary[$test]) && ($action == 'add' || $group_row['group_' . $test] != $submit_ary[$test] || isset($group_attributes['group_avatar']) && strpos($test, 'avatar') === 0))
+ if (isset($submit_ary[$test]) && ($action == 'add' || $group_row['group_' . $test] != $submit_ary[$test] || isset($group_attributes['group_avatar']) && strpos($test, 'avatar') === 0 || in_array($test, $set_attributes)))
{
settype($submit_ary[$test], $type);
$group_attributes['group_' . $test] = $group_row['group_' . $test] = $submit_ary[$test];
@@ -586,6 +604,7 @@ class ucp_groups
if (!($error = group_create($group_id, $group_type, $group_name, $group_desc, $group_attributes, $allow_desc_bbcode, $allow_desc_urls, $allow_desc_smilies)))
{
$cache->destroy('sql', GROUPS_TABLE);
+ $cache->destroy('sql', TEAMPAGE_TABLE);
$message = ($action == 'edit') ? 'GROUP_UPDATED' : 'GROUP_CREATED';
trigger_error($user->lang[$message] . $return_page);
@@ -672,8 +691,11 @@ class ucp_groups
}
}
- // Merge any avatars errors into the primary error array
- $error = array_merge($error, $phpbb_avatar_manager->localize_errors($user, $avatar_error));
+ if (isset($phpbb_avatar_manager) && !$update)
+ {
+ // Merge any avatars errors into the primary error array
+ $error = array_merge($error, $phpbb_avatar_manager->localize_errors($user, $avatar_error));
+ }
$template->assign_vars(array(
'S_EDIT' => true,
diff --git a/phpBB/includes/ucp/ucp_notifications.php b/phpBB/includes/ucp/ucp_notifications.php
index 338c921e94..72c41776b3 100644
--- a/phpBB/includes/ucp/ucp_notifications.php
+++ b/phpBB/includes/ucp/ucp_notifications.php
@@ -200,6 +200,10 @@ class ucp_notifications
}
}
}
+
+ $template->assign_vars(array(
+ strtoupper($block) . '_COLS' => sizeof($notification_methods) + 2,
+ ));
}
/**