diff options
Diffstat (limited to 'phpBB')
235 files changed, 7142 insertions, 3687 deletions
diff --git a/phpBB/adm/index.php b/phpBB/adm/index.php index e20bbe4bec..564a19ce64 100644 --- a/phpBB/adm/index.php +++ b/phpBB/adm/index.php @@ -42,7 +42,6 @@ if (!$auth->acl_get('a_')) // We define the admin variables now, because the user is now able to use the admin related features... define('IN_ADMIN', true); -$phpbb_admin_path = (defined('PHPBB_ADMIN_PATH')) ? PHPBB_ADMIN_PATH : './'; // Some oft used variables $safe_mode = (@ini_get('safe_mode') == '1' || strtolower(@ini_get('safe_mode')) === 'on') ? true : false; @@ -52,7 +51,7 @@ $mode = request_var('mode', ''); // Set custom style for admin area $phpbb_style->set_ext_dir_prefix('adm/'); -$phpbb_style->set_custom_style('admin', $phpbb_admin_path . 'style', ''); +$phpbb_style->set_custom_style('admin', $phpbb_admin_path . 'style', array(), ''); $template->assign_var('T_ASSETS_PATH', $phpbb_root_path . 'assets'); $template->assign_var('T_TEMPLATE_PATH', $phpbb_admin_path . 'style'); diff --git a/phpBB/adm/style/acp_forums.html b/phpBB/adm/style/acp_forums.html index cb9cae6c0d..d6c06bf6d8 100644 --- a/phpBB/adm/style/acp_forums.html +++ b/phpBB/adm/style/acp_forums.html @@ -241,6 +241,7 @@ <dt><label for="topics_per_page">{L_FORUM_TOPICS_PAGE}{L_COLON}</label><br /><span>{L_FORUM_TOPICS_PAGE_EXPLAIN}</span></dt> <dd><input type="text" id="topics_per_page" name="topics_per_page" value="{TOPICS_PER_PAGE}" size="4" maxlength="4" /></dd> </dl> + <!-- EVENT acp_forums_normal_settings_append --> </fieldset> <fieldset> @@ -454,12 +455,12 @@ <td style="vertical-align: top; width: 100px; text-align: right; white-space: nowrap;"> <!-- IF forums.S_FIRST_ROW && not forums.S_LAST_ROW --> <span class="up">{ICON_MOVE_UP_DISABLED}</span> - <span class="down"><a href="{forums.U_MOVE_DOWN}" data-ajax="forum_down" data-overlay="false">{ICON_MOVE_DOWN}</a></span> + <span class="down"><a href="{forums.U_MOVE_DOWN}" data-ajax="row_down" data-overlay="false">{ICON_MOVE_DOWN}</a></span> <!-- ELSEIF not forums.S_FIRST_ROW && not forums.S_LAST_ROW --> - <span class="up"><a href="{forums.U_MOVE_UP}" data-ajax="forum_up" data-overlay="false">{ICON_MOVE_UP}</a></span> - <span class="down"><a href="{forums.U_MOVE_DOWN}" data-ajax="forum_down" data-overlay="false">{ICON_MOVE_DOWN}</a></span> + <span class="up"><a href="{forums.U_MOVE_UP}" data-ajax="row_up" data-overlay="false">{ICON_MOVE_UP}</a></span> + <span class="down"><a href="{forums.U_MOVE_DOWN}" data-ajax="row_down" data-overlay="false">{ICON_MOVE_DOWN}</a></span> <!-- ELSEIF forums.S_LAST_ROW && not forums.S_FIRST_ROW --> - <span class="up"><a href="{forums.U_MOVE_UP}" data-ajax="forum_up" data-overlay="false">{ICON_MOVE_UP}</a></span> + <span class="up"><a href="{forums.U_MOVE_UP}" data-ajax="row_up" data-overlay="false">{ICON_MOVE_UP}</a></span> <span class="down">{ICON_MOVE_DOWN_DISABLED}</span> <!-- ELSE --> <span class="up">{ICON_MOVE_UP_DISABLED}</span> diff --git a/phpBB/adm/style/acp_main.html b/phpBB/adm/style/acp_main.html index 8b591294d4..b644862ce1 100644 --- a/phpBB/adm/style/acp_main.html +++ b/phpBB/adm/style/acp_main.html @@ -76,6 +76,8 @@ </div> <!-- ENDIF --> + <!-- EVENT acp_main_notice_after --> + <table cellspacing="1"> <caption>{L_FORUM_STATS}</caption> <col class="col1" /><col class="col2" /><col class="col1" /><col class="col2" /> @@ -202,6 +204,8 @@ <dd><input type="hidden" name="action" value="purge_cache" /><input class="button2" type="submit" id="action_purge_cache" name="action_purge_cache" value="{L_RUN}" /></dd> </dl> </form> + + <!-- EVENT acp_main_actions_append --> </fieldset> <!-- ENDIF --> diff --git a/phpBB/adm/style/acp_users_overview.html b/phpBB/adm/style/acp_users_overview.html index b7e3a9822e..a8e862c141 100644 --- a/phpBB/adm/style/acp_users_overview.html +++ b/phpBB/adm/style/acp_users_overview.html @@ -53,6 +53,7 @@ <dt><label for="password_confirm">{L_CONFIRM_PASSWORD}{L_COLON}</label><br /><span>{L_CONFIRM_PASSWORD_EXPLAIN}</span></dt> <dd><input type="password" id="password_confirm" name="password_confirm" value="" autocomplete="off" /></dd> </dl> +<!-- EVENT acp_users_overview_options_append --> <p class="quick"> <input class="button1" type="submit" name="update" value="{L_SUBMIT}" /> diff --git a/phpBB/adm/style/acp_users_profile.html b/phpBB/adm/style/acp_users_profile.html index 3232e8d1f5..36e9f340d4 100644 --- a/phpBB/adm/style/acp_users_profile.html +++ b/phpBB/adm/style/acp_users_profile.html @@ -11,10 +11,6 @@ <dd><input type="text" id="aim" name="aim" value="{AIM}" /></dd> </dl> <dl> - <dt><label for="msn">{L_UCP_MSNM}{L_COLON}</label></dt> - <dd><input type="text" id="msn" name="msn" value="{MSN}" /></dd> - </dl> - <dl> <dt><label for="yim">{L_UCP_YIM}{L_COLON}</label></dt> <dd><input type="text" id="yim" name="yim" value="{YIM}" /></dd> </dl> diff --git a/phpBB/adm/style/ajax.js b/phpBB/adm/style/ajax.js index 12541cb057..294a35b615 100644 --- a/phpBB/adm/style/ajax.js +++ b/phpBB/adm/style/ajax.js @@ -2,84 +2,102 @@ "use strict"; -var img_templates = { +var imgTemplates = { up: $('.template-up-img'), - up_disabled: $('.template-up-img-disabled'), + upDisabled: $('.template-up-img-disabled'), down: $('.template-down-img'), - down_disabled: $('.template-down-img-disabled') + downDisabled: $('.template-down-img-disabled') }; /** - * The following callbacks are for reording forums in acp_forums. forum_down - * is triggered when a forum is moved down, and forum_up is triggered when - * a forum is moved up. It moves the row up or down, and deactivates / + * The following callbacks are for reording items. row_down + * is triggered when an item is moved down, and row_up is triggered when + * an item is moved up. It moves the row up or down, and deactivates / * activates any up / down icons that require it (the ones at the top or bottom). */ -phpbb.add_ajax_callback('forum_down', function() { +phpbb.addAjaxCallback('row_down', function() { var el = $(this), - tr = el.parents('tr'); - - if (tr.is(':first-child')) - { - var up_img = img_templates.up.clone().attr('href', tr.attr('data-up')); - el.parents('span').siblings('.up').html(up_img); - - tr.next().find('.up').html(img_templates.up_disabled); + tr = el.parents('tr'), + trSwap = tr.next(); + + /* + * If the element was the first one, we have to: + * - Add the up-link to the row we moved + * - Remove the up-link on the next row + */ + if (tr.is(':first-child')) { + var upImg = imgTemplates.up.clone().attr('href', tr.attr('data-up')); + tr.find('.up').html(upImg); phpbb.ajaxify({ - selector: el.parents('span').siblings('.up').children('a'), - callback: 'forum_up', + selector: tr.find('.up').children('a'), + callback: 'row_up', overlay: false }); + + trSwap.find('.up').html(imgTemplates.upDisabled.clone()); } - tr.insertAfter(tr.next()); + tr.insertAfter(trSwap); - if (tr.is(':last-child')) - { - el.replaceWith(img_templates.down_disabled); + /* + * As well as: + * - Remove the down-link on the moved row, if it is now the last row + * - Add the down-link to the next row, if it was the last row + */ + if (tr.is(':last-child')) { + tr.find('.down').html(imgTemplates.downDisabled.clone()); - var down_img = img_templates.down.clone().attr('href', tr.attr('data-down')); - tr.prev().find('.down').html(down_img); + var downImg = imgTemplates.down.clone().attr('href', trSwap.attr('data-down')); + trSwap.find('.down').html(downImg); phpbb.ajaxify({ - selector: tr.prev().find('.down').children('a'), - callback: 'forum_down', + selector: trSwap.find('.down').children('a'), + callback: 'row_down', overlay: false }); } }); -phpbb.add_ajax_callback('forum_up', function() { +phpbb.addAjaxCallback('row_up', function() { var el = $(this), - tr = el.parents('tr'); - - if (tr.is(':last-child')) - { - var down_img = img_templates.down.clone().attr('href', tr.attr('data-down')); - el.parents('span').siblings('.down').html(down_img); - - tr.prev().find('.down').html(img_templates.down_disabled); + tr = el.parents('tr'), + trSwap = tr.prev(); + + /* + * If the element was the last one, we have to: + * - Add the down-link to the row we moved + * - Remove the down-link on the next row + */ + if (tr.is(':last-child')) { + var downImg = imgTemplates.down.clone().attr('href', tr.attr('data-down')); + tr.find('.down').html(downImg); phpbb.ajaxify({ - selector: el.parents('span').siblings('.down').children('a'), - callback: 'forum_down', + selector: tr.find('.down').children('a'), + callback: 'row_down', overlay: false }); + + trSwap.find('.down').html(imgTemplates.downDisabled.clone()); } - tr.insertBefore(tr.prev()); + tr.insertBefore(trSwap); - if (tr.is(':first-child')) - { - el.replaceWith(img_templates.up_disabled); + /* + * As well as: + * - Remove the up-link on the moved row, if it is now the first row + * - Add the up-link to the previous row, if it was the first row + */ + if (tr.is(':first-child')) { + tr.find('.up').html(imgTemplates.upDisabled.clone()); - var up_img = img_templates.up.clone().attr('href', tr.attr('data-up')); - tr.next().find('.up').html(up_img); + var upImg = imgTemplates.up.clone().attr('href', trSwap.attr('data-up')); + trSwap.find('.up').html(upImg); phpbb.ajaxify({ - selector: tr.next().find('.up').children('a'), - callback: 'forum_up', + selector: trSwap.find('.up').children('a'), + callback: 'row_up', overlay: false }); } @@ -90,29 +108,26 @@ phpbb.add_ajax_callback('forum_up', function() { * It does this by replacing the text, and replacing all instances of "activate" * in the href with "deactivate", and vice versa. */ -phpbb.add_ajax_callback('activate_deactivate', function(res) { +phpbb.addAjaxCallback('activate_deactivate', function(res) { var el = $(this), - new_href = el.attr('href'); + newHref = el.attr('href'); el.text(res.text); - if (new_href.indexOf('deactivate') !== -1) - { - new_href = new_href.replace('deactivate', 'activate') - } - else - { - new_href = new_href.replace('activate', 'deactivate') + if (newHref.indexOf('deactivate') !== -1) { + newHref = newHref.replace('deactivate', 'activate') + } else { + newHref = newHref.replace('activate', 'deactivate') } - el.attr('href', new_href); + el.attr('href', newHref); }); /** * The removes the parent row of the link or form that triggered the callback, * and is good for stuff like the removal of forums. */ -phpbb.add_ajax_callback('row_delete', function() { +phpbb.addAjaxCallback('row_delete', function() { $(this).parents('tr').remove(); }); @@ -123,8 +138,7 @@ $('[data-ajax]').each(function() { ajax = $this.attr('data-ajax'), fn; - if (ajax !== 'false') - { + if (ajax !== 'false') { fn = (ajax !== 'true') ? ajax : null; phpbb.ajaxify({ selector: this, diff --git a/phpBB/adm/style/install_header.html b/phpBB/adm/style/install_header.html index 6826654ded..5631b83e17 100644 --- a/phpBB/adm/style/install_header.html +++ b/phpBB/adm/style/install_header.html @@ -5,7 +5,7 @@ <!-- IF META -->{META}<!-- ENDIF --> <title>{PAGE_TITLE}</title> -<link href="../adm/style/admin.css" rel="stylesheet" type="text/css" media="screen" /> +<link href="{T_TEMPLATE_PATH}/admin.css" rel="stylesheet" type="text/css" media="screen" /> <script type="text/javascript"> // <![CDATA[ @@ -49,7 +49,7 @@ function dE(n, s, type) </form> <!-- ENDIF --> </div> - + <div id="page-body"> <div id="tabs"> <ul> @@ -73,5 +73,5 @@ function dE(n, s, type) <!-- END l_block2 --> </ul> </div> - + <div id="main" class="install-body"> diff --git a/phpBB/adm/style/install_update_diff.html b/phpBB/adm/style/install_update_diff.html index ecdc40e157..1f30fe4d13 100644 --- a/phpBB/adm/style/install_update_diff.html +++ b/phpBB/adm/style/install_update_diff.html @@ -5,7 +5,7 @@ <!-- IF META -->{META}<!-- ENDIF --> <title>{PAGE_TITLE}</title> -<link href="../adm/style/admin.css" rel="stylesheet" type="text/css" media="screen" /> +<link href="{T_TEMPLATE_PATH}/admin.css" rel="stylesheet" type="text/css" media="screen" /> <script type="text/javascript"> // <![CDATA[ diff --git a/phpBB/adm/style/overall_footer.html b/phpBB/adm/style/overall_footer.html index 2bc9ee52d7..2a8b46d458 100644 --- a/phpBB/adm/style/overall_footer.html +++ b/phpBB/adm/style/overall_footer.html @@ -42,5 +42,7 @@ <!-- INCLUDEJS ajax.js --> {SCRIPTS} +<!-- EVENT acp_overall_footer_after --> + </body> </html> diff --git a/phpBB/adm/style/overall_header.html b/phpBB/adm/style/overall_header.html index f7902e6d2e..8170931221 100644 --- a/phpBB/adm/style/overall_header.html +++ b/phpBB/adm/style/overall_header.html @@ -155,6 +155,7 @@ function switch_menu() // ]]> </script> +<!-- EVENT acp_overall_header_head_append --> </head> <body class="{S_CONTENT_DIRECTION}"> diff --git a/phpBB/adm/style/simple_footer.html b/phpBB/adm/style/simple_footer.html index 1d5c62b0a3..906a9bebed 100644 --- a/phpBB/adm/style/simple_footer.html +++ b/phpBB/adm/style/simple_footer.html @@ -18,6 +18,7 @@ <script type="text/javascript" src="{T_JQUERY_LINK}"></script> <!-- IF S_JQUERY_FALLBACK --><script type="text/javascript">window.jQuery || document.write(unescape('%3Cscript src="{T_ASSETS_PATH}/javascript/jquery.js?assets_version={T_ASSETS_VERSION}" type="text/javascript"%3E%3C/script%3E'));</script><!-- ENDIF --> +<!-- EVENT acp_simple_footer_after --> </body> </html> diff --git a/phpBB/adm/style/simple_header.html b/phpBB/adm/style/simple_header.html index 0ba445ca2a..6e0c360600 100644 --- a/phpBB/adm/style/simple_header.html +++ b/phpBB/adm/style/simple_header.html @@ -101,6 +101,7 @@ function find_username(url) // ]]> </script> +<!-- EVENT acp_simple_header_head_append --> </head> <body class="{S_CONTENT_DIRECTION}"> diff --git a/phpBB/adm/style/timezone.js b/phpBB/adm/style/timezone.js index 4556ea5f94..419d37c34f 100644 --- a/phpBB/adm/style/timezone.js +++ b/phpBB/adm/style/timezone.js @@ -1,11 +1,11 @@ (function($) { // Avoid conflicts with other libraries $('#tz_date').change(function() { - phpbb.timezone_switch_date(false); + phpbb.timezoneSwitchDate(false); }); $(document).ready( - phpbb.timezone_enable_date_selection + phpbb.timezoneEnableDateSelection ); })(jQuery); // Avoid conflicts with other libraries diff --git a/phpBB/adm/swatch.php b/phpBB/adm/swatch.php index 86498a255f..3ae38d0d8b 100644 --- a/phpBB/adm/swatch.php +++ b/phpBB/adm/swatch.php @@ -21,10 +21,8 @@ $user->session_begin(false); $auth->acl($user->data); $user->setup(); -$phpbb_admin_path = (defined('PHPBB_ADMIN_PATH')) ? PHPBB_ADMIN_PATH : './'; - // Set custom template for admin area -$phpbb_style->set_custom_style('admin', $phpbb_admin_path . 'style', ''); +$phpbb_style->set_custom_style('admin', $phpbb_admin_path . 'style', array(), ''); $template->set_filenames(array( 'body' => 'colour_swatch.html') diff --git a/phpBB/app.php b/phpBB/app.php new file mode 100644 index 0000000000..d93208d585 --- /dev/null +++ b/phpBB/app.php @@ -0,0 +1,31 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +*/ + +/** +* @ignore +*/ +define('IN_PHPBB', true); +$phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './'; +$phpEx = substr(strrchr(__FILE__, '.'), 1); +include($phpbb_root_path . 'common.' . $phpEx); +include($phpbb_root_path . 'includes/functions_url_matcher.' . $phpEx); + +// Start session management +$user->session_begin(); +$auth->acl($user->data); +$user->setup('app'); + +$symfony_request = phpbb_create_symfony_request($request); +$http_kernel = $phpbb_container->get('http_kernel'); +$response = $http_kernel->handle($symfony_request); +$response->send(); +$http_kernel->terminate($symfony_request, $response); diff --git a/phpBB/assets/javascript/core.js b/phpBB/assets/javascript/core.js index f7d6688f68..16ed04746d 100644 --- a/phpBB/assets/javascript/core.js +++ b/phpBB/assets/javascript/core.js @@ -1,5 +1,5 @@ var phpbb = {}; -phpbb.alert_time = 100; +phpbb.alertTime = 100; (function($) { // Avoid conflicts with other libraries @@ -12,35 +12,42 @@ var keymap = { }; var dark = $('#darkenwrapper'); -var loading_alert = $('#loadingalert'); +var loadingAlert = $('#loadingalert'); +var phpbbAlertTimer = null; /** - * Display a loading screen. + * Display a loading screen * - * @returns object Returns loading_alert. + * @returns object Returns loadingAlert. */ -phpbb.loading_alert = function() { - if (dark.is(':visible')) - { - loading_alert.fadeIn(phpbb.alert_time); - } - else - { - loading_alert.show(); - dark.fadeIn(phpbb.alert_time, function() { +phpbb.loadingAlert = function() { + if (dark.is(':visible')) { + loadingAlert.fadeIn(phpbb.alertTime); + } else { + loadingAlert.show(); + dark.fadeIn(phpbb.alertTime, function() { // Wait five seconds and display an error if nothing has been returned by then. - setTimeout(function() { - if (loading_alert.is(':visible')) - { + phpbbAlertTimer = setTimeout(function() { + if (loadingAlert.is(':visible')) { phpbb.alert($('#phpbb_alert').attr('data-l-err'), $('#phpbb_alert').attr('data-l-timeout-processing-req')); } }, 5000); }); } - return loading_alert; -} + return loadingAlert; +}; + +/** + * Clear loading alert timeout +*/ +phpbb.clearLoadingTimeout = function() { + if (phpbbAlertTimer !== null) { + clearTimeout(phpbbAlertTimer); + phpbbAlertTimer = null; + } +}; /** * Display a simple alert similar to JSs native alert(). @@ -67,7 +74,7 @@ phpbb.alert = function(title, msg, fadedark) { div.find('.alert_close').unbind('click'); fade = (typeof fadedark !== 'undefined' && !fadedark) ? div : dark; - fade.fadeOut(phpbb.alert_time, function() { + fade.fadeOut(phpbb.alertTime, function() { div.hide(); }); @@ -90,27 +97,22 @@ phpbb.alert = function(title, msg, fadedark) { e.preventDefault(); }); - if (loading_alert.is(':visible')) - { - loading_alert.fadeOut(phpbb.alert_time, function() { + if (loadingAlert.is(':visible')) { + loadingAlert.fadeOut(phpbb.alertTime, function() { dark.append(div); - div.fadeIn(phpbb.alert_time); + div.fadeIn(phpbb.alertTime); }); - } - else if (dark.is(':visible')) - { + } else if (dark.is(':visible')) { dark.append(div); - div.fadeIn(phpbb.alert_time); - } - else - { + div.fadeIn(phpbb.alertTime); + } else { dark.append(div); div.show(); - dark.fadeIn(phpbb.alert_time); + dark.fadeIn(phpbb.alertTime); } return div; -} +}; /** * Display a simple yes / no box to the user. @@ -133,13 +135,13 @@ phpbb.confirm = function(msg, callback, fadedark) { e.stopPropagation(); }); - var click_handler = function(e) { + var clickHandler = function(e) { var res = this.className === 'button1'; var fade = (typeof fadedark !== 'undefined' && !fadedark && res) ? div : dark; - fade.fadeOut(phpbb.alert_time, function() { + fade.fadeOut(phpbb.alertTime, function() { div.hide(); }); - div.find('input[type="button"]').unbind('click', click_handler); + div.find('input[type="button"]').unbind('click', clickHandler); callback(res); if (e) { @@ -147,11 +149,11 @@ phpbb.confirm = function(msg, callback, fadedark) { e.stopPropagation(); } }; - div.find('input[type="button"]').one('click', click_handler); + div.find('input[type="button"]').one('click', clickHandler); dark.one('click', function(e) { div.find('.alert_close').unbind('click'); - dark.fadeOut(phpbb.alert_time, function() { + dark.fadeOut(phpbb.alertTime, function() { div.hide(); }); callback(false); @@ -174,7 +176,7 @@ phpbb.confirm = function(msg, callback, fadedark) { div.find('.alert_close').one('click', function(e) { var fade = (typeof fadedark !== 'undefined' && fadedark) ? div : dark; - fade.fadeOut(phpbb.alert_time, function() { + fade.fadeOut(phpbb.alertTime, function() { div.hide(); }); callback(false); @@ -182,27 +184,22 @@ phpbb.confirm = function(msg, callback, fadedark) { e.preventDefault(); }); - if (loading_alert.is(':visible')) - { - loading_alert.fadeOut(phpbb.alert_time, function() { + if (loadingAlert.is(':visible')) { + loadingAlert.fadeOut(phpbb.alertTime, function() { dark.append(div); - div.fadeIn(phpbb.alert_time); + div.fadeIn(phpbb.alertTime); }); - } - else if (dark.is(':visible')) - { + } else if (dark.is(':visible')) { dark.append(div); - div.fadeIn(phpbb.alert_time); - } - else - { + div.fadeIn(phpbb.alertTime); + } else { dark.append(div); div.show(); - dark.fadeIn(phpbb.alert_time); + dark.fadeIn(phpbb.alertTime); } return div; -} +}; /** * Turn a querystring into an array. @@ -210,17 +207,16 @@ phpbb.confirm = function(msg, callback, fadedark) { * @argument string string The querystring to parse. * @returns object The object created. */ -phpbb.parse_querystring = function(string) { +phpbb.parseQuerystring = function(string) { var params = {}, i, split; string = string.split('&'); - for (i = 0; i < string.length; i++) - { + for (i = 0; i < string.length; i++) { split = string[i].split('='); params[split[0]] = decodeURIComponent(split[1]); } return params; -} +}; /** @@ -246,14 +242,13 @@ phpbb.ajaxify = function(options) { refresh = options.refresh, callback = options.callback, overlay = (typeof options.overlay !== 'undefined') ? options.overlay : true, - is_form = elements.is('form'), - event_name = is_form ? 'submit' : 'click'; + isForm = elements.is('form'), + eventName = isForm ? 'submit' : 'click'; - elements.bind(event_name, function(event) { + elements.bind(eventName, function(event) { var action, method, data, submit, that = this, $this = $(this); - if ($this.find('input[type="submit"][data-clicked]').attr('data-ajax') === 'false') - { + if ($this.find('input[type="submit"][data-clicked]').attr('data-ajax') === 'false') { return; } @@ -267,110 +262,88 @@ phpbb.ajaxify = function(options) { * * @param object res The object sent back by the server. */ - function return_handler(res) - { + function returnHandler(res) { var alert; + phpbb.clearLoadingTimeout(); + // Is a confirmation required? - if (typeof res.S_CONFIRM_ACTION === 'undefined') - { + if (typeof res.S_CONFIRM_ACTION === 'undefined') { // If a confirmation is not required, display an alert and call the // callbacks. - if (typeof res.MESSAGE_TITLE !== 'undefined') - { + if (typeof res.MESSAGE_TITLE !== 'undefined') { alert = phpbb.alert(res.MESSAGE_TITLE, res.MESSAGE_TEXT); - } - else - { - dark.fadeOut(phpbb.alert_time); + } else { + dark.fadeOut(phpbb.alertTime); } - if (typeof phpbb.ajax_callbacks[callback] === 'function') - { - phpbb.ajax_callbacks[callback].call(that, res); + if (typeof phpbb.ajaxCallbacks[callback] === 'function') { + phpbb.ajaxCallbacks[callback].call(that, res); } // If the server says to refresh the page, check whether the page should // be refreshed and refresh page after specified time if required. - if (res.REFRESH_DATA) - { - if (typeof refresh === 'function') - { + if (res.REFRESH_DATA) { + if (typeof refresh === 'function') { refresh = refresh(res.REFRESH_DATA.url); - } - else if (typeof refresh !== 'boolean') - { + } else if (typeof refresh !== 'boolean') { refresh = false; } setTimeout(function() { - if (refresh) - { + if (refresh) { window.location = res.REFRESH_DATA.url; } // Hide the alert even if we refresh the page, in case the user // presses the back button. - dark.fadeOut(phpbb.alert_time, function() { + dark.fadeOut(phpbb.alertTime, function() { alert.hide(); }); }, res.REFRESH_DATA.time * 1000); // Server specifies time in seconds } - } - else - { + } else { // If confirmation is required, display a diologue to the user. phpbb.confirm(res.MESSAGE_TEXT, function(del) { - if (del) - { - phpbb.loading_alert(); + if (del) { + phpbb.loadingAlert(); data = $('<form>' + res.S_HIDDEN_FIELDS + '</form>').serialize(); $.ajax({ url: res.S_CONFIRM_ACTION, type: 'POST', data: data + '&confirm=' + res.YES_VALUE, - success: return_handler, - error: error_handler + success: returnHandler, + error: errorHandler }); } }, false); } } - function error_handler() - { + function errorHandler() { var alert; + phpbb.clearLoadingTimeout(); alert = phpbb.alert(dark.attr('data-ajax-error-title'), dark.attr('data-ajax-error-text')); - - setTimeout(function () { - dark.fadeOut(phpbb.alert_time, function() { - alert.hide(); - }); - }, 5000); } // If the element is a form, POST must be used and some extra data must // be taken from the form. - var run_filter = (typeof options.filter === 'function'); + var runFilter = (typeof options.filter === 'function'); - if (is_form) - { + if (isForm) { action = $this.attr('action').replace('&', '&'); data = $this.serializeArray(); method = $this.attr('method') || 'GET'; - if ($this.find('input[type="submit"][data-clicked]')) - { + if ($this.find('input[type="submit"][data-clicked]')) { submit = $this.find('input[type="submit"][data-clicked]'); data.push({ name: submit.attr('name'), value: submit.val() }); } - } - else - { + } else { action = this.href; data = null; method = 'GET'; @@ -378,28 +351,27 @@ phpbb.ajaxify = function(options) { // If filter function returns false, cancel the AJAX functionality, // and return true (meaning that the HTTP request will be sent normally). - if (run_filter && !options.filter.call(this, data)) - { + if (runFilter && !options.filter.call(this, data)) { return; } if (overlay && (typeof $this.attr('data-overlay') === 'undefined' || $this.attr('data-overlay') == 'true')) { - phpbb.loading_alert(); + phpbb.loadingAlert(); } $.ajax({ url: action, type: method, data: data, - success: return_handler, - error: error_handler + success: returnHandler, + error: errorHandler }); event.preventDefault(); }); - if (is_form) { + if (isForm) { elements.find('input:submit').click(function () { var $this = $(this); @@ -409,14 +381,14 @@ phpbb.ajaxify = function(options) { } return this; -} +}; /** * Hide the optgroups that are not the selected timezone * -* @param bool keep_selection Shall we keep the value selected, or shall the user be forced to repick one. +* @param bool keepSelection Shall we keep the value selected, or shall the user be forced to repick one. */ -phpbb.timezone_switch_date = function(keep_selection) { +phpbb.timezoneSwitchDate = function(keepSelection) { if ($('#timezone_copy').length == 0) { // We make a backup of the original dropdown, so we can remove optgroups // instead of setting display to none, because IE and chrome will not @@ -440,27 +412,30 @@ phpbb.timezone_switch_date = function(keep_selection) { if ($("#timezone > optgroup[label='" + $('#tz_date').val() + "'] > option").size() == 1) { // If there is only one timezone for the selected date, we just select that automatically. $("#timezone > optgroup[label='" + $('#tz_date').val() + "'] > option:first").attr('selected', true); - keep_selection = true; + keepSelection = true; } - if (typeof keep_selection !== 'undefined' && !keep_selection) { - $('#timezone > option:first').attr('selected', true); + if (typeof keepSelection !== 'undefined' && !keepSelection) { + var timezoneOptions = $('#timezone > optgroup option'); + if (timezoneOptions.filter(':selected').length <= 0) { + timezoneOptions.filter(':first').attr('selected', true); + } } -} +}; /** * Display the date/time select */ -phpbb.timezone_enable_date_selection = function() { +phpbb.timezoneEnableDateSelection = function() { $('#tz_select_date').css('display', 'block'); -} +}; /** * Preselect a date/time or suggest one, if it is not picked. * -* @param bool force_selector Shall we select the suggestion? +* @param bool forceSelector Shall we select the suggestion? */ -phpbb.timezone_preselect_select = function(force_selector) { +phpbb.timezonePreselectSelect = function(forceSelector) { // The offset returned here is in minutes and negated. // http://www.w3schools.com/jsref/jsref_getTimezoneOffset.asp @@ -489,21 +464,21 @@ phpbb.timezone_preselect_select = function(force_selector) { } var prefix = 'GMT' + sign + hours + ':' + minutes; - var prefix_length = prefix.length; - var selector_options = $('#tz_date > option'); + var prefixLength = prefix.length; + var selectorOptions = $('#tz_date > option'); - for (var i = 0; i < selector_options.length; ++i) { - var option = selector_options[i]; + for (var i = 0; i < selectorOptions.length; ++i) { + var option = selectorOptions[i]; - if (option.value.substring(0, prefix_length) == prefix) { - if ($('#tz_date').val() != option.value && !force_selector) { + if (option.value.substring(0, prefixLength) == prefix) { + if ($('#tz_date').val() != option.value && !forceSelector) { // We do not select the option for the user, but notify him, // that we would suggest a different setting. - phpbb.timezone_switch_date(true); + phpbb.timezoneSwitchDate(true); $('#tz_select_date_suggest').css('display', 'inline'); } else { option.selected = true; - phpbb.timezone_switch_date(!force_selector); + phpbb.timezoneSwitchDate(!forceSelector); $('#tz_select_date_suggest').css('display', 'none'); } @@ -515,9 +490,9 @@ phpbb.timezone_preselect_select = function(force_selector) { return; } } -} +}; -phpbb.ajax_callbacks = {}; +phpbb.ajaxCallbacks = {}; /** * Adds an AJAX callback to be used by phpbb.ajaxify. @@ -527,14 +502,12 @@ phpbb.ajax_callbacks = {}; * @param string id The name of the callback. * @param function callback The callback to be called. */ -phpbb.add_ajax_callback = function(id, callback) -{ - if (typeof callback === 'function') - { - phpbb.ajax_callbacks[id] = callback; +phpbb.addAjaxCallback = function(id, callback) { + if (typeof callback === 'function') { + phpbb.ajaxCallbacks[id] = callback; } return this; -} +}; /** @@ -542,14 +515,14 @@ phpbb.add_ajax_callback = function(id, callback) * the alt-text data attribute, and replaces the text in the attribute with the * current text so that the process can be repeated. */ -phpbb.add_ajax_callback('alt_text', function() { +phpbb.addAjaxCallback('alt_text', function() { var el = $(this), - alt_text; + altText; - alt_text = el.attr('data-alt-text'); + altText = el.attr('data-alt-text'); el.attr('data-alt-text', el.text()); - el.attr('title', alt_text); - el.text(alt_text); + el.attr('title', altText); + el.text(altText); }); /** @@ -561,28 +534,28 @@ phpbb.add_ajax_callback('alt_text', function() { * Additionally it replaces the class of the link's parent * and changes the link itself. */ -phpbb.add_ajax_callback('toggle_link', function() { +phpbb.addAjaxCallback('toggle_link', function() { var el = $(this), - toggle_text, - toggle_url, - toggle_class; + toggleText, + toggleUrl, + toggleClass; // Toggle link text - toggle_text = el.attr('data-toggle-text'); + toggleText = el.attr('data-toggle-text'); el.attr('data-toggle-text', el.text()); - el.attr('title', toggle_text); - el.text(toggle_text); + el.attr('title', toggleText); + el.text(toggleText); // Toggle link url - toggle_url = el.attr('data-toggle-url'); + toggleUrl = el.attr('data-toggle-url'); el.attr('data-toggle-url', el.attr('href')); - el.attr('href', toggle_url); + el.attr('href', toggleUrl); // Toggle class of link parent - toggle_class = el.attr('data-toggle-class'); + toggleClass = el.attr('data-toggle-class'); el.attr('data-toggle-class', el.parent().attr('class')); - el.parent().attr('class', toggle_class); + el.parent().attr('class', toggleClass); }); })(jQuery); // Avoid conflicts with other libraries diff --git a/phpBB/common.php b/phpBB/common.php index e49c52cecb..f502d37c8f 100644 --- a/phpBB/common.php +++ b/phpBB/common.php @@ -8,10 +8,6 @@ * Minimum Requirement: PHP 5.3.3 */ -use Symfony\Component\Config\FileLocator; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; - /** */ if (!defined('IN_PHPBB')) @@ -67,31 +63,34 @@ if (!defined('PHPBB_INSTALLED')) exit; } +// In case $phpbb_adm_relative_path is not set (in case of an update), use the default. +$phpbb_adm_relative_path = (isset($phpbb_adm_relative_path)) ? $phpbb_adm_relative_path : 'adm/'; +$phpbb_admin_path = (defined('PHPBB_ADMIN_PATH')) ? PHPBB_ADMIN_PATH : $phpbb_root_path . $phpbb_adm_relative_path; + // Include files require($phpbb_root_path . 'includes/class_loader.' . $phpEx); -require($phpbb_root_path . 'includes/di/processor/interface.' . $phpEx); -require($phpbb_root_path . 'includes/di/processor/config.' . $phpEx); require($phpbb_root_path . 'includes/functions.' . $phpEx); require($phpbb_root_path . 'includes/functions_content.' . $phpEx); +require($phpbb_root_path . 'includes/functions_container.' . $phpEx); require($phpbb_root_path . 'includes/constants.' . $phpEx); -require($phpbb_root_path . 'includes/db/' . ltrim($dbms, 'dbal_') . '.' . $phpEx); require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx); // Set PHP error handler to ours set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handler'); -$phpbb_container = new ContainerBuilder(); -$loader = new YamlFileLoader($phpbb_container, new FileLocator(__DIR__.'/config')); -$loader->load('services.yml'); +// Setup class loader first +$phpbb_class_loader = new phpbb_class_loader('phpbb_', "{$phpbb_root_path}includes/", ".$phpEx"); +$phpbb_class_loader->register(); +$phpbb_class_loader_ext = new phpbb_class_loader('phpbb_ext_', "{$phpbb_root_path}ext/", ".$phpEx"); +$phpbb_class_loader_ext->register(); -$processor = new phpbb_di_processor_config($phpbb_root_path . 'config.' . $phpEx, $phpbb_root_path, $phpEx); -$processor->process($phpbb_container); +// Set up container +$phpbb_container = phpbb_create_default_container($phpbb_root_path, $phpEx); -// Setup class loader first -$phpbb_class_loader = $phpbb_container->get('class_loader'); -$phpbb_class_loader_ext = $phpbb_container->get('class_loader.ext'); +$phpbb_class_loader->set_cache($phpbb_container->get('cache.driver')); +$phpbb_class_loader_ext->set_cache($phpbb_container->get('cache.driver')); // set up caching $cache = $phpbb_container->get('cache'); @@ -118,18 +117,12 @@ $phpbb_subscriber_loader = $phpbb_container->get('event.subscriber_loader'); $template = $phpbb_container->get('template'); $phpbb_style = $phpbb_container->get('style'); -$ids = array_keys($phpbb_container->findTaggedServiceIds('container.processor')); -foreach ($ids as $id) -{ - $processor = $phpbb_container->get($id); - $processor->process($phpbb_container); -} - // Add own hook handler require($phpbb_root_path . 'includes/hooks/index.' . $phpEx); $phpbb_hook = new phpbb_hook(array('exit_handler', 'phpbb_user_session_handler', 'append_sid', array('phpbb_template', 'display'))); +$phpbb_hook_finder = $phpbb_container->get('hook_finder'); -foreach ($cache->obtain_hooks() as $hook) +foreach ($phpbb_hook_finder->find() as $hook) { @include($phpbb_root_path . 'includes/hooks/' . $hook . '.' . $phpEx); } diff --git a/phpBB/composer.json b/phpBB/composer.json index 5e88144bc4..d2536a73cf 100644 --- a/phpBB/composer.json +++ b/phpBB/composer.json @@ -4,9 +4,11 @@ "symfony/config": "2.1.*", "symfony/dependency-injection": "2.1.*", "symfony/event-dispatcher": "2.1.*", + "symfony/http-kernel": "2.1.*", + "symfony/routing": "2.1.*", "symfony/yaml": "2.1.*" }, "require-dev": { - "fabpot/goutte": "1.0.x-dev" + "fabpot/goutte": "v0.1.0" } } diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 6b0d3584d1..e96c15fe8b 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -1,74 +1,778 @@ { - "hash": "1632798bc1d5298a4f5bd3087c972a9f", + "hash": "c1a76530df6b9daa16b8033d61b76503", "packages": [ { - "package": "symfony/config", - "version": "v2.1.0-RC1" + "name": "symfony/config", + "version": "v2.1.3", + "target-dir": "Symfony/Component/Config", + "source": { + "type": "git", + "url": "https://github.com/symfony/Config", + "reference": "v2.1.3" + }, + "dist": { + "type": "zip", + "url": "https://github.com/symfony/Config/zipball/v2.1.3", + "reference": "v2.1.3", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "time": "2012-10-20 00:10:30", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Symfony\\Component\\Config": "" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "description": "Symfony Config Component", + "homepage": "http://symfony.com" }, { - "package": "symfony/dependency-injection", - "version": "v2.1.0-RC1" + "name": "symfony/dependency-injection", + "version": "v2.1.3", + "target-dir": "Symfony/Component/DependencyInjection", + "source": { + "type": "git", + "url": "https://github.com/symfony/DependencyInjection", + "reference": "v2.1.3" + }, + "dist": { + "type": "zip", + "url": "https://github.com/symfony/DependencyInjection/zipball/v2.1.3", + "reference": "v2.1.3", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "symfony/yaml": "2.1.*", + "symfony/config": "2.1.*" + }, + "suggest": { + "symfony/yaml": "2.1.*", + "symfony/config": "2.1.*" + }, + "time": "2012-10-22 07:37:12", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Symfony\\Component\\DependencyInjection": "" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "description": "Symfony DependencyInjection Component", + "homepage": "http://symfony.com" }, { - "package": "symfony/event-dispatcher", - "version": "v2.1.0-RC1" + "name": "symfony/event-dispatcher", + "version": "v2.1.3", + "target-dir": "Symfony/Component/EventDispatcher", + "source": { + "type": "git", + "url": "https://github.com/symfony/EventDispatcher", + "reference": "v2.1.3" + }, + "dist": { + "type": "zip", + "url": "https://github.com/symfony/EventDispatcher/zipball/v2.1.3", + "reference": "v2.1.3", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "symfony/dependency-injection": "2.1.*" + }, + "suggest": { + "symfony/dependency-injection": "2.1.*", + "symfony/http-kernel": "2.1.*" + }, + "time": "2012-10-04 08:17:57", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Symfony\\Component\\EventDispatcher": "" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "http://symfony.com" }, { - "package": "symfony/yaml", - "version": "v2.1.0-RC1" - } - ], - "packages-dev": [ - { - "package": "fabpot/goutte", - "version": "dev-master", - "alias-pretty-version": "1.0.x-dev", - "alias-version": "1.0.9999999.9999999-dev" + "name": "symfony/http-foundation", + "version": "v2.1.3", + "target-dir": "Symfony/Component/HttpFoundation", + "source": { + "type": "git", + "url": "https://github.com/symfony/HttpFoundation", + "reference": "v2.1.3" + }, + "dist": { + "type": "zip", + "url": "https://github.com/symfony/HttpFoundation/zipball/v2.1.3", + "reference": "v2.1.3", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "time": "2012-10-20 00:10:30", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Symfony\\Component\\HttpFoundation": "", + "SessionHandlerInterface": "Symfony/Component/HttpFoundation/Resources/stubs" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "description": "Symfony HttpFoundation Component", + "homepage": "http://symfony.com" }, { - "package": "fabpot/goutte", - "version": "dev-master", - "source-reference": "6d26279344736f6983a969e46afef082ebf30a67", - "commit-date": "1345141401" + "name": "symfony/http-kernel", + "version": "v2.1.3", + "target-dir": "Symfony/Component/HttpKernel", + "source": { + "type": "git", + "url": "https://github.com/symfony/HttpKernel", + "reference": "v2.1.3" + }, + "dist": { + "type": "zip", + "url": "https://github.com/symfony/HttpKernel/zipball/v2.1.3", + "reference": "v2.1.3", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "symfony/event-dispatcher": "2.1.*", + "symfony/http-foundation": "2.1.*" + }, + "require-dev": { + "symfony/browser-kit": "2.1.*", + "symfony/class-loader": "2.1.*", + "symfony/config": "2.1.*", + "symfony/console": "2.1.*", + "symfony/dependency-injection": "2.1.*", + "symfony/finder": "2.1.*", + "symfony/process": "2.1.*", + "symfony/routing": "2.1.*" + }, + "suggest": { + "symfony/browser-kit": "2.1.*", + "symfony/class-loader": "2.1.*", + "symfony/config": "2.1.*", + "symfony/console": "2.1.*", + "symfony/dependency-injection": "2.1.*", + "symfony/finder": "2.1.*" + }, + "time": "2012-10-30 01:14:14", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Symfony\\Component\\HttpKernel": "" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "description": "Symfony HttpKernel Component", + "homepage": "http://symfony.com" }, { - "package": "guzzle/common", - "version": "v2.8.4" + "name": "symfony/routing", + "version": "v2.1.3", + "target-dir": "Symfony/Component/Routing", + "source": { + "type": "git", + "url": "https://github.com/symfony/Routing", + "reference": "v2.1.3" + }, + "dist": { + "type": "zip", + "url": "https://github.com/symfony/Routing/zipball/v2.1.3", + "reference": "v2.1.3", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "symfony/config": "2.1.*", + "symfony/yaml": "2.1.*", + "symfony/http-kernel": "2.1.*", + "doctrine/common": ">=2.2,<2.4-dev" + }, + "suggest": { + "symfony/config": "2.1.*", + "symfony/yaml": "2.1.*", + "doctrine/common": ">=2.2,<2.4-dev" + }, + "time": "2012-10-26 02:26:42", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Symfony\\Component\\Routing": "" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "description": "Symfony Routing Component", + "homepage": "http://symfony.com" }, { - "package": "guzzle/http", - "version": "v2.8.4" + "name": "symfony/yaml", + "version": "v2.1.3", + "target-dir": "Symfony/Component/Yaml", + "source": { + "type": "git", + "url": "https://github.com/symfony/Yaml", + "reference": "v2.1.3" + }, + "dist": { + "type": "zip", + "url": "https://github.com/symfony/Yaml/zipball/v2.1.3", + "reference": "v2.1.3", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "time": "2012-10-29 04:15:41", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Symfony\\Component\\Yaml": "" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "http://symfony.com" + } + ], + "packages-dev": [ + { + "name": "fabpot/goutte", + "version": "v0.1.0", + "source": { + "type": "git", + "url": "https://github.com/fabpot/Goutte", + "reference": "v0.1.0" + }, + "dist": { + "type": "zip", + "url": "https://github.com/fabpot/Goutte/archive/v0.1.0.zip", + "reference": "v0.1.0", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "ext-curl": "*", + "symfony/browser-kit": "2.1.*", + "symfony/css-selector": "2.1.*", + "symfony/dom-crawler": "2.1.*", + "symfony/finder": "2.1.*", + "symfony/process": "2.1.*", + "guzzle/guzzle": "3.0.*" + }, + "time": "2012-12-02 13:44:35", + "type": "application", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "installation-source": "source", + "autoload": { + "psr-0": { + "Goutte": "." + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "A simple PHP Web Scraper", + "homepage": "https://github.com/fabpot/Goutte", + "keywords": [ + "scraper" + ] }, { - "package": "guzzle/parser", - "version": "v2.8.4" + "name": "guzzle/guzzle", + "version": "v3.0.5", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle", + "reference": "v3.0.5" + }, + "dist": { + "type": "zip", + "url": "https://github.com/guzzle/guzzle/archive/v3.0.5.zip", + "reference": "v3.0.5", + "shasum": "" + }, + "require": { + "php": ">=5.3.2", + "ext-curl": "*", + "symfony/event-dispatcher": "2.1.*" + }, + "replace": { + "guzzle/batch": "self.version", + "guzzle/cache": "self.version", + "guzzle/common": "self.version", + "guzzle/http": "self.version", + "guzzle/inflection": "self.version", + "guzzle/iterator": "self.version", + "guzzle/log": "self.version", + "guzzle/parser": "self.version", + "guzzle/plugin": "self.version", + "guzzle/plugin-async": "self.version", + "guzzle/plugin-backoff": "self.version", + "guzzle/plugin-cache": "self.version", + "guzzle/plugin-cookie": "self.version", + "guzzle/plugin-curlauth": "self.version", + "guzzle/plugin-history": "self.version", + "guzzle/plugin-log": "self.version", + "guzzle/plugin-md5": "self.version", + "guzzle/plugin-mock": "self.version", + "guzzle/plugin-oauth": "self.version", + "guzzle/service": "self.version", + "guzzle/stream": "self.version" + }, + "require-dev": { + "doctrine/common": "*", + "symfony/class-loader": "*", + "monolog/monolog": "1.*", + "zendframework/zend-cache": "2.0.*", + "zendframework/zend-log": "2.0.*", + "zend/zend-log1": "1.12", + "zend/zend-cache1": "1.12", + "phpunit/phpunit": "3.7.*" + }, + "time": "2012-11-19 00:15:33", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-0": { + "Guzzle\\Tests": "tests/", + "Guzzle": "src/" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Guzzle Community", + "homepage": "https://github.com/guzzle/guzzle/contributors" + } + ], + "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "framework", + "curl", + "http", + "rest", + "http client", + "client", + "web service" + ] }, { - "package": "symfony/browser-kit", - "version": "v2.1.0-RC1" + "name": "symfony/browser-kit", + "version": "v2.1.3", + "target-dir": "Symfony/Component/BrowserKit", + "source": { + "type": "git", + "url": "https://github.com/symfony/BrowserKit", + "reference": "v2.1.3" + }, + "dist": { + "type": "zip", + "url": "https://github.com/symfony/BrowserKit/zipball/v2.1.3", + "reference": "v2.1.3", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "symfony/dom-crawler": "2.1.*" + }, + "require-dev": { + "symfony/process": "2.1.*", + "symfony/css-selector": "2.1.*" + }, + "suggest": { + "symfony/process": "2.1.*" + }, + "time": "2012-10-25 06:11:50", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Symfony\\Component\\BrowserKit": "" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "description": "Symfony BrowserKit Component", + "homepage": "http://symfony.com" }, { - "package": "symfony/css-selector", - "version": "v2.1.0-RC1" + "name": "symfony/css-selector", + "version": "v2.1.3", + "target-dir": "Symfony/Component/CssSelector", + "source": { + "type": "git", + "url": "https://github.com/symfony/CssSelector", + "reference": "v2.1.3" + }, + "dist": { + "type": "zip", + "url": "https://github.com/symfony/CssSelector/zipball/v2.1.3", + "reference": "v2.1.3", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "time": "2012-10-04 08:17:57", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Symfony\\Component\\CssSelector": "" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "description": "Symfony CssSelector Component", + "homepage": "http://symfony.com" }, { - "package": "symfony/dom-crawler", - "version": "v2.1.0-RC1" + "name": "symfony/dom-crawler", + "version": "v2.1.3", + "target-dir": "Symfony/Component/DomCrawler", + "source": { + "type": "git", + "url": "https://github.com/symfony/DomCrawler", + "reference": "v2.1.3" + }, + "dist": { + "type": "zip", + "url": "https://github.com/symfony/DomCrawler/zipball/v2.1.3", + "reference": "v2.1.3", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "symfony/css-selector": "2.1.*" + }, + "suggest": { + "symfony/css-selector": "2.1.*" + }, + "time": "2012-10-18 14:16:01", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Symfony\\Component\\DomCrawler": "" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "description": "Symfony DomCrawler Component", + "homepage": "http://symfony.com" }, { - "package": "symfony/finder", - "version": "v2.1.0-RC1" + "name": "symfony/finder", + "version": "v2.1.3", + "target-dir": "Symfony/Component/Finder", + "source": { + "type": "git", + "url": "https://github.com/symfony/Finder", + "reference": "v2.1.3" + }, + "dist": { + "type": "zip", + "url": "https://github.com/symfony/Finder/zipball/v2.1.3", + "reference": "v2.1.3", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "time": "2012-10-20 00:10:30", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Symfony\\Component\\Finder": "" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "description": "Symfony Finder Component", + "homepage": "http://symfony.com" }, { - "package": "symfony/process", - "version": "v2.1.0-RC1" + "name": "symfony/process", + "version": "v2.1.3", + "target-dir": "Symfony/Component/Process", + "source": { + "type": "git", + "url": "https://github.com/symfony/Process", + "reference": "v2.1.3" + }, + "dist": { + "type": "zip", + "url": "https://github.com/symfony/Process/zipball/v2.1.3", + "reference": "v2.1.3", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "time": "2012-10-20 00:10:30", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Symfony\\Component\\Process": "" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "description": "Symfony Process Component", + "homepage": "http://symfony.com" } ], "aliases": [ ], "minimum-stability": "beta", - "stability-flags": { - "fabpot/goutte": 20 - } + "stability-flags": [ + + ] } diff --git a/phpBB/config/cron_tasks.yml b/phpBB/config/cron_tasks.yml index 74f57e449d..d1954b1877 100644 --- a/phpBB/config/cron_tasks.yml +++ b/phpBB/config/cron_tasks.yml @@ -6,6 +6,8 @@ services: - %core.php_ext% - @config - @dbal.conn + calls: + - [set_name, [cron.task.core.prune_all_forums]] tags: - { name: cron.task } @@ -16,6 +18,8 @@ services: - %core.php_ext% - @config - @dbal.conn + calls: + - [set_name, [cron.task.core.prune_forum]] tags: - { name: cron.task } @@ -25,6 +29,8 @@ services: - %core.root_path% - %core.php_ext% - @config + calls: + - [set_name, [cron.task.core.queue]] tags: - { name: cron.task } @@ -33,6 +39,8 @@ services: arguments: - @config - @cache.driver + calls: + - [set_name, [cron.task.core.tidy_cache]] tags: - { name: cron.task } @@ -42,6 +50,8 @@ services: - %core.root_path% - %core.php_ext% - @config + calls: + - [set_name, [cron.task.core.tidy_database]] tags: - { name: cron.task } @@ -54,6 +64,8 @@ services: - @config - @dbal.conn - @user + calls: + - [set_name, [cron.task.core.tidy_search]] tags: - { name: cron.task } @@ -62,6 +74,8 @@ services: arguments: - @config - @user + calls: + - [set_name, [cron.task.core.tidy_sessions]] tags: - { name: cron.task } @@ -71,5 +85,7 @@ services: - %core.root_path% - %core.php_ext% - @config + calls: + - [set_name, [cron.task.core.tidy_warnings]] tags: - { name: cron.task } diff --git a/phpBB/config/routing.yml b/phpBB/config/routing.yml new file mode 100644 index 0000000000..d8e890d063 --- /dev/null +++ b/phpBB/config/routing.yml @@ -0,0 +1,9 @@ +# Structure: +# +# foo_controller: +# pattern: /foo +# defaults: { _controller: foo_sevice:method } +# +# The above will be accessed via app.php?controller=foo and it will +# instantiate the "foo_service" service and call the "method" method. +# diff --git a/phpBB/config/services.yml b/phpBB/config/services.yml index 038c8a862d..5c450a5cf6 100644 --- a/phpBB/config/services.yml +++ b/phpBB/config/services.yml @@ -10,6 +10,10 @@ services: class: phpbb_cache_service arguments: - @cache.driver + - @config + - @dbal.conn + - %core.root_path% + - %core.php_ext% cache.driver: class: %cache.driver.class% @@ -44,15 +48,32 @@ services: - @cache.driver - %tables.config% - cron.task_provider: - class: phpbb_cron_task_provider + controller.helper: + class: phpbb_controller_helper arguments: - - @container + - @template + - @user + - %core.root_path% + - .%core.php_ext% + + controller.resolver: + class: phpbb_controller_resolver + arguments: + - @user + - @service_container + - @ext.finder + + cron.task_collection: + class: phpbb_di_service_collection + arguments: + - @service_container + tags: + - { name: service_collection, tag: cron.task } cron.manager: class: phpbb_cron_manager arguments: - - @cron.task_provider + - @cron.task_collection - %core.root_path% - %core.php_ext% @@ -65,6 +86,8 @@ services: dispatcher: class: phpbb_event_dispatcher + arguments: + - @service_container dbal.conn: class: %dbal.driver.class% @@ -89,12 +112,49 @@ services: - .%core.php_ext% - @cache.driver - processor.ext: - class: phpbb_di_processor_ext + ext.finder: + class: phpbb_extension_finder arguments: - @ext.manager + - %core.root_path% + - @cache.driver + - .%core.php_ext% + - _ext_finder + + http_kernel: + class: Symfony\Component\HttpKernel\HttpKernel + arguments: + - @dispatcher + - @controller.resolver + + hook_finder: + class: phpbb_hook_finder + arguments: + - %core.root_path% + - .%core.php_ext% + - @cache.driver + + kernel_request_subscriber: + class: phpbb_event_kernel_request_subscriber + arguments: + - @ext.finder + - %core.root_path% + - .%core.php_ext% tags: - - { name: container.processor } + - { name: kernel.event_subscriber } + + kernel_exception_subscriber: + class: phpbb_event_kernel_exception_subscriber + arguments: + - @template + - @user + tags: + - { name: kernel.event_subscriber } + + kernel_terminate_subscriber: + class: phpbb_event_kernel_terminate_subscriber + tags: + - { name: kernel.event_subscriber } request: class: phpbb_request @@ -131,6 +191,7 @@ services: - @user - @style.resource_locator - @template_context + - @ext.manager template_context: class: phpbb_template_context diff --git a/phpBB/develop/benchmark.php b/phpBB/develop/benchmark.php index c867b9262e..6517954dfe 100644 --- a/phpBB/develop/benchmark.php +++ b/phpBB/develop/benchmark.php @@ -377,7 +377,6 @@ function make_user($username) $viewemail = 0; $aim = 0; $yim = 0; - $msn = 0; $attachsig = 1; $allowsmilies = 1; $allowhtml = 1; @@ -422,8 +421,8 @@ function make_user($username) } - $sql = "INSERT INTO " . USERS_TABLE . " (user_id, username, user_regdate, user_password, user_email, user_icq, user_website, user_occ, user_from, user_interests, user_sig, user_sig_bbcode_uid, user_avatar, user_viewemail, user_aim, user_yim, user_msnm, user_attachsig, user_allowsmilies, user_allowhtml, user_allowbbcode, user_allow_viewonline, user_notify, user_notify_pm, user_timezone, user_dateformat, user_lang, user_style, user_level, user_allow_pm, user_active, user_actkey) - VALUES ($new_user_id, '$username', " . time() . ", '$password', '$email', '$icq', '$website', '$occupation', '$location', '$interests', '$signature', '$signature_bbcode_uid', '$avatar_filename', $viewemail, '$aim', '$yim', '$msn', $attachsig, $allowsmilies, $allowhtml, $allowbbcode, $allowviewonline, $notifyreply, $notifypm, $user_timezone, '$user_dateformat', '$user_lang', $user_style, 0, 1, "; + $sql = "INSERT INTO " . USERS_TABLE . " (user_id, username, user_regdate, user_password, user_email, user_icq, user_website, user_occ, user_from, user_interests, user_sig, user_sig_bbcode_uid, user_avatar, user_viewemail, user_aim, user_yim, user_attachsig, user_allowsmilies, user_allowhtml, user_allowbbcode, user_allow_viewonline, user_notify, user_notify_pm, user_timezone, user_dateformat, user_lang, user_style, user_level, user_allow_pm, user_active, user_actkey) + VALUES ($new_user_id, '$username', " . time() . ", '$password', '$email', '$icq', '$website', '$occupation', '$location', '$interests', '$signature', '$signature_bbcode_uid', '$avatar_filename', $viewemail, '$aim', '$yim', $attachsig, $allowsmilies, $allowhtml, $allowbbcode, $allowviewonline, $notifyreply, $notifypm, $user_timezone, '$user_dateformat', '$user_lang', $user_style, 0, 1, "; $sql .= "1, '')"; diff --git a/phpBB/develop/create_schema_files.php b/phpBB/develop/create_schema_files.php index 3d3e478032..c6012a633f 100644 --- a/phpBB/develop/create_schema_files.php +++ b/phpBB/develop/create_schema_files.php @@ -1520,18 +1520,21 @@ function get_schema_struct() $schema_data['phpbb_reports'] = array( 'COLUMNS' => array( - 'report_id' => array('UINT', NULL, 'auto_increment'), - 'reason_id' => array('USINT', 0), - 'post_id' => array('UINT', 0), - 'pm_id' => array('UINT', 0), - 'user_id' => array('UINT', 0), - 'user_notify' => array('BOOL', 0), - 'report_closed' => array('BOOL', 0), - 'report_time' => array('TIMESTAMP', 0), - 'report_text' => array('MTEXT_UNI', ''), - 'reported_post_text' => array('MTEXT_UNI', ''), - 'reported_post_uid' => array('VCHAR:8', ''), - 'reported_post_bitfield' => array('VCHAR:255', ''), + 'report_id' => array('UINT', NULL, 'auto_increment'), + 'reason_id' => array('USINT', 0), + 'post_id' => array('UINT', 0), + 'pm_id' => array('UINT', 0), + 'user_id' => array('UINT', 0), + 'user_notify' => array('BOOL', 0), + 'report_closed' => array('BOOL', 0), + 'report_time' => array('TIMESTAMP', 0), + 'report_text' => array('MTEXT_UNI', ''), + 'reported_post_text' => array('MTEXT_UNI', ''), + 'reported_post_uid' => array('VCHAR:8', ''), + 'reported_post_bitfield' => array('VCHAR:255', ''), + 'reported_post_enable_magic_url' => array('BOOL', 1), + 'reported_post_enable_smilies' => array('BOOL', 1), + 'reported_post_enable_bbcode' => array('BOOL', 1) ), 'PRIMARY_KEY' => 'report_id', 'KEYS' => array( @@ -1833,7 +1836,6 @@ function get_schema_struct() 'user_icq' => array('VCHAR:15', ''), 'user_aim' => array('VCHAR_UNI', ''), 'user_yim' => array('VCHAR_UNI', ''), - 'user_msnm' => array('VCHAR_UNI', ''), 'user_jabber' => array('VCHAR_UNI', ''), 'user_website' => array('VCHAR_UNI:200', ''), 'user_occ' => array('TEXT_UNI', ''), diff --git a/phpBB/develop/generate_utf_casefold.php b/phpBB/develop/generate_utf_casefold.php index 5b99f3e55e..ad511a6153 100644 --- a/phpBB/develop/generate_utf_casefold.php +++ b/phpBB/develop/generate_utf_casefold.php @@ -111,7 +111,7 @@ function my_var_export($var) * Download a file to the develop/ dir * * @param string $url URL of the file to download -* @return void +* @return null */ function download($url) { diff --git a/phpBB/develop/generate_utf_confusables.php b/phpBB/develop/generate_utf_confusables.php index 027d75b661..763d8ee875 100644 --- a/phpBB/develop/generate_utf_confusables.php +++ b/phpBB/develop/generate_utf_confusables.php @@ -199,7 +199,7 @@ function my_var_export($var) * Download a file to the develop/ dir * * @param string $url URL of the file to download -* @return void +* @return null */ function download($url) { diff --git a/phpBB/develop/generate_utf_tables.php b/phpBB/develop/generate_utf_tables.php index 71a5bea851..e5d907d6a5 100644 --- a/phpBB/develop/generate_utf_tables.php +++ b/phpBB/develop/generate_utf_tables.php @@ -481,7 +481,7 @@ function my_var_export($var) * Download a file to the develop/ dir * * @param string $url URL of the file to download -* @return void +* @return null */ function download($url) { diff --git a/phpBB/develop/mysql_upgrader.php b/phpBB/develop/mysql_upgrader.php index 7f82ebfeab..ca738aabf6 100644 --- a/phpBB/develop/mysql_upgrader.php +++ b/phpBB/develop/mysql_upgrader.php @@ -1265,7 +1265,6 @@ function get_schema_struct() 'user_icq' => array('VCHAR:15', ''), 'user_aim' => array('VCHAR_UNI', ''), 'user_yim' => array('VCHAR_UNI', ''), - 'user_msnm' => array('VCHAR_UNI', ''), 'user_jabber' => array('VCHAR_UNI', ''), 'user_website' => array('VCHAR_UNI:200', ''), 'user_occ' => array('TEXT_UNI', ''), diff --git a/phpBB/develop/utf_normalizer_test.php b/phpBB/develop/utf_normalizer_test.php index 186e10fea2..af8556507f 100644 --- a/phpBB/develop/utf_normalizer_test.php +++ b/phpBB/develop/utf_normalizer_test.php @@ -222,7 +222,7 @@ die("\n\nALL TESTS PASSED SUCCESSFULLY\n"); * Download a file to the develop/ dir * * @param string $url URL of the file to download -* @return void +* @return null */ function download($url) { diff --git a/phpBB/docs/INSTALL.html b/phpBB/docs/INSTALL.html index 07f0cbc8c2..58aeb904c7 100644 --- a/phpBB/docs/INSTALL.html +++ b/phpBB/docs/INSTALL.html @@ -132,7 +132,7 @@ <li>A SQL database system, <strong>one of</strong>: <ul> <li>MySQL 3.23 or above (MySQLi supported)</li> - <li>PostgreSQL 7.3+</li> + <li>PostgreSQL 8.3+</li> <li>SQLite 2.8.2+ (SQLite 3 is not supported)</li> <li>Firebird 2.1+</li> <li>MS SQL Server 2000 or above (directly or via ODBC or the native adapter)</li> diff --git a/phpBB/docs/README.html b/phpBB/docs/README.html index 0e0d3b14fd..164c4a2f55 100644 --- a/phpBB/docs/README.html +++ b/phpBB/docs/README.html @@ -324,11 +324,7 @@ <p>Please remember that running any application on a developmental version of PHP can lead to strange/unexpected results which may appear to be bugs in the application (which may not be true). Therefore we recommend you upgrade to the newest stable version of PHP before running phpBB3. If you are running a developmental version of PHP please check any bugs you find on a system running a stable release before submitting.</p> -<<<<<<< HEAD - <p>This board has been developed and tested under Linux and Windows (amongst others) running Apache using MySQL 3.23, 4.x, 5.x, MSSQL Server 2000, PostgreSQL 8.x, Oracle 8, SQLite and Firebird. Versions of PHP used range from 5.3.x to 5.4.x without problem.</p> -======= - <p>This board has been developed and tested under Linux and Windows (amongst others) running Apache using MySQL 3.23, 4.x, 5.x, MSSQL Server 2000, PostgreSQL 7.x, Oracle 8, SQLite 2 and Firebird. Versions of PHP used range from 4.3.3 to 5.4.x without problem. </p> ->>>>>>> develop-olympus + <p>This board has been developed and tested under Linux and Windows (amongst others) running Apache using MySQL 3.23, 4.x, 5.x, MSSQL Server 2000, PostgreSQL 8.x, Oracle 8, SQLite 2 and Firebird. Versions of PHP used range from 5.3.x to 5.4.x without problem.</p> <a name="phpsec"></a><h3>7.i. Notice on PHP security issues</h3> diff --git a/phpBB/docs/auth_api.html b/phpBB/docs/auth_api.html index 2302140030..249ceebfbc 100644 --- a/phpBB/docs/auth_api.html +++ b/phpBB/docs/auth_api.html @@ -193,7 +193,7 @@ $user_id = 2; $auth->acl_clear_prefetch($user_id); </pre></div> - <p>This method returns void.</p> + <p>This method returns null.</p> <a name="acl_get_list"></a><h3>2.viii. acl_get_list</h3> diff --git a/phpBB/docs/coding-guidelines.html b/phpBB/docs/coding-guidelines.html index 0e3a97c004..14c2281323 100644 --- a/phpBB/docs/coding-guidelines.html +++ b/phpBB/docs/coding-guidelines.html @@ -72,6 +72,7 @@ <ol style="list-style-type: lower-roman;"> <li><a href="#templates">General Templating</a></li> <li><a href="#stylestree">Styles Tree</a></li> + <li><a href="#template-events">Template Events</a></li> </ol></li> <li><a href="#charsets">Character Sets and Encodings</a></li> <li><a href="#translation">Translation (<abbr title="Internationalisation">i18n</abbr>/<abbr title="Localisation">L10n</abbr>) Guidelines</a> @@ -740,7 +741,7 @@ static private function f() <a name="sql"></a><h3>2.iii. SQL/SQL Layout</h3> <h4>Common SQL Guidelines: </h4> - <p>All SQL should be cross-DB compatible, if DB specific SQL is used alternatives must be provided which work on all supported DB's (MySQL3/4/5, MSSQL (7.0 and 2000), PostgreSQL (7.0+), Firebird, SQLite, Oracle8, ODBC (generalised if possible)).</p> + <p>All SQL should be cross-DB compatible, if DB specific SQL is used alternatives must be provided which work on all supported DB's (MySQL3/4/5, MSSQL (7.0 and 2000), PostgreSQL (8.3+), Firebird, SQLite, Oracle8, ODBC (generalised if possible)).</p> <p>All SQL commands should utilise the DataBase Abstraction Layer (DBAL)</p> <h4>SQL code layout:</h4> @@ -1678,6 +1679,57 @@ version = 3.1.0 parent = prosilver </pre></div> + <a name="template-events"></a><h3>4.iii. Template Events</h3> + <p>Template events must follow this format: <code><!-- EVENT event_name --></code></p> + <p>Using the above example, files named <code>event_name.html</code> located within extensions will be injected into the location of the event.</p> + + <h4>Template event naming guidelines:</h4> + <ul> + <li>An event name must be all lowercase, with each word separated by an underscore.</li> + <li>An event name must briefly describe the location and purpose of the event.</li> + <li>An event name must end with one of the following suffixes:</li> + <ul> + <li><code>_prepend</code> - This event adds an item to the beginning of a block of related items, or adds to the beginning of individual items in a block.</li> + <li><code>_append</code> - This event adds an item to the end of a block of related items, or adds to the end of individual items in a block.</li> + <li><code>_before</code> - This event adds content directly before the specified block</li> + <li><code>_after</code> - This event adds content directly after the specified block</li> + </ul> + </ul> + + <h4>Template event documentation</h4> + <p>Events must be documented in <code>phpBB/docs/events.md</code> in alphabetical order based on the event name. The format is as follows:</p> + + <ul><li>An event found in only one template file: + <div class="codebox"><pre>event_name +=== +* Location: styles/<style_name>/template/filename.html +* Purpose: A brief description of what this event should be used for. +This may span multiple lines. +</pre></div></li> + <li>An event found in multiple template files: + <div class="codebox"><pre>event_name +=== +* Locations: + + first/file/path.html + + second/file/path.html +* Purpose: Same as above. +</pre></div> + <li>An event that is found multiple times in a file should have the number of instances in parenthesis next to the filename. + <div class="codebox"><pre>event_name +=== +* Locations: + + first/file/path.html (2) + + second/file/path.html +* Purpose: Same as above. +</pre></div></li> + <li>An actual example event documentation: + <div class="codebox"><pre>forumlist_body_last_post_title_prepend +==== +* Locations: + + styles/prosilver/template/forumlist_body.html + + styles/subsilver2/template/forumlist_body.html +* Purpose: Add content before the post title of the latest post in a forum on the forum list.</pre></div></ul><br /> + </div> <div class="back2top"><a href="#wrap" class="top">Back to Top</a></div> diff --git a/phpBB/docs/events.md b/phpBB/docs/events.md new file mode 100644 index 0000000000..f0b3b81822 --- /dev/null +++ b/phpBB/docs/events.md @@ -0,0 +1,132 @@ +acp_forums_normal_settings_append +=== +* Location: adm/style/acp_forums.html +* Purpose: Add settings to forums + +acp_main_actions_append +=== +* Location: adm/style/acp_main.html +* Purpose: Add actions to the ACP main page below the cache purge action + +acp_main_notice_after +=== +* Location: adm/style/acp_main.html +* Purpose: Add notices or other blocks in the ACP below other configuration notices + +acp_overall_footer_after +=== +* Location: adm/style/overall_footer.html +* Purpose: Add content below the footer in the ACP + +acp_overall_header_head_append +=== +* Location: adm/style/overall_header.html +* Add assets within the `<head>` tags in the ACP + +acp_simple_footer_after +=== +* Location: adm/style/simple_footer.html +* Purpose: Add content below the simple footer in the ACP + +acp_simple_header_head_append +=== +* Location: adm/style/overall_header.html +* Add assets within the `<head>` tags in the simple header of the ACP + +acp_users_overview_options_append +=== +* Location: adm/style/acp_users.html +* Purpose: Add options and settings on user overview page + +forumlist_body_last_post_title_prepend +==== +* Locations: + + styles/prosilver/template/forumlist_body.html + + styles/subsilver2/template/forumlist_body.html +* Purpose: Add content before the post title of the latest post in a forum on the forum list. + +index_body_stat_blocks_before +=== +* Locations: + + styles/prosilver/template/index_body.html + + styles/subsilver2/template/index_body.html +* Purpose: Add new statistic blocks above the Who Is Online and Board Statistics blocks + +overall_footer_after +=== +* Locations: + + styles/prosilver/template/overall_footer.html + + styles/subsilver2/template/overall_footer.html +* Purpose: Add content at the end of the file, directly prior to the `</body>` tag + +overall_footer_breadcrumb_append +=== +* Location: styles/prosilver/template/overall_footer.html +* Purpose: Add links to the list of breadcrumbs in the footer + +overall_footer_copyright_append +=== +* Locations: + + styles/prosilver/template/overall_footer.html + + styles/subsilver2/template/overall_footer.html +* Purpose: Add content after the copyright line (no new line by default), before the ACP link + +overall_footer_copyright_prepend +=== +* Locations: + + styles/prosilver/template/overall_footer.html + + styles/subsilver2/template/overall_footer.html +* Purpose: Add content before the copyright line + +overall_header_breadcrumb_append +=== +* Locations: + + styles/prosilver/template/overall_header.html + + styles/subsilver2/template/breadcrumbs.html +* Purpose: Add links to the list of breadcrumbs in the header + +overall_header_head_append +=== +* Locations: + + styles/prosilver/template/overall_header.html + + styles/subsilver2/template/overall_header.html +* Purpose: Add asset calls directly before the `</head>` tag + +overall_header_navigation_append +=== +* Location: styles/prosilver/template/overall_header.html +* Purpose: Add links after the navigation links in the header + +overall_header_navigation_prepend +=== +* Location: styles/prosilver/template/overall_header.html +* Purpose: Add links before the navigation links in the header + +posting_editor_options_prepend +=== +* Locations: + + styles/prosilver/template/posting_editor.html + + styles/prosilver/template/posting_body.html +* Purpose: Add posting options on the posting screen + +simple_footer_after +=== +* Location: styles/prosilver/template/simple_footer.html +* Purpose: Add content directly prior to the `</body>` tag of the simple footer + +ucp_pm_viewmessage_print_head_append +=== +* Location: styles/prosilver/template/ucp_pm_viewmessage_print.html +* Purpose: Add asset calls directly before the `</head>` tag of the Print PM screen + +viewtopic_print_head_append +=== +* Location: styles/prosilver/template/viewtopic_print.html +* Purpose: Add asset calls directly before the `</head>` tag of the Print Topic screen + +viewtopic_topic_title_prepend +=== +* Locations: + + styles/prosilver/template/viewtopic_body.html + + styles/subsilver2/template/viewtopic_body.html +* Purpose: Add content directly before the topic title link on the View topic screen diff --git a/phpBB/docs/sphinx.sample.conf b/phpBB/docs/sphinx.sample.conf index aa0e8d905d..fcaba6dcf3 100644 --- a/phpBB/docs/sphinx.sample.conf +++ b/phpBB/docs/sphinx.sample.conf @@ -10,21 +10,36 @@ source source_phpbb_{SPHINX_ID}_main sql_query_pre = UPDATE phpbb_sphinx SET max_doc_id = MAX(post_id) WHERE counter_id = 1 sql_query_range = SELECT MIN(post_id), MAX(post_id) FROM phpbb_posts sql_range_step = 5000 - sql_query = SELECT
\ - p.post_id AS id,
\ - p.forum_id,
\ - p.topic_id,
\ - p.poster_id,
\ - CASE WHEN p.post_id = t.topic_first_post_id THEN 1 ELSE 0 END as topic_first_post,
\ - p.post_time,
\ - p.post_subject,
\ - p.post_subject as title,
\ - p.post_text as data,
\ - t.topic_last_post_time,
\ - 0 as deleted
\ - FROM phpbb_posts p, phpbb_topics t
\ - WHERE
\ - p.topic_id = t.topic_id
\ + sql_query = SELECT +\ + p.post_id AS id, +\ + p.forum_id, +\ + p.topic_id, +\ + p.poster_id, +\ + CASE WHEN p.post_id = t.topic_first_post_id THEN 1 ELSE 0 END as topic_first_post, +\ + p.post_time, +\ + p.post_subject, +\ + p.post_subject as title, +\ + p.post_text as data, +\ + t.topic_last_post_time, +\ + 0 as deleted +\ + FROM phpbb_posts p, phpbb_topics t +\ + WHERE +\ + p.topic_id = t.topic_id +\ AND p.post_id >= $start AND p.post_id <= $end sql_query_post = sql_query_post_index = UPDATE phpbb_sphinx SET max_doc_id = $maxid WHERE counter_id = 1 @@ -42,21 +57,36 @@ source source_phpbb_{SPHINX_ID}_delta : source_phpbb_{SPHINX_ID}_main { sql_query_range = sql_range_step = - sql_query = SELECT
\ - p.post_id AS id,
\ - p.forum_id,
\ - p.topic_id,
\ - p.poster_id,
\ - CASE WHEN p.post_id = t.topic_first_post_id THEN 1 ELSE 0 END as topic_first_post,
\ - p.post_time,
\ - p.post_subject,
\ - p.post_subject as title,
\ - p.post_text as data,
\ - t.topic_last_post_time,
\ - 0 as deleted
\ - FROM phpbb_posts p, phpbb_topics t
\ - WHERE
\ - p.topic_id = t.topic_id
\ + sql_query = SELECT +\ + p.post_id AS id, +\ + p.forum_id, +\ + p.topic_id, +\ + p.poster_id, +\ + CASE WHEN p.post_id = t.topic_first_post_id THEN 1 ELSE 0 END as topic_first_post, +\ + p.post_time, +\ + p.post_subject, +\ + p.post_subject as title, +\ + p.post_text as data, +\ + t.topic_last_post_time, +\ + 0 as deleted +\ + FROM phpbb_posts p, phpbb_topics t +\ + WHERE +\ + p.topic_id = t.topic_id +\ AND p.post_id >= ( SELECT max_doc_id FROM phpbb_sphinx WHERE counter_id=1 ) sql_query_pre = } diff --git a/phpBB/download/file.php b/phpBB/download/file.php index 7ed53d54b6..4a392b002d 100644 --- a/phpBB/download/file.php +++ b/phpBB/download/file.php @@ -42,24 +42,24 @@ if (isset($_GET['avatar'])) } require($phpbb_root_path . 'includes/class_loader.' . $phpEx); - require($phpbb_root_path . 'includes/di/processor/interface.' . $phpEx); - require($phpbb_root_path . 'includes/di/processor/config.' . $phpEx); - require($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx); require($phpbb_root_path . 'includes/constants.' . $phpEx); require($phpbb_root_path . 'includes/functions.' . $phpEx); + require($phpbb_root_path . 'includes/functions_container.' . $phpEx); require($phpbb_root_path . 'includes/functions_download' . '.' . $phpEx); require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx); - $phpbb_container = new ContainerBuilder(); - $loader = new YamlFileLoader($phpbb_container, new FileLocator(__DIR__.'/../config')); - $loader->load('services.yml'); + // Setup class loader first + $phpbb_class_loader = new phpbb_class_loader('phpbb_', "{$phpbb_root_path}includes/", ".$phpEx"); + $phpbb_class_loader->register(); + $phpbb_class_loader_ext = new phpbb_class_loader('phpbb_ext_', "{$phpbb_root_path}ext/", ".$phpEx"); + $phpbb_class_loader_ext->register(); - $processor = new phpbb_di_processor_config($phpbb_root_path . 'config.' . $phpEx, $phpbb_root_path, $phpEx); - $processor->process($phpbb_container); + // Set up container + $phpbb_container = phpbb_create_default_container($phpbb_root_path, $phpEx); - $phpbb_class_loader = $phpbb_container->get('class_loader'); - $phpbb_class_loader_ext = $phpbb_container->get('class_loader.ext'); + $phpbb_class_loader->set_cache($phpbb_container->get('cache.driver')); + $phpbb_class_loader_ext->set_cache($phpbb_container->get('cache.driver')); // set up caching $cache = $phpbb_container->get('cache'); @@ -85,13 +85,6 @@ if (isset($_GET['avatar'])) $phpbb_extension_manager = $phpbb_container->get('ext.manager'); $phpbb_subscriber_loader = $phpbb_container->get('event.subscriber_loader'); - $ids = array_keys($phpbb_container->findTaggedServiceIds('container.processor')); - foreach ($ids as $id) - { - $processor = $phpbb_container->get($id); - $processor->process($phpbb_container); - } - // worst-case default $browser = strtolower($request->header('User-Agent', 'msie 6.0')); @@ -392,7 +385,7 @@ else $disallowed[$attach['extension']] = $attach['extension']; continue; } - + $prefix = ''; if ($topic_id) { diff --git a/phpBB/feed.php b/phpBB/feed.php index 58ae251089..0dce22fb0c 100644 --- a/phpBB/feed.php +++ b/phpBB/feed.php @@ -555,12 +555,6 @@ class phpbb_feed_base $forum_ids = array_flip($this->get_moderator_approve_forums()); } - if (!$forum_id) - { - // Global announcement, your a moderator in any forum than it's okay. - return (!empty($forum_ids)) ? true : false; - } - return (isset($forum_ids[$forum_id])) ? true : false; } diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php index c6dbf5eb9c..7e8d5d8388 100644 --- a/phpBB/includes/acp/acp_forums.php +++ b/phpBB/includes/acp/acp_forums.php @@ -206,7 +206,7 @@ class acp_forums ($action != 'edit' || empty($forum_id) || ($auth->acl_get('a_fauth') && $auth->acl_get('a_authusers') && $auth->acl_get('a_authgroups') && $auth->acl_get('a_mauth')))) { copy_forum_permissions($forum_perm_from, $forum_data['forum_id'], ($action == 'edit') ? true : false); - cache_moderators(); + phpbb_cache_moderators($db, $cache, $auth); $copied_permissions = true; } /* Commented out because of questionable UI workflow - re-visit for 3.0.7 @@ -266,7 +266,7 @@ class acp_forums add_log('admin', 'LOG_FORUM_' . strtoupper($action), $row['forum_name'], $move_forum_name); $cache->destroy('sql', FORUMS_TABLE); } - + if ($request->is_ajax()) { $json_response = new phpbb_json_response; @@ -768,7 +768,7 @@ class acp_forums if (!empty($forum_perm_from) && $forum_perm_from != $forum_id) { copy_forum_permissions($forum_perm_from, $forum_id, true); - cache_moderators(); + phpbb_cache_moderators($db, $cache, $auth); $auth->acl_clear_prefetch(); $cache->destroy('sql', FORUMS_TABLE); diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php index d419bc3b99..c44bc1b8a6 100644 --- a/phpBB/includes/acp/acp_main.php +++ b/phpBB/includes/acp/acp_main.php @@ -24,7 +24,7 @@ class acp_main function main($id, $mode) { - global $config, $db, $user, $auth, $template, $request; + global $config, $db, $cache, $user, $auth, $template, $request; global $phpbb_root_path, $phpbb_admin_path, $phpEx; // Show restore permissions notice @@ -129,7 +129,7 @@ class acp_main set_config('record_online_users', 1, true); set_config('record_online_date', time(), true); add_log('admin', 'LOG_RESET_ONLINE'); - + if ($request->is_ajax()) { trigger_error('RESET_ONLINE_SUCCESS'); @@ -184,7 +184,7 @@ class acp_main update_last_username(); add_log('admin', 'LOG_RESYNC_STATS'); - + if ($request->is_ajax()) { trigger_error('RESYNC_STATS_SUCCESS'); @@ -251,7 +251,7 @@ class acp_main } add_log('admin', 'LOG_RESYNC_POSTCOUNTS'); - + if ($request->is_ajax()) { trigger_error('RESYNC_POSTCOUNTS_SUCCESS'); @@ -266,7 +266,7 @@ class acp_main set_config('board_startdate', time() - 1); add_log('admin', 'LOG_RESET_DATE'); - + if ($request->is_ajax()) { trigger_error('RESET_DATE_SUCCESS'); @@ -346,7 +346,7 @@ class acp_main } add_log('admin', 'LOG_RESYNC_POST_MARKING'); - + if ($request->is_ajax()) { trigger_error('RESYNC_POST_MARKING_SUCCESS'); @@ -359,10 +359,10 @@ class acp_main // Clear permissions $auth->acl_clear_prefetch(); - cache_moderators(); + phpbb_cache_moderators($db, $cache, $auth); add_log('admin', 'LOG_PURGE_CACHE'); - + if ($request->is_ajax()) { trigger_error('PURGE_CACHE_SUCCESS'); @@ -413,7 +413,7 @@ class acp_main $db->sql_query($sql); add_log('admin', 'LOG_PURGE_SESSIONS'); - + if ($request->is_ajax()) { trigger_error('PURGE_SESSIONS_SUCCESS'); diff --git a/phpBB/includes/acp/acp_modules.php b/phpBB/includes/acp/acp_modules.php index 8528dc91c4..52a82004e8 100644 --- a/phpBB/includes/acp/acp_modules.php +++ b/phpBB/includes/acp/acp_modules.php @@ -740,15 +740,15 @@ class acp_modules */ function remove_cache_file() { - global $cache; + global $phpbb_container; // Sanitise for future path use, it's escaped as appropriate for queries $p_class = str_replace(array('.', '/', '\\'), '', basename($this->module_class)); - $cache->destroy('_modules_' . $p_class); + $phpbb_container->get('cache.driver')->destroy('_modules_' . $p_class); // Additionally remove sql cache - $cache->destroy('sql', MODULES_TABLE); + $phpbb_container->get('cache.driver')->destroy('sql', MODULES_TABLE); } /** diff --git a/phpBB/includes/acp/acp_permissions.php b/phpBB/includes/acp/acp_permissions.php index dd071074de..a64765f4f5 100644 --- a/phpBB/includes/acp/acp_permissions.php +++ b/phpBB/includes/acp/acp_permissions.php @@ -656,7 +656,7 @@ class acp_permissions */ function set_permissions($mode, $permission_type, &$auth_admin, &$user_id, &$group_id) { - global $user, $auth; + global $db, $cache, $user, $auth; global $request; $psubmit = request_var('psubmit', array(0 => array(0 => 0))); @@ -726,13 +726,13 @@ class acp_permissions // Do we need to recache the moderator lists? if ($permission_type == 'm_') { - cache_moderators(); + phpbb_cache_moderators($db, $cache, $auth); } // Remove users who are now moderators or admins from everyones foes list if ($permission_type == 'm_' || $permission_type == 'a_') { - update_foes($group_id, $user_id); + phpbb_update_foes($db, $auth, $group_id, $user_id); } $this->log_action($mode, 'add', $permission_type, $ug_type, $ug_id, $forum_id); @@ -745,7 +745,7 @@ class acp_permissions */ function set_all_permissions($mode, $permission_type, &$auth_admin, &$user_id, &$group_id) { - global $user, $auth; + global $db, $cache, $user, $auth; global $request; // User or group to be set? @@ -794,13 +794,13 @@ class acp_permissions // Do we need to recache the moderator lists? if ($permission_type == 'm_') { - cache_moderators(); + phpbb_cache_moderators($db, $cache, $auth); } // Remove users who are now moderators or admins from everyones foes list if ($permission_type == 'm_' || $permission_type == 'a_') { - update_foes($group_id, $user_id); + phpbb_update_foes($db, $auth, $group_id, $user_id); } $this->log_action($mode, 'add', $permission_type, $ug_type, $ug_ids, $forum_ids); @@ -858,7 +858,7 @@ class acp_permissions */ function remove_permissions($mode, $permission_type, &$auth_admin, &$user_id, &$group_id, &$forum_id) { - global $user, $db, $auth; + global $user, $db, $cache, $auth; // User or group to be set? $ug_type = (sizeof($user_id)) ? 'user' : 'group'; @@ -874,7 +874,7 @@ class acp_permissions // Do we need to recache the moderator lists? if ($permission_type == 'm_') { - cache_moderators(); + phpbb_cache_moderators($db, $cache, $auth); } $this->log_action($mode, 'del', $permission_type, $ug_type, (($ug_type == 'user') ? $user_id : $group_id), (sizeof($forum_id) ? $forum_id : array(0 => 0))); @@ -952,12 +952,7 @@ class acp_permissions if ($user_id != $user->data['user_id']) { - $sql = 'SELECT user_id, username, user_permissions, user_type - FROM ' . USERS_TABLE . ' - WHERE user_id = ' . $user_id; - $result = $db->sql_query($sql); - $userdata = $db->sql_fetchrow($result); - $db->sql_freeresult($result); + $userdata = $auth->obtain_user_data($user_id); } else { @@ -1172,7 +1167,7 @@ class acp_permissions */ function copy_forum_permissions() { - global $auth, $cache, $template, $user; + global $db, $auth, $cache, $template, $user; $user->add_lang('acp/forums'); @@ -1187,7 +1182,7 @@ class acp_permissions { if (copy_forum_permissions($src, $dest)) { - cache_moderators(); + phpbb_cache_moderators($db, $cache, $auth); $auth->acl_clear_prefetch(); $cache->destroy('sql', FORUMS_TABLE); diff --git a/phpBB/includes/acp/acp_ranks.php b/phpBB/includes/acp/acp_ranks.php index d9ed5b17f1..6b06d03f52 100644 --- a/phpBB/includes/acp/acp_ranks.php +++ b/phpBB/includes/acp/acp_ranks.php @@ -71,7 +71,7 @@ class acp_ranks 'rank_min' => $min_posts, 'rank_image' => htmlspecialchars_decode($rank_image) ); - + if ($rank_id) { $sql = 'UPDATE ' . RANKS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " WHERE rank_id = $rank_id"; @@ -122,7 +122,7 @@ class acp_ranks $cache->destroy('_ranks'); add_log('admin', 'LOG_RANK_REMOVED', $rank_title); - + if ($request->is_ajax()) { $json_response = new phpbb_json_response; @@ -151,7 +151,7 @@ class acp_ranks case 'add': $data = $ranks = $existing_imgs = array(); - + $sql = 'SELECT * FROM ' . RANKS_TABLE . ' ORDER BY rank_min ASC, rank_special ASC'; @@ -209,17 +209,17 @@ class acp_ranks 'RANK_TITLE' => (isset($ranks['rank_title'])) ? $ranks['rank_title'] : '', 'S_FILENAME_LIST' => $filename_list, - 'RANK_IMAGE' => ($edit_img) ? $phpbb_root_path . $config['ranks_path'] . '/' . $edit_img : $phpbb_admin_path . 'images/spacer.gif', + 'RANK_IMAGE' => ($edit_img) ? $phpbb_root_path . $config['ranks_path'] . '/' . $edit_img : htmlspecialchars($phpbb_admin_path) . 'images/spacer.gif', 'S_SPECIAL_RANK' => (isset($ranks['rank_special']) && $ranks['rank_special']) ? true : false, 'MIN_POSTS' => (isset($ranks['rank_min']) && !$ranks['rank_special']) ? $ranks['rank_min'] : 0) ); - + return; break; } - + $template->assign_vars(array( 'U_ACTION' => $this->u_action) ); @@ -241,7 +241,7 @@ class acp_ranks 'U_EDIT' => $this->u_action . '&action=edit&id=' . $row['rank_id'], 'U_DELETE' => $this->u_action . '&action=delete&id=' . $row['rank_id']) - ); + ); } $db->sql_freeresult($result); diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php index db77825ae7..266495972b 100644 --- a/phpBB/includes/acp/acp_styles.php +++ b/phpBB/includes/acp/acp_styles.php @@ -137,11 +137,13 @@ class acp_styles */ protected function action_cache() { + global $db, $cache, $auth; + $this->cache->purge(); // Clear permissions $this->auth->acl_clear_prefetch(); - cache_moderators(); + phpbb_cache_moderators($db, $cache, $auth); add_log('admin', 'LOG_PURGE_CACHE'); diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index 82d8ef5cbb..2bdbf1441a 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -1352,7 +1352,6 @@ class acp_users $data = array( 'icq' => request_var('icq', $user_row['user_icq']), 'aim' => request_var('aim', $user_row['user_aim']), - 'msn' => request_var('msn', $user_row['user_msnm']), 'yim' => request_var('yim', $user_row['user_yim']), 'jabber' => utf8_normalize_nfc(request_var('jabber', $user_row['user_jabber'], true)), 'website' => request_var('website', $user_row['user_website']), @@ -1382,7 +1381,6 @@ class acp_users array('string', true, 3, 15), array('match', true, '#^[0-9]+$#i')), 'aim' => array('string', true, 3, 255), - 'msn' => array('string', true, 5, 255), 'jabber' => array( array('string', true, 5, 255), array('jabber')), @@ -1416,7 +1414,6 @@ class acp_users $sql_ary = array( 'user_icq' => $data['icq'], 'user_aim' => $data['aim'], - 'user_msnm' => $data['msn'], 'user_yim' => $data['yim'], 'user_jabber' => $data['jabber'], 'user_website' => $data['website'], @@ -1469,7 +1466,6 @@ class acp_users 'ICQ' => $data['icq'], 'YIM' => $data['yim'], 'AIM' => $data['aim'], - 'MSN' => $data['msn'], 'JABBER' => $data['jabber'], 'WEBSITE' => $data['website'], 'LOCATION' => $data['location'], diff --git a/phpBB/includes/acp/info/acp_extensions.php b/phpBB/includes/acp/info/acp_extensions.php index f5953fb1dd..03d7059165 100644 --- a/phpBB/includes/acp/info/acp_extensions.php +++ b/phpBB/includes/acp/info/acp_extensions.php @@ -16,10 +16,10 @@ class acp_extensions_info { return array( 'filename' => 'acp_extensions', - 'title' => 'ACP_EXTENSIONS', + 'title' => 'ACP_EXTENSIONS_MANAGEMENT', 'version' => '1.0.0', 'modes' => array( - 'main' => array('title' => 'ACP_EXTENSIONS', 'auth' => 'acl_a_extensions', 'cat' => array('ACP_GENERAL_TASKS')), + 'main' => array('title' => 'ACP_EXTENSIONS', 'auth' => 'acl_a_extensions', 'cat' => array('ACP_EXTENSIONS_MANAGEMENT')), ), ); } diff --git a/phpBB/includes/acp/info/acp_language.php b/phpBB/includes/acp/info/acp_language.php index 85dfb119ea..7f33a22fa6 100644 --- a/phpBB/includes/acp/info/acp_language.php +++ b/phpBB/includes/acp/info/acp_language.php @@ -19,7 +19,7 @@ class acp_language_info 'title' => 'ACP_LANGUAGE', 'version' => '1.0.0', 'modes' => array( - 'lang_packs' => array('title' => 'ACP_LANGUAGE_PACKS', 'auth' => 'acl_a_language', 'cat' => array('ACP_GENERAL_TASKS')), + 'lang_packs' => array('title' => 'ACP_LANGUAGE_PACKS', 'auth' => 'acl_a_language', 'cat' => array('ACP_LANGUAGE')), ), ); } diff --git a/phpBB/includes/auth/auth.php b/phpBB/includes/auth/auth.php index e3bccaf47b..2535247571 100644 --- a/phpBB/includes/auth/auth.php +++ b/phpBB/includes/auth/auth.php @@ -103,6 +103,26 @@ class phpbb_auth } /** + * Retrieves data wanted by acl function from the database for the + * specified user. + * + * @param int $user_id User ID + * @return array User attributes + */ + public function obtain_user_data($user_id) + { + global $db; + + $sql = 'SELECT user_id, username, user_permissions, user_type + FROM ' . USERS_TABLE . ' + WHERE user_id = ' . $user_id; + $result = $db->sql_query($sql); + $user_data = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + return $user_data; + } + + /** * Fill ACL array with relevant bitstrings from user_permissions column * @access private */ @@ -191,7 +211,7 @@ class phpbb_auth /** * Get forums with the specified permission setting - * if the option is prefixed with !, then the result becomes nagated + * if the option is prefixed with !, then the result becomes negated * * @param bool $clean set to true if only values needs to be returned which are set/unset */ diff --git a/phpBB/includes/bbcode.php b/phpBB/includes/bbcode.php index b9ffa8091c..e8681420d4 100644 --- a/phpBB/includes/bbcode.php +++ b/phpBB/includes/bbcode.php @@ -134,7 +134,7 @@ class bbcode $style_resource_locator = new phpbb_style_resource_locator(); $style_path_provider = new phpbb_style_extension_path_provider($phpbb_extension_manager, new phpbb_style_path_provider()); - $template = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, new phpbb_template_context()); + $template = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, new phpbb_template_context(), $phpbb_extension_manager); $style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, $style_path_provider, $template); $style->set_style(); $template->set_filenames(array('bbcode.html' => 'bbcode.html')); diff --git a/phpBB/includes/cache/driver/apc.php b/phpBB/includes/cache/driver/apc.php index dc0144fac3..0516b669c8 100644 --- a/phpBB/includes/cache/driver/apc.php +++ b/phpBB/includes/cache/driver/apc.php @@ -26,7 +26,7 @@ class phpbb_cache_driver_apc extends phpbb_cache_driver_memory /** * Purge cache data * - * @return void + * @return null */ function purge() { diff --git a/phpBB/includes/cache/driver/eaccelerator.php b/phpBB/includes/cache/driver/eaccelerator.php index 7939f043c9..257b90c76e 100644 --- a/phpBB/includes/cache/driver/eaccelerator.php +++ b/phpBB/includes/cache/driver/eaccelerator.php @@ -30,7 +30,7 @@ class phpbb_cache_driver_eaccelerator extends phpbb_cache_driver_memory /** * Purge cache data * - * @return void + * @return null */ function purge() { @@ -47,7 +47,7 @@ class phpbb_cache_driver_eaccelerator extends phpbb_cache_driver_memory /** * Perform cache garbage collection * - * @return void + * @return null */ function tidy() { diff --git a/phpBB/includes/cache/driver/file.php b/phpBB/includes/cache/driver/file.php index f64a9e3ea8..85decbe3e8 100644 --- a/phpBB/includes/cache/driver/file.php +++ b/phpBB/includes/cache/driver/file.php @@ -214,7 +214,12 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base while (($entry = readdir($dir)) !== false) { - if (strpos($entry, 'sql_') !== 0 && strpos($entry, 'data_') !== 0 && strpos($entry, 'ctpl_') !== 0 && strpos($entry, 'tpl_') !== 0) + if (strpos($entry, 'container_') !== 0 && + strpos($entry, 'url_matcher') !== 0 && + strpos($entry, 'sql_') !== 0 && + strpos($entry, 'data_') !== 0 && + strpos($entry, 'ctpl_') !== 0 && + strpos($entry, 'tpl_') !== 0) { continue; } @@ -362,12 +367,10 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base } /** - * Save sql query + * {@inheritDoc} */ - function sql_save($query, $query_result, $ttl) + function sql_save(phpbb_db_driver $db, $query, $query_result, $ttl) { - global $db; - // Remove extra spaces and tabs $query = preg_replace('/[\n\r\s\t]+/', ' ', $query); @@ -383,10 +386,10 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base if ($this->_write('sql_' . md5($query), $this->sql_rowset[$query_id], $ttl + time(), $query)) { - $query_result = $query_id; + return $query_id; } - return $query_id; + return $query_result; } /** @@ -648,10 +651,11 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base $file = "{$this->cache_dir}$filename.$phpEx"; + $lock = new phpbb_lock_flock($file); + $lock->acquire(); + if ($handle = @fopen($file, 'wb')) { - @flock($handle, LOCK_EX); - // File header fwrite($handle, '<' . '?php exit; ?' . '>'); @@ -692,7 +696,6 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base fwrite($handle, $data); } - @flock($handle, LOCK_UN); fclose($handle); if (!function_exists('phpbb_chmod')) @@ -703,10 +706,16 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base phpbb_chmod($file, CHMOD_READ | CHMOD_WRITE); - return true; + $return_value = true; + } + else + { + $return_value = false; } - return false; + $lock->release(); + + return $return_value; } /** diff --git a/phpBB/includes/cache/driver/interface.php b/phpBB/includes/cache/driver/interface.php index 847ba97262..53f684d1c8 100644 --- a/phpBB/includes/cache/driver/interface.php +++ b/phpBB/includes/cache/driver/interface.php @@ -63,42 +63,82 @@ interface phpbb_cache_driver_interface public function destroy($var_name, $table = ''); /** - * Check if a given cache entry exist + * Check if a given cache entry exists */ public function _exists($var_name); /** - * Load cached sql query + * Load result of an SQL query from cache. + * + * @param string $query SQL query + * + * @return int|bool Query ID (integer) if cache contains a rowset + * for the specified query. + * False otherwise. */ public function sql_load($query); /** - * Save sql query + * Save result of an SQL query in cache. + * + * In persistent cache stores, this function stores the query + * result to persistent storage. In other words, there is no need + * to call save() afterwards. + * + * @param phpbb_db_driver $db Database connection + * @param string $query SQL query, should be used for generating storage key + * @param mixed $query_result The result from dbal::sql_query, to be passed to + * dbal::sql_fetchrow to get all rows and store them + * in cache. + * @param int $ttl Time to live, after this timeout the query should + * expire from the cache. + * @return int|mixed If storing in cache succeeded, an integer $query_id + * representing the query should be returned. Otherwise + * the original $query_result should be returned. */ - public function sql_save($query, $query_result, $ttl); + public function sql_save(phpbb_db_driver $db, $query, $query_result, $ttl); /** - * Ceck if a given sql query exist in cache + * Check if result for a given SQL query exists in cache. + * + * @param int $query_id + * @return bool */ public function sql_exists($query_id); /** * Fetch row from cache (database) + * + * @param int $query_id + * @return array|bool The query result if found in the cache, otherwise + * false. */ public function sql_fetchrow($query_id); /** * Fetch a field from the current row of a cached database result (database) + * + * @param int $query_id + * @param $field The name of the column. + * @return string|bool The field of the query result if found in the cache, + * otherwise false. */ public function sql_fetchfield($query_id, $field); /** * Seek a specific row in an a cached database result (database) + * + * @param int $rownum Row to seek to. + * @param int $query_id + * @return bool */ public function sql_rowseek($rownum, $query_id); /** * Free memory used for a cached database result (database) + * + * @param int $query_id + * @return bool */ public function sql_freeresult($query_id); } diff --git a/phpBB/includes/cache/driver/memcache.php b/phpBB/includes/cache/driver/memcache.php index 9fe70f8b44..3fd16b23b0 100644 --- a/phpBB/includes/cache/driver/memcache.php +++ b/phpBB/includes/cache/driver/memcache.php @@ -64,7 +64,7 @@ class phpbb_cache_driver_memcache extends phpbb_cache_driver_memory /** * Unload the cache resources * - * @return void + * @return null */ function unload() { @@ -76,7 +76,7 @@ class phpbb_cache_driver_memcache extends phpbb_cache_driver_memory /** * Purge cache data * - * @return void + * @return null */ function purge() { diff --git a/phpBB/includes/cache/driver/memory.php b/phpBB/includes/cache/driver/memory.php index e0771ab1d3..f77a1df316 100644 --- a/phpBB/includes/cache/driver/memory.php +++ b/phpBB/includes/cache/driver/memory.php @@ -162,7 +162,12 @@ abstract class phpbb_cache_driver_memory extends phpbb_cache_driver_base while (($entry = readdir($dir)) !== false) { - if (strpos($entry, 'sql_') !== 0 && strpos($entry, 'data_') !== 0 && strpos($entry, 'ctpl_') !== 0 && strpos($entry, 'tpl_') !== 0) + if (strpos($entry, 'container_') !== 0 && + strpos($entry, 'url_matcher') !== 0 && + strpos($entry, 'sql_') !== 0 && + strpos($entry, 'data_') !== 0 && + strpos($entry, 'ctpl_') !== 0 && + strpos($entry, 'tpl_') !== 0) { continue; } @@ -278,12 +283,10 @@ abstract class phpbb_cache_driver_memory extends phpbb_cache_driver_base } /** - * Save sql query + * {@inheritDoc} */ - function sql_save($query, $query_result, $ttl) + function sql_save(phpbb_db_driver $db, $query, $query_result, $ttl) { - global $db; - // Remove extra spaces and tabs $query = preg_replace('/[\n\r\s\t]+/', ' ', $query); $hash = md5($query); @@ -294,7 +297,7 @@ abstract class phpbb_cache_driver_memory extends phpbb_cache_driver_base if (!preg_match('/FROM \\(?(`?\\w+`?(?: \\w+)?(?:, ?`?\\w+`?(?: \\w+)?)*)\\)?/', $query, $regs)) { // Bail out if the match fails. - return; + return $query_result; } $tables = array_map('trim', explode(',', $regs[1])); @@ -334,8 +337,6 @@ abstract class phpbb_cache_driver_memory extends phpbb_cache_driver_base $this->_write('sql_' . $hash, $this->sql_rowset[$query_id], $ttl); - $query_result = $query_id; - return $query_id; } diff --git a/phpBB/includes/cache/driver/null.php b/phpBB/includes/cache/driver/null.php index df2c6c026f..2fadc27ba3 100644 --- a/phpBB/includes/cache/driver/null.php +++ b/phpBB/includes/cache/driver/null.php @@ -105,10 +105,11 @@ class phpbb_cache_driver_null extends phpbb_cache_driver_base } /** - * Save sql query + * {@inheritDoc} */ - function sql_save($query, $query_result, $ttl) + function sql_save(phpbb_db_driver $db, $query, $query_result, $ttl) { + return $query_result; } /** diff --git a/phpBB/includes/cache/driver/redis.php b/phpBB/includes/cache/driver/redis.php index a768885962..960735b673 100644 --- a/phpBB/includes/cache/driver/redis.php +++ b/phpBB/includes/cache/driver/redis.php @@ -39,13 +39,39 @@ class phpbb_cache_driver_redis extends phpbb_cache_driver_memory var $redis; + /** + * Creates a redis cache driver. + * + * The following global constants affect operation: + * + * PHPBB_ACM_REDIS_HOST + * PHPBB_ACM_REDIS_PORT + * PHPBB_ACM_REDIS_PASSWORD + * PHPBB_ACM_REDIS_DB + * + * There are no publicly documented constructor parameters. + */ function __construct() { // Call the parent constructor parent::__construct(); $this->redis = new Redis(); - $this->redis->connect(PHPBB_ACM_REDIS_HOST, PHPBB_ACM_REDIS_PORT); + + $args = func_get_args(); + if (!empty($args)) + { + $ok = call_user_func_array(array($this->redis, 'connect'), $args); + } + else + { + $ok = $this->redis->connect(PHPBB_ACM_REDIS_HOST, PHPBB_ACM_REDIS_PORT); + } + + if (!$ok) + { + trigger_error('Could not connect to redis server'); + } if (defined('PHPBB_ACM_REDIS_PASSWORD')) { @@ -74,7 +100,7 @@ class phpbb_cache_driver_redis extends phpbb_cache_driver_memory /** * Unload the cache resources * - * @return void + * @return null */ function unload() { @@ -86,7 +112,7 @@ class phpbb_cache_driver_redis extends phpbb_cache_driver_memory /** * Purge cache data * - * @return void + * @return null */ function purge() { diff --git a/phpBB/includes/cache/driver/wincache.php b/phpBB/includes/cache/driver/wincache.php index fa9eb95f88..58f3b4a581 100644 --- a/phpBB/includes/cache/driver/wincache.php +++ b/phpBB/includes/cache/driver/wincache.php @@ -26,7 +26,7 @@ class phpbb_cache_driver_wincache extends phpbb_cache_driver_memory /** * Purge cache data * - * @return void + * @return null */ function purge() { diff --git a/phpBB/includes/cache/driver/xcache.php b/phpBB/includes/cache/driver/xcache.php index 0b768bdb3e..06c5fafd97 100644 --- a/phpBB/includes/cache/driver/xcache.php +++ b/phpBB/includes/cache/driver/xcache.php @@ -41,7 +41,7 @@ class phpbb_cache_driver_xcache extends phpbb_cache_driver_memory /** * Purge cache data * - * @return void + * @return null */ function purge() { diff --git a/phpBB/includes/cache/service.php b/phpBB/includes/cache/service.php index e63ec6e33a..69c5e0fdd0 100644 --- a/phpBB/includes/cache/service.php +++ b/phpBB/includes/cache/service.php @@ -21,16 +21,57 @@ if (!defined('IN_PHPBB')) */ class phpbb_cache_service { - private $driver; + /** + * Cache driver. + * + * @var phpbb_cache_driver_interface + */ + protected $driver; + + /** + * The config. + * + * @var phpbb_config + */ + protected $config; + + /** + * Database connection. + * + * @var phpbb_db_driver + */ + protected $db; + + /** + * Root path. + * + * @var string + */ + protected $phpbb_root_path; + + /** + * PHP extension. + * + * @var string + */ + protected $php_ext; /** * Creates a cache service around a cache driver * * @param phpbb_cache_driver_interface $driver The cache driver + * @param phpbb_config $config The config + * @param phpbb_db_driver $db Database connection + * @param string $phpbb_root_path Root path + * @param string $php_ext PHP extension */ - public function __construct(phpbb_cache_driver_interface $driver = null) + public function __construct(phpbb_cache_driver_interface $driver, phpbb_config $config, phpbb_db_driver $db, $phpbb_root_path, $php_ext) { $this->set_driver($driver); + $this->config = $config; + $this->db = $db; + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $php_ext; } /** @@ -64,21 +105,19 @@ class phpbb_cache_service */ function obtain_word_list() { - global $db; - if (($censors = $this->driver->get('_word_censors')) === false) { $sql = 'SELECT word, replacement FROM ' . WORDS_TABLE; - $result = $db->sql_query($sql); + $result = $this->db->sql_query($sql); $censors = array(); - while ($row = $db->sql_fetchrow($result)) + while ($row = $this->db->sql_fetchrow($result)) { $censors['match'][] = get_censor_preg_expression($row['word']); $censors['replace'][] = $row['replacement']; } - $db->sql_freeresult($result); + $this->db->sql_freeresult($result); $this->driver->put('_word_censors', $censors); } @@ -93,23 +132,21 @@ class phpbb_cache_service { if (($icons = $this->driver->get('_icons')) === false) { - global $db; - // Topic icons $sql = 'SELECT * FROM ' . ICONS_TABLE . ' ORDER BY icons_order'; - $result = $db->sql_query($sql); + $result = $this->db->sql_query($sql); $icons = array(); - while ($row = $db->sql_fetchrow($result)) + while ($row = $this->db->sql_fetchrow($result)) { $icons[$row['icons_id']]['img'] = $row['icons_url']; $icons[$row['icons_id']]['width'] = (int) $row['icons_width']; $icons[$row['icons_id']]['height'] = (int) $row['icons_height']; $icons[$row['icons_id']]['display'] = (bool) $row['display_on_posting']; } - $db->sql_freeresult($result); + $this->db->sql_freeresult($result); $this->driver->put('_icons', $icons); } @@ -124,15 +161,13 @@ class phpbb_cache_service { if (($ranks = $this->driver->get('_ranks')) === false) { - global $db; - $sql = 'SELECT * FROM ' . RANKS_TABLE . ' ORDER BY rank_min DESC'; - $result = $db->sql_query($sql); + $result = $this->db->sql_query($sql); $ranks = array(); - while ($row = $db->sql_fetchrow($result)) + while ($row = $this->db->sql_fetchrow($result)) { if ($row['rank_special']) { @@ -150,7 +185,7 @@ class phpbb_cache_service ); } } - $db->sql_freeresult($result); + $this->db->sql_freeresult($result); $this->driver->put('_ranks', $ranks); } @@ -169,8 +204,6 @@ class phpbb_cache_service { if (($extensions = $this->driver->get('_extensions')) === false) { - global $db; - $extensions = array( '_allowed_post' => array(), '_allowed_pm' => array(), @@ -181,9 +214,9 @@ class phpbb_cache_service FROM ' . EXTENSIONS_TABLE . ' e, ' . EXTENSION_GROUPS_TABLE . ' g WHERE e.group_id = g.group_id AND (g.allow_group = 1 OR g.allow_in_pm = 1)'; - $result = $db->sql_query($sql); + $result = $this->db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) + while ($row = $this->db->sql_fetchrow($result)) { $extension = strtolower(trim($row['extension'])); @@ -210,7 +243,7 @@ class phpbb_cache_service $extensions['_allowed_pm'][$extension] = 0; } } - $db->sql_freeresult($result); + $this->db->sql_freeresult($result); $this->driver->put('_extensions', $extensions); } @@ -275,9 +308,7 @@ class phpbb_cache_service { if (($bots = $this->driver->get('_bots')) === false) { - global $db; - - switch ($db->sql_layer) + switch ($this->db->sql_layer) { case 'mssql': case 'mssql_odbc': @@ -303,14 +334,14 @@ class phpbb_cache_service ORDER BY LENGTH(bot_agent) DESC'; break; } - $result = $db->sql_query($sql); + $result = $this->db->sql_query($sql); $bots = array(); - while ($row = $db->sql_fetchrow($result)) + while ($row = $this->db->sql_fetchrow($result)) { $bots[] = $row; } - $db->sql_freeresult($result); + $this->db->sql_freeresult($result); $this->driver->put('_bots', $bots); } @@ -323,8 +354,6 @@ class phpbb_cache_service */ function obtain_cfg_items($style) { - global $config, $phpbb_root_path; - $parsed_array = $this->driver->get('_cfg_' . $style['style_path']); if ($parsed_array === false) @@ -332,14 +361,14 @@ class phpbb_cache_service $parsed_array = array(); } - $filename = $phpbb_root_path . 'styles/' . $style['style_path'] . '/style.cfg'; + $filename = $this->phpbb_root_path . 'styles/' . $style['style_path'] . '/style.cfg'; if (!file_exists($filename)) { return $parsed_array; } - if (!isset($parsed_array['filetime']) || (($config['load_tplcompile'] && @filemtime($filename) > $parsed_array['filetime']))) + if (!isset($parsed_array['filetime']) || (($this->config['load_tplcompile'] && @filemtime($filename) > $parsed_array['filetime']))) { // Re-parse cfg file $parsed_array = parse_cfg_file($filename); @@ -358,54 +387,20 @@ class phpbb_cache_service { if (($usernames = $this->driver->get('_disallowed_usernames')) === false) { - global $db; - $sql = 'SELECT disallow_username FROM ' . DISALLOW_TABLE; - $result = $db->sql_query($sql); + $result = $this->db->sql_query($sql); $usernames = array(); - while ($row = $db->sql_fetchrow($result)) + while ($row = $this->db->sql_fetchrow($result)) { $usernames[] = str_replace('%', '.*?', preg_quote(utf8_clean_string($row['disallow_username']), '#')); } - $db->sql_freeresult($result); + $this->db->sql_freeresult($result); $this->driver->put('_disallowed_usernames', $usernames); } return $usernames; } - - /** - * Obtain hooks... - */ - function obtain_hooks() - { - global $phpbb_root_path, $phpEx; - - if (($hook_files = $this->driver->get('_hooks')) === false) - { - $hook_files = array(); - - // Now search for hooks... - $dh = @opendir($phpbb_root_path . 'includes/hooks/'); - - if ($dh) - { - while (($file = readdir($dh)) !== false) - { - if (strpos($file, 'hook_') === 0 && substr($file, -(strlen($phpEx) + 1)) === '.' . $phpEx) - { - $hook_files[] = substr($file, 0, -(strlen($phpEx) + 1)); - } - } - closedir($dh); - } - - $this->driver->put('_hooks', $hook_files); - } - - return $hook_files; - } } diff --git a/phpBB/includes/captcha/captcha_non_gd.php b/phpBB/includes/captcha/captcha_non_gd.php index c2b97423e6..bb5067cafa 100644 --- a/phpBB/includes/captcha/captcha_non_gd.php +++ b/phpBB/includes/captcha/captcha_non_gd.php @@ -118,7 +118,7 @@ class captcha $new_line = ''; $end = strlen($scanline) - ceil($width/2); - for ($i = floor($width/2); $i < $end; $i++) + for ($i = (int) floor($width / 2); $i < $end; $i++) { $pixel = ord($scanline{$i}); diff --git a/phpBB/includes/config/config.php b/phpBB/includes/config/config.php index 12a4a418b2..4b533dd55c 100644 --- a/phpBB/includes/config/config.php +++ b/phpBB/includes/config/config.php @@ -109,7 +109,7 @@ class phpbb_config implements ArrayAccess, IteratorAggregate, Countable * @param String $key The configuration option's name * @param bool $use_cache Whether this variable should be cached or if it * changes too frequently to be efficiently cached - * @return void + * @return null */ public function delete($key, $use_cache = true) { diff --git a/phpBB/includes/config/db.php b/phpBB/includes/config/db.php index 993a764a7f..b18369a479 100644 --- a/phpBB/includes/config/db.php +++ b/phpBB/includes/config/db.php @@ -29,7 +29,7 @@ class phpbb_config_db extends phpbb_config /** * Database connection - * @var dbal + * @var phpbb_db_driver */ protected $db; @@ -42,11 +42,11 @@ class phpbb_config_db extends phpbb_config /** * Creates a configuration container with a default set of values * - * @param dbal $db Database connection + * @param phpbb_db_driver $db Database connection * @param phpbb_cache_driver_interface $cache Cache instance * @param string $table Configuration table name */ - public function __construct(dbal $db, phpbb_cache_driver_interface $cache, $table) + public function __construct(phpbb_db_driver $db, phpbb_cache_driver_interface $cache, $table) { $this->db = $db; $this->cache = $cache; @@ -96,7 +96,7 @@ class phpbb_config_db extends phpbb_config * @param String $key The configuration option's name * @param bool $use_cache Whether this variable should be cached or if it * changes too frequently to be efficiently cached - * @return void + * @return null */ public function delete($key, $use_cache = true) { diff --git a/phpBB/includes/controller/exception.php b/phpBB/includes/controller/exception.php new file mode 100644 index 0000000000..faa8b6b584 --- /dev/null +++ b/phpBB/includes/controller/exception.php @@ -0,0 +1,24 @@ +<?php +/** +* +* @package controller +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Controller exception class +* @package phpBB3 +*/ +class phpbb_controller_exception extends RuntimeException +{ +} diff --git a/phpBB/includes/controller/helper.php b/phpBB/includes/controller/helper.php new file mode 100644 index 0000000000..6cacc8fefa --- /dev/null +++ b/phpBB/includes/controller/helper.php @@ -0,0 +1,117 @@ +<?php +/** +* +* @package controller +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +use Symfony\Component\HttpFoundation\Response; + +/** +* Controller helper class, contains methods that do things for controllers +* @package phpBB3 +*/ +class phpbb_controller_helper +{ + /** + * Template object + * @var phpbb_template + */ + protected $template; + + /** + * User object + * @var phpbb_user + */ + protected $user; + + /** + * phpBB root path + * @var string + */ + protected $phpbb_root_path; + + /** + * PHP extension + * @var string + */ + protected $php_ext; + + /** + * Constructor + * + * @param phpbb_template $template Template object + * @param phpbb_user $user User object + * @param string $phpbb_root_path phpBB root path + * @param string $php_ext PHP extension + */ + public function __construct(phpbb_template $template, phpbb_user $user, $phpbb_root_path, $php_ext) + { + $this->template = $template; + $this->user = $user; + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $php_ext; + } + + /** + * Automate setting up the page and creating the response object. + * + * @param string $handle The template handle to render + * @param string $page_title The title of the page to output + * @param int $status_code The status code to be sent to the page header + * @return Response object containing rendered page + */ + public function render($template_file, $page_title = '', $status_code = 200) + { + page_header($page_title); + + $this->template->set_filenames(array( + 'body' => $template_file, + )); + + page_footer(true, false, false); + + return new Response($this->template->assign_display('body'), $status_code); + } + + /** + * Easily generate a URL + * + * @param array $url_parts Each array element is a 'folder' + * i.e. array('my', 'ext') maps to ./app.php/my/ext + * @param mixed $query The Query string, passed directly into the second + * argument of append_sid() + * @return string A URL that has already been run through append_sid() + */ + public function url(array $url_parts, $query = '') + { + return append_sid($this->phpbb_root_path . implode('/', $url_parts), $query); + } + + /** + * Output an error, effectively the same thing as trigger_error + * + * @param string $message The error message + * @param string $code The error code (e.g. 404, 500, 503, etc.) + * @return Response A Reponse instance + */ + public function error($message, $code = 500) + { + $this->template->assign_vars(array( + 'MESSAGE_TEXT' => $message, + 'MESSAGE_TITLE' => $this->user->lang('INFORMATION'), + )); + + return $this->render('message_body.html', $this->user->lang('INFORMATION'), $code); + } +} diff --git a/phpBB/includes/controller/provider.php b/phpBB/includes/controller/provider.php new file mode 100644 index 0000000000..b2a5b9f6b2 --- /dev/null +++ b/phpBB/includes/controller/provider.php @@ -0,0 +1,82 @@ +<?php +/** +* +* @package controller +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\Routing\Loader\YamlFileLoader; +use Symfony\Component\Config\FileLocator; + +/** +* Controller interface +* @package phpBB3 +*/ +class phpbb_controller_provider +{ + /** + * YAML file(s) containing route information + * @var array + */ + protected $routing_paths; + + /** + * Construct method + * + * @param array() $routing_paths Array of strings containing paths + * to YAML files holding route information + */ + public function __construct($routing_paths = array()) + { + $this->routing_paths = $routing_paths; + } + + /** + * Locate paths containing routing files + * This sets an internal property but does not return the paths. + * + * @return The current instance of this object for method chaining + */ + public function import_paths_from_finder(phpbb_extension_finder $finder) + { + // We hardcode the path to the core config directory + // because the finder cannot find it + $this->routing_paths = array_merge(array('config'), array_map('dirname', array_keys($finder + ->directory('config') + ->prefix('routing') + ->suffix('yml') + ->find() + ))); + + return $this; + } + + /** + * Get a list of controllers and return it + * + * @param string $base_path Base path to prepend to file paths + * @return array Array of controllers and their route information + */ + public function find($base_path = '') + { + $routes = new RouteCollection; + foreach ($this->routing_paths as $path) + { + $loader = new YamlFileLoader(new FileLocator($base_path . $path)); + $routes->addCollection($loader->load('routing.yml')); + } + + return $routes; + } +} diff --git a/phpBB/includes/controller/resolver.php b/phpBB/includes/controller/resolver.php new file mode 100644 index 0000000000..ee469aa9c8 --- /dev/null +++ b/phpBB/includes/controller/resolver.php @@ -0,0 +1,128 @@ +<?php +/** +* +* @package controller +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\HttpFoundation\Request; + +/** +* Controller manager class +* @package phpBB3 +*/ +class phpbb_controller_resolver implements ControllerResolverInterface +{ + /** + * User object + * @var phpbb_user + */ + protected $user; + + /** + * ContainerInterface object + * @var ContainerInterface + */ + protected $container; + + /** + * Construct method + * + * @param phpbb_user $user User Object + * @param ContainerInterface $container ContainerInterface object + */ + public function __construct(phpbb_user $user, ContainerInterface $container) + { + $this->user = $user; + $this->container = $container; + } + + /** + * Load a controller callable + * + * @param Symfony\Component\HttpFoundation\Request $request Symfony Request object + * @return bool|Callable Callable or false + * @throws phpbb_controller_exception + */ + public function getController(Request $request) + { + $controller = $request->attributes->get('_controller'); + + if (!$controller) + { + throw new phpbb_controller_exception($this->user->lang['CONTROLLER_NOT_SPECIFIED']); + } + + // Require a method name along with the service name + if (stripos($controller, ':') === false) + { + throw new phpbb_controller_exception($this->user->lang['CONTROLLER_METHOD_NOT_SPECIFIED']); + } + + list($service, $method) = explode(':', $controller); + + if (!$this->container->has($service)) + { + throw new phpbb_controller_exception($this->user->lang('CONTROLLER_SERVICE_UNDEFINED', $service)); + } + + $controller_object = $this->container->get($service); + + return array($controller_object, $method); + } + + /** + * Dependencies should be specified in the service definition and can be + * then accessed in __construct(). Arguments are sent through the URL path + * and should match the parameters of the method you are using as your + * controller. + * + * @param Symfony\Component\HttpFoundation\Request $request Symfony Request object + * @param mixed $controller A callable (controller class, method) + * @return bool False + * @throws phpbb_controller_exception + */ + public function getArguments(Request $request, $controller) + { + // At this point, $controller contains the object and method name + list($object, $method) = $controller; + $mirror = new ReflectionMethod($object, $method); + + $arguments = array(); + $parameters = $mirror->getParameters(); + $attributes = $request->attributes->all(); + foreach ($parameters as $param) + { + if (array_key_exists($param->name, $attributes)) + { + $arguments[] = $attributes[$param->name]; + } + else if ($param->getClass() && $param->getClass()->isInstance($request)) + { + $arguments[] = $request; + } + else if ($param->isDefaultValueAvailable()) + { + $arguments[] = $param->getDefaultValue(); + } + else + { + throw new phpbb_controller_exception($this->user->lang('CONTROLLER_ARGUMENT_VALUE_MISSING', $param->getPosition() + 1, get_class($object) . ':' . $method, $param->name)); + } + } + + return $arguments; + } +} diff --git a/phpBB/includes/cron/manager.php b/phpBB/includes/cron/manager.php index ccaa4f3764..84c9650830 100644 --- a/phpBB/includes/cron/manager.php +++ b/phpBB/includes/cron/manager.php @@ -54,7 +54,7 @@ class phpbb_cron_manager * * @param array|Traversable $tasks Array of instances of phpbb_cron_task * - * @return void + * @return null */ public function load_tasks($tasks) { diff --git a/phpBB/includes/cron/task/core/prune_all_forums.php b/phpBB/includes/cron/task/core/prune_all_forums.php index 252e16e57d..2c5d38cec0 100644 --- a/phpBB/includes/cron/task/core/prune_all_forums.php +++ b/phpBB/includes/cron/task/core/prune_all_forums.php @@ -37,9 +37,9 @@ class phpbb_cron_task_core_prune_all_forums extends phpbb_cron_task_base * @param string $phpbb_root_path The root path * @param string $php_ext The PHP extension * @param phpbb_config $config The config - * @param dbal $db The db connection + * @param phpbb_db_driver $db The db connection */ - public function __construct($phpbb_root_path, $php_ext, phpbb_config $config, dbal $db) + public function __construct($phpbb_root_path, $php_ext, phpbb_config $config, phpbb_db_driver $db) { $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; @@ -50,7 +50,7 @@ class phpbb_cron_task_core_prune_all_forums extends phpbb_cron_task_base /** * Runs this cron task. * - * @return void + * @return null */ public function run() { diff --git a/phpBB/includes/cron/task/core/prune_forum.php b/phpBB/includes/cron/task/core/prune_forum.php index 41d60af921..e3c497f072 100644 --- a/phpBB/includes/cron/task/core/prune_forum.php +++ b/phpBB/includes/cron/task/core/prune_forum.php @@ -47,9 +47,9 @@ class phpbb_cron_task_core_prune_forum extends phpbb_cron_task_base implements p * @param string $phpbb_root_path The root path * @param string $php_ext The PHP extension * @param phpbb_config $config The config - * @param dbal $db The db connection + * @param phpbb_db_driver $db The db connection */ - public function __construct($phpbb_root_path, $php_ext, phpbb_config $config, dbal $db) + public function __construct($phpbb_root_path, $php_ext, phpbb_config $config, phpbb_db_driver $db) { $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; @@ -70,7 +70,7 @@ class phpbb_cron_task_core_prune_forum extends phpbb_cron_task_base implements p /** * Runs this cron task. * - * @return void + * @return null */ public function run() { @@ -138,7 +138,7 @@ class phpbb_cron_task_core_prune_forum extends phpbb_cron_task_base implements p * * @param phpbb_request_interface $request Request object. * - * @return void + * @return null */ public function parse_parameters(phpbb_request_interface $request) { diff --git a/phpBB/includes/cron/task/core/queue.php b/phpBB/includes/cron/task/core/queue.php index c765660906..732f9c6bea 100644 --- a/phpBB/includes/cron/task/core/queue.php +++ b/phpBB/includes/cron/task/core/queue.php @@ -43,7 +43,7 @@ class phpbb_cron_task_core_queue extends phpbb_cron_task_base /** * Runs this cron task. * - * @return void + * @return null */ public function run() { diff --git a/phpBB/includes/cron/task/core/tidy_cache.php b/phpBB/includes/cron/task/core/tidy_cache.php index 6017eea561..16a45dae7c 100644 --- a/phpBB/includes/cron/task/core/tidy_cache.php +++ b/phpBB/includes/cron/task/core/tidy_cache.php @@ -40,7 +40,7 @@ class phpbb_cron_task_core_tidy_cache extends phpbb_cron_task_base /** * Runs this cron task. * - * @return void + * @return null */ public function run() { diff --git a/phpBB/includes/cron/task/core/tidy_database.php b/phpBB/includes/cron/task/core/tidy_database.php index 1d256f964f..b882e7b500 100644 --- a/phpBB/includes/cron/task/core/tidy_database.php +++ b/phpBB/includes/cron/task/core/tidy_database.php @@ -43,7 +43,7 @@ class phpbb_cron_task_core_tidy_database extends phpbb_cron_task_base /** * Runs this cron task. * - * @return void + * @return null */ public function run() { diff --git a/phpBB/includes/cron/task/core/tidy_search.php b/phpBB/includes/cron/task/core/tidy_search.php index 2e5f3d79d5..3ec25aa021 100644 --- a/phpBB/includes/cron/task/core/tidy_search.php +++ b/phpBB/includes/cron/task/core/tidy_search.php @@ -38,10 +38,10 @@ class phpbb_cron_task_core_tidy_search extends phpbb_cron_task_base * @param string $php_ext The PHP extension * @param phpbb_auth $auth The auth * @param phpbb_config $config The config - * @param dbal $db The db connection + * @param phpbb_db_driver $db The db connection * @param phpbb_user $user The user */ - public function __construct($phpbb_root_path, $php_ext, phpbb_auth $auth, phpbb_config $config, dbal $db, phpbb_user $user) + public function __construct($phpbb_root_path, $php_ext, phpbb_auth $auth, phpbb_config $config, phpbb_db_driver $db, phpbb_user $user) { $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; @@ -54,7 +54,7 @@ class phpbb_cron_task_core_tidy_search extends phpbb_cron_task_base /** * Runs this cron task. * - * @return void + * @return null */ public function run() { diff --git a/phpBB/includes/cron/task/core/tidy_sessions.php b/phpBB/includes/cron/task/core/tidy_sessions.php index 13531aa30b..95f55235c9 100644 --- a/phpBB/includes/cron/task/core/tidy_sessions.php +++ b/phpBB/includes/cron/task/core/tidy_sessions.php @@ -40,7 +40,7 @@ class phpbb_cron_task_core_tidy_sessions extends phpbb_cron_task_base /** * Runs this cron task. * - * @return void + * @return null */ public function run() { diff --git a/phpBB/includes/cron/task/core/tidy_warnings.php b/phpBB/includes/cron/task/core/tidy_warnings.php index 8dd0674fe5..2a7798e56e 100644 --- a/phpBB/includes/cron/task/core/tidy_warnings.php +++ b/phpBB/includes/cron/task/core/tidy_warnings.php @@ -45,7 +45,7 @@ class phpbb_cron_task_core_tidy_warnings extends phpbb_cron_task_base /** * Runs this cron task. * - * @return void + * @return null */ public function run() { diff --git a/phpBB/includes/cron/task/parametrized.php b/phpBB/includes/cron/task/parametrized.php index 0714b2e701..5f0e46eafc 100644 --- a/phpBB/includes/cron/task/parametrized.php +++ b/phpBB/includes/cron/task/parametrized.php @@ -46,7 +46,7 @@ interface phpbb_cron_task_parametrized extends phpbb_cron_task * * @param phpbb_request_interface $request Request object. * - * @return void + * @return null */ public function parse_parameters(phpbb_request_interface $request); } diff --git a/phpBB/includes/cron/task/provider.php b/phpBB/includes/cron/task/provider.php deleted file mode 100644 index 134723ebd1..0000000000 --- a/phpBB/includes/cron/task/provider.php +++ /dev/null @@ -1,59 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @copyright (c) 2011 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -use Symfony\Component\DependencyInjection\TaggedContainerInterface; - -/** -* Provides cron manager with tasks -* -* Finds installed cron tasks and makes them available to the cron manager. -* -* @package phpBB3 -*/ -class phpbb_cron_task_provider implements IteratorAggregate -{ - private $container; - - public function __construct(TaggedContainerInterface $container) - { - $this->container = $container; - } - - /** - * Retrieve an iterator over all items - * - * @return ArrayIterator An iterator for the array of cron tasks - */ - public function getIterator() - { - $definitions = $this->container->findTaggedServiceIds('cron.task'); - - $tasks = array(); - foreach ($definitions as $name => $definition) - { - $task = $this->container->get($name); - if ($task instanceof phpbb_cron_task_base) - { - $task->set_name($name); - } - - $tasks[] = $task; - } - - return new ArrayIterator($tasks); - } -} diff --git a/phpBB/includes/cron/task/task.php b/phpBB/includes/cron/task/task.php index 7b08fed413..2d585df96d 100644 --- a/phpBB/includes/cron/task/task.php +++ b/phpBB/includes/cron/task/task.php @@ -31,7 +31,7 @@ interface phpbb_cron_task /** * Runs this cron task. * - * @return void + * @return null */ public function run(); diff --git a/phpBB/includes/db/db_tools.php b/phpBB/includes/db/db_tools.php index 6df3aac9ce..2bb016cebd 100644 --- a/phpBB/includes/db/db_tools.php +++ b/phpBB/includes/db/db_tools.php @@ -300,7 +300,7 @@ class phpbb_db_tools /** * Constructor. Set DB Object and set {@link $return_statements return_statements}. * - * @param phpbb_dbal $db DBAL object + * @param phpbb_db_driver $db Database connection * @param bool $return_statements True if only statements should be returned and no SQL being executed */ function phpbb_db_tools(&$db, $return_statements = false) diff --git a/phpBB/includes/db/dbal.php b/phpBB/includes/db/driver/driver.php index ef1dd7d14d..8dda94bc2c 100644 --- a/phpBB/includes/db/dbal.php +++ b/phpBB/includes/db/driver/driver.php @@ -19,7 +19,7 @@ if (!defined('IN_PHPBB')) * Database Abstraction Layer * @package dbal */ -class dbal +class phpbb_db_driver { var $db_connect_id; var $query_result; @@ -72,17 +72,17 @@ class dbal /** * Constructor */ - function dbal() + function __construct() { $this->num_queries = array( - 'cached' => 0, - 'normal' => 0, - 'total' => 0, + 'cached' => 0, + 'normal' => 0, + 'total' => 0, ); // Fill default sql layer based on the class being called. // This can be changed by the specified layer itself later if needed. - $this->sql_layer = substr(get_class($this), 5); + $this->sql_layer = substr(get_class($this), strlen('phpbb_db_driver_')); // Do not change this please! This variable is used to easy the use of it - and is hardcoded. $this->any_char = chr(0) . '%'; @@ -206,7 +206,7 @@ class dbal $query_id = $this->query_result; } - if ($cache->sql_exists($query_id)) + if ($cache && $cache->sql_exists($query_id)) { return $cache->sql_rowseek($rownum, $query_id); } @@ -256,7 +256,7 @@ class dbal $this->sql_rowseek($rownum, $query_id); } - if (!is_object($query_id) && $cache->sql_exists($query_id)) + if ($cache && !is_object($query_id) && $cache->sql_exists($query_id)) { return $cache->sql_fetchfield($query_id, $field); } @@ -822,7 +822,7 @@ class dbal */ function sql_report($mode, $query = '') { - global $cache, $starttime, $phpbb_root_path, $user; + global $cache, $starttime, $phpbb_root_path, $phpbb_admin_path, $user; global $request; if (is_object($request) && !$request->variable('explain', false)) @@ -852,7 +852,7 @@ class dbal <head> <meta charset="utf-8"> <title>SQL Report</title> - <link href="' . $phpbb_root_path . 'adm/style/admin.css" rel="stylesheet" type="text/css" media="screen" /> + <link href="' . htmlspecialchars($phpbb_admin_path) . 'style/admin.css" rel="stylesheet" type="text/css" media="screen" /> </head> <body id="errorpage"> <div id="wrap"> @@ -1042,8 +1042,3 @@ class dbal return $rows_total; } } - -/** -* This variable holds the class name to use later -*/ -$sql_db = (!empty($dbms)) ? 'dbal_' . basename($dbms) : 'dbal'; diff --git a/phpBB/includes/db/firebird.php b/phpBB/includes/db/driver/firebird.php index 5728eb901c..787c28b812 100644 --- a/phpBB/includes/db/firebird.php +++ b/phpBB/includes/db/driver/firebird.php @@ -15,14 +15,12 @@ if (!defined('IN_PHPBB')) exit; } -include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); - /** * Firebird/Interbase Database Abstraction Layer * Minimum Requirement is Firebird 2.1 * @package dbal */ -class dbal_firebird extends dbal +class phpbb_db_driver_firebird extends phpbb_db_driver { var $last_query_text = ''; var $service_handle = false; @@ -156,7 +154,7 @@ class dbal_firebird extends dbal } $this->last_query_text = $query; - $this->query_result = ($cache_ttl) ? $cache->sql_load($query) : false; + $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; $this->sql_add_num_queries($this->query_result); if ($this->query_result === false) @@ -269,10 +267,10 @@ class dbal_firebird extends dbal } } - if ($cache_ttl) + if ($cache && $cache_ttl) { $this->open_queries[(int) $this->query_result] = $this->query_result; - $this->query_result = $cache->sql_save($query, $this->query_result, $cache_ttl); + $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl); } else if (strpos($query, 'SELECT') === 0 && $this->query_result) { @@ -332,7 +330,7 @@ class dbal_firebird extends dbal $query_id = $this->query_result; } - if ($cache->sql_exists($query_id)) + if ($cache && $cache->sql_exists($query_id)) { return $cache->sql_fetchrow($query_id); } @@ -398,7 +396,7 @@ class dbal_firebird extends dbal $query_id = $this->query_result; } - if ($cache->sql_exists($query_id)) + if ($cache && $cache->sql_exists($query_id)) { return $cache->sql_freeresult($query_id); } diff --git a/phpBB/includes/db/mssql.php b/phpBB/includes/db/driver/mssql.php index 1ec8517308..89c2c2351b 100644 --- a/phpBB/includes/db/mssql.php +++ b/phpBB/includes/db/driver/mssql.php @@ -15,20 +15,26 @@ if (!defined('IN_PHPBB')) exit; } -include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); - /** * MSSQL Database Abstraction Layer * Minimum Requirement is MSSQL 2000+ * @package dbal */ -class dbal_mssql extends dbal +class phpbb_db_driver_mssql extends phpbb_db_driver { + var $connect_error = ''; + /** * Connect to server */ function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) { + if (!function_exists('mssql_connect')) + { + $this->connect_error = 'mssql_connect function does not exist, is mssql extension installed?'; + return $this->sql_error(''); + } + $this->persistency = $persistency; $this->user = $sqluser; $this->dbname = $database; @@ -144,7 +150,7 @@ class dbal_mssql extends dbal $this->sql_report('start', $query); } - $this->query_result = ($cache_ttl) ? $cache->sql_load($query) : false; + $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; $this->sql_add_num_queries($this->query_result); if ($this->query_result === false) @@ -159,10 +165,10 @@ class dbal_mssql extends dbal $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($query, $this->query_result, $cache_ttl); + $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl); } else if (strpos($query, 'SELECT') === 0 && $this->query_result) { @@ -234,7 +240,7 @@ class dbal_mssql extends dbal $query_id = $this->query_result; } - if ($cache->sql_exists($query_id)) + if ($cache && $cache->sql_exists($query_id)) { return $cache->sql_fetchrow($query_id); } @@ -271,7 +277,7 @@ class dbal_mssql extends dbal $query_id = $this->query_result; } - if ($cache->sql_exists($query_id)) + if ($cache && $cache->sql_exists($query_id)) { return $cache->sql_rowseek($rownum, $query_id); } @@ -310,7 +316,7 @@ class dbal_mssql extends dbal $query_id = $this->query_result; } - if ($cache->sql_exists($query_id)) + if ($cache && $cache->sql_exists($query_id)) { return $cache->sql_freeresult($query_id); } @@ -355,34 +361,44 @@ class dbal_mssql extends dbal */ function _sql_error() { - $error = array( - 'message' => @mssql_get_last_message(), - 'code' => '' - ); - - // Get error code number - $result_id = @mssql_query('SELECT @@ERROR as code', $this->db_connect_id); - if ($result_id) + if (function_exists('mssql_get_last_message')) { - $row = @mssql_fetch_assoc($result_id); - $error['code'] = $row['code']; - @mssql_free_result($result_id); - } + $error = array( + 'message' => @mssql_get_last_message(), + 'code' => '', + ); - // Get full error message if possible - $sql = 'SELECT CAST(description as varchar(255)) as message - FROM master.dbo.sysmessages - WHERE error = ' . $error['code']; - $result_id = @mssql_query($sql); - - if ($result_id) - { - $row = @mssql_fetch_assoc($result_id); - if (!empty($row['message'])) + // Get error code number + $result_id = @mssql_query('SELECT @@ERROR as code', $this->db_connect_id); + if ($result_id) { - $error['message'] .= '<br />' . $row['message']; + $row = @mssql_fetch_assoc($result_id); + $error['code'] = $row['code']; + @mssql_free_result($result_id); } - @mssql_free_result($result_id); + + // Get full error message if possible + $sql = 'SELECT CAST(description as varchar(255)) as message + FROM master.dbo.sysmessages + WHERE error = ' . $error['code']; + $result_id = @mssql_query($sql); + + if ($result_id) + { + $row = @mssql_fetch_assoc($result_id); + if (!empty($row['message'])) + { + $error['message'] .= '<br />' . $row['message']; + } + @mssql_free_result($result_id); + } + } + else + { + $error = array( + 'message' => $this->connect_error, + 'code' => '', + ); } return $error; diff --git a/phpBB/includes/db/mssql_odbc.php b/phpBB/includes/db/driver/mssql_odbc.php index 7c1ffbc808..f7834443eb 100644 --- a/phpBB/includes/db/mssql_odbc.php +++ b/phpBB/includes/db/driver/mssql_odbc.php @@ -15,8 +15,6 @@ if (!defined('IN_PHPBB')) exit; } -include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); - /** * Unified ODBC functions * Unified ODBC functions support any database having ODBC driver, for example Adabas D, IBM DB2, iODBC, Solid, Sybase SQL Anywhere... @@ -28,9 +26,10 @@ include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); * * @package dbal */ -class dbal_mssql_odbc extends dbal +class phpbb_db_driver_mssql_odbc extends phpbb_db_driver { var $last_query_text = ''; + var $connect_error = ''; /** * Connect to server @@ -67,7 +66,24 @@ class dbal_mssql_odbc extends dbal @ini_set('odbc.defaultlrl', $max_size); } - $this->db_connect_id = ($this->persistency) ? @odbc_pconnect($this->server, $this->user, $sqlpassword) : @odbc_connect($this->server, $this->user, $sqlpassword); + if ($this->persistency) + { + if (!function_exists('odbc_pconnect')) + { + $this->connect_error = 'odbc_pconnect function does not exist, is odbc extension installed?'; + return $this->sql_error(''); + } + $this->db_connect_id = @odbc_pconnect($this->server, $this->user, $sqlpassword); + } + else + { + if (!function_exists('odbc_connect')) + { + $this->connect_error = 'odbc_connect function does not exist, is odbc extension installed?'; + return $this->sql_error(''); + } + $this->db_connect_id = @odbc_connect($this->server, $this->user, $sqlpassword); + } return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error(''); } @@ -163,7 +179,7 @@ class dbal_mssql_odbc extends dbal } $this->last_query_text = $query; - $this->query_result = ($cache_ttl) ? $cache->sql_load($query) : false; + $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; $this->sql_add_num_queries($this->query_result); if ($this->query_result === false) @@ -178,10 +194,10 @@ class dbal_mssql_odbc extends dbal $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($query, $this->query_result, $cache_ttl); + $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl); } else if (strpos($query, 'SELECT') === 0 && $this->query_result) { @@ -254,7 +270,7 @@ class dbal_mssql_odbc extends dbal $query_id = $this->query_result; } - if ($cache->sql_exists($query_id)) + if ($cache && $cache->sql_exists($query_id)) { return $cache->sql_fetchrow($query_id); } @@ -295,7 +311,7 @@ class dbal_mssql_odbc extends dbal $query_id = $this->query_result; } - if ($cache->sql_exists($query_id)) + if ($cache && $cache->sql_exists($query_id)) { return $cache->sql_freeresult($query_id); } @@ -349,10 +365,22 @@ class dbal_mssql_odbc extends dbal */ function _sql_error() { - return array( - 'message' => @odbc_errormsg(), - 'code' => @odbc_error() - ); + if (function_exists('odbc_errormsg')) + { + $error = array( + 'message' => @odbc_errormsg(), + 'code' => @odbc_error(), + ); + } + else + { + $error = array( + 'message' => $this->connect_error, + 'code' => '', + ); + } + + return $error; } /** diff --git a/phpBB/includes/db/mssqlnative.php b/phpBB/includes/db/driver/mssqlnative.php index e9191fae8a..656cbd2437 100644 --- a/phpBB/includes/db/mssqlnative.php +++ b/phpBB/includes/db/driver/mssqlnative.php @@ -19,8 +19,6 @@ if (!defined('IN_PHPBB')) exit; } -include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); - /** * Prior to version 1.1 the SQL Server Native PHP driver didn't support sqlsrv_num_rows, or cursor based seeking so we recall all rows into an array * and maintain our own cursor index into that array. @@ -193,21 +191,23 @@ class result_mssqlnative /** * @package dbal */ -class dbal_mssqlnative extends dbal +class phpbb_db_driver_mssqlnative extends phpbb_db_driver { var $m_insert_id = NULL; var $last_query_text = ''; var $query_options = array(); + var $connect_error = ''; /** * Connect to server */ function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) { - # Test for driver support, to avoid suppressed fatal error + // Test for driver support, to avoid suppressed fatal error if (!function_exists('sqlsrv_connect')) { - trigger_error('Native MS SQL Server driver for PHP is missing or needs to be updated. Version 1.1 or later is required to install phpBB3. You can download the driver from: http://www.microsoft.com/sqlserver/2005/en/us/PHP-Driver.aspx\n', E_USER_ERROR); + $this->connect_error = 'Native MS SQL Server driver for PHP is missing or needs to be updated. Version 1.1 or later is required to install phpBB3. You can download the driver from: http://www.microsoft.com/sqlserver/2005/en/us/PHP-Driver.aspx'; + return $this->sql_error(''); } //set up connection variables @@ -317,7 +317,7 @@ class dbal_mssqlnative extends dbal } $this->last_query_text = $query; - $this->query_result = ($cache_ttl) ? $cache->sql_load($query) : false; + $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; $this->sql_add_num_queries($this->query_result); if ($this->query_result === false) @@ -337,7 +337,7 @@ class dbal_mssqlnative extends dbal if ($cache_ttl) { $this->open_queries[(int) $this->query_result] = $this->query_result; - $this->query_result = $cache->sql_save($query, $this->query_result, $cache_ttl); + $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl); } else if (strpos($query, 'SELECT') === 0 && $this->query_result) { @@ -521,31 +521,43 @@ class dbal_mssqlnative extends dbal */ function _sql_error() { - $errors = @sqlsrv_errors(SQLSRV_ERR_ERRORS); - $error_message = ''; - $code = 0; - - if ($errors != null) + if (function_exists('sqlsrv_errors')) { - foreach ($errors as $error) + $errors = @sqlsrv_errors(SQLSRV_ERR_ERRORS); + $error_message = ''; + $code = 0; + + if ($errors != null) { - $error_message .= "SQLSTATE: ".$error[ 'SQLSTATE']."\n"; - $error_message .= "code: ".$error[ 'code']."\n"; - $code = $error['code']; - $error_message .= "message: ".$error[ 'message']."\n"; + foreach ($errors as $error) + { + $error_message .= "SQLSTATE: " . $error[ 'SQLSTATE'] . "\n"; + $error_message .= "code: " . $error[ 'code'] . "\n"; + $code = $error['code']; + $error_message .= "message: " . $error[ 'message'] . "\n"; + } + $this->last_error_result = $error_message; + $error = $this->last_error_result; } - $this->last_error_result = $error_message; - $error = $this->last_error_result; + else + { + $error = (isset($this->last_error_result) && $this->last_error_result) ? $this->last_error_result : array(); + } + + $error = array( + 'message' => $error, + 'code' => $code, + ); } else { - $error = (isset($this->last_error_result) && $this->last_error_result) ? $this->last_error_result : array(); + $error = array( + 'message' => $this->connect_error, + 'code' => '', + ); } - return array( - 'message' => $error, - 'code' => $code, - ); + return $error; } /** diff --git a/phpBB/includes/db/mysql.php b/phpBB/includes/db/driver/mysql.php index f685ab055c..9de7283a42 100644 --- a/phpBB/includes/db/mysql.php +++ b/phpBB/includes/db/driver/mysql.php @@ -15,8 +15,6 @@ if (!defined('IN_PHPBB')) exit; } -include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); - /** * MySQL4 Database Abstraction Layer * Compatible with: @@ -26,9 +24,10 @@ include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); * MySQL 5.0+ * @package dbal */ -class dbal_mysql extends dbal +class phpbb_db_driver_mysql extends phpbb_db_driver { var $multi_insert = true; + var $connect_error = ''; /** * Connect to server @@ -43,7 +42,24 @@ class dbal_mysql extends dbal $this->sql_layer = 'mysql4'; - $this->db_connect_id = ($this->persistency) ? @mysql_pconnect($this->server, $this->user, $sqlpassword) : @mysql_connect($this->server, $this->user, $sqlpassword, $new_link); + if ($this->persistency) + { + if (!function_exists('mysql_pconnect')) + { + $this->connect_error = 'mysql_pconnect function does not exist, is mysql extension installed?'; + return $this->sql_error(''); + } + $this->db_connect_id = @mysql_pconnect($this->server, $this->user, $sqlpassword); + } + else + { + if (!function_exists('mysql_connect')) + { + $this->connect_error = 'mysql_connect function does not exist, is mysql extension installed?'; + return $this->sql_error(''); + } + $this->db_connect_id = @mysql_connect($this->server, $this->user, $sqlpassword, $new_link); + } if ($this->db_connect_id && $this->dbname != '') { @@ -172,7 +188,7 @@ class dbal_mysql extends dbal $this->sql_report('start', $query); } - $this->query_result = ($cache_ttl) ? $cache->sql_load($query) : false; + $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; $this->sql_add_num_queries($this->query_result); if ($this->query_result === false) @@ -187,10 +203,10 @@ class dbal_mysql extends dbal $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($query, $this->query_result, $cache_ttl); + $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl); } else if (strpos($query, 'SELECT') === 0 && $this->query_result) { @@ -249,7 +265,7 @@ class dbal_mysql extends dbal $query_id = $this->query_result; } - if ($cache->sql_exists($query_id)) + if ($cache && $cache->sql_exists($query_id)) { return $cache->sql_fetchrow($query_id); } @@ -270,7 +286,7 @@ class dbal_mysql extends dbal $query_id = $this->query_result; } - if ($cache->sql_exists($query_id)) + if ($cache && $cache->sql_exists($query_id)) { return $cache->sql_rowseek($rownum, $query_id); } @@ -298,7 +314,7 @@ class dbal_mysql extends dbal $query_id = $this->query_result; } - if ($cache->sql_exists($query_id)) + if ($cache && $cache->sql_exists($query_id)) { return $cache->sql_freeresult($query_id); } @@ -426,18 +442,29 @@ class dbal_mysql extends dbal */ function _sql_error() { - if (!$this->db_connect_id) + if ($this->db_connect_id) + { + $error = array( + 'message' => @mysql_error($this->db_connect_id), + 'code' => @mysql_errno($this->db_connect_id), + ); + } + else if (function_exists('mysql_error')) { - return array( + $error = array( 'message' => @mysql_error(), - 'code' => @mysql_errno() + 'code' => @mysql_errno(), + ); + } + else + { + $error = array( + 'message' => $this->connect_error, + 'code' => '', ); } - return array( - 'message' => @mysql_error($this->db_connect_id), - 'code' => @mysql_errno($this->db_connect_id) - ); + return $error; } /** diff --git a/phpBB/includes/db/mysqli.php b/phpBB/includes/db/driver/mysqli.php index 6d81b8bc3e..7448bf1670 100644 --- a/phpBB/includes/db/mysqli.php +++ b/phpBB/includes/db/driver/mysqli.php @@ -15,23 +15,28 @@ if (!defined('IN_PHPBB')) exit; } -include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); - /** * MySQLi Database Abstraction Layer * mysqli-extension has to be compiled with: * MySQL 4.1+ or MySQL 5.0+ * @package dbal */ -class dbal_mysqli extends dbal +class phpbb_db_driver_mysqli extends phpbb_db_driver { var $multi_insert = true; + var $connect_error = ''; /** * Connect to server */ function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false , $new_link = false) { + if (!function_exists('mysqli_connect')) + { + $this->connect_error = 'mysqli_connect function does not exist, is mysqli extension installed?'; + return $this->sql_error(''); + } + // Mysqli extension supports persistent connection since PHP 5.3.0 $this->persistency = (version_compare(PHP_VERSION, '5.3.0', '>=')) ? $persistency : false; $this->user = $sqluser; @@ -179,7 +184,7 @@ class dbal_mysqli extends dbal $this->sql_report('start', $query); } - $this->query_result = ($cache_ttl) ? $cache->sql_load($query) : false; + $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; $this->sql_add_num_queries($this->query_result); if ($this->query_result === false) @@ -194,9 +199,9 @@ class dbal_mysqli extends dbal $this->sql_report('stop', $query); } - if ($cache_ttl) + if ($cache && $cache_ttl) { - $this->query_result = $cache->sql_save($query, $this->query_result, $cache_ttl); + $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl); } } else if (defined('DEBUG')) @@ -251,7 +256,7 @@ class dbal_mysqli extends dbal $query_id = $this->query_result; } - if (!is_object($query_id) && $cache->sql_exists($query_id)) + if ($cache && !is_object($query_id) && $cache->sql_exists($query_id)) { return $cache->sql_fetchrow($query_id); } @@ -278,7 +283,7 @@ class dbal_mysqli extends dbal $query_id = $this->query_result; } - if (!is_object($query_id) && $cache->sql_exists($query_id)) + if ($cache && !is_object($query_id) && $cache->sql_exists($query_id)) { return $cache->sql_rowseek($rownum, $query_id); } @@ -306,7 +311,7 @@ class dbal_mysqli extends dbal $query_id = $this->query_result; } - if (!is_object($query_id) && $cache->sql_exists($query_id)) + if ($cache && !is_object($query_id) && $cache->sql_exists($query_id)) { return $cache->sql_freeresult($query_id); } @@ -423,18 +428,29 @@ class dbal_mysqli extends dbal */ function _sql_error() { - if (!$this->db_connect_id) + if ($this->db_connect_id) { - return array( + $error = array( + 'message' => @mysqli_error($this->db_connect_id), + 'code' => @mysqli_errno($this->db_connect_id) + ); + } + else if (function_exists('mysqli_connect_error')) + { + $error = array( 'message' => @mysqli_connect_error(), - 'code' => @mysqli_connect_errno() + 'code' => @mysqli_connect_errno(), + ); + } + else + { + $error = array( + 'message' => $this->connect_error, + 'code' => '', ); } - return array( - 'message' => @mysqli_error($this->db_connect_id), - 'code' => @mysqli_errno($this->db_connect_id) - ); + return $error; } /** diff --git a/phpBB/includes/db/oracle.php b/phpBB/includes/db/driver/oracle.php index 6d9339b2d8..e21e07055d 100644 --- a/phpBB/includes/db/oracle.php +++ b/phpBB/includes/db/driver/oracle.php @@ -15,15 +15,14 @@ if (!defined('IN_PHPBB')) exit; } -include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); - /** * Oracle Database Abstraction Layer * @package dbal */ -class dbal_oracle extends dbal +class phpbb_db_driver_oracle extends phpbb_db_driver { var $last_query_text = ''; + var $connect_error = ''; /** * Connect to server @@ -47,7 +46,33 @@ class dbal_oracle extends dbal $connect = $sqlserver . (($port) ? ':' . $port : '') . '/' . $database; } - $this->db_connect_id = ($new_link) ? @ocinlogon($this->user, $sqlpassword, $connect, 'UTF8') : (($this->persistency) ? @ociplogon($this->user, $sqlpassword, $connect, 'UTF8') : @ocilogon($this->user, $sqlpassword, $connect, 'UTF8')); + if ($new_link) + { + if (!function_exists('ocinlogon')) + { + $this->connect_error = 'ocinlogon function does not exist, is oci extension installed?'; + return $this->sql_error(''); + } + $this->db_connect_id = @ocinlogon($this->user, $sqlpassword, $connect, 'UTF8'); + } + else if ($this->persistency) + { + if (!function_exists('ociplogon')) + { + $this->connect_error = 'ociplogon function does not exist, is oci extension installed?'; + return $this->sql_error(''); + } + $this->db_connect_id = @ociplogon($this->user, $sqlpassword, $connect, 'UTF8'); + } + else + { + if (!function_exists('ocilogon')) + { + $this->connect_error = 'ocilogon function does not exist, is oci extension installed?'; + return $this->sql_error(''); + } + $this->db_connect_id = @ocilogon($this->user, $sqlpassword, $connect, 'UTF8'); + } return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error(''); } @@ -242,7 +267,7 @@ class dbal_oracle extends dbal } $this->last_query_text = $query; - $this->query_result = ($cache_ttl) ? $cache->sql_load($query) : false; + $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; $this->sql_add_num_queries($this->query_result); if ($this->query_result === false) @@ -418,10 +443,10 @@ class dbal_oracle extends dbal $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($query, $this->query_result, $cache_ttl); + $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl); } else if (strpos($query, 'SELECT') === 0 && $this->query_result) { @@ -473,7 +498,7 @@ class dbal_oracle extends dbal $query_id = $this->query_result; } - if ($cache->sql_exists($query_id)) + if ($cache && $cache->sql_exists($query_id)) { return $cache->sql_fetchrow($query_id); } @@ -525,7 +550,7 @@ class dbal_oracle extends dbal $query_id = $this->query_result; } - if ($cache->sql_exists($query_id)) + if ($cache && $cache->sql_exists($query_id)) { return $cache->sql_rowseek($rownum, $query_id); } @@ -594,7 +619,7 @@ class dbal_oracle extends dbal $query_id = $this->query_result; } - if ($cache->sql_exists($query_id)) + if ($cache && $cache->sql_exists($query_id)) { return $cache->sql_freeresult($query_id); } @@ -646,17 +671,27 @@ class dbal_oracle extends dbal */ function _sql_error() { - $error = @ocierror(); - $error = (!$error) ? @ocierror($this->query_result) : $error; - $error = (!$error) ? @ocierror($this->db_connect_id) : $error; - - if ($error) + if (function_exists('ocierror')) { - $this->last_error_result = $error; + $error = @ocierror(); + $error = (!$error) ? @ocierror($this->query_result) : $error; + $error = (!$error) ? @ocierror($this->db_connect_id) : $error; + + if ($error) + { + $this->last_error_result = $error; + } + else + { + $error = (isset($this->last_error_result) && $this->last_error_result) ? $this->last_error_result : array(); + } } else { - $error = (isset($this->last_error_result) && $this->last_error_result) ? $this->last_error_result : array(); + $error = array( + 'message' => $this->connect_error, + 'code' => '', + ); } return $error; diff --git a/phpBB/includes/db/postgres.php b/phpBB/includes/db/driver/postgres.php index 8dfbfc3b60..14854d179d 100644 --- a/phpBB/includes/db/postgres.php +++ b/phpBB/includes/db/driver/postgres.php @@ -15,19 +15,12 @@ if (!defined('IN_PHPBB')) exit; } -include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); - -if (!class_exists('phpbb_error_collector')) -{ - include($phpbb_root_path . 'includes/error_collector.' . $phpEx); -} - /** * PostgreSQL Database Abstraction Layer * Minimum Requirement is Version 7.3+ * @package dbal */ -class dbal_postgres extends dbal +class phpbb_db_driver_postgres extends phpbb_db_driver { var $last_query_text = ''; var $connect_error = ''; @@ -200,7 +193,7 @@ class dbal_postgres extends dbal } $this->last_query_text = $query; - $this->query_result = ($cache_ttl) ? $cache->sql_load($query) : false; + $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; $this->sql_add_num_queries($this->query_result); if ($this->query_result === false) @@ -215,10 +208,10 @@ class dbal_postgres extends dbal $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($query, $this->query_result, $cache_ttl); + $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl); } else if (strpos($query, 'SELECT') === 0 && $this->query_result) { @@ -285,7 +278,7 @@ class dbal_postgres extends dbal $query_id = $this->query_result; } - if ($cache->sql_exists($query_id)) + if ($cache && $cache->sql_exists($query_id)) { return $cache->sql_fetchrow($query_id); } @@ -306,7 +299,7 @@ class dbal_postgres extends dbal $query_id = $this->query_result; } - if ($cache->sql_exists($query_id)) + if ($cache && $cache->sql_exists($query_id)) { return $cache->sql_rowseek($rownum, $query_id); } @@ -355,7 +348,7 @@ class dbal_postgres extends dbal $query_id = $this->query_result; } - if ($cache->sql_exists($query_id)) + if ($cache && $cache->sql_exists($query_id)) { return $cache->sql_freeresult($query_id); } diff --git a/phpBB/includes/db/sqlite.php b/phpBB/includes/db/driver/sqlite.php index 5fc89ced18..7188f0daa2 100644 --- a/phpBB/includes/db/sqlite.php +++ b/phpBB/includes/db/driver/sqlite.php @@ -15,15 +15,15 @@ if (!defined('IN_PHPBB')) exit; } -include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); - /** * Sqlite Database Abstraction Layer * Minimum Requirement: 2.8.2+ * @package dbal */ -class dbal_sqlite extends dbal +class phpbb_db_driver_sqlite extends phpbb_db_driver { + var $connect_error = ''; + /** * Connect to server */ @@ -35,7 +35,24 @@ class dbal_sqlite extends dbal $this->dbname = $database; $error = ''; - $this->db_connect_id = ($this->persistency) ? @sqlite_popen($this->server, 0666, $error) : @sqlite_open($this->server, 0666, $error); + if ($this->persistency) + { + if (!function_exists('sqlite_popen')) + { + $this->connect_error = 'sqlite_popen function does not exist, is sqlite extension installed?'; + return $this->sql_error(''); + } + $this->db_connect_id = @sqlite_popen($this->server, 0666, $error); + } + else + { + if (!function_exists('sqlite_open')) + { + $this->connect_error = 'sqlite_open function does not exist, is sqlite extension installed?'; + return $this->sql_error(''); + } + $this->db_connect_id = @sqlite_open($this->server, 0666, $error); + } if ($this->db_connect_id) { @@ -117,7 +134,7 @@ class dbal_sqlite extends dbal $this->sql_report('start', $query); } - $this->query_result = ($cache_ttl) ? $cache->sql_load($query) : false; + $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false; $this->sql_add_num_queries($this->query_result); if ($this->query_result === false) @@ -132,10 +149,10 @@ class dbal_sqlite extends dbal $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($query, $this->query_result, $cache_ttl); + $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl); } else if (strpos($query, 'SELECT') === 0 && $this->query_result) { @@ -193,7 +210,7 @@ class dbal_sqlite extends dbal $query_id = $this->query_result; } - if ($cache->sql_exists($query_id)) + if ($cache && $cache->sql_exists($query_id)) { return $cache->sql_fetchrow($query_id); } @@ -214,7 +231,7 @@ class dbal_sqlite extends dbal $query_id = $this->query_result; } - if ($cache->sql_exists($query_id)) + if ($cache && $cache->sql_exists($query_id)) { return $cache->sql_rowseek($rownum, $query_id); } @@ -242,7 +259,7 @@ class dbal_sqlite extends dbal $query_id = $this->query_result; } - if ($cache->sql_exists($query_id)) + if ($cache && $cache->sql_exists($query_id)) { return $cache->sql_freeresult($query_id); } @@ -280,10 +297,22 @@ class dbal_sqlite extends dbal */ function _sql_error() { - return array( - 'message' => @sqlite_error_string(@sqlite_last_error($this->db_connect_id)), - 'code' => @sqlite_last_error($this->db_connect_id) - ); + if (function_exists('sqlite_error_string')) + { + $error = array( + 'message' => @sqlite_error_string(@sqlite_last_error($this->db_connect_id)), + 'code' => @sqlite_last_error($this->db_connect_id), + ); + } + else + { + $error = array( + 'message' => $this->connect_error, + 'code' => '', + ); + } + + return $error; } /** diff --git a/phpBB/includes/di/extension/config.php b/phpBB/includes/di/extension/config.php new file mode 100644 index 0000000000..6c272a6588 --- /dev/null +++ b/phpBB/includes/di/extension/config.php @@ -0,0 +1,84 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\HttpKernel\DependencyInjection\Extension; +use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; +use Symfony\Component\Config\FileLocator; + +/** +* Container config extension +*/ +class phpbb_di_extension_config extends Extension +{ + public function __construct($config_file) + { + $this->config_file = $config_file; + } + + /** + * Loads a specific configuration. + * + * @param array $config An array of configuration values + * @param ContainerBuilder $container A ContainerBuilder instance + * + * @throws InvalidArgumentException When provided tag is not defined in this extension + */ + public function load(array $config, ContainerBuilder $container) + { + require($this->config_file); + + $container->setParameter('core.adm_relative_path', (isset($phpbb_adm_relative_path) ? $phpbb_adm_relative_path : 'adm/')); + $container->setParameter('core.table_prefix', $table_prefix); + $container->setParameter('cache.driver.class', $this->convert_30_acm_type($acm_type)); + $container->setParameter('dbal.driver.class', phpbb_convert_30_dbms_to_31($dbms)); + $container->setParameter('dbal.dbhost', $dbhost); + $container->setParameter('dbal.dbuser', $dbuser); + $container->setParameter('dbal.dbpasswd', $dbpasswd); + $container->setParameter('dbal.dbname', $dbname); + $container->setParameter('dbal.dbport', $dbport); + $container->setParameter('dbal.new_link', defined('PHPBB_DB_NEW_LINK') && PHPBB_DB_NEW_LINK); + } + + /** + * Returns the recommended alias to use in XML. + * + * This alias is also the mandatory prefix to use when using YAML. + * + * @return string The alias + */ + public function getAlias() + { + return 'config'; + } + + /** + * Convert 3.0 ACM type to 3.1 cache driver class name + * + * @param string $acm_type ACM type + * @return cache driver class + */ + protected function convert_30_acm_type($acm_type) + { + if (preg_match('#^[a-z]+$#', $acm_type)) + { + return 'phpbb_cache_driver_'.$acm_type; + } + + return $acm_type; + } +} diff --git a/phpBB/includes/di/extension/core.php b/phpBB/includes/di/extension/core.php new file mode 100644 index 0000000000..9c36ba2fc4 --- /dev/null +++ b/phpBB/includes/di/extension/core.php @@ -0,0 +1,69 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\HttpKernel\DependencyInjection\Extension; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; +use Symfony\Component\Config\FileLocator; + +/** +* Container core extension +*/ +class phpbb_di_extension_core extends Extension +{ + /** + * phpBB Root path + * @var string + */ + protected $root_path; + + /** + * Constructor + * + * @param string $root_path Root path + */ + public function __construct($root_path) + { + $this->root_path = $root_path; + } + + /** + * Loads a specific configuration. + * + * @param array $config An array of configuration values + * @param ContainerBuilder $container A ContainerBuilder instance + * + * @throws InvalidArgumentException When provided tag is not defined in this extension + */ + public function load(array $config, ContainerBuilder $container) + { + $loader = new YamlFileLoader($container, new FileLocator(phpbb_realpath($this->root_path . 'config'))); + $loader->load('services.yml'); + } + + /** + * Returns the recommended alias to use in XML. + * + * This alias is also the mandatory prefix to use when using YAML. + * + * @return string The alias + */ + public function getAlias() + { + return 'core'; + } +} diff --git a/phpBB/includes/di/extension/ext.php b/phpBB/includes/di/extension/ext.php new file mode 100644 index 0000000000..7d9b433751 --- /dev/null +++ b/phpBB/includes/di/extension/ext.php @@ -0,0 +1,69 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\HttpKernel\DependencyInjection\Extension; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; +use Symfony\Component\Config\FileLocator; + +/** +* Container ext extension +*/ +class phpbb_di_extension_ext extends Extension +{ + protected $paths = array(); + + public function __construct($enabled_extensions) + { + foreach ($enabled_extensions as $ext => $path) + { + $this->paths[] = $path; + } + } + + /** + * Loads a specific configuration. + * + * @param array $config An array of configuration values + * @param ContainerBuilder $container A ContainerBuilder instance + * + * @throws InvalidArgumentException When provided tag is not defined in this extension + */ + public function load(array $config, ContainerBuilder $container) + { + foreach ($this->paths as $path) + { + if (file_exists($path . '/config/services.yml')) + { + $loader = new YamlFileLoader($container, new FileLocator(phpbb_realpath($path . '/config'))); + $loader->load('services.yml'); + } + } + } + + /** + * Returns the recommended alias to use in XML. + * + * This alias is also the mandatory prefix to use when using YAML. + * + * @return string The alias + */ + public function getAlias() + { + return 'ext'; + } +} diff --git a/phpBB/includes/di/pass/collection_pass.php b/phpBB/includes/di/pass/collection_pass.php new file mode 100644 index 0000000000..63a5c7dfc4 --- /dev/null +++ b/phpBB/includes/di/pass/collection_pass.php @@ -0,0 +1,46 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; + +/** +* Appends an add method call to the definition of each collection service for +* the services tagged with the appropriate name defined in the collection's +* service_collection tag. +*/ +class phpbb_di_pass_collection_pass implements CompilerPassInterface +{ + /** + * Modify the container before it is passed to the rest of the code + * + * @param ContainerBuilder $container ContainerBuilder object + * @return null + */ + public function process(ContainerBuilder $container) + { + foreach ($container->findTaggedServiceIds('service_collection') as $id => $data) + { + $definition = $container->getDefinition($id); + + foreach ($container->findTaggedServiceIds($data[0]['tag']) as $service_id => $service_data) + { + $definition->addMethodCall('add', array($service_id)); + } + } + } +} diff --git a/phpBB/includes/di/pass/kernel_pass.php b/phpBB/includes/di/pass/kernel_pass.php new file mode 100644 index 0000000000..a701ebcfa6 --- /dev/null +++ b/phpBB/includes/di/pass/kernel_pass.php @@ -0,0 +1,68 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; + +class phpbb_di_pass_kernel_pass implements CompilerPassInterface +{ + /** + * Modify the container before it is passed to the rest of the code + * + * @param ContainerBuilder $container ContainerBuilder object + * @return null + */ + public function process(ContainerBuilder $container) + { + $definition = $container->getDefinition('dispatcher'); + + foreach ($container->findTaggedServiceIds('kernel.event_listener') as $id => $events) + { + foreach ($events as $event) + { + $priority = isset($event['priority']) ? $event['priority'] : 0; + + if (!isset($event['event'])) + { + throw new InvalidArgumentException(sprintf('Service "%1$s" must define the "event" attribute on "kernel.event_listener" tags.', $id)); + } + + if (!isset($event['method'])) + { + throw new InvalidArgumentException(sprintf('Service "%1$s" must define the "method" attribute on "kernel.event_listener" tags.', $id)); + } + + $definition->addMethodCall('addListenerService', array($event['event'], array($id, $event['method']), $priority)); + } + } + + foreach ($container->findTaggedServiceIds('kernel.event_subscriber') as $id => $attributes) + { + // We must assume that the class value has been correctly filled, even if the service is created by a factory + $class = $container->getDefinition($id)->getClass(); + + $refClass = new ReflectionClass($class); + $interface = 'Symfony\Component\EventDispatcher\EventSubscriberInterface'; + if (!$refClass->implementsInterface($interface)) + { + throw new InvalidArgumentException(sprintf('Service "%1$s" must implement interface "%2$s".', $id, $interface)); + } + + $definition->addMethodCall('addSubscriberService', array($id, $class)); + } + } +} diff --git a/phpBB/includes/di/processor/config.php b/phpBB/includes/di/processor/config.php deleted file mode 100644 index 22b6252a6d..0000000000 --- a/phpBB/includes/di/processor/config.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** -* Configure the container for phpBB's services though -* user-defined parameters defined in the config.php file. -*/ -class phpbb_di_processor_config implements phpbb_di_processor_interface -{ - private $config_file; - private $phpbb_root_path; - private $php_ext; - - /** - * Constructor. - * - * @param string $config_file The config file - * @param string $phpbb_root_path The root path - * @param string $php_ext The PHP extension - */ - public function __construct($config_file, $phpbb_root_path, $php_ext) - { - $this->config_file = $config_file; - $this->phpbb_root_path = $phpbb_root_path; - $this->php_ext = $php_ext; - } - - /** - * @inheritdoc - */ - public function process(ContainerBuilder $container) - { - require $this->config_file; - - $container->setParameter('core.root_path', $this->phpbb_root_path); - $container->setParameter('core.php_ext', $this->php_ext); - - $container->setParameter('core.table_prefix', $table_prefix); - $container->setParameter('cache.driver.class', $this->fix_acm_type($acm_type)); - $container->setParameter('dbal.driver.class', 'dbal_'.$dbms); - $container->setParameter('dbal.dbhost', $dbhost); - $container->setParameter('dbal.dbuser', $dbuser); - $container->setParameter('dbal.dbpasswd', $dbpasswd); - $container->setParameter('dbal.dbname', $dbname); - $container->setParameter('dbal.dbport', $dbport); - $container->setParameter('dbal.new_link', defined('PHPBB_DB_NEW_LINK') && PHPBB_DB_NEW_LINK); - - $container->set('container', $container); - } - - protected function fix_acm_type($acm_type) - { - if (preg_match('#^[a-z]+$#', $acm_type)) - { - return 'phpbb_cache_driver_'.$acm_type; - } - - return $acm_type; - } -} diff --git a/phpBB/includes/di/processor/ext.php b/phpBB/includes/di/processor/ext.php deleted file mode 100644 index e69a3d73b3..0000000000 --- a/phpBB/includes/di/processor/ext.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -use Symfony\Component\Config\FileLocator; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; - -/** -* Load the service configurations from all extensions into the container. -*/ -class phpbb_di_processor_ext implements phpbb_di_processor_interface -{ - private $extension_manager; - - /** - * Constructor. - * - * @param string $extension_manager The extension manager - */ - public function __construct($extension_manager) - { - $this->extension_manager = $extension_manager; - } - - /** - * @inheritdoc - */ - public function process(ContainerBuilder $container) - { - $enabled_exts = $this->extension_manager->all_enabled(); - foreach ($enabled_exts as $name => $path) - { - if (file_exists($path . '/config/services.yml')) - { - $loader = new YamlFileLoader($container, new FileLocator($path . '/config')); - $loader->load('services.yml'); - } - } - } -} diff --git a/phpBB/includes/di/processor/interface.php b/phpBB/includes/di/processor/interface.php deleted file mode 100644 index b8563791cc..0000000000 --- a/phpBB/includes/di/processor/interface.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @copyright (c) 2012 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -use Symfony\Component\DependencyInjection\ContainerBuilder; - -interface phpbb_di_processor_interface -{ - /** - * Mutate the container. - * - * @param ContainerBuilder $container The container - */ - public function process(ContainerBuilder $container); -} diff --git a/phpBB/includes/di/service_collection.php b/phpBB/includes/di/service_collection.php new file mode 100644 index 0000000000..880cb46d4d --- /dev/null +++ b/phpBB/includes/di/service_collection.php @@ -0,0 +1,49 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** +* Collection of services to be configured at container compile time. +* +* @package phpBB3 +*/ +class phpbb_di_service_collection extends ArrayObject +{ + /** + * Constructor + * + * @param ContainerInterface $container Container object + */ + public function __construct(ContainerInterface $container) + { + $this->container = $container; + } + + /** + * Add a service to the collection + * + * @param string $name The service name + * @return null + */ + public function add($name) + { + $task = $this->container->get($name); + + $this->offsetSet($name, $task); + } +} diff --git a/phpBB/includes/event/dispatcher.php b/phpBB/includes/event/dispatcher.php index 2bf46b9b06..4f637ce3bb 100644 --- a/phpBB/includes/event/dispatcher.php +++ b/phpBB/includes/event/dispatcher.php @@ -15,7 +15,7 @@ if (!defined('IN_PHPBB')) exit; } -use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher; /** * Extension of the Symfony2 EventDispatcher @@ -31,7 +31,7 @@ use Symfony\Component\EventDispatcher\EventDispatcher; * extract($phpbb_dispatcher->trigger_event('core.index', compact($vars))); * */ -class phpbb_event_dispatcher extends EventDispatcher +class phpbb_event_dispatcher extends ContainerAwareEventDispatcher { public function trigger_event($eventName, $data = array()) { diff --git a/phpBB/includes/event/kernel_exception_subscriber.php b/phpBB/includes/event/kernel_exception_subscriber.php new file mode 100644 index 0000000000..f90989a74c --- /dev/null +++ b/phpBB/includes/event/kernel_exception_subscriber.php @@ -0,0 +1,85 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; +use Symfony\Component\HttpKernel\Exception\HttpException; +use Symfony\Component\HttpFoundation\Response; + +class phpbb_event_kernel_exception_subscriber implements EventSubscriberInterface +{ + /** + * Template object + * @var phpbb_template + */ + protected $template; + + /** + * User object + * @var phpbb_user + */ + protected $user; + + /** + * Construct method + * + * @param phpbb_template $template Template object + * @param phpbb_user $user User object + */ + public function __construct(phpbb_template $template, phpbb_user $user) + { + $this->template = $template; + $this->user = $user; + } + + /** + * This listener is run when the KernelEvents::EXCEPTION event is triggered + * + * @param GetResponseForExceptionEvent $event + * @return null + */ + public function on_kernel_exception(GetResponseForExceptionEvent $event) + { + page_header($this->user->lang('INFORMATION')); + + $exception = $event->getException(); + + $this->template->assign_vars(array( + 'MESSAGE_TITLE' => $this->user->lang('INFORMATION'), + 'MESSAGE_TEXT' => $exception->getMessage(), + )); + + $this->template->set_filenames(array( + 'body' => 'message_body.html', + )); + + page_footer(true, false, false); + + + $status_code = $exception instanceof HttpException ? $exception->getStatusCode() : 500; + $response = new Response($this->template->assign_display('body'), $status_code); + $event->setResponse($response); + } + + public static function getSubscribedEvents() + { + return array( + KernelEvents::EXCEPTION => 'on_kernel_exception', + ); + } +} diff --git a/phpBB/includes/event/kernel_request_subscriber.php b/phpBB/includes/event/kernel_request_subscriber.php new file mode 100644 index 0000000000..afb8464f80 --- /dev/null +++ b/phpBB/includes/event/kernel_request_subscriber.php @@ -0,0 +1,83 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\HttpKernel\EventListener\RouterListener; +use Symfony\Component\Routing\RequestContext; + +class phpbb_event_kernel_request_subscriber implements EventSubscriberInterface +{ + /** + * Extension finder object + * @var phpbb_extension_finder + */ + protected $finder; + + /** + * PHP extension + * @var string + */ + protected $php_ext; + + /** + * Root path + * @var string + */ + protected $root_path; + + /** + * Construct method + * + * @param phpbb_extension_finder $finder Extension finder object + * @param string $root_path Root path + * @param string $php_ext PHP extension + */ + public function __construct(phpbb_extension_finder $finder, $root_path, $php_ext) + { + $this->finder = $finder; + $this->root_path = $root_path; + $this->php_ext = $php_ext; + } + + /** + * This listener is run when the KernelEvents::REQUEST event is triggered + * + * This is responsible for setting up the routing information + * + * @param GetResponseEvent $event + * @return null + */ + public function on_kernel_request(GetResponseEvent $event) + { + $request = $event->getRequest(); + $context = new RequestContext(); + $context->fromRequest($request); + + $matcher = phpbb_get_url_matcher($this->finder, $context, $this->root_path, $this->php_ext); + $router_listener = new RouterListener($matcher, $context); + $router_listener->onKernelRequest($event); + } + + public static function getSubscribedEvents() + { + return array( + KernelEvents::REQUEST => 'on_kernel_request', + ); + } +} diff --git a/phpBB/includes/event/kernel_terminate_subscriber.php b/phpBB/includes/event/kernel_terminate_subscriber.php new file mode 100644 index 0000000000..1eaf890e42 --- /dev/null +++ b/phpBB/includes/event/kernel_terminate_subscriber.php @@ -0,0 +1,43 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\HttpKernel\Event\PostResponseEvent; + +class phpbb_event_kernel_terminate_subscriber implements EventSubscriberInterface +{ + /** + * This listener is run when the KernelEvents::TERMINATE event is triggered + * This comes after a Response has been sent to the server; this is + * primarily cleanup stuff. + * + * @param PostResponseEvent $event + * @return null + */ + public function on_kernel_terminate(PostResponseEvent $event) + { + exit_handler(); + } + + public static function getSubscribedEvents() + { + return array( + KernelEvents::TERMINATE => 'on_kernel_terminate', + ); + } +} diff --git a/phpBB/includes/extension/controller.php b/phpBB/includes/extension/controller.php deleted file mode 100644 index f97b69c7ed..0000000000 --- a/phpBB/includes/extension/controller.php +++ /dev/null @@ -1,84 +0,0 @@ -<?php -/** -* -* @package extension -* @copyright (c) 2011 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Abstract class extended by extension front controller classes -* -* @package extension -*/ -abstract class phpbb_extension_controller implements phpbb_extension_controller_interface -{ - /** - * Request class object - * @var phpbb_request - */ - protected $request; - - /** - * DBAL class object - * @var dbal - */ - protected $db; - - /** - * User class object - * @var phpbb_user - */ - protected $user; - - /** - * Template class object - * @var phpbb_template - */ - protected $template; - - /** - * Config object - * @var phpbb_config - */ - protected $config; - - /** - * PHP Extension - * @var string - */ - protected $php_ext; - - /** - * Relative path to board root - * @var string - */ - protected $phpbb_root_path; - - /** - * Constructor method that provides the common phpBB objects as inherited class - * properties for automatic availability in extension controllers - */ - public function __construct() - { - global $request, $db, $user, $template, $config; - global $phpEx, $phpbb_root_path; - - $this->request = $request; - $this->db = $db; - $this->user = $user; - $this->template = $template; - $this->config = $config; - $this->php_ext = $phpEx; - $this->phpbb_root_path = $phpbb_root_path; - } -} diff --git a/phpBB/includes/extension/controller_interface.php b/phpBB/includes/extension/controller_interface.php deleted file mode 100644 index 2b88925388..0000000000 --- a/phpBB/includes/extension/controller_interface.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php -/** -* -* @package extension -* @copyright (c) 2011 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* The interface that extension classes have to implement to run front pages -* -* @package extension -*/ -interface phpbb_extension_controller_interface -{ - /** - * Handle the request to display a page from an extension - * - * @return null - */ - public function handle(); -} diff --git a/phpBB/includes/extension/interface.php b/phpBB/includes/extension/interface.php index 74ecb9b762..7b36a12bf6 100644 --- a/phpBB/includes/extension/interface.php +++ b/phpBB/includes/extension/interface.php @@ -45,7 +45,9 @@ interface phpbb_extension_interface * * @param mixed $old_state The return value of the previous call * of this method, or false on the first call - * @return null + * @return mixed Returns false after last step, otherwise + * temporary state which is passed as an + * argument to the next step */ public function disable_step($old_state); diff --git a/phpBB/includes/extension/manager.php b/phpBB/includes/extension/manager.php index cfa6a0e000..de6f364320 100644 --- a/phpBB/includes/extension/manager.php +++ b/phpBB/includes/extension/manager.php @@ -34,7 +34,7 @@ class phpbb_extension_manager /** * Creates a manager and loads information from database * - * @param dbal $db A database connection + * @param phpbb_db_driver $db A database connection * @param phpbb_config $config phpbb_config * @param string $extension_table The name of the table holding extensions * @param string $phpbb_root_path Path to the phpbb includes directory. @@ -42,7 +42,7 @@ 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(dbal $db, phpbb_config $config, $extension_table, $phpbb_root_path, $php_ext = '.php', phpbb_cache_driver_interface $cache = null, $cache_name = '_ext') + public function __construct(phpbb_db_driver $db, phpbb_config $config, $extension_table, $phpbb_root_path, $php_ext = '.php', phpbb_cache_driver_interface $cache = null, $cache_name = '_ext') { $this->phpbb_root_path = $phpbb_root_path; $this->db = $db; @@ -195,7 +195,7 @@ class phpbb_extension_manager if ($this->cache) { - $this->cache->destroy($this->cache_name); + $this->cache->purge(); } return !$active; @@ -252,7 +252,7 @@ class phpbb_extension_manager if ($this->cache) { - $this->cache->destroy($this->cache_name); + $this->cache->purge(); } return true; @@ -272,7 +272,7 @@ class phpbb_extension_manager if ($this->cache) { - $this->cache->destroy($this->cache_name); + $this->cache->purge(); } return false; @@ -335,7 +335,7 @@ class phpbb_extension_manager if ($this->cache) { - $this->cache->destroy($this->cache_name); + $this->cache->purge(); } return true; @@ -349,7 +349,7 @@ class phpbb_extension_manager if ($this->cache) { - $this->cache->destroy($this->cache_name); + $this->cache->purge(); } return false; @@ -384,7 +384,7 @@ class phpbb_extension_manager } $iterator = new RecursiveIteratorIterator( - new RecursiveDirectoryIterator($this->phpbb_root_path . 'ext/'), + new RecursiveDirectoryIterator($this->phpbb_root_path . 'ext/', FilesystemIterator::NEW_CURRENT_AND_KEY | FilesystemIterator::FOLLOW_SYMLINKS), RecursiveIteratorIterator::SELF_FIRST); foreach ($iterator as $file_info) { diff --git a/phpBB/includes/extension/metadata_manager.php b/phpBB/includes/extension/metadata_manager.php index ea85bd3c4e..36b0f8b184 100644 --- a/phpBB/includes/extension/metadata_manager.php +++ b/phpBB/includes/extension/metadata_manager.php @@ -34,12 +34,12 @@ class phpbb_extension_metadata_manager /** * Creates the metadata manager * - * @param dbal $db A database connection + * @param phpbb_db_driver $db A database connection * @param string $extension_manager An instance of the phpbb extension manager * @param string $phpbb_root_path Path to the phpbb includes directory. * @param string $phpEx php file extension */ - public function __construct($ext_name, dbal $db, phpbb_extension_manager $extension_manager, $phpbb_root_path, $phpEx = '.php', phpbb_template $template, phpbb_config $config) + public function __construct($ext_name, phpbb_db_driver $db, phpbb_extension_manager $extension_manager, $phpbb_root_path, $phpEx = '.php', phpbb_template $template, phpbb_config $config) { $this->phpbb_root_path = $phpbb_root_path; $this->db = $db; diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 804d89d1a2..d0ef2759d5 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -7,6 +7,8 @@ * */ +use Symfony\Component\HttpFoundation\Request; + /** * @ignore */ @@ -229,7 +231,8 @@ function phpbb_gmgetdate($time = false) /** * Return formatted string for filesizes * -* @param int $value filesize in bytes +* @param mixed $value filesize in bytes +* (non-negative number; int, float or string) * @param bool $string_only true if language string should be returned * @param array $allowed_units only allow these units (data array indexes) * @@ -241,6 +244,12 @@ function get_formatted_filesize($value, $string_only = true, $allowed_units = fa global $user; $available_units = array( + 'tb' => array( + 'min' => 1099511627776, // pow(2, 40) + 'index' => 4, + 'si_unit' => 'TB', + 'iec_unit' => 'TIB', + ), 'gb' => array( 'min' => 1073741824, // pow(2, 30) 'index' => 3, @@ -2847,12 +2856,10 @@ function meta_refresh($time, $url, $disable_cd_check = false) * * @param int $code HTTP status code * @param string $message Message for the status code -* @return void +* @return null */ function send_status_line($code, $message) { - global $request; - if (substr(strtolower(@php_sapi_name()), 0, 3) === 'cgi') { // in theory, we shouldn't need that due to php doing it. Reality offers a differing opinion, though @@ -2860,18 +2867,35 @@ function send_status_line($code, $message) } else { - if ($request->server('SERVER_PROTOCOL')) - { - $version = $request->server('SERVER_PROTOCOL'); - } - else - { - $version = 'HTTP/1.0'; - } + $version = phpbb_request_http_version(); header("$version $code $message", true, $code); } } +/** +* Returns the HTTP version used in the current request. +* +* Handles the case of being called before $request is present, +* in which case it falls back to the $_SERVER superglobal. +* +* @return string HTTP version +*/ +function phpbb_request_http_version() +{ + global $request; + + if ($request && $request->server('SERVER_PROTOCOL')) + { + return $request->server('SERVER_PROTOCOL'); + } + else if (isset($_SERVER['SERVER_PROTOCOL'])) + { + return $_SERVER['SERVER_PROTOCOL']; + } + + return 'HTTP/1.0'; +} + //Form validation @@ -4771,7 +4795,7 @@ function phpbb_get_plural_form($rule, $number) * * @param array $param Parameter array, see $param_defaults array. * -* @return void +* @return null */ function phpbb_http_login($param) { @@ -4870,12 +4894,107 @@ function phpbb_http_login($param) } /** +* Escapes and quotes a string for use as an HTML/XML attribute value. +* +* This is a port of Python xml.sax.saxutils quoteattr. +* +* The function will attempt to choose a quote character in such a way as to +* avoid escaping quotes in the string. If this is not possible the string will +* be wrapped in double quotes and double quotes will be escaped. +* +* @param string $data The string to be escaped +* @param array $entities Associative array of additional entities to be escaped +* @return string Escaped and quoted string +*/ +function phpbb_quoteattr($data, $entities = null) +{ + $data = str_replace('&', '&', $data); + $data = str_replace('>', '>', $data); + $data = str_replace('<', '<', $data); + + $data = str_replace("\n", ' ', $data); + $data = str_replace("\r", ' ', $data); + $data = str_replace("\t", '	', $data); + + if (!empty($entities)) + { + $data = str_replace(array_keys($entities), array_values($entities), $data); + } + + if (strpos($data, '"') !== false) + { + if (strpos($data, "'") !== false) + { + $data = '"' . str_replace('"', '"', $data) . '"'; + } + else + { + $data = "'" . $data . "'"; + } + } + else + { + $data = '"' . $data . '"'; + } + + return $data; +} + +/** +* Converts query string (GET) parameters in request into hidden fields. +* +* Useful for forwarding GET parameters when submitting forms with GET method. +* +* It is possible to omit some of the GET parameters, which is useful if +* they are specified in the form being submitted. +* +* sid is always omitted. +* +* @param phpbb_request $request Request object +* @param array $exclude A list of variable names that should not be forwarded +* @return string HTML with hidden fields +*/ +function phpbb_build_hidden_fields_for_query_params($request, $exclude = null) +{ + $names = $request->variable_names(phpbb_request_interface::GET); + $hidden = ''; + foreach ($names as $name) + { + // Sessions are dealt with elsewhere, omit sid always + if ($name == 'sid') + { + continue; + } + + // Omit any additional parameters requested + if (!empty($exclude) && in_array($name, $exclude)) + { + continue; + } + + $escaped_name = phpbb_quoteattr($name); + + // Note: we might retrieve the variable from POST or cookies + // here. To avoid exposing cookies, skip variables that are + // overwritten somewhere other than GET entirely. + $value = $request->variable($name, '', true); + $get_value = $request->variable($name, '', true, phpbb_request_interface::GET); + if ($value === $get_value) + { + $escaped_value = phpbb_quoteattr($value); + $hidden .= "<input type='hidden' name=$escaped_name value=$escaped_value />"; + } + } + return $hidden; +} + +/** * Generate page header */ function page_header($page_title = '', $display_online_list = true, $item_id = 0, $item = 'forum') { global $db, $config, $template, $SID, $_SID, $_EXTRA_URL, $user, $auth, $phpEx, $phpbb_root_path; - global $phpbb_dispatcher; + global $phpbb_dispatcher, $request; if (defined('HEADER_INC')) { @@ -5064,6 +5183,8 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 $timezone_name = $user->lang['timezones'][$timezone_name]; } + $hidden_fields_for_jumpbox = phpbb_build_hidden_fields_for_query_params($request, array('f')); + // The following assigns all _common_ variables that may be used at any point in a template. $template->assign_vars(array( 'SITENAME' => $config['sitename'], @@ -5078,6 +5199,7 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 'RECORD_USERS' => $l_online_record, 'PRIVATE_MESSAGE_INFO' => $l_privmsgs_text, 'PRIVATE_MESSAGE_INFO_UNREAD' => $l_privmsgs_text_unread, + 'HIDDEN_FIELDS_FOR_JUMPBOX' => $hidden_fields_for_jumpbox, 'S_USER_NEW_PRIVMSG' => $user->data['user_new_privmsg'], 'S_USER_UNREAD_PRIVMSG' => $user->data['user_unread_privmsg'], @@ -5209,11 +5331,15 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 /** * Generate page footer +* +* @param bool $run_cron Whether or not to run the cron +* @param bool $display_template Whether or not to display the template +* @param bool $exit_handler Whether or not to run the exit_handler() */ -function page_footer($run_cron = true) +function page_footer($run_cron = true, $display_template = true, $exit_handler = true) { global $db, $config, $template, $user, $auth, $cache, $starttime, $phpbb_root_path, $phpEx; - global $request, $phpbb_dispatcher; + global $request, $phpbb_dispatcher, $phpbb_admin_path; // A listener can set this variable to `true` when it overrides this function $page_footer_override = false; @@ -5269,7 +5395,7 @@ function page_footer($run_cron = true) 'TRANSLATION_INFO' => (!empty($user->lang['TRANSLATION_INFO'])) ? $user->lang['TRANSLATION_INFO'] : '', 'CREDIT_LINE' => $user->lang('POWERED_BY', '<a href="https://www.phpbb.com/">phpBB</a>® Forum Software © phpBB Group'), - 'U_ACP' => ($auth->acl_get('a_') && !empty($user->data['is_registered'])) ? append_sid("{$phpbb_root_path}adm/index.$phpEx", false, true, $user->session_id) : '') + 'U_ACP' => ($auth->acl_get('a_') && !empty($user->data['is_registered'])) ? append_sid("{$phpbb_admin_path}index.$phpEx", false, true, $user->session_id) : '') ); // Call cron-type script @@ -5305,10 +5431,17 @@ function page_footer($run_cron = true) } } - $template->display('body'); + if ($display_template) + { + $template->display('body'); + } garbage_collection(); - exit_handler(); + + if ($exit_handler) + { + exit_handler(); + } } /** @@ -5326,7 +5459,10 @@ function garbage_collection() * @event core.garbage_collection * @since 3.1-A1 */ - $phpbb_dispatcher->dispatch('core.garbage_collection'); + if (!empty($phpbb_dispatcher)) + { + $phpbb_dispatcher->dispatch('core.garbage_collection'); + } // Unload cache, must be done before the DB connection if closed if (!empty($cache)) @@ -5412,3 +5548,95 @@ function phpbb_to_numeric($input) { return ($input > PHP_INT_MAX) ? (float) $input : (int) $input; } + +/** +* Convert either 3.0 dbms or 3.1 db driver class name to 3.1 db driver class name. +* +* If $dbms is a valid 3.1 db driver class name, returns it unchanged. +* Otherwise prepends phpbb_db_driver_ to the dbms to convert a 3.0 dbms +* to 3.1 db driver class name. +* +* @param string $dbms dbms parameter +* @return db driver class +*/ +function phpbb_convert_30_dbms_to_31($dbms) +{ + // Note: this check is done first because mysqli extension + // supplies a mysqli class, and class_exists($dbms) would return + // true for mysqli class. + // However, per the docblock any valid 3.1 driver name should be + // recognized by this function, and have priority over 3.0 dbms. + if (class_exists('phpbb_db_driver_' . $dbms)) + { + return 'phpbb_db_driver_' . $dbms; + } + + if (class_exists($dbms)) + { + // Additionally we could check that $dbms extends phpbb_db_driver. + // http://php.net/manual/en/class.reflectionclass.php + // Beware of possible performance issues: + // http://stackoverflow.com/questions/294582/php-5-reflection-api-performance + // We could check for interface implementation in all paths or + // only when we do not prepend phpbb_db_driver_. + + /* + $reflection = new \ReflectionClass($dbms); + + if ($reflection->isSubclassOf('phpbb_db_driver')) + { + return $dbms; + } + */ + + return $dbms; + } + + throw new \RuntimeException("You have specified an invalid dbms driver: $dbms"); +} + +/** +* Create a Symfony Request object from phpbb_request object +* +* @param phpbb_request $request Request object +* @return Request A Symfony Request object +*/ +function phpbb_create_symfony_request(phpbb_request $request) +{ + // This function is meant to sanitize the global input arrays + $sanitizer = function(&$value, $key) { + $type_cast_helper = new phpbb_request_type_cast_helper(); + $type_cast_helper->set_var($value, $value, gettype($value), true); + }; + + // We need to re-enable the super globals so we can access them here + $request->enable_super_globals(); + $get_parameters = $_GET; + $post_parameters = $_POST; + $server_parameters = $_SERVER; + $files_parameters = $_FILES; + $cookie_parameters = $_COOKIE; + // And now disable them again for security + $request->disable_super_globals(); + + array_walk_recursive($get_parameters, $sanitizer); + array_walk_recursive($post_parameters, $sanitizer); + + // Until we fix the issue with relative paths, we have to fake path info + // to allow urls like app.php?controller=foo/bar + $controller = $request->variable('controller', ''); + $path_info = '/' . $controller; + $request_uri = $server_parameters['REQUEST_URI']; + + // Remove the query string from REQUEST_URI + if ($pos = strpos($request_uri, '?')) + { + $request_uri = substr($request_uri, 0, $pos); + } + + // Add the path info (i.e. controller route) to the REQUEST_URI + $server_parameters['REQUEST_URI'] = $request_uri . $path_info; + $server_parameters['SCRIPT_NAME'] = ''; + + return new Request($get_parameters, $post_parameters, array(), $cookie_parameters, $files_parameters, $server_parameters); +} diff --git a/phpBB/includes/functions_acp.php b/phpBB/includes/functions_acp.php index 2f3fd7bac0..32fd76e74d 100644 --- a/phpBB/includes/functions_acp.php +++ b/phpBB/includes/functions_acp.php @@ -82,16 +82,16 @@ function adm_page_header($page_title) 'T_RANKS_PATH' => "{$phpbb_root_path}{$config['ranks_path']}/", 'T_UPLOAD_PATH' => "{$phpbb_root_path}{$config['upload_path']}/", - 'ICON_MOVE_UP' => '<img src="' . $phpbb_admin_path . 'images/icon_up.gif" alt="' . $user->lang['MOVE_UP'] . '" title="' . $user->lang['MOVE_UP'] . '" />', - 'ICON_MOVE_UP_DISABLED' => '<img src="' . $phpbb_admin_path . 'images/icon_up_disabled.gif" alt="' . $user->lang['MOVE_UP'] . '" title="' . $user->lang['MOVE_UP'] . '" />', - 'ICON_MOVE_DOWN' => '<img src="' . $phpbb_admin_path . 'images/icon_down.gif" alt="' . $user->lang['MOVE_DOWN'] . '" title="' . $user->lang['MOVE_DOWN'] . '" />', - 'ICON_MOVE_DOWN_DISABLED' => '<img src="' . $phpbb_admin_path . 'images/icon_down_disabled.gif" alt="' . $user->lang['MOVE_DOWN'] . '" title="' . $user->lang['MOVE_DOWN'] . '" />', - 'ICON_EDIT' => '<img src="' . $phpbb_admin_path . 'images/icon_edit.gif" alt="' . $user->lang['EDIT'] . '" title="' . $user->lang['EDIT'] . '" />', - 'ICON_EDIT_DISABLED' => '<img src="' . $phpbb_admin_path . 'images/icon_edit_disabled.gif" alt="' . $user->lang['EDIT'] . '" title="' . $user->lang['EDIT'] . '" />', - 'ICON_DELETE' => '<img src="' . $phpbb_admin_path . 'images/icon_delete.gif" alt="' . $user->lang['DELETE'] . '" title="' . $user->lang['DELETE'] . '" />', - 'ICON_DELETE_DISABLED' => '<img src="' . $phpbb_admin_path . 'images/icon_delete_disabled.gif" alt="' . $user->lang['DELETE'] . '" title="' . $user->lang['DELETE'] . '" />', - 'ICON_SYNC' => '<img src="' . $phpbb_admin_path . 'images/icon_sync.gif" alt="' . $user->lang['RESYNC'] . '" title="' . $user->lang['RESYNC'] . '" />', - 'ICON_SYNC_DISABLED' => '<img src="' . $phpbb_admin_path . 'images/icon_sync_disabled.gif" alt="' . $user->lang['RESYNC'] . '" title="' . $user->lang['RESYNC'] . '" />', + 'ICON_MOVE_UP' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_up.gif" alt="' . $user->lang['MOVE_UP'] . '" title="' . $user->lang['MOVE_UP'] . '" />', + 'ICON_MOVE_UP_DISABLED' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_up_disabled.gif" alt="' . $user->lang['MOVE_UP'] . '" title="' . $user->lang['MOVE_UP'] . '" />', + 'ICON_MOVE_DOWN' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_down.gif" alt="' . $user->lang['MOVE_DOWN'] . '" title="' . $user->lang['MOVE_DOWN'] . '" />', + 'ICON_MOVE_DOWN_DISABLED' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_down_disabled.gif" alt="' . $user->lang['MOVE_DOWN'] . '" title="' . $user->lang['MOVE_DOWN'] . '" />', + 'ICON_EDIT' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_edit.gif" alt="' . $user->lang['EDIT'] . '" title="' . $user->lang['EDIT'] . '" />', + 'ICON_EDIT_DISABLED' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_edit_disabled.gif" alt="' . $user->lang['EDIT'] . '" title="' . $user->lang['EDIT'] . '" />', + 'ICON_DELETE' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_delete.gif" alt="' . $user->lang['DELETE'] . '" title="' . $user->lang['DELETE'] . '" />', + 'ICON_DELETE_DISABLED' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_delete_disabled.gif" alt="' . $user->lang['DELETE'] . '" title="' . $user->lang['DELETE'] . '" />', + 'ICON_SYNC' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_sync.gif" alt="' . $user->lang['RESYNC'] . '" title="' . $user->lang['RESYNC'] . '" />', + 'ICON_SYNC_DISABLED' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_sync_disabled.gif" alt="' . $user->lang['RESYNC'] . '" title="' . $user->lang['RESYNC'] . '" />', 'S_USER_LANG' => $user->lang['USER_LANG'], 'S_CONTENT_DIRECTION' => $user->lang['DIRECTION'], diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index 5e2ee8c8f6..5529f2af46 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -2292,13 +2292,17 @@ function auto_prune($forum_id, $prune_mode, $prune_flags, $prune_days, $prune_fr } /** -* Cache moderators, called whenever permissions are changed via admin_permissions. Changes of username -* and group names must be carried through for the moderators table +* Cache moderators. Called whenever permissions are changed +* via admin_permissions. Changes of usernames and group names +* must be carried through for the moderators table. +* +* @param phpbb_db_driver $db Database connection +* @param phpbb_cache_driver_interface Cache driver +* @param phpbb_auth $auth Authentication object +* @return null */ -function cache_moderators() +function phpbb_cache_moderators($db, $cache, $auth) { - global $db, $cache, $auth, $phpbb_root_path, $phpEx; - // Remove cached sql results $cache->destroy('sql', MODERATOR_CACHE_TABLE); @@ -2469,6 +2473,20 @@ function cache_moderators() } /** +* Cache moderators. Called whenever permissions are changed +* via admin_permissions. Changes of usernames and group names +* must be carried through for the moderators table. +* +* @deprecated 3.1 +* @return null +*/ +function cache_moderators() +{ + global $db, $cache, $auth; + return phpbb_cache_moderators($db, $cache, $auth); +} + +/** * View log * If $log_count is set to false, we will skip counting all entries in the database. */ @@ -2740,12 +2758,16 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id } /** -* Update foes - remove moderators and administrators from foe lists... +* Removes moderators and administrators from foe lists. +* +* @param phpbb_db_driver $db Database connection +* @param phpbb_auth $auth Authentication object +* @param array|bool $group_id If an array, remove all members of this group from foe lists, or false to ignore +* @param array|bool $user_id If an array, remove this user from foe lists, or false to ignore +* @return null */ -function update_foes($group_id = false, $user_id = false) +function phpbb_update_foes($db, $auth, $group_id = false, $user_id = false) { - global $db, $auth; - // update foes for some user if (is_array($user_id) && sizeof($user_id)) { @@ -2855,6 +2877,20 @@ function update_foes($group_id = false, $user_id = false) } /** +* Removes moderators and administrators from foe lists. +* +* @deprecated 3.1 +* @param array|bool $group_id If an array, remove all members of this group from foe lists, or false to ignore +* @param array|bool $user_id If an array, remove this user from foe lists, or false to ignore +* @return null +*/ +function update_foes($group_id = false, $user_id = false) +{ + global $db, $auth; + return phpbb_update_foes($db, $auth, $group_id, $user_id); +} + +/** * Lists inactive users */ function view_inactive_users(&$users, &$user_count, $limit = 0, $offset = 0, $limit_days = 0, $sort_by = 'user_inactive_time DESC') @@ -3308,7 +3344,7 @@ function obtain_latest_version_info($force_update = false, $warn_fail = false, $ * @param int $flag The binary flag which is OR-ed with the current column value * @param string $sql_more This string is attached to the sql query generated to update the table. * - * @return void + * @return null */ function enable_bitfield_column_flag($table_name, $column_name, $flag, $sql_more = '') { diff --git a/phpBB/includes/functions_container.php b/phpBB/includes/functions_container.php new file mode 100644 index 0000000000..a3ed21c35b --- /dev/null +++ b/phpBB/includes/functions_container.php @@ -0,0 +1,199 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +use Symfony\Component\Config\FileLocator; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Dumper\PhpDumper; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Create the ContainerBuilder object +* +* @param array $extensions Array of Container extension objects +* @param string $phpbb_root_path Root path +* @param string $php_ext PHP Extension +* @return ContainerBuilder object +*/ +function phpbb_create_container(array $extensions, $phpbb_root_path, $php_ext) +{ + $container = new ContainerBuilder(); + + foreach ($extensions as $extension) + { + $container->registerExtension($extension); + $container->loadFromExtension($extension->getAlias()); + } + + $container->setParameter('core.root_path', $phpbb_root_path); + $container->setParameter('core.php_ext', $php_ext); + + return $container; +} + +/** +* Create installer container +* +* @param string $phpbb_root_path Root path +* @param string $php_ext PHP Extension +* @return ContainerBuilder object +*/ +function phpbb_create_install_container($phpbb_root_path, $php_ext) +{ + $core = new phpbb_di_extension_core($phpbb_root_path); + $container = phpbb_create_container(array($core), $phpbb_root_path, $php_ext); + + $container->setParameter('core.root_path', $phpbb_root_path); + $container->setParameter('core.php_ext', $php_ext); + $container->setParameter('core.table_prefix', ''); + + $container->register('dbal.conn')->setSynthetic(true); + + $container->setAlias('cache.driver', 'cache.driver.install'); + + $container->compile(); + + return $container; +} + +/** +* Create a compiled ContainerBuilder object +* +* @param array $extensions Array of Container extension objects +* @param array $passes Array of Compiler Pass objects +* @param string $phpbb_root_path Root path +* @param string $php_ext PHP Extension +* @return ContainerBuilder object (compiled) +*/ +function phpbb_create_compiled_container(array $extensions, array $passes, $phpbb_root_path, $php_ext) +{ + // Create a temporary container for access to the ext.manager service + $tmp_container = phpbb_create_container($extensions, $phpbb_root_path, $php_ext); + $tmp_container->compile(); + + // XXX stop writing to global $cache when + // http://tracker.phpbb.com/browse/PHPBB3-11203 is fixed + $GLOBALS['cache'] = $tmp_container->get('cache'); + $installed_exts = $tmp_container->get('ext.manager')->all_enabled(); + + // Now pass the enabled extension paths into the ext compiler extension + $extensions[] = new phpbb_di_extension_ext($installed_exts); + + // Create the final container to be compiled and cached + $container = phpbb_create_container($extensions, $phpbb_root_path, $php_ext); + + // Compile the container + foreach ($passes as $pass) + { + $container->addCompilerPass($pass); + } + $container->compile(); + + return $container; +} + +/** +* Create a compiled and dumped ContainerBuilder object +* +* @param array $extensions Array of Container extension objects +* @param array $passes Array of Compiler Pass objects +* @param string $phpbb_root_path Root path +* @param string $php_ext PHP Extension +* @return ContainerBuilder object (compiled) +*/ +function phpbb_create_dumped_container(array $extensions, array $passes, $phpbb_root_path, $php_ext) +{ + // Check for our cached container; if it exists, use it + $container_filename = phpbb_container_filename($phpbb_root_path, $php_ext); + if (file_exists($container_filename)) + { + require($container_filename); + return new phpbb_cache_container(); + } + + $container = phpbb_create_compiled_container($extensions, $passes, $phpbb_root_path, $php_ext); + + // Lastly, we create our cached container class + $dumper = new PhpDumper($container); + $cached_container_dump = $dumper->dump(array( + 'class' => 'phpbb_cache_container', + 'base_class' => 'Symfony\\Component\\DependencyInjection\\ContainerBuilder', + )); + + file_put_contents($container_filename, $cached_container_dump); + + return $container; +} + +/** +* Create an environment-specific ContainerBuilder object +* +* If debug is enabled, the container is re-compiled every time. +* This ensures that the latest changes will always be reflected +* during development. +* +* Otherwise it will get the existing dumped container and use +* that one instead. +* +* @param array $extensions Array of Container extension objects +* @param array $passes Array of Compiler Pass objects +* @param string $phpbb_root_path Root path +* @param string $php_ext PHP Extension +* @return ContainerBuilder object (compiled) +*/ +function phpbb_create_dumped_container_unless_debug(array $extensions, array $passes, $phpbb_root_path, $php_ext) +{ + $container_factory = defined('DEBUG') ? 'phpbb_create_compiled_container' : 'phpbb_create_dumped_container'; + return $container_factory($extensions, $passes, $phpbb_root_path, $php_ext); +} + +/** +* Create a default ContainerBuilder object +* +* Contains the default configuration of the phpBB container. +* +* @param array $extensions Array of Container extension objects +* @param array $passes Array of Compiler Pass objects +* @return ContainerBuilder object (compiled) +*/ +function phpbb_create_default_container($phpbb_root_path, $php_ext) +{ + return phpbb_create_dumped_container_unless_debug( + array( + new phpbb_di_extension_config($phpbb_root_path . 'config.' . $php_ext), + new phpbb_di_extension_core($phpbb_root_path), + ), + array( + new phpbb_di_pass_collection_pass(), + new phpbb_di_pass_kernel_pass(), + ), + $phpbb_root_path, + $php_ext + ); +} + +/** +* Get the filename under which the dumped container will be stored. +* +* @param string $phpbb_root_path Root path +* @param string $php_ext PHP Extension +* @return Path for dumped container +*/ +function phpbb_container_filename($phpbb_root_path, $php_ext) +{ + $filename = str_replace(array('/', '.'), array('slash', 'dot'), $phpbb_root_path); + return $phpbb_root_path . 'cache/container_' . $filename . '.' . $php_ext; +} diff --git a/phpBB/includes/functions_database_helper.php b/phpBB/includes/functions_database_helper.php new file mode 100644 index 0000000000..1b508e6a02 --- /dev/null +++ b/phpBB/includes/functions_database_helper.php @@ -0,0 +1,206 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Updates rows in given table from a set of values to a new value. +* If this results in rows violating uniqueness constraints, the duplicate +* rows are eliminated. +* +* The only supported table is bookmarks. +* +* @param phpbb_db_driver $db Database object +* @param string $table Table on which to perform the update +* @param string $column Column whose values to change +* @param array $from_values An array of values that should be changed +* @param int $to_value The new value +* @return null +*/ +function phpbb_update_rows_avoiding_duplicates(phpbb_db_driver $db, $table, $column, $from_values, $to_value) +{ + $sql = "SELECT $column, user_id + FROM $table + WHERE " . $db->sql_in_set($column, $from_values); + $result = $db->sql_query($sql); + + $old_user_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $old_user_ids[$row[$column]][] = (int) $row['user_id']; + } + $db->sql_freeresult($result); + + $sql = "SELECT $column, user_id + FROM $table + WHERE $column = " . (int) $to_value; + $result = $db->sql_query($sql); + + $new_user_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $new_user_ids[$row[$column]][] = (int) $row['user_id']; + } + $db->sql_freeresult($result); + + $queries = array(); + foreach ($from_values as $from_value) + { + if (!isset($old_user_ids[$from_value])) + { + continue; + } + if (empty($new_user_ids)) + { + $sql = "UPDATE $table + SET $column = " . (int) $to_value . " + WHERE $column = '" . $db->sql_escape($from_value) . "'"; + $queries[] = $sql; + } + else + { + $different_user_ids = array_diff($old_user_ids[$from_value], $new_user_ids[$to_value]); + if (!empty($different_user_ids)) + { + $sql = "UPDATE $table + SET $column = " . (int) $to_value . " + WHERE $column = '" . $db->sql_escape($from_value) . "' + AND " . $db->sql_in_set('user_id', $different_user_ids); + $queries[] = $sql; + } + } + } + + if (!empty($queries)) + { + $db->sql_transaction('begin'); + + foreach ($queries as $sql) + { + $db->sql_query($sql); + } + + $sql = "DELETE FROM $table + WHERE " . $db->sql_in_set($column, $from_values); + $db->sql_query($sql); + + $db->sql_transaction('commit'); + } +} + +/** +* Updates rows in given table from a set of values to a new value. +* If this results in rows violating uniqueness constraints, the duplicate +* rows are merged respecting notify_status (0 takes precedence over 1). +* +* The only supported table is topics_watch. +* +* @param phpbb_db_driver $db Database object +* @param string $table Table on which to perform the update +* @param string $column Column whose values to change +* @param array $from_values An array of values that should be changed +* @param int $to_value The new value +* @return null +*/ +function phpbb_update_rows_avoiding_duplicates_notify_status(phpbb_db_driver $db, $table, $column, $from_values, $to_value) +{ + $sql = "SELECT $column, user_id, notify_status + FROM $table + WHERE " . $db->sql_in_set($column, $from_values); + $result = $db->sql_query($sql); + + $old_user_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $old_user_ids[(int) $row['notify_status']][$row[$column]][] = (int) $row['user_id']; + } + $db->sql_freeresult($result); + + $sql = "SELECT $column, user_id + FROM $table + WHERE $column = " . (int) $to_value; + $result = $db->sql_query($sql); + + $new_user_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $new_user_ids[$row[$column]][] = (int) $row['user_id']; + } + $db->sql_freeresult($result); + + $queries = array(); + $extra_updates = array( + 0 => 'notify_status = 0', + 1 => '', + ); + foreach ($from_values as $from_value) + { + foreach ($extra_updates as $notify_status => $extra_update) + { + if (!isset($old_user_ids[$notify_status][$from_value])) + { + continue; + } + if (empty($new_user_ids)) + { + $sql = "UPDATE $table + SET $column = " . (int) $to_value . " + WHERE $column = '" . $db->sql_escape($from_value) . "'"; + $queries[] = $sql; + } + else + { + $different_user_ids = array_diff($old_user_ids[$notify_status][$from_value], $new_user_ids[$to_value]); + if (!empty($different_user_ids)) + { + $sql = "UPDATE $table + SET $column = " . (int) $to_value . " + WHERE $column = '" . $db->sql_escape($from_value) . "' + AND " . $db->sql_in_set('user_id', $different_user_ids); + $queries[] = $sql; + } + + if ($extra_update) + { + $same_user_ids = array_diff($old_user_ids[$notify_status][$from_value], $different_user_ids); + if (!empty($same_user_ids)) + { + $sql = "UPDATE $table + SET $extra_update + WHERE $column = '" . (int) $to_value . "' + AND " . $db->sql_in_set('user_id', $same_user_ids); + $queries[] = $sql; + } + } + } + } + } + + if (!empty($queries)) + { + $db->sql_transaction('begin'); + + foreach ($queries as $sql) + { + $db->sql_query($sql); + } + + $sql = "DELETE FROM $table + WHERE " . $db->sql_in_set($column, $from_values); + $db->sql_query($sql); + + $db->sql_transaction('commit'); + } +} diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php index 73129803ee..cd4c901b58 100644 --- a/phpBB/includes/functions_display.php +++ b/phpBB/includes/functions_display.php @@ -61,6 +61,20 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod { markread('all', false, false, request_var('mark_time', 0)); + if ($request->is_ajax()) + { + // Tell the ajax script what language vars and URL need to be replaced + $data = array( + 'NO_UNREAD_POSTS' => $user->lang['NO_UNREAD_POSTS'], + 'UNREAD_POSTS' => $user->lang['UNREAD_POSTS'], + 'U_MARK_FORUMS' => ($user->data['is_registered'] || $config['load_anon_lastread']) ? append_sid("{$phpbb_root_path}index.$phpEx", 'hash=' . generate_link_hash('global') . '&mark=forums&mark_time=' . time()) : '', + 'MESSAGE_TITLE' => $user->lang['INFORMATION'], + 'MESSAGE_TEXT' => $user->lang['FORUMS_MARKED'] + ); + $json_response = new phpbb_json_response(); + $json_response->send($data); + } + trigger_error( $user->lang['FORUMS_MARKED'] . '<br /><br />' . sprintf($user->lang['RETURN_INDEX'], '<a href="' . $redirect . '">', '</a>') @@ -313,6 +327,20 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod $message = sprintf($user->lang['RETURN_FORUM'], '<a href="' . $redirect . '">', '</a>'); meta_refresh(3, $redirect); + if ($request->is_ajax()) + { + // Tell the ajax script what language vars and URL need to be replaced + $data = array( + 'NO_UNREAD_POSTS' => $user->lang['NO_UNREAD_POSTS'], + 'UNREAD_POSTS' => $user->lang['UNREAD_POSTS'], + 'U_MARK_FORUMS' => ($user->data['is_registered'] || $config['load_anon_lastread']) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'hash=' . generate_link_hash('global') . '&f=' . $root_data['forum_id'] . '&mark=forums&mark_time=' . time()) : '', + 'MESSAGE_TITLE' => $user->lang['INFORMATION'], + 'MESSAGE_TEXT' => $user->lang['FORUMS_MARKED'] + ); + $json_response = new phpbb_json_response(); + $json_response->send($data); + } + trigger_error($user->lang['FORUMS_MARKED'] . '<br /><br />' . $message); } else diff --git a/phpBB/includes/functions_download.php b/phpBB/includes/functions_download.php index b6371dbecc..9ae647d806 100644 --- a/phpBB/includes/functions_download.php +++ b/phpBB/includes/functions_download.php @@ -433,7 +433,7 @@ function set_modified_headers($stamp, $browser) * * @param bool $exit Whether to die or not. * -* @return void +* @return null */ function file_gc($exit = true) { @@ -596,7 +596,7 @@ function phpbb_parse_range_request($request_array, $filesize) /** * Increments the download count of all provided attachments * -* @param dbal $db The database object +* @param phpbb_db_driver $db The database object * @param array|int $ids The attach_id of each attachment * * @return null @@ -617,7 +617,7 @@ function phpbb_increment_downloads($db, $ids) /** * Handles authentication when downloading attachments from a post or topic * -* @param dbal $db The database object +* @param phpbb_db_driver $db The database object * @param phpbb_auth $auth The authentication object * @param int $topic_id The id of the topic that we are downloading from * @@ -651,7 +651,7 @@ function phpbb_download_handle_forum_auth($db, $auth, $topic_id) /** * Handles authentication when downloading attachments from PMs * -* @param dbal $db The database object +* @param phpbb_db_driver $db The database object * @param phpbb_auth $auth The authentication object * @param int $user_id The user id * @param int $msg_id The id of the PM that we are downloading from @@ -678,7 +678,7 @@ function phpbb_download_handle_pm_auth($db, $auth, $user_id, $msg_id) /** * Checks whether a user can download from a particular PM * -* @param dbal $db The database object +* @param phpbb_db_driver $db The database object * @param int $user_id The user id * @param int $msg_id The id of the PM that we are downloading from * diff --git a/phpBB/includes/functions_install.php b/phpBB/includes/functions_install.php index 7a799993db..8978e3fadd 100644 --- a/phpBB/includes/functions_install.php +++ b/phpBB/includes/functions_install.php @@ -28,16 +28,18 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20 'SCHEMA' => 'firebird', 'MODULE' => 'interbase', 'DELIM' => ';;', - 'DRIVER' => 'firebird', + 'DRIVER' => 'phpbb_db_driver_firebird', 'AVAILABLE' => true, '2.0.x' => false, ), + // Note: php 5.5 alpha 2 deprecated mysql. + // Keep mysqli before mysql in this list. 'mysqli' => array( 'LABEL' => 'MySQL with MySQLi Extension', 'SCHEMA' => 'mysql_41', 'MODULE' => 'mysqli', 'DELIM' => ';', - 'DRIVER' => 'mysqli', + 'DRIVER' => 'phpbb_db_driver_mysqli', 'AVAILABLE' => true, '2.0.x' => true, ), @@ -46,7 +48,7 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20 'SCHEMA' => 'mysql', 'MODULE' => 'mysql', 'DELIM' => ';', - 'DRIVER' => 'mysql', + 'DRIVER' => 'phpbb_db_driver_mysql', 'AVAILABLE' => true, '2.0.x' => true, ), @@ -55,7 +57,7 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20 'SCHEMA' => 'mssql', 'MODULE' => 'mssql', 'DELIM' => 'GO', - 'DRIVER' => 'mssql', + 'DRIVER' => 'phpbb_db_driver_mssql', 'AVAILABLE' => true, '2.0.x' => true, ), @@ -64,7 +66,7 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20 'SCHEMA' => 'mssql', 'MODULE' => 'odbc', 'DELIM' => 'GO', - 'DRIVER' => 'mssql_odbc', + 'DRIVER' => 'phpbb_db_driver_mssql_odbc', 'AVAILABLE' => true, '2.0.x' => true, ), @@ -73,7 +75,7 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20 'SCHEMA' => 'mssql', 'MODULE' => 'sqlsrv', 'DELIM' => 'GO', - 'DRIVER' => 'mssqlnative', + 'DRIVER' => 'phpbb_db_driver_mssqlnative', 'AVAILABLE' => true, '2.0.x' => false, ), @@ -82,16 +84,16 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20 'SCHEMA' => 'oracle', 'MODULE' => 'oci8', 'DELIM' => '/', - 'DRIVER' => 'oracle', + 'DRIVER' => 'phpbb_db_driver_oracle', 'AVAILABLE' => true, '2.0.x' => false, ), 'postgres' => array( - 'LABEL' => 'PostgreSQL 7.x/8.x', + 'LABEL' => 'PostgreSQL 8.3+', 'SCHEMA' => 'postgres', 'MODULE' => 'pgsql', 'DELIM' => ';', - 'DRIVER' => 'postgres', + 'DRIVER' => 'phpbb_db_driver_postgres', 'AVAILABLE' => true, '2.0.x' => true, ), @@ -100,7 +102,7 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20 'SCHEMA' => 'sqlite', 'MODULE' => 'sqlite', 'DELIM' => ';', - 'DRIVER' => 'sqlite', + 'DRIVER' => 'phpbb_db_driver_sqlite', 'AVAILABLE' => true, '2.0.x' => false, ), @@ -205,26 +207,19 @@ function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix, $dbms = $dbms_details['DRIVER']; - if ($load_dbal) - { - // Include the DB layer - include($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx); - } - // Instantiate it and set return on error true - $sql_db = 'dbal_' . $dbms; - $db = new $sql_db(); + $db = new $dbms(); $db->sql_return_on_error(true); // Check that we actually have a database name before going any further..... - if ($dbms_details['DRIVER'] != 'sqlite' && $dbms_details['DRIVER'] != 'oracle' && $dbname === '') + if ($dbms_details['DRIVER'] != 'phpbb_db_driver_sqlite' && $dbms_details['DRIVER'] != 'phpbb_db_driver_oracle' && $dbname === '') { $error[] = $lang['INST_ERR_DB_NO_NAME']; return false; } // Make sure we don't have a daft user who thinks having the SQLite database in the forum directory is a good idea - if ($dbms_details['DRIVER'] == 'sqlite' && stripos(phpbb_realpath($dbhost), phpbb_realpath('../')) === 0) + if ($dbms_details['DRIVER'] == 'phpbb_db_driver_sqlite' && stripos(phpbb_realpath($dbhost), phpbb_realpath('../')) === 0) { $error[] = $lang['INST_ERR_DB_FORUM_PATH']; return false; @@ -233,8 +228,8 @@ function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix, // Check the prefix length to ensure that index names are not too long and does not contain invalid characters switch ($dbms_details['DRIVER']) { - case 'mysql': - case 'mysqli': + case 'phpbb_db_driver_mysql': + case 'phpbb_db_driver_mysqli': if (strspn($table_prefix, '-./\\') !== 0) { $error[] = $lang['INST_ERR_PREFIX_INVALID']; @@ -243,22 +238,22 @@ function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix, // no break; - case 'postgres': + case 'phpbb_db_driver_postgres': $prefix_length = 36; break; - case 'mssql': - case 'mssql_odbc': - case 'mssqlnative': + case 'phpbb_db_driver_mssql': + case 'phpbb_db_driver_mssql_odbc': + case 'phpbb_db_driver_mssqlnative': $prefix_length = 90; break; - case 'sqlite': + case 'phpbb_db_driver_sqlite': $prefix_length = 200; break; - case 'firebird': - case 'oracle': + case 'phpbb_db_driver_firebird': + case 'phpbb_db_driver_oracle': $prefix_length = 6; break; } @@ -296,21 +291,21 @@ function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix, // Make sure that the user has selected a sensible DBAL for the DBMS actually installed switch ($dbms_details['DRIVER']) { - case 'mysqli': + case 'phpbb_db_driver_mysqli': if (version_compare(mysqli_get_server_info($db->db_connect_id), '4.1.3', '<')) { $error[] = $lang['INST_ERR_DB_NO_MYSQLI']; } break; - case 'sqlite': + case 'phpbb_db_driver_sqlite': if (version_compare(sqlite_libversion(), '2.8.2', '<')) { $error[] = $lang['INST_ERR_DB_NO_SQLITE']; } break; - case 'firebird': + case 'phpbb_db_driver_firebird': // check the version of FB, use some hackery if we can't get access to the server info if ($db->service_handle !== false && function_exists('ibase_server_info')) { @@ -391,7 +386,7 @@ function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix, } break; - case 'oracle': + case 'phpbb_db_driver_oracle': if ($unicode_check) { $sql = "SELECT * @@ -413,7 +408,7 @@ function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix, } break; - case 'postgres': + case 'phpbb_db_driver_postgres': if ($unicode_check) { $sql = "SHOW server_encoding;"; @@ -515,6 +510,9 @@ function phpbb_create_config_file_data($data, $dbms, $debug = false, $debug_test 'dbuser' => $data['dbuser'], 'dbpasswd' => htmlspecialchars_decode($data['dbpasswd']), 'table_prefix' => $data['table_prefix'], + + 'adm_relative_path' => 'adm/', + 'acm_type' => 'phpbb_cache_driver_file', ); diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index cf03de08c4..d0a02567ad 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -210,7 +210,7 @@ class messenger { $style_resource_locator = new phpbb_style_resource_locator(); $style_path_provider = new phpbb_style_extension_path_provider($phpbb_extension_manager, new phpbb_style_path_provider()); - $tpl = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, new phpbb_template_context()); + $tpl = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, new phpbb_template_context(), $phpbb_extension_manager); $style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, $style_path_provider, $tpl); $this->tpl_msg[$template_lang . $template_file] = $tpl; @@ -231,7 +231,7 @@ class messenger } } - $style->set_custom_style($template_lang . '_email', array($template_path, $fallback_template_path), ''); + $style->set_custom_style($template_lang . '_email', array($template_path, $fallback_template_path), array(), ''); $tpl->set_filenames(array( 'body' => $template_file . '.txt', @@ -651,64 +651,6 @@ class queue } /** - * Obtains exclusive lock on queue cache file. - * Returns resource representing the lock - */ - function lock() - { - // For systems that can't have two processes opening - // one file for writing simultaneously - if (file_exists($this->cache_file . '.lock')) - { - $mode = 'rb'; - } - else - { - $mode = 'wb'; - } - - $lock_fp = @fopen($this->cache_file . '.lock', $mode); - - if ($mode == 'wb') - { - if (!$lock_fp) - { - // Two processes may attempt to create lock file at the same time. - // Have the losing process try opening the lock file again for reading - // on the assumption that the winning process created it - $mode = 'rb'; - $lock_fp = @fopen($this->cache_file . '.lock', $mode); - } - else - { - // Only need to set mode when the lock file is written - @chmod($this->cache_file . '.lock', 0666); - } - } - - if ($lock_fp) - { - @flock($lock_fp, LOCK_EX); - } - - return $lock_fp; - } - - /** - * Releases lock on queue cache file, using resource obtained from lock() - */ - function unlock($lock_fp) - { - // lock() will return null if opening lock file, and thus locking, failed. - // Accept null values here so that client code does not need to check them - if ($lock_fp) - { - @flock($lock_fp, LOCK_UN); - fclose($lock_fp); - } - } - - /** * Process queue * Using lock file */ @@ -716,16 +658,24 @@ class queue { global $db, $config, $phpEx, $phpbb_root_path, $user; - $lock_fp = $this->lock(); + $lock = new phpbb_lock_flock($this->cache_file); + $lock->acquire(); - set_config('last_queue_run', time(), true); - - if (!file_exists($this->cache_file) || filemtime($this->cache_file) > time() - $config['queue_interval']) + // avoid races, check file existence once + $have_cache_file = file_exists($this->cache_file); + if (!$have_cache_file || $config['last_queue_run'] > time() - $config['queue_interval']) { - $this->unlock($lock_fp); + if (!$have_cache_file) + { + set_config('last_queue_run', time(), true); + } + + $lock->release(); return; } + set_config('last_queue_run', time(), true); + include($this->cache_file); foreach ($this->queue_data as $object => $data_ary) @@ -789,7 +739,7 @@ class queue break; default: - $this->unlock($lock_fp); + $lock->release(); return; } @@ -865,7 +815,7 @@ class queue } } - $this->unlock($lock_fp); + $lock->release(); } /** @@ -878,7 +828,8 @@ class queue return; } - $lock_fp = $this->lock(); + $lock = new phpbb_lock_flock($this->cache_file); + $lock->acquire(); if (file_exists($this->cache_file)) { @@ -905,7 +856,7 @@ class queue phpbb_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE); } - $this->unlock($lock_fp); + $lock->release(); } } diff --git a/phpBB/includes/functions_module.php b/phpBB/includes/functions_module.php index ad76be9f2f..0d387ace6d 100644 --- a/phpBB/includes/functions_module.php +++ b/phpBB/includes/functions_module.php @@ -759,7 +759,26 @@ class p_master } } - $u_title = $module_url . $delim . 'i=' . (($item_ary['cat']) ? $item_ary['id'] : $item_ary['name'] . (($item_ary['is_duplicate']) ? '&icat=' . $current_id : '') . '&mode=' . $item_ary['mode']); + $u_title = $module_url . $delim . 'i='; + // if the item has a name use it, else use its id + if (empty($item_ary['name'])) + { + $u_title .= $item_ary['id']; + } + else + { + // if the category has a name, then use it. + $u_title .= $item_ary['name']; + } + // If the item is not a category append the mode + if (!$item_ary['cat']) + { + if ($item_ary['is_duplicate']) + { + $u_title .= '&icat=' . $current_id; + } + $u_title .= '&mode=' . $item_ary['mode']; + } // Was not allowed in categories before - /*!$item_ary['cat'] && */ $u_title .= (isset($item_ary['url_extra'])) ? $item_ary['url_extra'] : ''; diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index 171cf988ce..8aea27a9ef 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -1695,8 +1695,9 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u // The variable name should be $post_approved, because it indicates if the post is approved or not $post_approval = 1; - // Check the permissions for post approval. Moderators are not affected. - if (!$auth->acl_get('f_noapprove', $data['forum_id']) && !$auth->acl_get('m_approve', $data['forum_id'])) + // Check the permissions for post approval. + // Moderators must go through post approval like ordinary users. + if (!$auth->acl_get('f_noapprove', $data['forum_id'])) { // Post not approved, but in queue $post_approval = 0; diff --git a/phpBB/includes/functions_upload.php b/phpBB/includes/functions_upload.php index b467aa93d1..4f31a85e83 100644 --- a/phpBB/includes/functions_upload.php +++ b/phpBB/includes/functions_upload.php @@ -70,7 +70,7 @@ class filespec $this->mimetype = 'application/octetstream'; } - $this->extension = strtolower($this->get_extension($this->realname)); + $this->extension = strtolower(self::get_extension($this->realname)); // Try to get real filesize from temporary folder (not always working) ;) $this->filesize = (@filesize($this->filename)) ? @filesize($this->filename) : $this->filesize; @@ -187,8 +187,11 @@ class filespec /** * Get file extension + * + * @param string Filename that needs to be checked + * @return string Extension of the supplied filename */ - function get_extension($filename) + static public function get_extension($filename) { if (strpos($filename, '.') === false) { @@ -369,7 +372,7 @@ class filespec } // Check image type - $types = $this->upload->image_types(); + $types = fileupload::image_types(); if (!isset($types[$this->image_info[2]]) || !in_array($this->extension, $types[$this->image_info[2]])) { @@ -1019,9 +1022,11 @@ class fileupload } /** - * Return image type/extension mapping + * Get image type/extension mapping + * + * @return array Array containing the image types and their extensions */ - function image_types() + static public function image_types() { return array( IMAGETYPE_GIF => array('gif'), diff --git a/phpBB/includes/functions_url_matcher.php b/phpBB/includes/functions_url_matcher.php new file mode 100644 index 0000000000..7280cb74eb --- /dev/null +++ b/phpBB/includes/functions_url_matcher.php @@ -0,0 +1,106 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper; +use Symfony\Component\Routing\Matcher\UrlMatcher; +use Symfony\Component\Routing\RequestContext; + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Create a new UrlMatcher class and dump it into the cache file +* +* @param phpbb_extension_finder $finder Extension finder +* @param RequestContext $context Symfony RequestContext object +* @param string $root_path Root path +* @param string $php_ext PHP extension +* @return null +*/ +function phpbb_get_url_matcher(phpbb_extension_finder $finder, RequestContext $context, $root_path, $php_ext) +{ + if (defined('DEBUG')) + { + return phpbb_create_url_matcher($finder, $context); + } + + if (!phpbb_url_matcher_dumped($root_path, $php_ext)) + { + phpbb_create_dumped_url_matcher($finder, $root_path, $php_ext); + } + + return phpbb_load_url_matcher($context, $root_path, $php_ext); +} + +/** +* Create a new UrlMatcher class and dump it into the cache file +* +* @param phpbb_extension_finder $finder Extension finder +* @param string $root_path Root path +* @param string $php_ext PHP extension +* @return null +*/ +function phpbb_create_dumped_url_matcher(phpbb_extension_finder $finder, $root_path, $php_ext) +{ + $provider = new phpbb_controller_provider(); + $routes = $provider->import_paths_from_finder($finder)->find(); + $dumper = new PhpMatcherDumper($routes); + $cached_url_matcher_dump = $dumper->dump(array( + 'class' => 'phpbb_url_matcher', + )); + + file_put_contents($root_path . 'cache/url_matcher' . $php_ext, $cached_url_matcher_dump); +} + +/** +* Create a non-cached UrlMatcher +* +* @param phpbb_extension_finder $finder Extension finder +* @param RequestContext $context Symfony RequestContext object +* @return UrlMatcher +*/ +function phpbb_create_url_matcher(phpbb_extension_finder $finder, RequestContext $context) +{ + $provider = new phpbb_controller_provider(); + $routes = $provider->import_paths_from_finder($finder)->find(); + return new UrlMatcher($routes, $context); +} + +/** +* Load the cached phpbb_url_matcher class +* +* @param RequestContext $context Symfony RequestContext object +* @param string $root_path Root path +* @param string $php_ext PHP extension +* @return phpbb_url_matcher +*/ +function phpbb_load_url_matcher(RequestContext $context, $root_path, $php_ext) +{ + require($root_path . 'cache/url_matcher' . $php_ext); + return new phpbb_url_matcher($context); +} + +/** +* Determine whether we have our dumped URL matcher +* +* The class is automatically dumped to the cache directory +* +* @param string $root_path Root path +* @param string $php_ext PHP extension +* @return bool True if it exists, false if not +*/ +function phpbb_url_matcher_dumped($root_path, $php_ext) +{ + return file_exists($root_path . 'cache/url_matcher' . $php_ext); +} diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index 8f9c9198f4..6abcdee8f2 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -2842,7 +2842,7 @@ function avatar_remove_db($avatar_name) */ function group_delete($group_id, $group_name = false) { - global $db, $phpbb_root_path, $phpEx, $phpbb_dispatcher; + global $db, $cache, $auth, $phpbb_root_path, $phpEx, $phpbb_dispatcher; if (!$group_name) { @@ -2913,12 +2913,12 @@ function group_delete($group_id, $group_name = false) extract($phpbb_dispatcher->trigger_event('core.delete_group_after', compact($vars))); // Re-cache moderators - if (!function_exists('cache_moderators')) + if (!function_exists('phpbb_cache_moderators')) { include($phpbb_root_path . 'includes/functions_admin.' . $phpEx); } - cache_moderators(); + phpbb_cache_moderators($db, $cache, $auth); add_log('admin', 'LOG_GROUP_DELETE', $group_name); @@ -3463,7 +3463,7 @@ function group_validate_groupname($group_id, $group_name) */ function group_set_user_default($group_id, $user_id_ary, $group_attributes = false, $update_listing = false) { - global $cache, $db, $phpbb_dispatcher; + global $phpbb_container, $db, $phpbb_dispatcher; if (empty($user_id_ary)) { @@ -3579,7 +3579,7 @@ function group_set_user_default($group_id, $user_id_ary, $group_attributes = fal } // Because some tables/caches use usercolour-specific data we need to purge this here. - $cache->destroy('sql', MODERATOR_CACHE_TABLE); + $phpbb_container->get('cache.driver')->destroy('sql', MODERATOR_CACHE_TABLE); } /** @@ -3678,7 +3678,7 @@ function group_memberships($group_id_ary = false, $user_id_ary = false, $return_ */ function group_update_listings($group_id) { - global $auth; + global $db, $cache, $auth; $hold_ary = $auth->acl_group_raw_data($group_id, array('a_', 'm_')); @@ -3720,22 +3720,22 @@ function group_update_listings($group_id) if ($mod_permissions) { - if (!function_exists('cache_moderators')) + if (!function_exists('phpbb_cache_moderators')) { global $phpbb_root_path, $phpEx; include($phpbb_root_path . 'includes/functions_admin.' . $phpEx); } - cache_moderators(); + phpbb_cache_moderators($db, $cache, $auth); } if ($mod_permissions || $admin_permissions) { - if (!function_exists('update_foes')) + if (!function_exists('phpbb_update_foes')) { global $phpbb_root_path, $phpEx; include($phpbb_root_path . 'includes/functions_admin.' . $phpEx); } - update_foes(array($group_id)); + phpbb_update_foes($db, $auth, array($group_id)); } } diff --git a/phpBB/includes/group_positions.php b/phpBB/includes/group_positions.php index 74de3516cb..60352ed97d 100644 --- a/phpBB/includes/group_positions.php +++ b/phpBB/includes/group_positions.php @@ -104,7 +104,7 @@ class phpbb_group_positions * Addes a group by group_id * * @param int $group_id group_id of the group to be added - * @return void + * @return null */ public function add_group($group_id) { @@ -128,7 +128,7 @@ class phpbb_group_positions * * @param int $group_id group_id of the group to be deleted * @param bool $skip_group Skip setting the group to GROUP_DISABLED, to save the query, when you need to update it anyway. - * @return void + * @return null */ public function delete_group($group_id, $skip_group = false) { @@ -159,7 +159,7 @@ class phpbb_group_positions * Moves a group up by group_id * * @param int $group_id group_id of the group to be moved - * @return void + * @return null */ public function move_up($group_id) { @@ -170,7 +170,7 @@ class phpbb_group_positions * Moves a group down by group_id * * @param int $group_id group_id of the group to be moved - * @return void + * @return null */ public function move_down($group_id) { @@ -184,7 +184,7 @@ class phpbb_group_positions * @param int $delta number of steps: * - positive = move up * - negative = move down - * @return void + * @return null */ public function move($group_id, $delta) { diff --git a/phpBB/includes/hook/finder.php b/phpBB/includes/hook/finder.php new file mode 100644 index 0000000000..065e685514 --- /dev/null +++ b/phpBB/includes/hook/finder.php @@ -0,0 +1,84 @@ +<?php +/** +* +* @package extension +* @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 hook finder locates installed hooks. +* +* @package phpBB3 +*/ +class phpbb_hook_finder +{ + protected $phpbb_root_path; + protected $cache; + protected $php_ext; + + /** + * Creates a new finder instance. + * + * @param string $phpbb_root_path Path to the phpbb root directory + * @param string $php_ext php file extension + * @param phpbb_cache_driver_interface $cache A cache instance or null + */ + public function __construct($phpbb_root_path, $php_ext, phpbb_cache_driver_interface $cache = null) + { + $this->phpbb_root_path = $phpbb_root_path; + $this->cache = $cache; + $this->php_ext = $php_ext; + } + + /** + * Finds all hook files. + * + * @param bool $cache Whether the result should be cached + * @return array An array of paths to found hook files + */ + public function find($cache = true) + { + if (!defined('DEBUG') && $cache && $this->cache) + { + $hook_files = $this->cache->get('_hooks'); + if ($hook_files !== false) + { + return $hook_files; + } + } + + $hook_files = array(); + + // Now search for hooks... + $dh = @opendir($this->phpbb_root_path . 'includes/hooks/'); + + if ($dh) + { + while (($file = readdir($dh)) !== false) + { + if (strpos($file, 'hook_') === 0 && substr($file, -(strlen($this->php_ext) + 1)) === '.' . $this->php_ext) + { + $hook_files[] = substr($file, 0, -(strlen($this->php_ext) + 1)); + } + } + closedir($dh); + } + + if ($cache && $this->cache) + { + $this->cache->put('_hooks', $hook_files); + } + + return $hook_files; + } +} diff --git a/phpBB/includes/lock/db.php b/phpBB/includes/lock/db.php index fa559d6887..ccdaed0b28 100644 --- a/phpBB/includes/lock/db.php +++ b/phpBB/includes/lock/db.php @@ -48,7 +48,7 @@ class phpbb_lock_db /** * A database connection - * @var dbal + * @var phpbb_db_driver */ private $db; @@ -59,9 +59,9 @@ class phpbb_lock_db * * @param string $config_name A config variable to be used for locking * @param array $config The phpBB configuration - * @param dbal $db A database connection + * @param phpbb_db_driver $db A database connection */ - public function __construct($config_name, phpbb_config $config, dbal $db) + public function __construct($config_name, phpbb_config $config, phpbb_db_driver $db) { $this->config_name = $config_name; $this->config = $config; @@ -125,7 +125,7 @@ class phpbb_lock_db * Note: Attempting to release a lock that is already released, * that is, calling release() multiple times, is harmless. * - * @return void + * @return null */ public function release() { diff --git a/phpBB/includes/lock/flock.php b/phpBB/includes/lock/flock.php new file mode 100644 index 0000000000..97bc7dd2b9 --- /dev/null +++ b/phpBB/includes/lock/flock.php @@ -0,0 +1,133 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* File locking class +* @package phpBB3 +*/ +class phpbb_lock_flock +{ + /** + * Path to the file to which access is controlled + * + * @var string + */ + private $path; + + /** + * File pointer for the lock file + * @var string + */ + private $lock_fp; + + /** + * Constructor. + * + * You have to call acquire() to actually acquire the lock. + * + * @param string $path Path to the file to which access is controlled + */ + public function __construct($path) + { + $this->path = $path; + $this->lock_fp = null; + } + + /** + * Tries to acquire the lock. + * + * If the lock is already held by another process, this call will block + * until the other process releases the lock. If a lock is acquired and + * is not released before script finishes but the process continues to + * live (apache/fastcgi) then subsequent processes trying to acquire + * the same lock will be blocked forever. + * + * If the lock is already held by the same process via another instance + * of this class, this call will block forever. + * + * If flock function is disabled in php or fails to work, lock + * acquisition will fail and false will be returned. + * + * @return bool true if lock was acquired + * false otherwise + */ + public function acquire() + { + if ($this->lock_fp) + { + return false; + } + + // For systems that can't have two processes opening + // one file for writing simultaneously + if (file_exists($this->path . '.lock')) + { + $mode = 'rb'; + } + else + { + $mode = 'wb'; + } + + $this->lock_fp = @fopen($this->path . '.lock', $mode); + + if ($mode == 'wb') + { + if (!$this->lock_fp) + { + // Two processes may attempt to create lock file at the same time. + // Have the losing process try opening the lock file again for reading + // on the assumption that the winning process created it + $mode = 'rb'; + $this->lock_fp = @fopen($this->path . '.lock', $mode); + } + else + { + // Only need to set mode when the lock file is written + @chmod($this->path . '.lock', 0666); + } + } + + if ($this->lock_fp) + { + @flock($this->lock_fp, LOCK_EX); + } + + return (bool) $this->lock_fp; + } + + /** + * Releases the lock. + * + * The lock must have been previously obtained, that is, acquire() call + * was issued and returned true. + * + * Note: Attempting to release a lock that is already released, + * that is, calling release() multiple times, is harmless. + * + * @return null + */ + public function release() + { + if ($this->lock_fp) + { + @flock($this->lock_fp, LOCK_UN); + fclose($this->lock_fp); + $this->lock_fp = null; + } + } +} diff --git a/phpBB/includes/mcp/mcp_forum.php b/phpBB/includes/mcp/mcp_forum.php index 4dd5e5856a..0fad9e2a22 100644 --- a/phpBB/includes/mcp/mcp_forum.php +++ b/phpBB/includes/mcp/mcp_forum.php @@ -430,13 +430,16 @@ function merge_topics($forum_id, $topic_ids, $to_topic_id) // Message and return links $success_msg = 'POSTS_MERGED_SUCCESS'; - // If the topic no longer exist, we will update the topic watch table. - // To not let it error out on users watching both topics, we just return on an error... - $db->sql_return_on_error(true); - $db->sql_query('UPDATE ' . TOPICS_WATCH_TABLE . ' SET topic_id = ' . (int) $to_topic_id . ' WHERE ' . $db->sql_in_set('topic_id', $topic_ids)); - $db->sql_return_on_error(false); + if (!function_exists('phpbb_update_rows_avoiding_duplicates_notify_status')) + { + include($phpbb_root_path . 'includes/functions_database_helper.' . $phpEx); + } + + // Update the topic watch table. + phpbb_update_rows_avoiding_duplicates_notify_status($db, TOPICS_WATCH_TABLE, 'topic_id', $topic_ids, $to_topic_id); - $db->sql_query('DELETE FROM ' . TOPICS_WATCH_TABLE . ' WHERE ' . $db->sql_in_set('topic_id', $topic_ids)); + // Update the bookmarks table. + phpbb_update_rows_avoiding_duplicates($db, BOOKMARKS_TABLE, 'topic_id', $topic_ids, $to_topic_id); // Link to the new topic $return_link .= (($return_link) ? '<br /><br />' : '') . sprintf($user->lang['RETURN_NEW_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $to_forum_id . '&t=' . $to_topic_id) . '">', '</a>'); diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php index 95ca7c2e1b..c28b466bcf 100644 --- a/phpBB/includes/mcp/mcp_main.php +++ b/phpBB/includes/mcp/mcp_main.php @@ -1080,6 +1080,7 @@ function mcp_fork_topic($topic_ids) } } + // Copy topic subscriptions to new topic $sql = 'SELECT user_id, notify_status FROM ' . TOPICS_WATCH_TABLE . ' WHERE topic_id = ' . $topic_id; @@ -1100,6 +1101,27 @@ function mcp_fork_topic($topic_ids) { $db->sql_multi_insert(TOPICS_WATCH_TABLE, $sql_ary); } + + // Copy bookmarks to new topic + $sql = 'SELECT user_id + FROM ' . BOOKMARKS_TABLE . ' + WHERE topic_id = ' . $topic_id; + $result = $db->sql_query($sql); + + $sql_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + $sql_ary[] = array( + 'topic_id' => (int) $new_topic_id, + 'user_id' => (int) $row['user_id'], + ); + } + $db->sql_freeresult($result); + + if (sizeof($sql_ary)) + { + $db->sql_multi_insert(BOOKMARKS_TABLE, $sql_ary); + } } // Sync new topics, parent forums and board stats diff --git a/phpBB/includes/mcp/mcp_pm_reports.php b/phpBB/includes/mcp/mcp_pm_reports.php index be18dba944..86650947c7 100644 --- a/phpBB/includes/mcp/mcp_pm_reports.php +++ b/phpBB/includes/mcp/mcp_pm_reports.php @@ -122,6 +122,7 @@ class mcp_pm_reports $message = bbcode_nl2br($message); $message = smiley_text($message); + $report['report_text'] = make_clickable(bbcode_nl2br($report['report_text'])); if ($pm_info['message_attachment'] && $auth->acl_get('u_pm_download')) { diff --git a/phpBB/includes/mcp/mcp_reports.php b/phpBB/includes/mcp/mcp_reports.php index 3426d62cdb..8da303f6e3 100644 --- a/phpBB/includes/mcp/mcp_reports.php +++ b/phpBB/includes/mcp/mcp_reports.php @@ -71,7 +71,7 @@ class mcp_reports // closed reports are accessed by report id $report_id = request_var('r', 0); - $sql = 'SELECT r.post_id, r.user_id, r.report_id, r.report_closed, report_time, r.report_text, r.reported_post_text, r.reported_post_uid, r.reported_post_bitfield, rr.reason_title, rr.reason_description, u.username, u.username_clean, u.user_colour + $sql = 'SELECT r.post_id, r.user_id, r.report_id, r.report_closed, report_time, r.report_text, r.reported_post_text, r.reported_post_uid, r.reported_post_bitfield, r.reported_post_enable_magic_url, r.reported_post_enable_smilies, r.reported_post_enable_bbcode, rr.reason_title, rr.reason_description, u.username, u.username_clean, u.user_colour FROM ' . REPORTS_TABLE . ' r, ' . REPORTS_REASONS_TABLE . ' rr, ' . USERS_TABLE . ' u WHERE ' . (($report_id) ? 'r.report_id = ' . $report_id : "r.post_id = $post_id") . ' AND rr.reason_id = r.reason_id @@ -94,6 +94,10 @@ class mcp_reports $post_id = $report['post_id']; $report_id = $report['report_id']; + + $parse_post_flags = $report['reported_post_enable_bbcode'] ? OPTION_FLAG_BBCODE : 0; + $parse_post_flags += $report['reported_post_enable_smilies'] ? OPTION_FLAG_SMILIES : 0; + $parse_post_flags += $report['reported_post_enable_magic_url'] ? OPTION_FLAG_LINKS : 0; $post_info = get_post_data(array($post_id), 'm_report', true); @@ -136,18 +140,7 @@ class mcp_reports $post_unread = (isset($topic_tracking_info[$post_info['topic_id']]) && $post_info['post_time'] > $topic_tracking_info[$post_info['topic_id']]) ? true : false; - // Process message, leave it uncensored - $message = $post_info['post_text']; - if ($post_info['bbcode_bitfield']) - { - include_once($phpbb_root_path . 'includes/bbcode.' . $phpEx); - $bbcode = new bbcode($post_info['bbcode_bitfield']); - $bbcode->bbcode_second_pass($message, $post_info['bbcode_uid'], $post_info['bbcode_bitfield']); - } - - $message = bbcode_nl2br($message); - $message = smiley_text($message); $report['report_text'] = make_clickable(bbcode_nl2br($report['report_text'])); if ($post_info['post_attachment'] && $auth->acl_get('u_download') && $auth->acl_get('f_download', $post_info['forum_id'])) @@ -168,7 +161,7 @@ class mcp_reports if (sizeof($attachments)) { $update_count = array(); - parse_attachments($post_info['forum_id'], $message, $attachments, $update_count); + parse_attachments($post_info['forum_id'], $report['reported_post_text'], $attachments, $update_count); } // Display not already displayed Attachments for this post, we already parsed them. ;) @@ -227,7 +220,7 @@ class mcp_reports 'REPORTER_NAME' => get_username_string('username', $report['user_id'], $report['username'], $report['user_colour']), 'U_VIEW_REPORTER_PROFILE' => get_username_string('profile', $report['user_id'], $report['username'], $report['user_colour']), - 'POST_PREVIEW' => generate_text_for_display($report['reported_post_text'], $report['reported_post_uid'], $report['reported_post_bitfield'], OPTION_FLAG_BBCODE | OPTION_FLAG_SMILIES, false), + 'POST_PREVIEW' => generate_text_for_display($report['reported_post_text'], $report['reported_post_uid'], $report['reported_post_bitfield'], $parse_post_flags, false), 'POST_SUBJECT' => ($post_info['post_subject']) ? $post_info['post_subject'] : $user->lang['NO_SUBJECT'], 'POST_DATE' => $user->format_date($post_info['post_time']), 'POST_IP' => $post_info['poster_ip'], diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php index 63ff7bed72..e3dd5a6b57 100644 --- a/phpBB/includes/mcp/mcp_topic.php +++ b/phpBB/includes/mcp/mcp_topic.php @@ -521,6 +521,49 @@ function split_topic($action, $topic_id, $to_forum_id, $subject) WHERE post_id = {$post_id_list[0]}"; $db->sql_query($sql); + // Copy topic subscriptions to new topic + $sql = 'SELECT user_id, notify_status + FROM ' . TOPICS_WATCH_TABLE . ' + WHERE topic_id = ' . $topic_id; + $result = $db->sql_query($sql); + + $sql_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + $sql_ary[] = array( + 'topic_id' => (int) $to_topic_id, + 'user_id' => (int) $row['user_id'], + 'notify_status' => (int) $row['notify_status'], + ); + } + $db->sql_freeresult($result); + + if (sizeof($sql_ary)) + { + $db->sql_multi_insert(TOPICS_WATCH_TABLE, $sql_ary); + } + + // Copy bookmarks to new topic + $sql = 'SELECT user_id + FROM ' . BOOKMARKS_TABLE . ' + WHERE topic_id = ' . $topic_id; + $result = $db->sql_query($sql); + + $sql_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + $sql_ary[] = array( + 'topic_id' => (int) $to_topic_id, + 'user_id' => (int) $row['user_id'], + ); + } + $db->sql_freeresult($result); + + if (sizeof($sql_ary)) + { + $db->sql_multi_insert(BOOKMARKS_TABLE, $sql_ary); + } + $success_msg = 'TOPIC_SPLIT_SUCCESS'; // Update forum statistics @@ -623,13 +666,16 @@ function merge_posts($topic_id, $to_topic_id) } else { + if (!function_exists('phpbb_update_rows_avoiding_duplicates_notify_status')) + { + include($phpbb_root_path . 'includes/functions_database_helper.' . $phpEx); + } + // If the topic no longer exist, we will update the topic watch table. - // To not let it error out on users watching both topics, we just return on an error... - $db->sql_return_on_error(true); - $db->sql_query('UPDATE ' . TOPICS_WATCH_TABLE . ' SET topic_id = ' . (int) $to_topic_id . ' WHERE topic_id = ' . (int) $topic_id); - $db->sql_return_on_error(false); + phpbb_update_rows_avoiding_duplicates_notify_status($db, TOPICS_WATCH_TABLE, 'topic_id', $topic_ids, $to_topic_id); - $db->sql_query('DELETE FROM ' . TOPICS_WATCH_TABLE . ' WHERE topic_id = ' . (int) $topic_id); + // If the topic no longer exist, we will update the bookmarks table. + phpbb_update_rows_avoiding_duplicates($db, BOOKMARKS_TABLE, 'topic_id', $topic_id, $to_topic_id); } // Link to the new topic diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index 1cd2a46fa1..44960dd78d 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -702,17 +702,6 @@ class bbcode_firstpass extends bbcode { global $config, $user; - /** - * If you change this code, make sure the cases described within the following reports are still working: - * #3572 - [quote="[test]test"]test [ test[/quote] - (correct: parsed) - * #14667 - [quote]test[/quote] test ] and [ test [quote]test[/quote] (correct: parsed) - * #14770 - [quote="["]test[/quote] (correct: parsed) - * [quote="[i]test[/i]"]test[/quote] (correct: parsed) - * [quote="[quote]test[/quote]"]test[/quote] (correct: parsed - Username displayed as [quote]test[/quote]) - * #20735 - [quote]test[/[/b]quote] test [/quote][/quote] test - (correct: quoted: "test[/[/b]quote] test" / non-quoted: "[/quote] test" - also failed if layout distorted) - * #40565 - [quote="a"]a[/quote][quote="a]a[/quote] (correct: first quote tag parsed, second quote tag unparsed) - */ - $in = str_replace("\r\n", "\n", str_replace('\"', '"', trim($in))); if (!$in) diff --git a/phpBB/includes/questionnaire/questionnaire.php b/phpBB/includes/questionnaire/questionnaire.php index f0fb8c3c06..6f2727a38c 100644 --- a/phpBB/includes/questionnaire/questionnaire.php +++ b/phpBB/includes/questionnaire/questionnaire.php @@ -70,7 +70,7 @@ class phpbb_questionnaire_data_collector /** * Collect info into the data property. * - * @return void + * @return null */ function collect() { @@ -260,6 +260,8 @@ class phpbb_questionnaire_phpbb_data_provider include("{$phpbb_root_path}config.$phpEx"); unset($dbhost, $dbport, $dbname, $dbuser, $dbpasswd); // Just a precaution + $dbms = phpbb_convert_30_dbms_to_31($dbms); + // Only send certain config vars $config_vars = array( 'active_sessions' => true, diff --git a/phpBB/includes/search/fulltext_mysql.php b/phpBB/includes/search/fulltext_mysql.php index 58a4dd7d6a..324c214e91 100644 --- a/phpBB/includes/search/fulltext_mysql.php +++ b/phpBB/includes/search/fulltext_mysql.php @@ -41,8 +41,8 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base protected $config; /** - * DBAL object - * @var dbal + * Database connection + * @var phpbb_db_driver */ protected $db; @@ -86,6 +86,14 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base $this->word_length = array('min' => $this->config['fulltext_mysql_min_word_len'], 'max' => $this->config['fulltext_mysql_max_word_len']); + /** + * Load the UTF tools + */ + if (!function_exists('utf8_strlen')) + { + include($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx); + } + $error = false; } @@ -230,7 +238,7 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base } else { - $tmp_split_words[] = $word . ' '; + $tmp_split_words[] = $word; } } if ($phrase) diff --git a/phpBB/includes/search/fulltext_native.php b/phpBB/includes/search/fulltext_native.php index 4623326fc7..53df8348ae 100644 --- a/phpBB/includes/search/fulltext_native.php +++ b/phpBB/includes/search/fulltext_native.php @@ -85,8 +85,8 @@ class phpbb_search_fulltext_native extends phpbb_search_base protected $config; /** - * DBAL object - * @var dbal + * Database connection + * @var phpbb_db_driver */ protected $db; diff --git a/phpBB/includes/search/fulltext_postgres.php b/phpBB/includes/search/fulltext_postgres.php index 08f64735b6..1475cc31d0 100644 --- a/phpBB/includes/search/fulltext_postgres.php +++ b/phpBB/includes/search/fulltext_postgres.php @@ -66,8 +66,8 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base protected $config; /** - * DBAL object - * @var dbal + * Database connection + * @var phpbb_db_driver */ protected $db; @@ -121,6 +121,14 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base } } + /** + * Load the UTF tools + */ + if (!function_exists('utf8_strlen')) + { + include($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx); + } + $error = false; } @@ -468,10 +476,14 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base $tmp_sql_match[] = "to_tsvector ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', " . $sql_match_column . ") @@ to_tsquery ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', '" . $this->db->sql_escape($this->tsearch_query) . "')"; } + $this->db->sql_transaction('begin'); + + $sql_from = "FROM $sql_from$sql_sort_table" . POSTS_TABLE . " p"; + $sql_where = "WHERE (" . implode(' OR ', $tmp_sql_match) . ") + $sql_where_options"; $sql = "SELECT $sql_select - FROM $sql_from$sql_sort_table" . POSTS_TABLE . " p - WHERE (" . implode(' OR ', $tmp_sql_match) . ") - $sql_where_options + $sql_from + $sql_where ORDER BY $sql_sort"; $result = $this->db->sql_query_limit($sql, $this->config['search_block_size'], $start); @@ -491,7 +503,12 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base // if the total result count is not cached yet, retrieve it from the db if (!$result_count) { - $result_count = sizeof ($id_ary); + $sql_count = "SELECT COUNT(*) as result_count + $sql_from + $sql_where"; + $result = $this->db->sql_query($sql_count); + $result_count = (int) $this->db->sql_fetchfield('result_count'); + $this->db->sql_freeresult($result); if (!$result_count) { @@ -499,6 +516,8 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base } } + $this->db->sql_transaction('commit'); + // store the ids, from start on then delete anything that isn't on the current page because we only need ids for one page $this->save_ids($search_key, implode(' ', $this->split_words), $author_ary, $result_count, $id_ary, $start, $sort_dir); $id_ary = array_slice($id_ary, 0, (int) $per_page); @@ -639,6 +658,8 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base $field = 'topic_id'; } + $this->db->sql_transaction('begin'); + // Only read one block of posts from the db and then cache it $result = $this->db->sql_query_limit($sql, $this->config['search_block_size'], $start); @@ -651,7 +672,35 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base // retrieve the total result count if needed if (!$result_count) { - $result_count = sizeof ($id_ary); + if ($type == 'posts') + { + $sql_count = "SELECT COUNT(*) as result_count + FROM " . $sql_sort_table . POSTS_TABLE . ' p' . (($firstpost_only) ? ', ' . TOPICS_TABLE . ' t ' : ' ') . " + WHERE $sql_author + $sql_topic_id + $sql_firstpost + $m_approve_fid_sql + $sql_fora + $sql_sort_join + $sql_time"; + } + else + { + $sql_count = "SELECT COUNT(*) as result_count + FROM " . $sql_sort_table . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p + WHERE $sql_author + $sql_topic_id + $sql_firstpost + $m_approve_fid_sql + $sql_fora + AND t.topic_id = p.topic_id + $sql_sort_join + $sql_time + GROUP BY t.topic_id, $sort_by_sql[$sort_key]"; + } + + $result = $this->db->sql_query($sql_count); + $result_count = (int) $this->db->sql_fetchfield('result_count'); if (!$result_count) { @@ -659,6 +708,8 @@ class phpbb_search_fulltext_postgres extends phpbb_search_base } } + $this->db->sql_transaction('commit'); + if (sizeof($id_ary)) { $this->save_ids($search_key, '', $author_ary, $result_count, $id_ary, $start, $sort_dir); diff --git a/phpBB/includes/search/fulltext_sphinx.php b/phpBB/includes/search/fulltext_sphinx.php index dd5634b623..4bacf74f93 100644 --- a/phpBB/includes/search/fulltext_sphinx.php +++ b/phpBB/includes/search/fulltext_sphinx.php @@ -84,8 +84,8 @@ class phpbb_search_fulltext_sphinx protected $config; /** - * DBAL object - * @var dbal + * Database connection + * @var phpbb_db_driver */ protected $db; @@ -875,7 +875,7 @@ class phpbb_search_fulltext_sphinx </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="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> </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'] . '</dt> diff --git a/phpBB/includes/sphinxapi.php b/phpBB/includes/sphinxapi.php index bd83b1d2e0..6c3b66710c 100644 --- a/phpBB/includes/sphinxapi.php +++ b/phpBB/includes/sphinxapi.php @@ -1,1712 +1,1712 @@ -<?php
-
-//
-// $Id: sphinxapi.php 3087 2012-01-30 23:07:35Z shodan $
-//
-
-//
-// Copyright (c) 2001-2012, Andrew Aksyonoff
-// Copyright (c) 2008-2012, Sphinx Technologies Inc
-// All rights reserved
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License. You should have
-// received a copy of the GPL license along with this program; if you
-// did not, you can find it at http://www.gnu.org/
-//
-
-/////////////////////////////////////////////////////////////////////////////
-// PHP version of Sphinx searchd client (PHP API)
-/////////////////////////////////////////////////////////////////////////////
-
-/// known searchd commands
-define ( "SEARCHD_COMMAND_SEARCH", 0 );
-define ( "SEARCHD_COMMAND_EXCERPT", 1 );
-define ( "SEARCHD_COMMAND_UPDATE", 2 );
-define ( "SEARCHD_COMMAND_KEYWORDS", 3 );
-define ( "SEARCHD_COMMAND_PERSIST", 4 );
-define ( "SEARCHD_COMMAND_STATUS", 5 );
-define ( "SEARCHD_COMMAND_FLUSHATTRS", 7 );
-
-/// current client-side command implementation versions
-define ( "VER_COMMAND_SEARCH", 0x119 );
-define ( "VER_COMMAND_EXCERPT", 0x104 );
-define ( "VER_COMMAND_UPDATE", 0x102 );
-define ( "VER_COMMAND_KEYWORDS", 0x100 );
-define ( "VER_COMMAND_STATUS", 0x100 );
-define ( "VER_COMMAND_QUERY", 0x100 );
-define ( "VER_COMMAND_FLUSHATTRS", 0x100 );
-
-/// known searchd status codes
-define ( "SEARCHD_OK", 0 );
-define ( "SEARCHD_ERROR", 1 );
-define ( "SEARCHD_RETRY", 2 );
-define ( "SEARCHD_WARNING", 3 );
-
-/// known match modes
-define ( "SPH_MATCH_ALL", 0 );
-define ( "SPH_MATCH_ANY", 1 );
-define ( "SPH_MATCH_PHRASE", 2 );
-define ( "SPH_MATCH_BOOLEAN", 3 );
-define ( "SPH_MATCH_EXTENDED", 4 );
-define ( "SPH_MATCH_FULLSCAN", 5 );
-define ( "SPH_MATCH_EXTENDED2", 6 ); // extended engine V2 (TEMPORARY, WILL BE REMOVED)
-
-/// known ranking modes (ext2 only)
-define ( "SPH_RANK_PROXIMITY_BM25", 0 ); ///< default mode, phrase proximity major factor and BM25 minor one
-define ( "SPH_RANK_BM25", 1 ); ///< statistical mode, BM25 ranking only (faster but worse quality)
-define ( "SPH_RANK_NONE", 2 ); ///< no ranking, all matches get a weight of 1
-define ( "SPH_RANK_WORDCOUNT", 3 ); ///< simple word-count weighting, rank is a weighted sum of per-field keyword occurence counts
-define ( "SPH_RANK_PROXIMITY", 4 );
-define ( "SPH_RANK_MATCHANY", 5 );
-define ( "SPH_RANK_FIELDMASK", 6 );
-define ( "SPH_RANK_SPH04", 7 );
-define ( "SPH_RANK_EXPR", 8 );
-define ( "SPH_RANK_TOTAL", 9 );
-
-/// known sort modes
-define ( "SPH_SORT_RELEVANCE", 0 );
-define ( "SPH_SORT_ATTR_DESC", 1 );
-define ( "SPH_SORT_ATTR_ASC", 2 );
-define ( "SPH_SORT_TIME_SEGMENTS", 3 );
-define ( "SPH_SORT_EXTENDED", 4 );
-define ( "SPH_SORT_EXPR", 5 );
-
-/// known filter types
-define ( "SPH_FILTER_VALUES", 0 );
-define ( "SPH_FILTER_RANGE", 1 );
-define ( "SPH_FILTER_FLOATRANGE", 2 );
-
-/// known attribute types
-define ( "SPH_ATTR_INTEGER", 1 );
-define ( "SPH_ATTR_TIMESTAMP", 2 );
-define ( "SPH_ATTR_ORDINAL", 3 );
-define ( "SPH_ATTR_BOOL", 4 );
-define ( "SPH_ATTR_FLOAT", 5 );
-define ( "SPH_ATTR_BIGINT", 6 );
-define ( "SPH_ATTR_STRING", 7 );
-define ( "SPH_ATTR_MULTI", 0x40000001 );
-define ( "SPH_ATTR_MULTI64", 0x40000002 );
-
-/// known grouping functions
-define ( "SPH_GROUPBY_DAY", 0 );
-define ( "SPH_GROUPBY_WEEK", 1 );
-define ( "SPH_GROUPBY_MONTH", 2 );
-define ( "SPH_GROUPBY_YEAR", 3 );
-define ( "SPH_GROUPBY_ATTR", 4 );
-define ( "SPH_GROUPBY_ATTRPAIR", 5 );
-
-// important properties of PHP's integers:
-// - always signed (one bit short of PHP_INT_SIZE)
-// - conversion from string to int is saturated
-// - float is double
-// - div converts arguments to floats
-// - mod converts arguments to ints
-
-// the packing code below works as follows:
-// - when we got an int, just pack it
-// if performance is a problem, this is the branch users should aim for
-//
-// - otherwise, we got a number in string form
-// this might be due to different reasons, but we assume that this is
-// because it didn't fit into PHP int
-//
-// - factor the string into high and low ints for packing
-// - if we have bcmath, then it is used
-// - if we don't, we have to do it manually (this is the fun part)
-//
-// - x64 branch does factoring using ints
-// - x32 (ab)uses floats, since we can't fit unsigned 32-bit number into an int
-//
-// unpacking routines are pretty much the same.
-// - return ints if we can
-// - otherwise format number into a string
-
-/// pack 64-bit signed
-function sphPackI64 ( $v )
-{
- assert ( is_numeric($v) );
-
- // x64
- if ( PHP_INT_SIZE>=8 )
- {
- $v = (int)$v;
- return pack ( "NN", $v>>32, $v&0xFFFFFFFF );
- }
-
- // x32, int
- if ( is_int($v) )
- return pack ( "NN", $v < 0 ? -1 : 0, $v );
-
- // x32, bcmath
- if ( function_exists("bcmul") )
- {
- if ( bccomp ( $v, 0 ) == -1 )
- $v = bcadd ( "18446744073709551616", $v );
- $h = bcdiv ( $v, "4294967296", 0 );
- $l = bcmod ( $v, "4294967296" );
- return pack ( "NN", (float)$h, (float)$l ); // conversion to float is intentional; int would lose 31st bit
- }
-
- // x32, no-bcmath
- $p = max(0, strlen($v) - 13);
- $lo = abs((float)substr($v, $p));
- $hi = abs((float)substr($v, 0, $p));
-
- $m = $lo + $hi*1316134912.0; // (10 ^ 13) % (1 << 32) = 1316134912
- $q = floor($m/4294967296.0);
- $l = $m - ($q*4294967296.0);
- $h = $hi*2328.0 + $q; // (10 ^ 13) / (1 << 32) = 2328
-
- if ( $v<0 )
- {
- if ( $l==0 )
- $h = 4294967296.0 - $h;
- else
- {
- $h = 4294967295.0 - $h;
- $l = 4294967296.0 - $l;
- }
- }
- return pack ( "NN", $h, $l );
-}
-
-/// pack 64-bit unsigned
-function sphPackU64 ( $v )
-{
- assert ( is_numeric($v) );
-
- // x64
- if ( PHP_INT_SIZE>=8 )
- {
- assert ( $v>=0 );
-
- // x64, int
- if ( is_int($v) )
- return pack ( "NN", $v>>32, $v&0xFFFFFFFF );
-
- // x64, bcmath
- if ( function_exists("bcmul") )
- {
- $h = bcdiv ( $v, 4294967296, 0 );
- $l = bcmod ( $v, 4294967296 );
- return pack ( "NN", $h, $l );
- }
-
- // x64, no-bcmath
- $p = max ( 0, strlen($v) - 13 );
- $lo = (int)substr ( $v, $p );
- $hi = (int)substr ( $v, 0, $p );
-
- $m = $lo + $hi*1316134912;
- $l = $m % 4294967296;
- $h = $hi*2328 + (int)($m/4294967296);
-
- return pack ( "NN", $h, $l );
- }
-
- // x32, int
- if ( is_int($v) )
- return pack ( "NN", 0, $v );
-
- // x32, bcmath
- if ( function_exists("bcmul") )
- {
- $h = bcdiv ( $v, "4294967296", 0 );
- $l = bcmod ( $v, "4294967296" );
- return pack ( "NN", (float)$h, (float)$l ); // conversion to float is intentional; int would lose 31st bit
- }
-
- // x32, no-bcmath
- $p = max(0, strlen($v) - 13);
- $lo = (float)substr($v, $p);
- $hi = (float)substr($v, 0, $p);
-
- $m = $lo + $hi*1316134912.0;
- $q = floor($m / 4294967296.0);
- $l = $m - ($q * 4294967296.0);
- $h = $hi*2328.0 + $q;
-
- return pack ( "NN", $h, $l );
-}
-
-// unpack 64-bit unsigned
-function sphUnpackU64 ( $v )
-{
- list ( $hi, $lo ) = array_values ( unpack ( "N*N*", $v ) );
-
- if ( PHP_INT_SIZE>=8 )
- {
- if ( $hi<0 ) $hi += (1<<32); // because php 5.2.2 to 5.2.5 is totally fucked up again
- if ( $lo<0 ) $lo += (1<<32);
-
- // x64, int
- if ( $hi<=2147483647 )
- return ($hi<<32) + $lo;
-
- // x64, bcmath
- if ( function_exists("bcmul") )
- return bcadd ( $lo, bcmul ( $hi, "4294967296" ) );
-
- // x64, no-bcmath
- $C = 100000;
- $h = ((int)($hi / $C) << 32) + (int)($lo / $C);
- $l = (($hi % $C) << 32) + ($lo % $C);
- if ( $l>$C )
- {
- $h += (int)($l / $C);
- $l = $l % $C;
- }
-
- if ( $h==0 )
- return $l;
- return sprintf ( "%d%05d", $h, $l );
- }
-
- // x32, int
- if ( $hi==0 )
- {
- if ( $lo>0 )
- return $lo;
- return sprintf ( "%u", $lo );
- }
-
- $hi = sprintf ( "%u", $hi );
- $lo = sprintf ( "%u", $lo );
-
- // x32, bcmath
- if ( function_exists("bcmul") )
- return bcadd ( $lo, bcmul ( $hi, "4294967296" ) );
-
- // x32, no-bcmath
- $hi = (float)$hi;
- $lo = (float)$lo;
-
- $q = floor($hi/10000000.0);
- $r = $hi - $q*10000000.0;
- $m = $lo + $r*4967296.0;
- $mq = floor($m/10000000.0);
- $l = $m - $mq*10000000.0;
- $h = $q*4294967296.0 + $r*429.0 + $mq;
-
- $h = sprintf ( "%.0f", $h );
- $l = sprintf ( "%07.0f", $l );
- if ( $h=="0" )
- return sprintf( "%.0f", (float)$l );
- return $h . $l;
-}
-
-// unpack 64-bit signed
-function sphUnpackI64 ( $v )
-{
- list ( $hi, $lo ) = array_values ( unpack ( "N*N*", $v ) );
-
- // x64
- if ( PHP_INT_SIZE>=8 )
- {
- if ( $hi<0 ) $hi += (1<<32); // because php 5.2.2 to 5.2.5 is totally fucked up again
- if ( $lo<0 ) $lo += (1<<32);
-
- return ($hi<<32) + $lo;
- }
-
- // x32, int
- if ( $hi==0 )
- {
- if ( $lo>0 )
- return $lo;
- return sprintf ( "%u", $lo );
- }
- // x32, int
- elseif ( $hi==-1 )
- {
- if ( $lo<0 )
- return $lo;
- return sprintf ( "%.0f", $lo - 4294967296.0 );
- }
-
- $neg = "";
- $c = 0;
- if ( $hi<0 )
- {
- $hi = ~$hi;
- $lo = ~$lo;
- $c = 1;
- $neg = "-";
- }
-
- $hi = sprintf ( "%u", $hi );
- $lo = sprintf ( "%u", $lo );
-
- // x32, bcmath
- if ( function_exists("bcmul") )
- return $neg . bcadd ( bcadd ( $lo, bcmul ( $hi, "4294967296" ) ), $c );
-
- // x32, no-bcmath
- $hi = (float)$hi;
- $lo = (float)$lo;
-
- $q = floor($hi/10000000.0);
- $r = $hi - $q*10000000.0;
- $m = $lo + $r*4967296.0;
- $mq = floor($m/10000000.0);
- $l = $m - $mq*10000000.0 + $c;
- $h = $q*4294967296.0 + $r*429.0 + $mq;
- if ( $l==10000000 )
- {
- $l = 0;
- $h += 1;
- }
-
- $h = sprintf ( "%.0f", $h );
- $l = sprintf ( "%07.0f", $l );
- if ( $h=="0" )
- return $neg . sprintf( "%.0f", (float)$l );
- return $neg . $h . $l;
-}
-
-
-function sphFixUint ( $value )
-{
- if ( PHP_INT_SIZE>=8 )
- {
- // x64 route, workaround broken unpack() in 5.2.2+
- if ( $value<0 ) $value += (1<<32);
- return $value;
- }
- else
- {
- // x32 route, workaround php signed/unsigned braindamage
- return sprintf ( "%u", $value );
- }
-}
-
-
-/// sphinx searchd client class
-class SphinxClient
-{
- var $_host; ///< searchd host (default is "localhost")
- var $_port; ///< searchd port (default is 9312)
- var $_offset; ///< how many records to seek from result-set start (default is 0)
- var $_limit; ///< how many records to return from result-set starting at offset (default is 20)
- var $_mode; ///< query matching mode (default is SPH_MATCH_ALL)
- var $_weights; ///< per-field weights (default is 1 for all fields)
- var $_sort; ///< match sorting mode (default is SPH_SORT_RELEVANCE)
- var $_sortby; ///< attribute to sort by (defualt is "")
- var $_min_id; ///< min ID to match (default is 0, which means no limit)
- var $_max_id; ///< max ID to match (default is 0, which means no limit)
- var $_filters; ///< search filters
- var $_groupby; ///< group-by attribute name
- var $_groupfunc; ///< group-by function (to pre-process group-by attribute value with)
- var $_groupsort; ///< group-by sorting clause (to sort groups in result set with)
- var $_groupdistinct;///< group-by count-distinct attribute
- var $_maxmatches; ///< max matches to retrieve
- var $_cutoff; ///< cutoff to stop searching at (default is 0)
- var $_retrycount; ///< distributed retries count
- var $_retrydelay; ///< distributed retries delay
- var $_anchor; ///< geographical anchor point
- var $_indexweights; ///< per-index weights
- var $_ranker; ///< ranking mode (default is SPH_RANK_PROXIMITY_BM25)
- var $_rankexpr; ///< ranking mode expression (for SPH_RANK_EXPR)
- var $_maxquerytime; ///< max query time, milliseconds (default is 0, do not limit)
- var $_fieldweights; ///< per-field-name weights
- var $_overrides; ///< per-query attribute values overrides
- var $_select; ///< select-list (attributes or expressions, with optional aliases)
-
- var $_error; ///< last error message
- var $_warning; ///< last warning message
- var $_connerror; ///< connection error vs remote error flag
-
- var $_reqs; ///< requests array for multi-query
- var $_mbenc; ///< stored mbstring encoding
- var $_arrayresult; ///< whether $result["matches"] should be a hash or an array
- var $_timeout; ///< connect timeout
-
- /////////////////////////////////////////////////////////////////////////////
- // common stuff
- /////////////////////////////////////////////////////////////////////////////
-
- /// create a new client object and fill defaults
- function SphinxClient ()
- {
- // per-client-object settings
- $this->_host = "localhost";
- $this->_port = 9312;
- $this->_path = false;
- $this->_socket = false;
-
- // per-query settings
- $this->_offset = 0;
- $this->_limit = 20;
- $this->_mode = SPH_MATCH_ALL;
- $this->_weights = array ();
- $this->_sort = SPH_SORT_RELEVANCE;
- $this->_sortby = "";
- $this->_min_id = 0;
- $this->_max_id = 0;
- $this->_filters = array ();
- $this->_groupby = "";
- $this->_groupfunc = SPH_GROUPBY_DAY;
- $this->_groupsort = "@group desc";
- $this->_groupdistinct= "";
- $this->_maxmatches = 1000;
- $this->_cutoff = 0;
- $this->_retrycount = 0;
- $this->_retrydelay = 0;
- $this->_anchor = array ();
- $this->_indexweights= array ();
- $this->_ranker = SPH_RANK_PROXIMITY_BM25;
- $this->_rankexpr = "";
- $this->_maxquerytime= 0;
- $this->_fieldweights= array();
- $this->_overrides = array();
- $this->_select = "*";
-
- $this->_error = ""; // per-reply fields (for single-query case)
- $this->_warning = "";
- $this->_connerror = false;
-
- $this->_reqs = array (); // requests storage (for multi-query case)
- $this->_mbenc = "";
- $this->_arrayresult = false;
- $this->_timeout = 0;
- }
-
- function __destruct()
- {
- if ( $this->_socket !== false )
- fclose ( $this->_socket );
- }
-
- /// get last error message (string)
- function GetLastError ()
- {
- return $this->_error;
- }
-
- /// get last warning message (string)
- function GetLastWarning ()
- {
- return $this->_warning;
- }
-
- /// get last error flag (to tell network connection errors from searchd errors or broken responses)
- function IsConnectError()
- {
- return $this->_connerror;
- }
-
- /// set searchd host name (string) and port (integer)
- function SetServer ( $host, $port = 0 )
- {
- assert ( is_string($host) );
- if ( $host[0] == '/')
- {
- $this->_path = 'unix://' . $host;
- return;
- }
- if ( substr ( $host, 0, 7 )=="unix://" )
- {
- $this->_path = $host;
- return;
- }
-
- assert ( is_int($port) );
- $this->_host = $host;
- $this->_port = $port;
- $this->_path = '';
-
- }
-
- /// set server connection timeout (0 to remove)
- function SetConnectTimeout ( $timeout )
- {
- assert ( is_numeric($timeout) );
- $this->_timeout = $timeout;
- }
-
-
- function _Send ( $handle, $data, $length )
- {
- if ( feof($handle) || fwrite ( $handle, $data, $length ) !== $length )
- {
- $this->_error = 'connection unexpectedly closed (timed out?)';
- $this->_connerror = true;
- return false;
- }
- return true;
- }
-
- /////////////////////////////////////////////////////////////////////////////
-
- /// enter mbstring workaround mode
- function _MBPush ()
- {
- $this->_mbenc = "";
- if ( ini_get ( "mbstring.func_overload" ) & 2 )
- {
- $this->_mbenc = mb_internal_encoding();
- mb_internal_encoding ( "latin1" );
- }
- }
-
- /// leave mbstring workaround mode
- function _MBPop ()
- {
- if ( $this->_mbenc )
- mb_internal_encoding ( $this->_mbenc );
- }
-
- /// connect to searchd server
- function _Connect ()
- {
- if ( $this->_socket!==false )
- {
- // we are in persistent connection mode, so we have a socket
- // however, need to check whether it's still alive
- if ( !@feof ( $this->_socket ) )
- return $this->_socket;
-
- // force reopen
- $this->_socket = false;
- }
-
- $errno = 0;
- $errstr = "";
- $this->_connerror = false;
-
- if ( $this->_path )
- {
- $host = $this->_path;
- $port = 0;
- }
- else
- {
- $host = $this->_host;
- $port = $this->_port;
- }
-
- if ( $this->_timeout<=0 )
- $fp = @fsockopen ( $host, $port, $errno, $errstr );
- else
- $fp = @fsockopen ( $host, $port, $errno, $errstr, $this->_timeout );
-
- if ( !$fp )
- {
- if ( $this->_path )
- $location = $this->_path;
- else
- $location = "{$this->_host}:{$this->_port}";
-
- $errstr = trim ( $errstr );
- $this->_error = "connection to $location failed (errno=$errno, msg=$errstr)";
- $this->_connerror = true;
- return false;
- }
-
- // send my version
- // this is a subtle part. we must do it before (!) reading back from searchd.
- // because otherwise under some conditions (reported on FreeBSD for instance)
- // TCP stack could throttle write-write-read pattern because of Nagle.
- if ( !$this->_Send ( $fp, pack ( "N", 1 ), 4 ) )
- {
- fclose ( $fp );
- $this->_error = "failed to send client protocol version";
- return false;
- }
-
- // check version
- list(,$v) = unpack ( "N*", fread ( $fp, 4 ) );
- $v = (int)$v;
- if ( $v<1 )
- {
- fclose ( $fp );
- $this->_error = "expected searchd protocol version 1+, got version '$v'";
- return false;
- }
-
- return $fp;
- }
-
- /// get and check response packet from searchd server
- function _GetResponse ( $fp, $client_ver )
- {
- $response = "";
- $len = 0;
-
- $header = fread ( $fp, 8 );
- if ( strlen($header)==8 )
- {
- list ( $status, $ver, $len ) = array_values ( unpack ( "n2a/Nb", $header ) );
- $left = $len;
- while ( $left>0 && !feof($fp) )
- {
- $chunk = fread ( $fp, min ( 8192, $left ) );
- if ( $chunk )
- {
- $response .= $chunk;
- $left -= strlen($chunk);
- }
- }
- }
- if ( $this->_socket === false )
- fclose ( $fp );
-
- // check response
- $read = strlen ( $response );
- if ( !$response || $read!=$len )
- {
- $this->_error = $len
- ? "failed to read searchd response (status=$status, ver=$ver, len=$len, read=$read)"
- : "received zero-sized searchd response";
- return false;
- }
-
- // check status
- if ( $status==SEARCHD_WARNING )
- {
- list(,$wlen) = unpack ( "N*", substr ( $response, 0, 4 ) );
- $this->_warning = substr ( $response, 4, $wlen );
- return substr ( $response, 4+$wlen );
- }
- if ( $status==SEARCHD_ERROR )
- {
- $this->_error = "searchd error: " . substr ( $response, 4 );
- return false;
- }
- if ( $status==SEARCHD_RETRY )
- {
- $this->_error = "temporary searchd error: " . substr ( $response, 4 );
- return false;
- }
- if ( $status!=SEARCHD_OK )
- {
- $this->_error = "unknown status code '$status'";
- return false;
- }
-
- // check version
- if ( $ver<$client_ver )
- {
- $this->_warning = sprintf ( "searchd command v.%d.%d older than client's v.%d.%d, some options might not work",
- $ver>>8, $ver&0xff, $client_ver>>8, $client_ver&0xff );
- }
-
- return $response;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // searching
- /////////////////////////////////////////////////////////////////////////////
-
- /// set offset and count into result set,
- /// and optionally set max-matches and cutoff limits
- function SetLimits ( $offset, $limit, $max=0, $cutoff=0 )
- {
- assert ( is_int($offset) );
- assert ( is_int($limit) );
- assert ( $offset>=0 );
- assert ( $limit>0 );
- assert ( $max>=0 );
- $this->_offset = $offset;
- $this->_limit = $limit;
- if ( $max>0 )
- $this->_maxmatches = $max;
- if ( $cutoff>0 )
- $this->_cutoff = $cutoff;
- }
-
- /// set maximum query time, in milliseconds, per-index
- /// integer, 0 means "do not limit"
- function SetMaxQueryTime ( $max )
- {
- assert ( is_int($max) );
- assert ( $max>=0 );
- $this->_maxquerytime = $max;
- }
-
- /// set matching mode
- function SetMatchMode ( $mode )
- {
- assert ( $mode==SPH_MATCH_ALL
- || $mode==SPH_MATCH_ANY
- || $mode==SPH_MATCH_PHRASE
- || $mode==SPH_MATCH_BOOLEAN
- || $mode==SPH_MATCH_EXTENDED
- || $mode==SPH_MATCH_FULLSCAN
- || $mode==SPH_MATCH_EXTENDED2 );
- $this->_mode = $mode;
- }
-
- /// set ranking mode
- function SetRankingMode ( $ranker, $rankexpr="" )
- {
- assert ( $ranker>=0 && $ranker<SPH_RANK_TOTAL );
- assert ( is_string($rankexpr) );
- $this->_ranker = $ranker;
- $this->_rankexpr = $rankexpr;
- }
-
- /// set matches sorting mode
- function SetSortMode ( $mode, $sortby="" )
- {
- assert (
- $mode==SPH_SORT_RELEVANCE ||
- $mode==SPH_SORT_ATTR_DESC ||
- $mode==SPH_SORT_ATTR_ASC ||
- $mode==SPH_SORT_TIME_SEGMENTS ||
- $mode==SPH_SORT_EXTENDED ||
- $mode==SPH_SORT_EXPR );
- assert ( is_string($sortby) );
- assert ( $mode==SPH_SORT_RELEVANCE || strlen($sortby)>0 );
-
- $this->_sort = $mode;
- $this->_sortby = $sortby;
- }
-
- /// bind per-field weights by order
- /// DEPRECATED; use SetFieldWeights() instead
- function SetWeights ( $weights )
- {
- assert ( is_array($weights) );
- foreach ( $weights as $weight )
- assert ( is_int($weight) );
-
- $this->_weights = $weights;
- }
-
- /// bind per-field weights by name
- function SetFieldWeights ( $weights )
- {
- assert ( is_array($weights) );
- foreach ( $weights as $name=>$weight )
- {
- assert ( is_string($name) );
- assert ( is_int($weight) );
- }
- $this->_fieldweights = $weights;
- }
-
- /// bind per-index weights by name
- function SetIndexWeights ( $weights )
- {
- assert ( is_array($weights) );
- foreach ( $weights as $index=>$weight )
- {
- assert ( is_string($index) );
- assert ( is_int($weight) );
- }
- $this->_indexweights = $weights;
- }
-
- /// set IDs range to match
- /// only match records if document ID is beetwen $min and $max (inclusive)
- function SetIDRange ( $min, $max )
- {
- assert ( is_numeric($min) );
- assert ( is_numeric($max) );
- assert ( $min<=$max );
- $this->_min_id = $min;
- $this->_max_id = $max;
- }
-
- /// set values set filter
- /// only match records where $attribute value is in given set
- function SetFilter ( $attribute, $values, $exclude=false )
- {
- assert ( is_string($attribute) );
- assert ( is_array($values) );
- assert ( count($values) );
-
- if ( is_array($values) && count($values) )
- {
- foreach ( $values as $value )
- assert ( is_numeric($value) );
-
- $this->_filters[] = array ( "type"=>SPH_FILTER_VALUES, "attr"=>$attribute, "exclude"=>$exclude, "values"=>$values );
- }
- }
-
- /// set range filter
- /// only match records if $attribute value is beetwen $min and $max (inclusive)
- function SetFilterRange ( $attribute, $min, $max, $exclude=false )
- {
- assert ( is_string($attribute) );
- assert ( is_numeric($min) );
- assert ( is_numeric($max) );
- assert ( $min<=$max );
-
- $this->_filters[] = array ( "type"=>SPH_FILTER_RANGE, "attr"=>$attribute, "exclude"=>$exclude, "min"=>$min, "max"=>$max );
- }
-
- /// set float range filter
- /// only match records if $attribute value is beetwen $min and $max (inclusive)
- function SetFilterFloatRange ( $attribute, $min, $max, $exclude=false )
- {
- assert ( is_string($attribute) );
- assert ( is_float($min) );
- assert ( is_float($max) );
- assert ( $min<=$max );
-
- $this->_filters[] = array ( "type"=>SPH_FILTER_FLOATRANGE, "attr"=>$attribute, "exclude"=>$exclude, "min"=>$min, "max"=>$max );
- }
-
- /// setup anchor point for geosphere distance calculations
- /// required to use @geodist in filters and sorting
- /// latitude and longitude must be in radians
- function SetGeoAnchor ( $attrlat, $attrlong, $lat, $long )
- {
- assert ( is_string($attrlat) );
- assert ( is_string($attrlong) );
- assert ( is_float($lat) );
- assert ( is_float($long) );
-
- $this->_anchor = array ( "attrlat"=>$attrlat, "attrlong"=>$attrlong, "lat"=>$lat, "long"=>$long );
- }
-
- /// set grouping attribute and function
- function SetGroupBy ( $attribute, $func, $groupsort="@group desc" )
- {
- assert ( is_string($attribute) );
- assert ( is_string($groupsort) );
- assert ( $func==SPH_GROUPBY_DAY
- || $func==SPH_GROUPBY_WEEK
- || $func==SPH_GROUPBY_MONTH
- || $func==SPH_GROUPBY_YEAR
- || $func==SPH_GROUPBY_ATTR
- || $func==SPH_GROUPBY_ATTRPAIR );
-
- $this->_groupby = $attribute;
- $this->_groupfunc = $func;
- $this->_groupsort = $groupsort;
- }
-
- /// set count-distinct attribute for group-by queries
- function SetGroupDistinct ( $attribute )
- {
- assert ( is_string($attribute) );
- $this->_groupdistinct = $attribute;
- }
-
- /// set distributed retries count and delay
- function SetRetries ( $count, $delay=0 )
- {
- assert ( is_int($count) && $count>=0 );
- assert ( is_int($delay) && $delay>=0 );
- $this->_retrycount = $count;
- $this->_retrydelay = $delay;
- }
-
- /// set result set format (hash or array; hash by default)
- /// PHP specific; needed for group-by-MVA result sets that may contain duplicate IDs
- function SetArrayResult ( $arrayresult )
- {
- assert ( is_bool($arrayresult) );
- $this->_arrayresult = $arrayresult;
- }
-
- /// set attribute values override
- /// there can be only one override per attribute
- /// $values must be a hash that maps document IDs to attribute values
- function SetOverride ( $attrname, $attrtype, $values )
- {
- assert ( is_string ( $attrname ) );
- assert ( in_array ( $attrtype, array ( SPH_ATTR_INTEGER, SPH_ATTR_TIMESTAMP, SPH_ATTR_BOOL, SPH_ATTR_FLOAT, SPH_ATTR_BIGINT ) ) );
- assert ( is_array ( $values ) );
-
- $this->_overrides[$attrname] = array ( "attr"=>$attrname, "type"=>$attrtype, "values"=>$values );
- }
-
- /// set select-list (attributes or expressions), SQL-like syntax
- function SetSelect ( $select )
- {
- assert ( is_string ( $select ) );
- $this->_select = $select;
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- /// clear all filters (for multi-queries)
- function ResetFilters ()
- {
- $this->_filters = array();
- $this->_anchor = array();
- }
-
- /// clear groupby settings (for multi-queries)
- function ResetGroupBy ()
- {
- $this->_groupby = "";
- $this->_groupfunc = SPH_GROUPBY_DAY;
- $this->_groupsort = "@group desc";
- $this->_groupdistinct= "";
- }
-
- /// clear all attribute value overrides (for multi-queries)
- function ResetOverrides ()
- {
- $this->_overrides = array ();
- }
-
- //////////////////////////////////////////////////////////////////////////////
-
- /// connect to searchd server, run given search query through given indexes,
- /// and return the search results
- function Query ( $query, $index="*", $comment="" )
- {
- assert ( empty($this->_reqs) );
-
- $this->AddQuery ( $query, $index, $comment );
- $results = $this->RunQueries ();
- $this->_reqs = array (); // just in case it failed too early
-
- if ( !is_array($results) )
- return false; // probably network error; error message should be already filled
-
- $this->_error = $results[0]["error"];
- $this->_warning = $results[0]["warning"];
- if ( $results[0]["status"]==SEARCHD_ERROR )
- return false;
- else
- return $results[0];
- }
-
- /// helper to pack floats in network byte order
- function _PackFloat ( $f )
- {
- $t1 = pack ( "f", $f ); // machine order
- list(,$t2) = unpack ( "L*", $t1 ); // int in machine order
- return pack ( "N", $t2 );
- }
-
- /// add query to multi-query batch
- /// returns index into results array from RunQueries() call
- function AddQuery ( $query, $index="*", $comment="" )
- {
- // mbstring workaround
- $this->_MBPush ();
-
- // build request
- $req = pack ( "NNNN", $this->_offset, $this->_limit, $this->_mode, $this->_ranker );
- if ( $this->_ranker==SPH_RANK_EXPR )
- $req .= pack ( "N", strlen($this->_rankexpr) ) . $this->_rankexpr;
- $req .= pack ( "N", $this->_sort ); // (deprecated) sort mode
- $req .= pack ( "N", strlen($this->_sortby) ) . $this->_sortby;
- $req .= pack ( "N", strlen($query) ) . $query; // query itself
- $req .= pack ( "N", count($this->_weights) ); // weights
- foreach ( $this->_weights as $weight )
- $req .= pack ( "N", (int)$weight );
- $req .= pack ( "N", strlen($index) ) . $index; // indexes
- $req .= pack ( "N", 1 ); // id64 range marker
- $req .= sphPackU64 ( $this->_min_id ) . sphPackU64 ( $this->_max_id ); // id64 range
-
- // filters
- $req .= pack ( "N", count($this->_filters) );
- foreach ( $this->_filters as $filter )
- {
- $req .= pack ( "N", strlen($filter["attr"]) ) . $filter["attr"];
- $req .= pack ( "N", $filter["type"] );
- switch ( $filter["type"] )
- {
- case SPH_FILTER_VALUES:
- $req .= pack ( "N", count($filter["values"]) );
- foreach ( $filter["values"] as $value )
- $req .= sphPackI64 ( $value );
- break;
-
- case SPH_FILTER_RANGE:
- $req .= sphPackI64 ( $filter["min"] ) . sphPackI64 ( $filter["max"] );
- break;
-
- case SPH_FILTER_FLOATRANGE:
- $req .= $this->_PackFloat ( $filter["min"] ) . $this->_PackFloat ( $filter["max"] );
- break;
-
- default:
- assert ( 0 && "internal error: unhandled filter type" );
- }
- $req .= pack ( "N", $filter["exclude"] );
- }
-
- // group-by clause, max-matches count, group-sort clause, cutoff count
- $req .= pack ( "NN", $this->_groupfunc, strlen($this->_groupby) ) . $this->_groupby;
- $req .= pack ( "N", $this->_maxmatches );
- $req .= pack ( "N", strlen($this->_groupsort) ) . $this->_groupsort;
- $req .= pack ( "NNN", $this->_cutoff, $this->_retrycount, $this->_retrydelay );
- $req .= pack ( "N", strlen($this->_groupdistinct) ) . $this->_groupdistinct;
-
- // anchor point
- if ( empty($this->_anchor) )
- {
- $req .= pack ( "N", 0 );
- } else
- {
- $a =& $this->_anchor;
- $req .= pack ( "N", 1 );
- $req .= pack ( "N", strlen($a["attrlat"]) ) . $a["attrlat"];
- $req .= pack ( "N", strlen($a["attrlong"]) ) . $a["attrlong"];
- $req .= $this->_PackFloat ( $a["lat"] ) . $this->_PackFloat ( $a["long"] );
- }
-
- // per-index weights
- $req .= pack ( "N", count($this->_indexweights) );
- foreach ( $this->_indexweights as $idx=>$weight )
- $req .= pack ( "N", strlen($idx) ) . $idx . pack ( "N", $weight );
-
- // max query time
- $req .= pack ( "N", $this->_maxquerytime );
-
- // per-field weights
- $req .= pack ( "N", count($this->_fieldweights) );
- foreach ( $this->_fieldweights as $field=>$weight )
- $req .= pack ( "N", strlen($field) ) . $field . pack ( "N", $weight );
-
- // comment
- $req .= pack ( "N", strlen($comment) ) . $comment;
-
- // attribute overrides
- $req .= pack ( "N", count($this->_overrides) );
- foreach ( $this->_overrides as $key => $entry )
- {
- $req .= pack ( "N", strlen($entry["attr"]) ) . $entry["attr"];
- $req .= pack ( "NN", $entry["type"], count($entry["values"]) );
- foreach ( $entry["values"] as $id=>$val )
- {
- assert ( is_numeric($id) );
- assert ( is_numeric($val) );
-
- $req .= sphPackU64 ( $id );
- switch ( $entry["type"] )
- {
- case SPH_ATTR_FLOAT: $req .= $this->_PackFloat ( $val ); break;
- case SPH_ATTR_BIGINT: $req .= sphPackI64 ( $val ); break;
- default: $req .= pack ( "N", $val ); break;
- }
- }
- }
-
- // select-list
- $req .= pack ( "N", strlen($this->_select) ) . $this->_select;
-
- // mbstring workaround
- $this->_MBPop ();
-
- // store request to requests array
- $this->_reqs[] = $req;
- return count($this->_reqs)-1;
- }
-
- /// connect to searchd, run queries batch, and return an array of result sets
- function RunQueries ()
- {
- if ( empty($this->_reqs) )
- {
- $this->_error = "no queries defined, issue AddQuery() first";
- return false;
- }
-
- // mbstring workaround
- $this->_MBPush ();
-
- if (!( $fp = $this->_Connect() ))
- {
- $this->_MBPop ();
- return false;
- }
-
- // send query, get response
- $nreqs = count($this->_reqs);
- $req = join ( "", $this->_reqs );
- $len = 8+strlen($req);
- $req = pack ( "nnNNN", SEARCHD_COMMAND_SEARCH, VER_COMMAND_SEARCH, $len, 0, $nreqs ) . $req; // add header
-
- if ( !( $this->_Send ( $fp, $req, $len+8 ) ) ||
- !( $response = $this->_GetResponse ( $fp, VER_COMMAND_SEARCH ) ) )
- {
- $this->_MBPop ();
- return false;
- }
-
- // query sent ok; we can reset reqs now
- $this->_reqs = array ();
-
- // parse and return response
- return $this->_ParseSearchResponse ( $response, $nreqs );
- }
-
- /// parse and return search query (or queries) response
- function _ParseSearchResponse ( $response, $nreqs )
- {
- $p = 0; // current position
- $max = strlen($response); // max position for checks, to protect against broken responses
-
- $results = array ();
- for ( $ires=0; $ires<$nreqs && $p<$max; $ires++ )
- {
- $results[] = array();
- $result =& $results[$ires];
-
- $result["error"] = "";
- $result["warning"] = "";
-
- // extract status
- list(,$status) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
- $result["status"] = $status;
- if ( $status!=SEARCHD_OK )
- {
- list(,$len) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
- $message = substr ( $response, $p, $len ); $p += $len;
-
- if ( $status==SEARCHD_WARNING )
- {
- $result["warning"] = $message;
- } else
- {
- $result["error"] = $message;
- continue;
- }
- }
-
- // read schema
- $fields = array ();
- $attrs = array ();
-
- list(,$nfields) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
- while ( $nfields-->0 && $p<$max )
- {
- list(,$len) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
- $fields[] = substr ( $response, $p, $len ); $p += $len;
- }
- $result["fields"] = $fields;
-
- list(,$nattrs) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
- while ( $nattrs-->0 && $p<$max )
- {
- list(,$len) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
- $attr = substr ( $response, $p, $len ); $p += $len;
- list(,$type) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
- $attrs[$attr] = $type;
- }
- $result["attrs"] = $attrs;
-
- // read match count
- list(,$count) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
- list(,$id64) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
-
- // read matches
- $idx = -1;
- while ( $count-->0 && $p<$max )
- {
- // index into result array
- $idx++;
-
- // parse document id and weight
- if ( $id64 )
- {
- $doc = sphUnpackU64 ( substr ( $response, $p, 8 ) ); $p += 8;
- list(,$weight) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
- }
- else
- {
- list ( $doc, $weight ) = array_values ( unpack ( "N*N*",
- substr ( $response, $p, 8 ) ) );
- $p += 8;
- $doc = sphFixUint($doc);
- }
- $weight = sprintf ( "%u", $weight );
-
- // create match entry
- if ( $this->_arrayresult )
- $result["matches"][$idx] = array ( "id"=>$doc, "weight"=>$weight );
- else
- $result["matches"][$doc]["weight"] = $weight;
-
- // parse and create attributes
- $attrvals = array ();
- foreach ( $attrs as $attr=>$type )
- {
- // handle 64bit ints
- if ( $type==SPH_ATTR_BIGINT )
- {
- $attrvals[$attr] = sphUnpackI64 ( substr ( $response, $p, 8 ) ); $p += 8;
- continue;
- }
-
- // handle floats
- if ( $type==SPH_ATTR_FLOAT )
- {
- list(,$uval) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
- list(,$fval) = unpack ( "f*", pack ( "L", $uval ) );
- $attrvals[$attr] = $fval;
- continue;
- }
-
- // handle everything else as unsigned ints
- list(,$val) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
- if ( $type==SPH_ATTR_MULTI )
- {
- $attrvals[$attr] = array ();
- $nvalues = $val;
- while ( $nvalues-->0 && $p<$max )
- {
- list(,$val) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
- $attrvals[$attr][] = sphFixUint($val);
- }
- } else if ( $type==SPH_ATTR_MULTI64 )
- {
- $attrvals[$attr] = array ();
- $nvalues = $val;
- while ( $nvalues>0 && $p<$max )
- {
- $attrvals[$attr][] = sphUnpackU64 ( substr ( $response, $p, 8 ) ); $p += 8;
- $nvalues -= 2;
- }
- } else if ( $type==SPH_ATTR_STRING )
- {
- $attrvals[$attr] = substr ( $response, $p, $val );
- $p += $val;
- } else
- {
- $attrvals[$attr] = sphFixUint($val);
- }
- }
-
- if ( $this->_arrayresult )
- $result["matches"][$idx]["attrs"] = $attrvals;
- else
- $result["matches"][$doc]["attrs"] = $attrvals;
- }
-
- list ( $total, $total_found, $msecs, $words ) =
- array_values ( unpack ( "N*N*N*N*", substr ( $response, $p, 16 ) ) );
- $result["total"] = sprintf ( "%u", $total );
- $result["total_found"] = sprintf ( "%u", $total_found );
- $result["time"] = sprintf ( "%.3f", $msecs/1000 );
- $p += 16;
-
- while ( $words-->0 && $p<$max )
- {
- list(,$len) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
- $word = substr ( $response, $p, $len ); $p += $len;
- list ( $docs, $hits ) = array_values ( unpack ( "N*N*", substr ( $response, $p, 8 ) ) ); $p += 8;
- $result["words"][$word] = array (
- "docs"=>sprintf ( "%u", $docs ),
- "hits"=>sprintf ( "%u", $hits ) );
- }
- }
-
- $this->_MBPop ();
- return $results;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // excerpts generation
- /////////////////////////////////////////////////////////////////////////////
-
- /// connect to searchd server, and generate exceprts (snippets)
- /// of given documents for given query. returns false on failure,
- /// an array of snippets on success
- function BuildExcerpts ( $docs, $index, $words, $opts=array() )
- {
- assert ( is_array($docs) );
- assert ( is_string($index) );
- assert ( is_string($words) );
- assert ( is_array($opts) );
-
- $this->_MBPush ();
-
- if (!( $fp = $this->_Connect() ))
- {
- $this->_MBPop();
- return false;
- }
-
- /////////////////
- // fixup options
- /////////////////
-
- if ( !isset($opts["before_match"]) ) $opts["before_match"] = "<b>";
- if ( !isset($opts["after_match"]) ) $opts["after_match"] = "</b>";
- if ( !isset($opts["chunk_separator"]) ) $opts["chunk_separator"] = " ... ";
- if ( !isset($opts["limit"]) ) $opts["limit"] = 256;
- if ( !isset($opts["limit_passages"]) ) $opts["limit_passages"] = 0;
- if ( !isset($opts["limit_words"]) ) $opts["limit_words"] = 0;
- if ( !isset($opts["around"]) ) $opts["around"] = 5;
- if ( !isset($opts["exact_phrase"]) ) $opts["exact_phrase"] = false;
- if ( !isset($opts["single_passage"]) ) $opts["single_passage"] = false;
- if ( !isset($opts["use_boundaries"]) ) $opts["use_boundaries"] = false;
- if ( !isset($opts["weight_order"]) ) $opts["weight_order"] = false;
- if ( !isset($opts["query_mode"]) ) $opts["query_mode"] = false;
- if ( !isset($opts["force_all_words"]) ) $opts["force_all_words"] = false;
- if ( !isset($opts["start_passage_id"]) ) $opts["start_passage_id"] = 1;
- if ( !isset($opts["load_files"]) ) $opts["load_files"] = false;
- if ( !isset($opts["html_strip_mode"]) ) $opts["html_strip_mode"] = "index";
- if ( !isset($opts["allow_empty"]) ) $opts["allow_empty"] = false;
- if ( !isset($opts["passage_boundary"]) ) $opts["passage_boundary"] = "none";
- if ( !isset($opts["emit_zones"]) ) $opts["emit_zones"] = false;
- if ( !isset($opts["load_files_scattered"]) ) $opts["load_files_scattered"] = false;
-
-
- /////////////////
- // build request
- /////////////////
-
- // v.1.2 req
- $flags = 1; // remove spaces
- if ( $opts["exact_phrase"] ) $flags |= 2;
- if ( $opts["single_passage"] ) $flags |= 4;
- if ( $opts["use_boundaries"] ) $flags |= 8;
- if ( $opts["weight_order"] ) $flags |= 16;
- if ( $opts["query_mode"] ) $flags |= 32;
- if ( $opts["force_all_words"] ) $flags |= 64;
- if ( $opts["load_files"] ) $flags |= 128;
- if ( $opts["allow_empty"] ) $flags |= 256;
- if ( $opts["emit_zones"] ) $flags |= 512;
- if ( $opts["load_files_scattered"] ) $flags |= 1024;
- $req = pack ( "NN", 0, $flags ); // mode=0, flags=$flags
- $req .= pack ( "N", strlen($index) ) . $index; // req index
- $req .= pack ( "N", strlen($words) ) . $words; // req words
-
- // options
- $req .= pack ( "N", strlen($opts["before_match"]) ) . $opts["before_match"];
- $req .= pack ( "N", strlen($opts["after_match"]) ) . $opts["after_match"];
- $req .= pack ( "N", strlen($opts["chunk_separator"]) ) . $opts["chunk_separator"];
- $req .= pack ( "NN", (int)$opts["limit"], (int)$opts["around"] );
- $req .= pack ( "NNN", (int)$opts["limit_passages"], (int)$opts["limit_words"], (int)$opts["start_passage_id"] ); // v.1.2
- $req .= pack ( "N", strlen($opts["html_strip_mode"]) ) . $opts["html_strip_mode"];
- $req .= pack ( "N", strlen($opts["passage_boundary"]) ) . $opts["passage_boundary"];
-
- // documents
- $req .= pack ( "N", count($docs) );
- foreach ( $docs as $doc )
- {
- assert ( is_string($doc) );
- $req .= pack ( "N", strlen($doc) ) . $doc;
- }
-
- ////////////////////////////
- // send query, get response
- ////////////////////////////
-
- $len = strlen($req);
- $req = pack ( "nnN", SEARCHD_COMMAND_EXCERPT, VER_COMMAND_EXCERPT, $len ) . $req; // add header
- if ( !( $this->_Send ( $fp, $req, $len+8 ) ) ||
- !( $response = $this->_GetResponse ( $fp, VER_COMMAND_EXCERPT ) ) )
- {
- $this->_MBPop ();
- return false;
- }
-
- //////////////////
- // parse response
- //////////////////
-
- $pos = 0;
- $res = array ();
- $rlen = strlen($response);
- for ( $i=0; $i<count($docs); $i++ )
- {
- list(,$len) = unpack ( "N*", substr ( $response, $pos, 4 ) );
- $pos += 4;
-
- if ( $pos+$len > $rlen )
- {
- $this->_error = "incomplete reply";
- $this->_MBPop ();
- return false;
- }
- $res[] = $len ? substr ( $response, $pos, $len ) : "";
- $pos += $len;
- }
-
- $this->_MBPop ();
- return $res;
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- // keyword generation
- /////////////////////////////////////////////////////////////////////////////
-
- /// connect to searchd server, and generate keyword list for a given query
- /// returns false on failure,
- /// an array of words on success
- function BuildKeywords ( $query, $index, $hits )
- {
- assert ( is_string($query) );
- assert ( is_string($index) );
- assert ( is_bool($hits) );
-
- $this->_MBPush ();
-
- if (!( $fp = $this->_Connect() ))
- {
- $this->_MBPop();
- return false;
- }
-
- /////////////////
- // build request
- /////////////////
-
- // v.1.0 req
- $req = pack ( "N", strlen($query) ) . $query; // req query
- $req .= pack ( "N", strlen($index) ) . $index; // req index
- $req .= pack ( "N", (int)$hits );
-
- ////////////////////////////
- // send query, get response
- ////////////////////////////
-
- $len = strlen($req);
- $req = pack ( "nnN", SEARCHD_COMMAND_KEYWORDS, VER_COMMAND_KEYWORDS, $len ) . $req; // add header
- if ( !( $this->_Send ( $fp, $req, $len+8 ) ) ||
- !( $response = $this->_GetResponse ( $fp, VER_COMMAND_KEYWORDS ) ) )
- {
- $this->_MBPop ();
- return false;
- }
-
- //////////////////
- // parse response
- //////////////////
-
- $pos = 0;
- $res = array ();
- $rlen = strlen($response);
- list(,$nwords) = unpack ( "N*", substr ( $response, $pos, 4 ) );
- $pos += 4;
- for ( $i=0; $i<$nwords; $i++ )
- {
- list(,$len) = unpack ( "N*", substr ( $response, $pos, 4 ) ); $pos += 4;
- $tokenized = $len ? substr ( $response, $pos, $len ) : "";
- $pos += $len;
-
- list(,$len) = unpack ( "N*", substr ( $response, $pos, 4 ) ); $pos += 4;
- $normalized = $len ? substr ( $response, $pos, $len ) : "";
- $pos += $len;
-
- $res[] = array ( "tokenized"=>$tokenized, "normalized"=>$normalized );
-
- if ( $hits )
- {
- list($ndocs,$nhits) = array_values ( unpack ( "N*N*", substr ( $response, $pos, 8 ) ) );
- $pos += 8;
- $res [$i]["docs"] = $ndocs;
- $res [$i]["hits"] = $nhits;
- }
-
- if ( $pos > $rlen )
- {
- $this->_error = "incomplete reply";
- $this->_MBPop ();
- return false;
- }
- }
-
- $this->_MBPop ();
- return $res;
- }
-
- function EscapeString ( $string )
- {
- $from = array ( '\\', '(',')','|','-','!','@','~','"','&', '/', '^', '$', '=' );
- $to = array ( '\\\\', '\(','\)','\|','\-','\!','\@','\~','\"', '\&', '\/', '\^', '\$', '\=' );
-
- return str_replace ( $from, $to, $string );
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // attribute updates
- /////////////////////////////////////////////////////////////////////////////
-
- /// batch update given attributes in given rows in given indexes
- /// returns amount of updated documents (0 or more) on success, or -1 on failure
- function UpdateAttributes ( $index, $attrs, $values, $mva=false )
- {
- // verify everything
- assert ( is_string($index) );
- assert ( is_bool($mva) );
-
- assert ( is_array($attrs) );
- foreach ( $attrs as $attr )
- assert ( is_string($attr) );
-
- assert ( is_array($values) );
- foreach ( $values as $id=>$entry )
- {
- assert ( is_numeric($id) );
- assert ( is_array($entry) );
- assert ( count($entry)==count($attrs) );
- foreach ( $entry as $v )
- {
- if ( $mva )
- {
- assert ( is_array($v) );
- foreach ( $v as $vv )
- assert ( is_int($vv) );
- } else
- assert ( is_int($v) );
- }
- }
-
- // build request
- $this->_MBPush ();
- $req = pack ( "N", strlen($index) ) . $index;
-
- $req .= pack ( "N", count($attrs) );
- foreach ( $attrs as $attr )
- {
- $req .= pack ( "N", strlen($attr) ) . $attr;
- $req .= pack ( "N", $mva ? 1 : 0 );
- }
-
- $req .= pack ( "N", count($values) );
- foreach ( $values as $id=>$entry )
- {
- $req .= sphPackU64 ( $id );
- foreach ( $entry as $v )
- {
- $req .= pack ( "N", $mva ? count($v) : $v );
- if ( $mva )
- foreach ( $v as $vv )
- $req .= pack ( "N", $vv );
- }
- }
-
- // connect, send query, get response
- if (!( $fp = $this->_Connect() ))
- {
- $this->_MBPop ();
- return -1;
- }
-
- $len = strlen($req);
- $req = pack ( "nnN", SEARCHD_COMMAND_UPDATE, VER_COMMAND_UPDATE, $len ) . $req; // add header
- if ( !$this->_Send ( $fp, $req, $len+8 ) )
- {
- $this->_MBPop ();
- return -1;
- }
-
- if (!( $response = $this->_GetResponse ( $fp, VER_COMMAND_UPDATE ) ))
- {
- $this->_MBPop ();
- return -1;
- }
-
- // parse response
- list(,$updated) = unpack ( "N*", substr ( $response, 0, 4 ) );
- $this->_MBPop ();
- return $updated;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // persistent connections
- /////////////////////////////////////////////////////////////////////////////
-
- function Open()
- {
- if ( $this->_socket !== false )
- {
- $this->_error = 'already connected';
- return false;
- }
- if ( !$fp = $this->_Connect() )
- return false;
-
- // command, command version = 0, body length = 4, body = 1
- $req = pack ( "nnNN", SEARCHD_COMMAND_PERSIST, 0, 4, 1 );
- if ( !$this->_Send ( $fp, $req, 12 ) )
- return false;
-
- $this->_socket = $fp;
- return true;
- }
-
- function Close()
- {
- if ( $this->_socket === false )
- {
- $this->_error = 'not connected';
- return false;
- }
-
- fclose ( $this->_socket );
- $this->_socket = false;
-
- return true;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // status
- //////////////////////////////////////////////////////////////////////////
-
- function Status ()
- {
- $this->_MBPush ();
- if (!( $fp = $this->_Connect() ))
- {
- $this->_MBPop();
- return false;
- }
-
- $req = pack ( "nnNN", SEARCHD_COMMAND_STATUS, VER_COMMAND_STATUS, 4, 1 ); // len=4, body=1
- if ( !( $this->_Send ( $fp, $req, 12 ) ) ||
- !( $response = $this->_GetResponse ( $fp, VER_COMMAND_STATUS ) ) )
- {
- $this->_MBPop ();
- return false;
- }
-
- $res = substr ( $response, 4 ); // just ignore length, error handling, etc
- $p = 0;
- list ( $rows, $cols ) = array_values ( unpack ( "N*N*", substr ( $response, $p, 8 ) ) ); $p += 8;
-
- $res = array();
- for ( $i=0; $i<$rows; $i++ )
- for ( $j=0; $j<$cols; $j++ )
- {
- list(,$len) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
- $res[$i][] = substr ( $response, $p, $len ); $p += $len;
- }
-
- $this->_MBPop ();
- return $res;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // flush
- //////////////////////////////////////////////////////////////////////////
-
- function FlushAttributes ()
- {
- $this->_MBPush ();
- if (!( $fp = $this->_Connect() ))
- {
- $this->_MBPop();
- return -1;
- }
-
- $req = pack ( "nnN", SEARCHD_COMMAND_FLUSHATTRS, VER_COMMAND_FLUSHATTRS, 0 ); // len=0
- if ( !( $this->_Send ( $fp, $req, 8 ) ) ||
- !( $response = $this->_GetResponse ( $fp, VER_COMMAND_FLUSHATTRS ) ) )
- {
- $this->_MBPop ();
- return -1;
- }
-
- $tag = -1;
- if ( strlen($response)==4 )
- list(,$tag) = unpack ( "N*", $response );
- else
- $this->_error = "unexpected response length";
-
- $this->_MBPop ();
- return $tag;
- }
-}
-
-//
-// $Id: sphinxapi.php 3087 2012-01-30 23:07:35Z shodan $
-//
+<?php + +// +// $Id: sphinxapi.php 3087 2012-01-30 23:07:35Z shodan $ +// + +// +// Copyright (c) 2001-2012, Andrew Aksyonoff +// Copyright (c) 2008-2012, Sphinx Technologies Inc +// All rights reserved +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License. You should have +// received a copy of the GPL license along with this program; if you +// did not, you can find it at http://www.gnu.org/ +// + +///////////////////////////////////////////////////////////////////////////// +// PHP version of Sphinx searchd client (PHP API) +///////////////////////////////////////////////////////////////////////////// + +/// known searchd commands +define ( "SEARCHD_COMMAND_SEARCH", 0 ); +define ( "SEARCHD_COMMAND_EXCERPT", 1 ); +define ( "SEARCHD_COMMAND_UPDATE", 2 ); +define ( "SEARCHD_COMMAND_KEYWORDS", 3 ); +define ( "SEARCHD_COMMAND_PERSIST", 4 ); +define ( "SEARCHD_COMMAND_STATUS", 5 ); +define ( "SEARCHD_COMMAND_FLUSHATTRS", 7 ); + +/// current client-side command implementation versions +define ( "VER_COMMAND_SEARCH", 0x119 ); +define ( "VER_COMMAND_EXCERPT", 0x104 ); +define ( "VER_COMMAND_UPDATE", 0x102 ); +define ( "VER_COMMAND_KEYWORDS", 0x100 ); +define ( "VER_COMMAND_STATUS", 0x100 ); +define ( "VER_COMMAND_QUERY", 0x100 ); +define ( "VER_COMMAND_FLUSHATTRS", 0x100 ); + +/// known searchd status codes +define ( "SEARCHD_OK", 0 ); +define ( "SEARCHD_ERROR", 1 ); +define ( "SEARCHD_RETRY", 2 ); +define ( "SEARCHD_WARNING", 3 ); + +/// known match modes +define ( "SPH_MATCH_ALL", 0 ); +define ( "SPH_MATCH_ANY", 1 ); +define ( "SPH_MATCH_PHRASE", 2 ); +define ( "SPH_MATCH_BOOLEAN", 3 ); +define ( "SPH_MATCH_EXTENDED", 4 ); +define ( "SPH_MATCH_FULLSCAN", 5 ); +define ( "SPH_MATCH_EXTENDED2", 6 ); // extended engine V2 (TEMPORARY, WILL BE REMOVED) + +/// known ranking modes (ext2 only) +define ( "SPH_RANK_PROXIMITY_BM25", 0 ); ///< default mode, phrase proximity major factor and BM25 minor one +define ( "SPH_RANK_BM25", 1 ); ///< statistical mode, BM25 ranking only (faster but worse quality) +define ( "SPH_RANK_NONE", 2 ); ///< no ranking, all matches get a weight of 1 +define ( "SPH_RANK_WORDCOUNT", 3 ); ///< simple word-count weighting, rank is a weighted sum of per-field keyword occurence counts +define ( "SPH_RANK_PROXIMITY", 4 ); +define ( "SPH_RANK_MATCHANY", 5 ); +define ( "SPH_RANK_FIELDMASK", 6 ); +define ( "SPH_RANK_SPH04", 7 ); +define ( "SPH_RANK_EXPR", 8 ); +define ( "SPH_RANK_TOTAL", 9 ); + +/// known sort modes +define ( "SPH_SORT_RELEVANCE", 0 ); +define ( "SPH_SORT_ATTR_DESC", 1 ); +define ( "SPH_SORT_ATTR_ASC", 2 ); +define ( "SPH_SORT_TIME_SEGMENTS", 3 ); +define ( "SPH_SORT_EXTENDED", 4 ); +define ( "SPH_SORT_EXPR", 5 ); + +/// known filter types +define ( "SPH_FILTER_VALUES", 0 ); +define ( "SPH_FILTER_RANGE", 1 ); +define ( "SPH_FILTER_FLOATRANGE", 2 ); + +/// known attribute types +define ( "SPH_ATTR_INTEGER", 1 ); +define ( "SPH_ATTR_TIMESTAMP", 2 ); +define ( "SPH_ATTR_ORDINAL", 3 ); +define ( "SPH_ATTR_BOOL", 4 ); +define ( "SPH_ATTR_FLOAT", 5 ); +define ( "SPH_ATTR_BIGINT", 6 ); +define ( "SPH_ATTR_STRING", 7 ); +define ( "SPH_ATTR_MULTI", 0x40000001 ); +define ( "SPH_ATTR_MULTI64", 0x40000002 ); + +/// known grouping functions +define ( "SPH_GROUPBY_DAY", 0 ); +define ( "SPH_GROUPBY_WEEK", 1 ); +define ( "SPH_GROUPBY_MONTH", 2 ); +define ( "SPH_GROUPBY_YEAR", 3 ); +define ( "SPH_GROUPBY_ATTR", 4 ); +define ( "SPH_GROUPBY_ATTRPAIR", 5 ); + +// important properties of PHP's integers: +// - always signed (one bit short of PHP_INT_SIZE) +// - conversion from string to int is saturated +// - float is double +// - div converts arguments to floats +// - mod converts arguments to ints + +// the packing code below works as follows: +// - when we got an int, just pack it +// if performance is a problem, this is the branch users should aim for +// +// - otherwise, we got a number in string form +// this might be due to different reasons, but we assume that this is +// because it didn't fit into PHP int +// +// - factor the string into high and low ints for packing +// - if we have bcmath, then it is used +// - if we don't, we have to do it manually (this is the fun part) +// +// - x64 branch does factoring using ints +// - x32 (ab)uses floats, since we can't fit unsigned 32-bit number into an int +// +// unpacking routines are pretty much the same. +// - return ints if we can +// - otherwise format number into a string + +/// pack 64-bit signed +function sphPackI64 ( $v ) +{ + assert ( is_numeric($v) ); + + // x64 + if ( PHP_INT_SIZE>=8 ) + { + $v = (int)$v; + return pack ( "NN", $v>>32, $v&0xFFFFFFFF ); + } + + // x32, int + if ( is_int($v) ) + return pack ( "NN", $v < 0 ? -1 : 0, $v ); + + // x32, bcmath + if ( function_exists("bcmul") ) + { + if ( bccomp ( $v, 0 ) == -1 ) + $v = bcadd ( "18446744073709551616", $v ); + $h = bcdiv ( $v, "4294967296", 0 ); + $l = bcmod ( $v, "4294967296" ); + return pack ( "NN", (float)$h, (float)$l ); // conversion to float is intentional; int would lose 31st bit + } + + // x32, no-bcmath + $p = max(0, strlen($v) - 13); + $lo = abs((float)substr($v, $p)); + $hi = abs((float)substr($v, 0, $p)); + + $m = $lo + $hi*1316134912.0; // (10 ^ 13) % (1 << 32) = 1316134912 + $q = floor($m/4294967296.0); + $l = $m - ($q*4294967296.0); + $h = $hi*2328.0 + $q; // (10 ^ 13) / (1 << 32) = 2328 + + if ( $v<0 ) + { + if ( $l==0 ) + $h = 4294967296.0 - $h; + else + { + $h = 4294967295.0 - $h; + $l = 4294967296.0 - $l; + } + } + return pack ( "NN", $h, $l ); +} + +/// pack 64-bit unsigned +function sphPackU64 ( $v ) +{ + assert ( is_numeric($v) ); + + // x64 + if ( PHP_INT_SIZE>=8 ) + { + assert ( $v>=0 ); + + // x64, int + if ( is_int($v) ) + return pack ( "NN", $v>>32, $v&0xFFFFFFFF ); + + // x64, bcmath + if ( function_exists("bcmul") ) + { + $h = bcdiv ( $v, 4294967296, 0 ); + $l = bcmod ( $v, 4294967296 ); + return pack ( "NN", $h, $l ); + } + + // x64, no-bcmath + $p = max ( 0, strlen($v) - 13 ); + $lo = (int)substr ( $v, $p ); + $hi = (int)substr ( $v, 0, $p ); + + $m = $lo + $hi*1316134912; + $l = $m % 4294967296; + $h = $hi*2328 + (int)($m/4294967296); + + return pack ( "NN", $h, $l ); + } + + // x32, int + if ( is_int($v) ) + return pack ( "NN", 0, $v ); + + // x32, bcmath + if ( function_exists("bcmul") ) + { + $h = bcdiv ( $v, "4294967296", 0 ); + $l = bcmod ( $v, "4294967296" ); + return pack ( "NN", (float)$h, (float)$l ); // conversion to float is intentional; int would lose 31st bit + } + + // x32, no-bcmath + $p = max(0, strlen($v) - 13); + $lo = (float)substr($v, $p); + $hi = (float)substr($v, 0, $p); + + $m = $lo + $hi*1316134912.0; + $q = floor($m / 4294967296.0); + $l = $m - ($q * 4294967296.0); + $h = $hi*2328.0 + $q; + + return pack ( "NN", $h, $l ); +} + +// unpack 64-bit unsigned +function sphUnpackU64 ( $v ) +{ + list ( $hi, $lo ) = array_values ( unpack ( "N*N*", $v ) ); + + if ( PHP_INT_SIZE>=8 ) + { + if ( $hi<0 ) $hi += (1<<32); // because php 5.2.2 to 5.2.5 is totally fucked up again + if ( $lo<0 ) $lo += (1<<32); + + // x64, int + if ( $hi<=2147483647 ) + return ($hi<<32) + $lo; + + // x64, bcmath + if ( function_exists("bcmul") ) + return bcadd ( $lo, bcmul ( $hi, "4294967296" ) ); + + // x64, no-bcmath + $C = 100000; + $h = ((int)($hi / $C) << 32) + (int)($lo / $C); + $l = (($hi % $C) << 32) + ($lo % $C); + if ( $l>$C ) + { + $h += (int)($l / $C); + $l = $l % $C; + } + + if ( $h==0 ) + return $l; + return sprintf ( "%d%05d", $h, $l ); + } + + // x32, int + if ( $hi==0 ) + { + if ( $lo>0 ) + return $lo; + return sprintf ( "%u", $lo ); + } + + $hi = sprintf ( "%u", $hi ); + $lo = sprintf ( "%u", $lo ); + + // x32, bcmath + if ( function_exists("bcmul") ) + return bcadd ( $lo, bcmul ( $hi, "4294967296" ) ); + + // x32, no-bcmath + $hi = (float)$hi; + $lo = (float)$lo; + + $q = floor($hi/10000000.0); + $r = $hi - $q*10000000.0; + $m = $lo + $r*4967296.0; + $mq = floor($m/10000000.0); + $l = $m - $mq*10000000.0; + $h = $q*4294967296.0 + $r*429.0 + $mq; + + $h = sprintf ( "%.0f", $h ); + $l = sprintf ( "%07.0f", $l ); + if ( $h=="0" ) + return sprintf( "%.0f", (float)$l ); + return $h . $l; +} + +// unpack 64-bit signed +function sphUnpackI64 ( $v ) +{ + list ( $hi, $lo ) = array_values ( unpack ( "N*N*", $v ) ); + + // x64 + if ( PHP_INT_SIZE>=8 ) + { + if ( $hi<0 ) $hi += (1<<32); // because php 5.2.2 to 5.2.5 is totally fucked up again + if ( $lo<0 ) $lo += (1<<32); + + return ($hi<<32) + $lo; + } + + // x32, int + if ( $hi==0 ) + { + if ( $lo>0 ) + return $lo; + return sprintf ( "%u", $lo ); + } + // x32, int + elseif ( $hi==-1 ) + { + if ( $lo<0 ) + return $lo; + return sprintf ( "%.0f", $lo - 4294967296.0 ); + } + + $neg = ""; + $c = 0; + if ( $hi<0 ) + { + $hi = ~$hi; + $lo = ~$lo; + $c = 1; + $neg = "-"; + } + + $hi = sprintf ( "%u", $hi ); + $lo = sprintf ( "%u", $lo ); + + // x32, bcmath + if ( function_exists("bcmul") ) + return $neg . bcadd ( bcadd ( $lo, bcmul ( $hi, "4294967296" ) ), $c ); + + // x32, no-bcmath + $hi = (float)$hi; + $lo = (float)$lo; + + $q = floor($hi/10000000.0); + $r = $hi - $q*10000000.0; + $m = $lo + $r*4967296.0; + $mq = floor($m/10000000.0); + $l = $m - $mq*10000000.0 + $c; + $h = $q*4294967296.0 + $r*429.0 + $mq; + if ( $l==10000000 ) + { + $l = 0; + $h += 1; + } + + $h = sprintf ( "%.0f", $h ); + $l = sprintf ( "%07.0f", $l ); + if ( $h=="0" ) + return $neg . sprintf( "%.0f", (float)$l ); + return $neg . $h . $l; +} + + +function sphFixUint ( $value ) +{ + if ( PHP_INT_SIZE>=8 ) + { + // x64 route, workaround broken unpack() in 5.2.2+ + if ( $value<0 ) $value += (1<<32); + return $value; + } + else + { + // x32 route, workaround php signed/unsigned braindamage + return sprintf ( "%u", $value ); + } +} + + +/// sphinx searchd client class +class SphinxClient +{ + var $_host; ///< searchd host (default is "localhost") + var $_port; ///< searchd port (default is 9312) + var $_offset; ///< how many records to seek from result-set start (default is 0) + var $_limit; ///< how many records to return from result-set starting at offset (default is 20) + var $_mode; ///< query matching mode (default is SPH_MATCH_ALL) + var $_weights; ///< per-field weights (default is 1 for all fields) + var $_sort; ///< match sorting mode (default is SPH_SORT_RELEVANCE) + var $_sortby; ///< attribute to sort by (defualt is "") + var $_min_id; ///< min ID to match (default is 0, which means no limit) + var $_max_id; ///< max ID to match (default is 0, which means no limit) + var $_filters; ///< search filters + var $_groupby; ///< group-by attribute name + var $_groupfunc; ///< group-by function (to pre-process group-by attribute value with) + var $_groupsort; ///< group-by sorting clause (to sort groups in result set with) + var $_groupdistinct;///< group-by count-distinct attribute + var $_maxmatches; ///< max matches to retrieve + var $_cutoff; ///< cutoff to stop searching at (default is 0) + var $_retrycount; ///< distributed retries count + var $_retrydelay; ///< distributed retries delay + var $_anchor; ///< geographical anchor point + var $_indexweights; ///< per-index weights + var $_ranker; ///< ranking mode (default is SPH_RANK_PROXIMITY_BM25) + var $_rankexpr; ///< ranking mode expression (for SPH_RANK_EXPR) + var $_maxquerytime; ///< max query time, milliseconds (default is 0, do not limit) + var $_fieldweights; ///< per-field-name weights + var $_overrides; ///< per-query attribute values overrides + var $_select; ///< select-list (attributes or expressions, with optional aliases) + + var $_error; ///< last error message + var $_warning; ///< last warning message + var $_connerror; ///< connection error vs remote error flag + + var $_reqs; ///< requests array for multi-query + var $_mbenc; ///< stored mbstring encoding + var $_arrayresult; ///< whether $result["matches"] should be a hash or an array + var $_timeout; ///< connect timeout + + ///////////////////////////////////////////////////////////////////////////// + // common stuff + ///////////////////////////////////////////////////////////////////////////// + + /// create a new client object and fill defaults + function SphinxClient () + { + // per-client-object settings + $this->_host = "localhost"; + $this->_port = 9312; + $this->_path = false; + $this->_socket = false; + + // per-query settings + $this->_offset = 0; + $this->_limit = 20; + $this->_mode = SPH_MATCH_ALL; + $this->_weights = array (); + $this->_sort = SPH_SORT_RELEVANCE; + $this->_sortby = ""; + $this->_min_id = 0; + $this->_max_id = 0; + $this->_filters = array (); + $this->_groupby = ""; + $this->_groupfunc = SPH_GROUPBY_DAY; + $this->_groupsort = "@group desc"; + $this->_groupdistinct= ""; + $this->_maxmatches = 1000; + $this->_cutoff = 0; + $this->_retrycount = 0; + $this->_retrydelay = 0; + $this->_anchor = array (); + $this->_indexweights= array (); + $this->_ranker = SPH_RANK_PROXIMITY_BM25; + $this->_rankexpr = ""; + $this->_maxquerytime= 0; + $this->_fieldweights= array(); + $this->_overrides = array(); + $this->_select = "*"; + + $this->_error = ""; // per-reply fields (for single-query case) + $this->_warning = ""; + $this->_connerror = false; + + $this->_reqs = array (); // requests storage (for multi-query case) + $this->_mbenc = ""; + $this->_arrayresult = false; + $this->_timeout = 0; + } + + function __destruct() + { + if ( $this->_socket !== false ) + fclose ( $this->_socket ); + } + + /// get last error message (string) + function GetLastError () + { + return $this->_error; + } + + /// get last warning message (string) + function GetLastWarning () + { + return $this->_warning; + } + + /// get last error flag (to tell network connection errors from searchd errors or broken responses) + function IsConnectError() + { + return $this->_connerror; + } + + /// set searchd host name (string) and port (integer) + function SetServer ( $host, $port = 0 ) + { + assert ( is_string($host) ); + if ( $host[0] == '/') + { + $this->_path = 'unix://' . $host; + return; + } + if ( substr ( $host, 0, 7 )=="unix://" ) + { + $this->_path = $host; + return; + } + + assert ( is_int($port) ); + $this->_host = $host; + $this->_port = $port; + $this->_path = ''; + + } + + /// set server connection timeout (0 to remove) + function SetConnectTimeout ( $timeout ) + { + assert ( is_numeric($timeout) ); + $this->_timeout = $timeout; + } + + + function _Send ( $handle, $data, $length ) + { + if ( feof($handle) || fwrite ( $handle, $data, $length ) !== $length ) + { + $this->_error = 'connection unexpectedly closed (timed out?)'; + $this->_connerror = true; + return false; + } + return true; + } + + ///////////////////////////////////////////////////////////////////////////// + + /// enter mbstring workaround mode + function _MBPush () + { + $this->_mbenc = ""; + if ( ini_get ( "mbstring.func_overload" ) & 2 ) + { + $this->_mbenc = mb_internal_encoding(); + mb_internal_encoding ( "latin1" ); + } + } + + /// leave mbstring workaround mode + function _MBPop () + { + if ( $this->_mbenc ) + mb_internal_encoding ( $this->_mbenc ); + } + + /// connect to searchd server + function _Connect () + { + if ( $this->_socket!==false ) + { + // we are in persistent connection mode, so we have a socket + // however, need to check whether it's still alive + if ( !@feof ( $this->_socket ) ) + return $this->_socket; + + // force reopen + $this->_socket = false; + } + + $errno = 0; + $errstr = ""; + $this->_connerror = false; + + if ( $this->_path ) + { + $host = $this->_path; + $port = 0; + } + else + { + $host = $this->_host; + $port = $this->_port; + } + + if ( $this->_timeout<=0 ) + $fp = @fsockopen ( $host, $port, $errno, $errstr ); + else + $fp = @fsockopen ( $host, $port, $errno, $errstr, $this->_timeout ); + + if ( !$fp ) + { + if ( $this->_path ) + $location = $this->_path; + else + $location = "{$this->_host}:{$this->_port}"; + + $errstr = trim ( $errstr ); + $this->_error = "connection to $location failed (errno=$errno, msg=$errstr)"; + $this->_connerror = true; + return false; + } + + // send my version + // this is a subtle part. we must do it before (!) reading back from searchd. + // because otherwise under some conditions (reported on FreeBSD for instance) + // TCP stack could throttle write-write-read pattern because of Nagle. + if ( !$this->_Send ( $fp, pack ( "N", 1 ), 4 ) ) + { + fclose ( $fp ); + $this->_error = "failed to send client protocol version"; + return false; + } + + // check version + list(,$v) = unpack ( "N*", fread ( $fp, 4 ) ); + $v = (int)$v; + if ( $v<1 ) + { + fclose ( $fp ); + $this->_error = "expected searchd protocol version 1+, got version '$v'"; + return false; + } + + return $fp; + } + + /// get and check response packet from searchd server + function _GetResponse ( $fp, $client_ver ) + { + $response = ""; + $len = 0; + + $header = fread ( $fp, 8 ); + if ( strlen($header)==8 ) + { + list ( $status, $ver, $len ) = array_values ( unpack ( "n2a/Nb", $header ) ); + $left = $len; + while ( $left>0 && !feof($fp) ) + { + $chunk = fread ( $fp, min ( 8192, $left ) ); + if ( $chunk ) + { + $response .= $chunk; + $left -= strlen($chunk); + } + } + } + if ( $this->_socket === false ) + fclose ( $fp ); + + // check response + $read = strlen ( $response ); + if ( !$response || $read!=$len ) + { + $this->_error = $len + ? "failed to read searchd response (status=$status, ver=$ver, len=$len, read=$read)" + : "received zero-sized searchd response"; + return false; + } + + // check status + if ( $status==SEARCHD_WARNING ) + { + list(,$wlen) = unpack ( "N*", substr ( $response, 0, 4 ) ); + $this->_warning = substr ( $response, 4, $wlen ); + return substr ( $response, 4+$wlen ); + } + if ( $status==SEARCHD_ERROR ) + { + $this->_error = "searchd error: " . substr ( $response, 4 ); + return false; + } + if ( $status==SEARCHD_RETRY ) + { + $this->_error = "temporary searchd error: " . substr ( $response, 4 ); + return false; + } + if ( $status!=SEARCHD_OK ) + { + $this->_error = "unknown status code '$status'"; + return false; + } + + // check version + if ( $ver<$client_ver ) + { + $this->_warning = sprintf ( "searchd command v.%d.%d older than client's v.%d.%d, some options might not work", + $ver>>8, $ver&0xff, $client_ver>>8, $client_ver&0xff ); + } + + return $response; + } + + ///////////////////////////////////////////////////////////////////////////// + // searching + ///////////////////////////////////////////////////////////////////////////// + + /// set offset and count into result set, + /// and optionally set max-matches and cutoff limits + function SetLimits ( $offset, $limit, $max=0, $cutoff=0 ) + { + assert ( is_int($offset) ); + assert ( is_int($limit) ); + assert ( $offset>=0 ); + assert ( $limit>0 ); + assert ( $max>=0 ); + $this->_offset = $offset; + $this->_limit = $limit; + if ( $max>0 ) + $this->_maxmatches = $max; + if ( $cutoff>0 ) + $this->_cutoff = $cutoff; + } + + /// set maximum query time, in milliseconds, per-index + /// integer, 0 means "do not limit" + function SetMaxQueryTime ( $max ) + { + assert ( is_int($max) ); + assert ( $max>=0 ); + $this->_maxquerytime = $max; + } + + /// set matching mode + function SetMatchMode ( $mode ) + { + assert ( $mode==SPH_MATCH_ALL + || $mode==SPH_MATCH_ANY + || $mode==SPH_MATCH_PHRASE + || $mode==SPH_MATCH_BOOLEAN + || $mode==SPH_MATCH_EXTENDED + || $mode==SPH_MATCH_FULLSCAN + || $mode==SPH_MATCH_EXTENDED2 ); + $this->_mode = $mode; + } + + /// set ranking mode + function SetRankingMode ( $ranker, $rankexpr="" ) + { + assert ( $ranker>=0 && $ranker<SPH_RANK_TOTAL ); + assert ( is_string($rankexpr) ); + $this->_ranker = $ranker; + $this->_rankexpr = $rankexpr; + } + + /// set matches sorting mode + function SetSortMode ( $mode, $sortby="" ) + { + assert ( + $mode==SPH_SORT_RELEVANCE || + $mode==SPH_SORT_ATTR_DESC || + $mode==SPH_SORT_ATTR_ASC || + $mode==SPH_SORT_TIME_SEGMENTS || + $mode==SPH_SORT_EXTENDED || + $mode==SPH_SORT_EXPR ); + assert ( is_string($sortby) ); + assert ( $mode==SPH_SORT_RELEVANCE || strlen($sortby)>0 ); + + $this->_sort = $mode; + $this->_sortby = $sortby; + } + + /// bind per-field weights by order + /// DEPRECATED; use SetFieldWeights() instead + function SetWeights ( $weights ) + { + assert ( is_array($weights) ); + foreach ( $weights as $weight ) + assert ( is_int($weight) ); + + $this->_weights = $weights; + } + + /// bind per-field weights by name + function SetFieldWeights ( $weights ) + { + assert ( is_array($weights) ); + foreach ( $weights as $name=>$weight ) + { + assert ( is_string($name) ); + assert ( is_int($weight) ); + } + $this->_fieldweights = $weights; + } + + /// bind per-index weights by name + function SetIndexWeights ( $weights ) + { + assert ( is_array($weights) ); + foreach ( $weights as $index=>$weight ) + { + assert ( is_string($index) ); + assert ( is_int($weight) ); + } + $this->_indexweights = $weights; + } + + /// set IDs range to match + /// only match records if document ID is beetwen $min and $max (inclusive) + function SetIDRange ( $min, $max ) + { + assert ( is_numeric($min) ); + assert ( is_numeric($max) ); + assert ( $min<=$max ); + $this->_min_id = $min; + $this->_max_id = $max; + } + + /// set values set filter + /// only match records where $attribute value is in given set + function SetFilter ( $attribute, $values, $exclude=false ) + { + assert ( is_string($attribute) ); + assert ( is_array($values) ); + assert ( count($values) ); + + if ( is_array($values) && count($values) ) + { + foreach ( $values as $value ) + assert ( is_numeric($value) ); + + $this->_filters[] = array ( "type"=>SPH_FILTER_VALUES, "attr"=>$attribute, "exclude"=>$exclude, "values"=>$values ); + } + } + + /// set range filter + /// only match records if $attribute value is beetwen $min and $max (inclusive) + function SetFilterRange ( $attribute, $min, $max, $exclude=false ) + { + assert ( is_string($attribute) ); + assert ( is_numeric($min) ); + assert ( is_numeric($max) ); + assert ( $min<=$max ); + + $this->_filters[] = array ( "type"=>SPH_FILTER_RANGE, "attr"=>$attribute, "exclude"=>$exclude, "min"=>$min, "max"=>$max ); + } + + /// set float range filter + /// only match records if $attribute value is beetwen $min and $max (inclusive) + function SetFilterFloatRange ( $attribute, $min, $max, $exclude=false ) + { + assert ( is_string($attribute) ); + assert ( is_float($min) ); + assert ( is_float($max) ); + assert ( $min<=$max ); + + $this->_filters[] = array ( "type"=>SPH_FILTER_FLOATRANGE, "attr"=>$attribute, "exclude"=>$exclude, "min"=>$min, "max"=>$max ); + } + + /// setup anchor point for geosphere distance calculations + /// required to use @geodist in filters and sorting + /// latitude and longitude must be in radians + function SetGeoAnchor ( $attrlat, $attrlong, $lat, $long ) + { + assert ( is_string($attrlat) ); + assert ( is_string($attrlong) ); + assert ( is_float($lat) ); + assert ( is_float($long) ); + + $this->_anchor = array ( "attrlat"=>$attrlat, "attrlong"=>$attrlong, "lat"=>$lat, "long"=>$long ); + } + + /// set grouping attribute and function + function SetGroupBy ( $attribute, $func, $groupsort="@group desc" ) + { + assert ( is_string($attribute) ); + assert ( is_string($groupsort) ); + assert ( $func==SPH_GROUPBY_DAY + || $func==SPH_GROUPBY_WEEK + || $func==SPH_GROUPBY_MONTH + || $func==SPH_GROUPBY_YEAR + || $func==SPH_GROUPBY_ATTR + || $func==SPH_GROUPBY_ATTRPAIR ); + + $this->_groupby = $attribute; + $this->_groupfunc = $func; + $this->_groupsort = $groupsort; + } + + /// set count-distinct attribute for group-by queries + function SetGroupDistinct ( $attribute ) + { + assert ( is_string($attribute) ); + $this->_groupdistinct = $attribute; + } + + /// set distributed retries count and delay + function SetRetries ( $count, $delay=0 ) + { + assert ( is_int($count) && $count>=0 ); + assert ( is_int($delay) && $delay>=0 ); + $this->_retrycount = $count; + $this->_retrydelay = $delay; + } + + /// set result set format (hash or array; hash by default) + /// PHP specific; needed for group-by-MVA result sets that may contain duplicate IDs + function SetArrayResult ( $arrayresult ) + { + assert ( is_bool($arrayresult) ); + $this->_arrayresult = $arrayresult; + } + + /// set attribute values override + /// there can be only one override per attribute + /// $values must be a hash that maps document IDs to attribute values + function SetOverride ( $attrname, $attrtype, $values ) + { + assert ( is_string ( $attrname ) ); + assert ( in_array ( $attrtype, array ( SPH_ATTR_INTEGER, SPH_ATTR_TIMESTAMP, SPH_ATTR_BOOL, SPH_ATTR_FLOAT, SPH_ATTR_BIGINT ) ) ); + assert ( is_array ( $values ) ); + + $this->_overrides[$attrname] = array ( "attr"=>$attrname, "type"=>$attrtype, "values"=>$values ); + } + + /// set select-list (attributes or expressions), SQL-like syntax + function SetSelect ( $select ) + { + assert ( is_string ( $select ) ); + $this->_select = $select; + } + + ////////////////////////////////////////////////////////////////////////////// + + /// clear all filters (for multi-queries) + function ResetFilters () + { + $this->_filters = array(); + $this->_anchor = array(); + } + + /// clear groupby settings (for multi-queries) + function ResetGroupBy () + { + $this->_groupby = ""; + $this->_groupfunc = SPH_GROUPBY_DAY; + $this->_groupsort = "@group desc"; + $this->_groupdistinct= ""; + } + + /// clear all attribute value overrides (for multi-queries) + function ResetOverrides () + { + $this->_overrides = array (); + } + + ////////////////////////////////////////////////////////////////////////////// + + /// connect to searchd server, run given search query through given indexes, + /// and return the search results + function Query ( $query, $index="*", $comment="" ) + { + assert ( empty($this->_reqs) ); + + $this->AddQuery ( $query, $index, $comment ); + $results = $this->RunQueries (); + $this->_reqs = array (); // just in case it failed too early + + if ( !is_array($results) ) + return false; // probably network error; error message should be already filled + + $this->_error = $results[0]["error"]; + $this->_warning = $results[0]["warning"]; + if ( $results[0]["status"]==SEARCHD_ERROR ) + return false; + else + return $results[0]; + } + + /// helper to pack floats in network byte order + function _PackFloat ( $f ) + { + $t1 = pack ( "f", $f ); // machine order + list(,$t2) = unpack ( "L*", $t1 ); // int in machine order + return pack ( "N", $t2 ); + } + + /// add query to multi-query batch + /// returns index into results array from RunQueries() call + function AddQuery ( $query, $index="*", $comment="" ) + { + // mbstring workaround + $this->_MBPush (); + + // build request + $req = pack ( "NNNN", $this->_offset, $this->_limit, $this->_mode, $this->_ranker ); + if ( $this->_ranker==SPH_RANK_EXPR ) + $req .= pack ( "N", strlen($this->_rankexpr) ) . $this->_rankexpr; + $req .= pack ( "N", $this->_sort ); // (deprecated) sort mode + $req .= pack ( "N", strlen($this->_sortby) ) . $this->_sortby; + $req .= pack ( "N", strlen($query) ) . $query; // query itself + $req .= pack ( "N", count($this->_weights) ); // weights + foreach ( $this->_weights as $weight ) + $req .= pack ( "N", (int)$weight ); + $req .= pack ( "N", strlen($index) ) . $index; // indexes + $req .= pack ( "N", 1 ); // id64 range marker + $req .= sphPackU64 ( $this->_min_id ) . sphPackU64 ( $this->_max_id ); // id64 range + + // filters + $req .= pack ( "N", count($this->_filters) ); + foreach ( $this->_filters as $filter ) + { + $req .= pack ( "N", strlen($filter["attr"]) ) . $filter["attr"]; + $req .= pack ( "N", $filter["type"] ); + switch ( $filter["type"] ) + { + case SPH_FILTER_VALUES: + $req .= pack ( "N", count($filter["values"]) ); + foreach ( $filter["values"] as $value ) + $req .= sphPackI64 ( $value ); + break; + + case SPH_FILTER_RANGE: + $req .= sphPackI64 ( $filter["min"] ) . sphPackI64 ( $filter["max"] ); + break; + + case SPH_FILTER_FLOATRANGE: + $req .= $this->_PackFloat ( $filter["min"] ) . $this->_PackFloat ( $filter["max"] ); + break; + + default: + assert ( 0 && "internal error: unhandled filter type" ); + } + $req .= pack ( "N", $filter["exclude"] ); + } + + // group-by clause, max-matches count, group-sort clause, cutoff count + $req .= pack ( "NN", $this->_groupfunc, strlen($this->_groupby) ) . $this->_groupby; + $req .= pack ( "N", $this->_maxmatches ); + $req .= pack ( "N", strlen($this->_groupsort) ) . $this->_groupsort; + $req .= pack ( "NNN", $this->_cutoff, $this->_retrycount, $this->_retrydelay ); + $req .= pack ( "N", strlen($this->_groupdistinct) ) . $this->_groupdistinct; + + // anchor point + if ( empty($this->_anchor) ) + { + $req .= pack ( "N", 0 ); + } else + { + $a =& $this->_anchor; + $req .= pack ( "N", 1 ); + $req .= pack ( "N", strlen($a["attrlat"]) ) . $a["attrlat"]; + $req .= pack ( "N", strlen($a["attrlong"]) ) . $a["attrlong"]; + $req .= $this->_PackFloat ( $a["lat"] ) . $this->_PackFloat ( $a["long"] ); + } + + // per-index weights + $req .= pack ( "N", count($this->_indexweights) ); + foreach ( $this->_indexweights as $idx=>$weight ) + $req .= pack ( "N", strlen($idx) ) . $idx . pack ( "N", $weight ); + + // max query time + $req .= pack ( "N", $this->_maxquerytime ); + + // per-field weights + $req .= pack ( "N", count($this->_fieldweights) ); + foreach ( $this->_fieldweights as $field=>$weight ) + $req .= pack ( "N", strlen($field) ) . $field . pack ( "N", $weight ); + + // comment + $req .= pack ( "N", strlen($comment) ) . $comment; + + // attribute overrides + $req .= pack ( "N", count($this->_overrides) ); + foreach ( $this->_overrides as $key => $entry ) + { + $req .= pack ( "N", strlen($entry["attr"]) ) . $entry["attr"]; + $req .= pack ( "NN", $entry["type"], count($entry["values"]) ); + foreach ( $entry["values"] as $id=>$val ) + { + assert ( is_numeric($id) ); + assert ( is_numeric($val) ); + + $req .= sphPackU64 ( $id ); + switch ( $entry["type"] ) + { + case SPH_ATTR_FLOAT: $req .= $this->_PackFloat ( $val ); break; + case SPH_ATTR_BIGINT: $req .= sphPackI64 ( $val ); break; + default: $req .= pack ( "N", $val ); break; + } + } + } + + // select-list + $req .= pack ( "N", strlen($this->_select) ) . $this->_select; + + // mbstring workaround + $this->_MBPop (); + + // store request to requests array + $this->_reqs[] = $req; + return count($this->_reqs)-1; + } + + /// connect to searchd, run queries batch, and return an array of result sets + function RunQueries () + { + if ( empty($this->_reqs) ) + { + $this->_error = "no queries defined, issue AddQuery() first"; + return false; + } + + // mbstring workaround + $this->_MBPush (); + + if (!( $fp = $this->_Connect() )) + { + $this->_MBPop (); + return false; + } + + // send query, get response + $nreqs = count($this->_reqs); + $req = join ( "", $this->_reqs ); + $len = 8+strlen($req); + $req = pack ( "nnNNN", SEARCHD_COMMAND_SEARCH, VER_COMMAND_SEARCH, $len, 0, $nreqs ) . $req; // add header + + if ( !( $this->_Send ( $fp, $req, $len+8 ) ) || + !( $response = $this->_GetResponse ( $fp, VER_COMMAND_SEARCH ) ) ) + { + $this->_MBPop (); + return false; + } + + // query sent ok; we can reset reqs now + $this->_reqs = array (); + + // parse and return response + return $this->_ParseSearchResponse ( $response, $nreqs ); + } + + /// parse and return search query (or queries) response + function _ParseSearchResponse ( $response, $nreqs ) + { + $p = 0; // current position + $max = strlen($response); // max position for checks, to protect against broken responses + + $results = array (); + for ( $ires=0; $ires<$nreqs && $p<$max; $ires++ ) + { + $results[] = array(); + $result =& $results[$ires]; + + $result["error"] = ""; + $result["warning"] = ""; + + // extract status + list(,$status) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4; + $result["status"] = $status; + if ( $status!=SEARCHD_OK ) + { + list(,$len) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4; + $message = substr ( $response, $p, $len ); $p += $len; + + if ( $status==SEARCHD_WARNING ) + { + $result["warning"] = $message; + } else + { + $result["error"] = $message; + continue; + } + } + + // read schema + $fields = array (); + $attrs = array (); + + list(,$nfields) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4; + while ( $nfields-->0 && $p<$max ) + { + list(,$len) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4; + $fields[] = substr ( $response, $p, $len ); $p += $len; + } + $result["fields"] = $fields; + + list(,$nattrs) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4; + while ( $nattrs-->0 && $p<$max ) + { + list(,$len) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4; + $attr = substr ( $response, $p, $len ); $p += $len; + list(,$type) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4; + $attrs[$attr] = $type; + } + $result["attrs"] = $attrs; + + // read match count + list(,$count) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4; + list(,$id64) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4; + + // read matches + $idx = -1; + while ( $count-->0 && $p<$max ) + { + // index into result array + $idx++; + + // parse document id and weight + if ( $id64 ) + { + $doc = sphUnpackU64 ( substr ( $response, $p, 8 ) ); $p += 8; + list(,$weight) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4; + } + else + { + list ( $doc, $weight ) = array_values ( unpack ( "N*N*", + substr ( $response, $p, 8 ) ) ); + $p += 8; + $doc = sphFixUint($doc); + } + $weight = sprintf ( "%u", $weight ); + + // create match entry + if ( $this->_arrayresult ) + $result["matches"][$idx] = array ( "id"=>$doc, "weight"=>$weight ); + else + $result["matches"][$doc]["weight"] = $weight; + + // parse and create attributes + $attrvals = array (); + foreach ( $attrs as $attr=>$type ) + { + // handle 64bit ints + if ( $type==SPH_ATTR_BIGINT ) + { + $attrvals[$attr] = sphUnpackI64 ( substr ( $response, $p, 8 ) ); $p += 8; + continue; + } + + // handle floats + if ( $type==SPH_ATTR_FLOAT ) + { + list(,$uval) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4; + list(,$fval) = unpack ( "f*", pack ( "L", $uval ) ); + $attrvals[$attr] = $fval; + continue; + } + + // handle everything else as unsigned ints + list(,$val) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4; + if ( $type==SPH_ATTR_MULTI ) + { + $attrvals[$attr] = array (); + $nvalues = $val; + while ( $nvalues-->0 && $p<$max ) + { + list(,$val) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4; + $attrvals[$attr][] = sphFixUint($val); + } + } else if ( $type==SPH_ATTR_MULTI64 ) + { + $attrvals[$attr] = array (); + $nvalues = $val; + while ( $nvalues>0 && $p<$max ) + { + $attrvals[$attr][] = sphUnpackU64 ( substr ( $response, $p, 8 ) ); $p += 8; + $nvalues -= 2; + } + } else if ( $type==SPH_ATTR_STRING ) + { + $attrvals[$attr] = substr ( $response, $p, $val ); + $p += $val; + } else + { + $attrvals[$attr] = sphFixUint($val); + } + } + + if ( $this->_arrayresult ) + $result["matches"][$idx]["attrs"] = $attrvals; + else + $result["matches"][$doc]["attrs"] = $attrvals; + } + + list ( $total, $total_found, $msecs, $words ) = + array_values ( unpack ( "N*N*N*N*", substr ( $response, $p, 16 ) ) ); + $result["total"] = sprintf ( "%u", $total ); + $result["total_found"] = sprintf ( "%u", $total_found ); + $result["time"] = sprintf ( "%.3f", $msecs/1000 ); + $p += 16; + + while ( $words-->0 && $p<$max ) + { + list(,$len) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4; + $word = substr ( $response, $p, $len ); $p += $len; + list ( $docs, $hits ) = array_values ( unpack ( "N*N*", substr ( $response, $p, 8 ) ) ); $p += 8; + $result["words"][$word] = array ( + "docs"=>sprintf ( "%u", $docs ), + "hits"=>sprintf ( "%u", $hits ) ); + } + } + + $this->_MBPop (); + return $results; + } + + ///////////////////////////////////////////////////////////////////////////// + // excerpts generation + ///////////////////////////////////////////////////////////////////////////// + + /// connect to searchd server, and generate exceprts (snippets) + /// of given documents for given query. returns false on failure, + /// an array of snippets on success + function BuildExcerpts ( $docs, $index, $words, $opts=array() ) + { + assert ( is_array($docs) ); + assert ( is_string($index) ); + assert ( is_string($words) ); + assert ( is_array($opts) ); + + $this->_MBPush (); + + if (!( $fp = $this->_Connect() )) + { + $this->_MBPop(); + return false; + } + + ///////////////// + // fixup options + ///////////////// + + if ( !isset($opts["before_match"]) ) $opts["before_match"] = "<b>"; + if ( !isset($opts["after_match"]) ) $opts["after_match"] = "</b>"; + if ( !isset($opts["chunk_separator"]) ) $opts["chunk_separator"] = " ... "; + if ( !isset($opts["limit"]) ) $opts["limit"] = 256; + if ( !isset($opts["limit_passages"]) ) $opts["limit_passages"] = 0; + if ( !isset($opts["limit_words"]) ) $opts["limit_words"] = 0; + if ( !isset($opts["around"]) ) $opts["around"] = 5; + if ( !isset($opts["exact_phrase"]) ) $opts["exact_phrase"] = false; + if ( !isset($opts["single_passage"]) ) $opts["single_passage"] = false; + if ( !isset($opts["use_boundaries"]) ) $opts["use_boundaries"] = false; + if ( !isset($opts["weight_order"]) ) $opts["weight_order"] = false; + if ( !isset($opts["query_mode"]) ) $opts["query_mode"] = false; + if ( !isset($opts["force_all_words"]) ) $opts["force_all_words"] = false; + if ( !isset($opts["start_passage_id"]) ) $opts["start_passage_id"] = 1; + if ( !isset($opts["load_files"]) ) $opts["load_files"] = false; + if ( !isset($opts["html_strip_mode"]) ) $opts["html_strip_mode"] = "index"; + if ( !isset($opts["allow_empty"]) ) $opts["allow_empty"] = false; + if ( !isset($opts["passage_boundary"]) ) $opts["passage_boundary"] = "none"; + if ( !isset($opts["emit_zones"]) ) $opts["emit_zones"] = false; + if ( !isset($opts["load_files_scattered"]) ) $opts["load_files_scattered"] = false; + + + ///////////////// + // build request + ///////////////// + + // v.1.2 req + $flags = 1; // remove spaces + if ( $opts["exact_phrase"] ) $flags |= 2; + if ( $opts["single_passage"] ) $flags |= 4; + if ( $opts["use_boundaries"] ) $flags |= 8; + if ( $opts["weight_order"] ) $flags |= 16; + if ( $opts["query_mode"] ) $flags |= 32; + if ( $opts["force_all_words"] ) $flags |= 64; + if ( $opts["load_files"] ) $flags |= 128; + if ( $opts["allow_empty"] ) $flags |= 256; + if ( $opts["emit_zones"] ) $flags |= 512; + if ( $opts["load_files_scattered"] ) $flags |= 1024; + $req = pack ( "NN", 0, $flags ); // mode=0, flags=$flags + $req .= pack ( "N", strlen($index) ) . $index; // req index + $req .= pack ( "N", strlen($words) ) . $words; // req words + + // options + $req .= pack ( "N", strlen($opts["before_match"]) ) . $opts["before_match"]; + $req .= pack ( "N", strlen($opts["after_match"]) ) . $opts["after_match"]; + $req .= pack ( "N", strlen($opts["chunk_separator"]) ) . $opts["chunk_separator"]; + $req .= pack ( "NN", (int)$opts["limit"], (int)$opts["around"] ); + $req .= pack ( "NNN", (int)$opts["limit_passages"], (int)$opts["limit_words"], (int)$opts["start_passage_id"] ); // v.1.2 + $req .= pack ( "N", strlen($opts["html_strip_mode"]) ) . $opts["html_strip_mode"]; + $req .= pack ( "N", strlen($opts["passage_boundary"]) ) . $opts["passage_boundary"]; + + // documents + $req .= pack ( "N", count($docs) ); + foreach ( $docs as $doc ) + { + assert ( is_string($doc) ); + $req .= pack ( "N", strlen($doc) ) . $doc; + } + + //////////////////////////// + // send query, get response + //////////////////////////// + + $len = strlen($req); + $req = pack ( "nnN", SEARCHD_COMMAND_EXCERPT, VER_COMMAND_EXCERPT, $len ) . $req; // add header + if ( !( $this->_Send ( $fp, $req, $len+8 ) ) || + !( $response = $this->_GetResponse ( $fp, VER_COMMAND_EXCERPT ) ) ) + { + $this->_MBPop (); + return false; + } + + ////////////////// + // parse response + ////////////////// + + $pos = 0; + $res = array (); + $rlen = strlen($response); + for ( $i=0; $i<count($docs); $i++ ) + { + list(,$len) = unpack ( "N*", substr ( $response, $pos, 4 ) ); + $pos += 4; + + if ( $pos+$len > $rlen ) + { + $this->_error = "incomplete reply"; + $this->_MBPop (); + return false; + } + $res[] = $len ? substr ( $response, $pos, $len ) : ""; + $pos += $len; + } + + $this->_MBPop (); + return $res; + } + + + ///////////////////////////////////////////////////////////////////////////// + // keyword generation + ///////////////////////////////////////////////////////////////////////////// + + /// connect to searchd server, and generate keyword list for a given query + /// returns false on failure, + /// an array of words on success + function BuildKeywords ( $query, $index, $hits ) + { + assert ( is_string($query) ); + assert ( is_string($index) ); + assert ( is_bool($hits) ); + + $this->_MBPush (); + + if (!( $fp = $this->_Connect() )) + { + $this->_MBPop(); + return false; + } + + ///////////////// + // build request + ///////////////// + + // v.1.0 req + $req = pack ( "N", strlen($query) ) . $query; // req query + $req .= pack ( "N", strlen($index) ) . $index; // req index + $req .= pack ( "N", (int)$hits ); + + //////////////////////////// + // send query, get response + //////////////////////////// + + $len = strlen($req); + $req = pack ( "nnN", SEARCHD_COMMAND_KEYWORDS, VER_COMMAND_KEYWORDS, $len ) . $req; // add header + if ( !( $this->_Send ( $fp, $req, $len+8 ) ) || + !( $response = $this->_GetResponse ( $fp, VER_COMMAND_KEYWORDS ) ) ) + { + $this->_MBPop (); + return false; + } + + ////////////////// + // parse response + ////////////////// + + $pos = 0; + $res = array (); + $rlen = strlen($response); + list(,$nwords) = unpack ( "N*", substr ( $response, $pos, 4 ) ); + $pos += 4; + for ( $i=0; $i<$nwords; $i++ ) + { + list(,$len) = unpack ( "N*", substr ( $response, $pos, 4 ) ); $pos += 4; + $tokenized = $len ? substr ( $response, $pos, $len ) : ""; + $pos += $len; + + list(,$len) = unpack ( "N*", substr ( $response, $pos, 4 ) ); $pos += 4; + $normalized = $len ? substr ( $response, $pos, $len ) : ""; + $pos += $len; + + $res[] = array ( "tokenized"=>$tokenized, "normalized"=>$normalized ); + + if ( $hits ) + { + list($ndocs,$nhits) = array_values ( unpack ( "N*N*", substr ( $response, $pos, 8 ) ) ); + $pos += 8; + $res [$i]["docs"] = $ndocs; + $res [$i]["hits"] = $nhits; + } + + if ( $pos > $rlen ) + { + $this->_error = "incomplete reply"; + $this->_MBPop (); + return false; + } + } + + $this->_MBPop (); + return $res; + } + + function EscapeString ( $string ) + { + $from = array ( '\\', '(',')','|','-','!','@','~','"','&', '/', '^', '$', '=' ); + $to = array ( '\\\\', '\(','\)','\|','\-','\!','\@','\~','\"', '\&', '\/', '\^', '\$', '\=' ); + + return str_replace ( $from, $to, $string ); + } + + ///////////////////////////////////////////////////////////////////////////// + // attribute updates + ///////////////////////////////////////////////////////////////////////////// + + /// batch update given attributes in given rows in given indexes + /// returns amount of updated documents (0 or more) on success, or -1 on failure + function UpdateAttributes ( $index, $attrs, $values, $mva=false ) + { + // verify everything + assert ( is_string($index) ); + assert ( is_bool($mva) ); + + assert ( is_array($attrs) ); + foreach ( $attrs as $attr ) + assert ( is_string($attr) ); + + assert ( is_array($values) ); + foreach ( $values as $id=>$entry ) + { + assert ( is_numeric($id) ); + assert ( is_array($entry) ); + assert ( count($entry)==count($attrs) ); + foreach ( $entry as $v ) + { + if ( $mva ) + { + assert ( is_array($v) ); + foreach ( $v as $vv ) + assert ( is_int($vv) ); + } else + assert ( is_int($v) ); + } + } + + // build request + $this->_MBPush (); + $req = pack ( "N", strlen($index) ) . $index; + + $req .= pack ( "N", count($attrs) ); + foreach ( $attrs as $attr ) + { + $req .= pack ( "N", strlen($attr) ) . $attr; + $req .= pack ( "N", $mva ? 1 : 0 ); + } + + $req .= pack ( "N", count($values) ); + foreach ( $values as $id=>$entry ) + { + $req .= sphPackU64 ( $id ); + foreach ( $entry as $v ) + { + $req .= pack ( "N", $mva ? count($v) : $v ); + if ( $mva ) + foreach ( $v as $vv ) + $req .= pack ( "N", $vv ); + } + } + + // connect, send query, get response + if (!( $fp = $this->_Connect() )) + { + $this->_MBPop (); + return -1; + } + + $len = strlen($req); + $req = pack ( "nnN", SEARCHD_COMMAND_UPDATE, VER_COMMAND_UPDATE, $len ) . $req; // add header + if ( !$this->_Send ( $fp, $req, $len+8 ) ) + { + $this->_MBPop (); + return -1; + } + + if (!( $response = $this->_GetResponse ( $fp, VER_COMMAND_UPDATE ) )) + { + $this->_MBPop (); + return -1; + } + + // parse response + list(,$updated) = unpack ( "N*", substr ( $response, 0, 4 ) ); + $this->_MBPop (); + return $updated; + } + + ///////////////////////////////////////////////////////////////////////////// + // persistent connections + ///////////////////////////////////////////////////////////////////////////// + + function Open() + { + if ( $this->_socket !== false ) + { + $this->_error = 'already connected'; + return false; + } + if ( !$fp = $this->_Connect() ) + return false; + + // command, command version = 0, body length = 4, body = 1 + $req = pack ( "nnNN", SEARCHD_COMMAND_PERSIST, 0, 4, 1 ); + if ( !$this->_Send ( $fp, $req, 12 ) ) + return false; + + $this->_socket = $fp; + return true; + } + + function Close() + { + if ( $this->_socket === false ) + { + $this->_error = 'not connected'; + return false; + } + + fclose ( $this->_socket ); + $this->_socket = false; + + return true; + } + + ////////////////////////////////////////////////////////////////////////// + // status + ////////////////////////////////////////////////////////////////////////// + + function Status () + { + $this->_MBPush (); + if (!( $fp = $this->_Connect() )) + { + $this->_MBPop(); + return false; + } + + $req = pack ( "nnNN", SEARCHD_COMMAND_STATUS, VER_COMMAND_STATUS, 4, 1 ); // len=4, body=1 + if ( !( $this->_Send ( $fp, $req, 12 ) ) || + !( $response = $this->_GetResponse ( $fp, VER_COMMAND_STATUS ) ) ) + { + $this->_MBPop (); + return false; + } + + $res = substr ( $response, 4 ); // just ignore length, error handling, etc + $p = 0; + list ( $rows, $cols ) = array_values ( unpack ( "N*N*", substr ( $response, $p, 8 ) ) ); $p += 8; + + $res = array(); + for ( $i=0; $i<$rows; $i++ ) + for ( $j=0; $j<$cols; $j++ ) + { + list(,$len) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4; + $res[$i][] = substr ( $response, $p, $len ); $p += $len; + } + + $this->_MBPop (); + return $res; + } + + ////////////////////////////////////////////////////////////////////////// + // flush + ////////////////////////////////////////////////////////////////////////// + + function FlushAttributes () + { + $this->_MBPush (); + if (!( $fp = $this->_Connect() )) + { + $this->_MBPop(); + return -1; + } + + $req = pack ( "nnN", SEARCHD_COMMAND_FLUSHATTRS, VER_COMMAND_FLUSHATTRS, 0 ); // len=0 + if ( !( $this->_Send ( $fp, $req, 8 ) ) || + !( $response = $this->_GetResponse ( $fp, VER_COMMAND_FLUSHATTRS ) ) ) + { + $this->_MBPop (); + return -1; + } + + $tag = -1; + if ( strlen($response)==4 ) + list(,$tag) = unpack ( "N*", $response ); + else + $this->_error = "unexpected response length"; + + $this->_MBPop (); + return $tag; + } +} + +// +// $Id: sphinxapi.php 3087 2012-01-30 23:07:35Z shodan $ +// diff --git a/phpBB/includes/style/resource_locator.php b/phpBB/includes/style/resource_locator.php index 8658fe4a36..4cf767c062 100644 --- a/phpBB/includes/style/resource_locator.php +++ b/phpBB/includes/style/resource_locator.php @@ -44,7 +44,7 @@ class phpbb_style_resource_locator implements phpbb_template_locator * style directory, such as admin control panel templates. * @var string */ - public $template_path = 'template/'; + private $template_path; /** * Map from root index to handles to source template file paths. @@ -64,6 +64,16 @@ class phpbb_style_resource_locator implements phpbb_template_locator private $filenames = array(); /** + * Constructor. + * + * Sets default template path to template/. + */ + public function __construct() + { + $this->set_default_template_path(); + } + + /** * Sets the list of style paths * * These paths will be searched for style files in the provided order. @@ -94,6 +104,31 @@ class phpbb_style_resource_locator implements phpbb_template_locator } /** + * Sets the location of templates directory within style directories. + * + * The location must be a relative path, with a trailing slash. + * Typically it is one directory level deep, e.g. "template/". + * + * @param string $template_path Relative path to templates directory within style directories + * @return null + */ + public function set_template_path($template_path) + { + $this->template_path = $template_path; + } + + /** + * Sets the location of templates directory within style directories + * to the default, which is "template/". + * + * @return null + */ + public function set_default_template_path() + { + $this->template_path = 'template/'; + } + + /** * {@inheritDoc} */ public function set_filenames(array $filename_array) @@ -229,4 +264,85 @@ class phpbb_style_resource_locator implements phpbb_template_locator // search failed return $default_result; } + + /** + * Obtains filesystem path for a template file. + * + * The simplest use is specifying a single template file as a string + * in the first argument. This template file should be a basename + * of a template file in the selected style, or its parent styles + * if template inheritance is being utilized. + * + * Note: "selected style" is whatever style the style resource locator + * is configured for. + * + * The return value then will be a path, relative to the current + * directory or absolute, to the template file in the selected style + * or its closest parent. + * + * If the selected style does not have the template file being searched, + * (and if inheritance is involved, none of the parents have it either), + * false will be returned. + * + * Specifying true for $return_default will cause the function to + * return the first path which was checked for existence in the event + * that the template file was not found, instead of false. + * This is the path in the selected style itself, not any of its + * parents. + * + * $files can be given an array of templates instead of a single + * template. When given an array, the function will try to resolve + * each template in the array to a path, and will return the first + * path that exists, or false if none exist. + * + * If $files is an array and template inheritance is involved, first + * each of the files will be checked in the selected style, then each + * of the files will be checked in the immediate parent, and so on. + * + * If $return_full_path is false, then instead of returning a usable + * path (when the template is found) only the template's basename + * will be returned. This can be used to check which of the templates + * specified in $files exists. Naturally more than one template must + * be given in $files. + * + * This function works identically to get_first_file_location except + * it operates on a list of templates, not files. Practically speaking, + * the templates given in the first argument first are prepended with + * the template path (property in this class), then given to + * get_first_file_location for the rest of the processing. + * + * Templates given to this function can be relative paths for templates + * located in subdirectories of the template directories. The paths + * should be relative to the templates directory (template/ by default). + * + * @param string or array $files List of templates to locate. If there is only + * one template, $files can be a string to make code easier to read. + * @param bool $return_default Determines what to return if template does not + * exist. If true, function will return location where template is + * supposed to be. If false, function will return false. + * @param bool $return_full_path If true, function will return full path + * to template. If false, function will return template file name. + * This parameter can be used to check which one of set of template + * files is available. + * @return string or boolean Source template path if template exists or $return_default is + * true. False if template does not exist and $return_default is false + */ + public function get_first_template_location($templates, $return_default = false, $return_full_path = true) + { + // add template path prefix + $files = array(); + if (is_string($templates)) + { + $files[] = $this->template_path . $templates; + } + else + { + foreach ($templates as $template) + { + $files[] = $this->template_path . $template; + } + } + + return $this->get_first_file_location($files, $return_default, $return_full_path); + } } diff --git a/phpBB/includes/style/style.php b/phpBB/includes/style/style.php index 36298b49ec..4703c3a219 100644 --- a/phpBB/includes/style/style.php +++ b/phpBB/includes/style/style.php @@ -91,16 +91,22 @@ class phpbb_style { $style_path = $this->user->style['style_path']; $style_dirs = ($this->user->style['style_parent_id']) ? array_reverse(explode('/', $this->user->style['style_parent_tree'])) : array(); - $paths = array($this->get_style_path($style_path)); + + $names = array($style_path); foreach ($style_dirs as $dir) { - $paths[] = $this->get_style_path($dir); + $names[] = $dir; } + // Add 'all' path, used as last fallback path by events and extensions + //$names[] = 'all'; - // Add 'all' path, used as last fallback path by hooks and extensions - $paths[] = $this->get_style_path('all'); + $paths = array(); + foreach ($names as $name) + { + $paths[] = $this->get_style_path($name); + } - return $this->set_custom_style($style_path, $paths); + return $this->set_custom_style($style_path, $paths, $names); } /** @@ -110,25 +116,38 @@ class phpbb_style * * @param string $name Name of style, used for cache prefix. Examples: "admin", "prosilver" * @param array or string $paths Array of style paths, relative to current root directory - * @param string $template_path Path to templates, relative to style directory. False if path should not be changed. + * @param array $names Array of names of templates in inheritance tree order, used by extensions. If empty, $name will be used. + * @param string $template_path Path to templates, relative to style directory. False if path should be set to default (templates/). */ - public function set_custom_style($name, $paths, $template_path = false) + public function set_custom_style($name, $paths, $names = array(), $template_path = false) { if (is_string($paths)) { $paths = array($paths); } + if (empty($names)) + { + $names = array($name); + } + $this->names = $names; + $this->provider->set_styles($paths); $this->locator->set_paths($this->provider); - $this->template->cachepath = $this->phpbb_root_path . 'cache/tpl_' . str_replace('_', '-', $name) . '_'; + $this->template->set_style_names($names); if ($template_path !== false) { - $this->template->template_path = $this->locator->template_path = $template_path; + $this->locator->set_template_path($template_path); + } + else + { + $this->locator->set_default_template_path(); } + $this->template->cachepath = $this->phpbb_root_path . 'cache/tpl_' . str_replace('_', '-', $name) . '_'; + return true; } diff --git a/phpBB/includes/template/compile.php b/phpBB/includes/template/compile.php index 82b301c1a2..fcdaf7abda 100644 --- a/phpBB/includes/template/compile.php +++ b/phpBB/includes/template/compile.php @@ -35,16 +35,23 @@ class phpbb_template_compile /** * Constructor. * - * @param bool @allow_php Whether PHP code will be allowed in templates (inline PHP code, PHP tag and INCLUDEPHP tag) + * @param bool $allow_php Whether PHP code will be allowed in templates (inline PHP code, PHP tag and INCLUDEPHP tag) + * @param array $style_names Name of style to which the template being compiled belongs and parents in style tree order * @param phpbb_style_resource_locator $locator Resource locator * @param string $phpbb_root_path Path to phpBB root directory + * @param phpbb_extension_manager $extension_manager Extension manager to use for finding template fragments in extensions; if null, template events will not be invoked + * @param phpbb_user $user Current user */ - public function __construct($allow_php, $locator, $phpbb_root_path) + 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, - 'phpbb_root_path' => $phpbb_root_path + 'phpbb_root_path' => $phpbb_root_path, + 'extension_manager' => $extension_manager, + 'user' => $user, + 'template_compile' => $this, ); } @@ -58,6 +65,9 @@ class phpbb_template_compile */ public function compile_file_to_file($source_file, $compiled_file) { + $lock = new phpbb_lock_flock($compiled_file); + $lock->acquire(); + $source_handle = @fopen($source_file, 'rb'); $destination_handle = @fopen($compiled_file, 'wb'); @@ -66,16 +76,15 @@ class phpbb_template_compile return false; } - @flock($destination_handle, LOCK_EX); - $this->compile_stream_to_stream($source_handle, $destination_handle); @fclose($source_handle); - @flock($destination_handle, LOCK_UN); @fclose($destination_handle); phpbb_chmod($compiled_file, CHMOD_READ | CHMOD_WRITE); + $lock->release(); + clearstatcache(); return true; @@ -118,7 +127,7 @@ class phpbb_template_compile * * @param resource $source_stream Source stream * @param resource $dest_stream Destination stream - * @return void + * @return null */ private function compile_stream_to_stream($source_stream, $dest_stream) { diff --git a/phpBB/includes/template/filter.php b/phpBB/includes/template/filter.php index 66d28242a3..f73ad28ba1 100644 --- a/phpBB/includes/template/filter.php +++ b/phpBB/includes/template/filter.php @@ -88,6 +88,37 @@ class phpbb_template_filter extends php_user_filter private $phpbb_root_path; /** + * Name of the style that the template being compiled and/or rendered + * belongs to, and its parents, in inheritance tree order. + * + * Used to invoke style-specific template events. + * + * @var array + */ + private $style_names; + + /** + * Extension manager. + * + * @var phpbb_extension_manager + */ + private $extension_manager; + + /** + * Current user + * + * @var phpbb_user + */ + private $user; + + /** + * Template compiler. + * + * @var phpbb_template_compile + */ + private $template_compile; + + /** * Stream filter * * Is invoked for evey chunk of the stream, allowing us @@ -138,8 +169,10 @@ class phpbb_template_filter extends php_user_filter /** * Initializer, called on creation. * - * Get the allow_php option, root directory and locator from params, + * Get the allow_php option, style_names, root directory and locator from params, * which are passed to stream_filter_append. + * + * @return boolean Returns true */ public function onCreate() { @@ -148,6 +181,13 @@ class phpbb_template_filter extends php_user_filter $this->allow_php = $this->params['allow_php']; $this->locator = $this->params['locator']; $this->phpbb_root_path = $this->params['phpbb_root_path']; + $this->style_names = $this->params['style_names']; + $this->extension_manager = $this->params['extension_manager']; + if (isset($this->params['user'])) + { + $this->user = $this->params['user']; + } + $this->template_compile = $this->params['template_compile']; return true; } @@ -229,7 +269,9 @@ class phpbb_template_filter extends php_user_filter } /** - * Callback for replacing matched tokens with PHP code + * Callback for replacing matched tokens with compiled template code. + * + * Compiled template code is an HTML stream with embedded PHP. * * @param array $matches Regular expression matches * @return string compiled template code @@ -317,6 +359,10 @@ class phpbb_template_filter extends php_user_filter return '<!-- ENDPHP -->'; break; + case 'EVENT': + return '<?php ' . $this->compile_tag_event($matches[2]) . '?>'; + break; + default: return $matches[0]; break; @@ -836,6 +882,97 @@ class phpbb_template_filter extends php_user_filter } /** + * Compile EVENT tag. + * + * $tag_args should be a single string identifying the event. + * The event name can contain letters, numbers and underscores only. + * If an invalid event name is specified, an E_USER_ERROR will be + * triggered. + * + * Event tags are only functional when the template engine has + * an instance of the extension manager. Extension manager would + * be called upon to find all extensions listening for the specified + * event, and to obtain additional template fragments. All such + * template fragments will be compiled and included in the generated + * compiled template code for the current template being compiled. + * + * The above means that whenever an extension is enabled or disabled, + * template cache should be cleared in order to update the compiled + * template code for the active set of template event listeners. + * + * This also means that extensions cannot return different template + * fragments at different times. Once templates are compiled, changing + * such template fragments would have no effect. + * + * @param string $tag_args EVENT tag arguments, as a string - for EVENT this is the event name + * @return string compiled template code + */ + private function compile_tag_event($tag_args) + { + if (!preg_match('/^\w+$/', $tag_args)) + { + // The event location is improperly formatted, + if ($this->user) + { + trigger_error($this->user->lang('ERR_TEMPLATE_EVENT_LOCATION', $tag_args), E_USER_ERROR); + } + else + { + trigger_error(sprintf('The specified template event location <em>[%s]</em> is improperly formatted.', $tag_args), E_USER_ERROR); + } + } + $location = $tag_args; + + if ($this->extension_manager) + { + $finder = $this->extension_manager->get_finder(); + + $files = $finder + ->extension_prefix($location) + ->extension_suffix('.html') + ->extension_directory("/styles/all/template") + ->get_files(); + + foreach ($this->style_names as $style_name) + { + $more_files = $finder + ->extension_prefix($location) + ->extension_suffix('.html') + ->extension_directory("/styles/" . $style_name . "/template") + ->get_files(); + if (!empty($more_files)) + { + $files = array_merge($files, $more_files); + break; + } + } + + $all_compiled = ''; + foreach ($files as $file) + { + $compiled = $this->template_compile->compile_file($file); + + if ($compiled === false) + { + if ($this->user) + { + trigger_error($this->user->lang('ERR_TEMPLATE_COMPILATION', phpbb_filter_root_path($file)), E_USER_ERROR); + } + else + { + trigger_error(sprintf('The file could not be compiled: %s', phpbb_filter_root_path($file)), E_USER_ERROR); + } + } + + $all_compiled .= $compiled; + } + // Need spaces inside php tags as php cannot grok + // < ?php? > sans the spaces + return ' ?' . '>' . $all_compiled . '<?php '; + } + } + + /** * parse expression * This is from Smarty */ diff --git a/phpBB/includes/template/locator.php b/phpBB/includes/template/locator.php index 01c79eec4e..f6fd20bcc2 100644 --- a/phpBB/includes/template/locator.php +++ b/phpBB/includes/template/locator.php @@ -39,7 +39,7 @@ interface phpbb_template_locator * Sets the template filenames for handles. $filename_array * should be a hash of handle => filename pairs. * - * @param array $filname_array Should be a hash of handle => filename pairs. + * @param array $filename_array Should be a hash of handle => filename pairs. */ public function set_filenames(array $filename_array); @@ -66,7 +66,7 @@ interface phpbb_template_locator * returns actually exists, it is faster than get_source_file_for_handle. * * Use get_source_file_for_handle to obtain the actual path that is - * guaranteed to exist (which might come from the parent style + * guaranteed to exist (which might come from the parent style * directory if primary style has parent styles). * * This function will trigger an error if the handle was never @@ -99,12 +99,54 @@ interface phpbb_template_locator public function get_source_file_for_handle($handle, $find_all = false); /** - * Locates source file path, accounting for styles tree and verifying that - * the path exists. + * Obtains a complete filesystem path for a file in a style. * - * Unlike previous functions, this function works without template handle - * and it can search for more than one file. If more than one file name is - * specified, it will return location of file that it finds first. + * This function traverses the style tree (selected style and + * its parents in order, if inheritance is being used) and finds + * the first file on the filesystem matching specified relative path, + * or the first of the specified paths if more than one path is given. + * + * This function can be used to determine filesystem path of any + * file under any style, with the consequence being that complete + * relative to the style directory path must be provided as an argument. + * + * In particular, this function can be used to locate templates + * and javascript files. + * + * For locating templates get_first_template_location should be used + * as it prepends the configured template path to the template basename. + * + * Note: "selected style" is whatever style the style resource locator + * is configured for. + * + * The return value then will be a path, relative to the current + * directory or absolute, to the first existing file in the selected + * style or its closest parent. + * + * If the selected style does not have the file being searched, + * (and if inheritance is involved, none of the parents have it either), + * false will be returned. + * + * Multiple files can be specified, in which case the first file in + * the list that can be found on the filesystem is returned. + * + * If multiple files are specified and inheritance is involved, + * first each of the specified files is checked in the selected style, + * then each of the specified files is checked in the immediate parent, + * etc. + * + * Specifying true for $return_default will cause the function to + * return the first path which was checked for existence in the event + * that the template file was not found, instead of false. + * This is always a path in the selected style itself, not any of its + * parents. + * + * If $return_full_path is false, then instead of returning a usable + * path (when the file is found) the file's path relative to the style + * directory will be returned. This is the same path as was given to + * the function as a parameter. This can be used to check which of the + * files specified in $files exists. Naturally this requires passing + * more than one file in $files. * * @param array $files List of files to locate. * @param bool $return_default Determines what to return if file does not diff --git a/phpBB/includes/template/template.php b/phpBB/includes/template/template.php index 8a7dc6b2f3..bbec768613 100644 --- a/phpBB/includes/template/template.php +++ b/phpBB/includes/template/template.php @@ -75,10 +75,21 @@ class phpbb_template private $locator; /** - * Location of templates directory within style directories - * @var string + * Extension manager. + * + * @var phpbb_extension_manager + */ + private $extension_manager; + + /** + * Name of the style that the template being compiled and/or rendered + * belongs to, and its parents, in inheritance tree order. + * + * Used to invoke style-specific template events. + * + * @var array */ - public $template_path = 'template/'; + private $style_names; /** * Constructor. @@ -87,22 +98,23 @@ class phpbb_template * @param user $user current user * @param phpbb_template_locator $locator template locator * @param phpbb_template_context $context template context + * @param phpbb_extension_manager $extension_manager extension manager, if null then template events will not be invoked */ - public function __construct($phpbb_root_path, $php_ext, $config, $user, phpbb_template_locator $locator, phpbb_template_context $context) + public function __construct($phpbb_root_path, $php_ext, $config, $user, phpbb_template_locator $locator, phpbb_template_context $context, phpbb_extension_manager $extension_manager = null) { $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; $this->config = $config; $this->user = $user; $this->locator = $locator; - $this->template_path = $this->locator->template_path; $this->context = $context; + $this->extension_manager = $extension_manager; } /** * Sets the template filenames for handles. * - * @param array $filname_array Should be a hash of handle => filename pairs. + * @param array $filename_array Should be a hash of handle => filename pairs. */ public function set_filenames(array $filename_array) { @@ -112,6 +124,18 @@ class phpbb_template } /** + * Sets the style names corresponding to style hierarchy being compiled + * and/or rendered. + * + * @param array $style_names List of style names in inheritance tree order + * @return null + */ + public function set_style_names(array $style_names) + { + $this->style_names = $style_names; + } + + /** * Clears all variables and blocks assigned to this template. */ public function destroy() @@ -289,7 +313,7 @@ class phpbb_template return new phpbb_template_renderer_include($output_file, $this); } - $compile = new phpbb_template_compile($this->config['tpl_allow_php'], $this->locator, $this->phpbb_root_path); + $compile = new phpbb_template_compile($this->config['tpl_allow_php'], $this->style_names, $this->locator, $this->phpbb_root_path, $this->extension_manager, $this->user); if ($compile->compile_file_to_file($source_file, $output_file) !== false) { @@ -459,74 +483,6 @@ class phpbb_template } /** - * Obtains filesystem path for a template file. - * - * The simplest use is specifying a single template file as a string - * in the first argument. This template file should be a basename - * of a template file in the selected style, or its parent styles - * if template inheritance is being utilized. - * - * Note: "selected style" is whatever style the style resource locator - * is configured for. - * - * The return value then will be a path, relative to the current - * directory or absolute, to the template file in the selected style - * or its closest parent. - * - * If the selected style does not have the template file being searched, - * (and if inheritance is involved, none of the parents have it either), - * false will be returned. - * - * Specifying true for $return_default will cause the function to - * return the first path which was checked for existence in the event - * that the template file was not found, instead of false. - * This is the path in the selected style itself, not any of its - * parents. - * - * $files can be given an array of templates instead of a single - * template. When given an array, the function will try to resolve - * each template in the array to a path, and will return the first - * path that exists, or false if none exist. - * - * If $return_full_path is false, then instead of returning a usable - * path (when the template is found) only the template's basename - * will be returned. This can be used to check which of the templates - * specified in $files exists, provided different file names are - * used for different templates. - * - * @param string or array $files List of templates to locate. If there is only - * one template, $files can be a string to make code easier to read. - * @param bool $return_default Determines what to return if template does not - * exist. If true, function will return location where template is - * supposed to be. If false, function will return false. - * @param bool $return_full_path If true, function will return full path - * to template. If false, function will return template file name. - * This parameter can be used to check which one of set of template - * files is available. - * @return string or boolean Source template path if template exists or $return_default is - * true. False if template does not exist and $return_default is false - */ - public function locate($files, $return_default = false, $return_full_path = true) - { - // add template path prefix - $templates = array(); - if (is_string($files)) - { - $templates[] = $this->template_path . $files; - } - else - { - foreach ($files as $file) - { - $templates[] = $this->template_path . $file; - } - } - - // use resource locator to find files - return $this->locator->get_first_file_location($templates, $return_default, $return_full_path); - } - - /** * Include JS file * * @param string $file file name diff --git a/phpBB/includes/ucp/info/ucp_profile.php b/phpBB/includes/ucp/info/ucp_profile.php index 201216e9fd..3581a7f533 100644 --- a/phpBB/includes/ucp/info/ucp_profile.php +++ b/phpBB/includes/ucp/info/ucp_profile.php @@ -19,7 +19,7 @@ class ucp_profile_info 'title' => 'UCP_PROFILE', 'version' => '1.0.0', 'modes' => array( - 'profile_info' => array('title' => 'UCP_PROFILE_PROFILE_INFO', 'auth' => '', 'cat' => array('UCP_PROFILE')), + 'profile_info' => array('title' => 'UCP_PROFILE_PROFILE_INFO', 'auth' => 'acl_u_chgprofileinfo', 'cat' => array('UCP_PROFILE')), 'signature' => array('title' => 'UCP_PROFILE_SIGNATURE', 'auth' => 'acl_u_sig', 'cat' => array('UCP_PROFILE')), 'avatar' => array('title' => 'UCP_PROFILE_AVATAR', 'auth' => 'cfg_allow_avatar && (cfg_allow_avatar_local || cfg_allow_avatar_remote || cfg_allow_avatar_upload || cfg_allow_avatar_remote_upload)', 'cat' => array('UCP_PROFILE')), 'reg_details' => array('title' => 'UCP_PROFILE_REG_DETAILS', 'auth' => '', 'cat' => array('UCP_PROFILE')), diff --git a/phpBB/includes/ucp/ucp_groups.php b/phpBB/includes/ucp/ucp_groups.php index 9652986cf2..d92aea91f8 100644 --- a/phpBB/includes/ucp/ucp_groups.php +++ b/phpBB/includes/ucp/ucp_groups.php @@ -25,7 +25,7 @@ class ucp_groups function main($id, $mode) { - global $config, $phpbb_root_path, $phpEx; + global $config, $phpbb_root_path, $phpEx, $phpbb_admin_path; global $db, $user, $auth, $cache, $template; global $request; @@ -438,7 +438,7 @@ class ucp_groups $group_name = $group_row['group_name']; $group_type = $group_row['group_type']; - $avatar_img = (!empty($group_row['group_avatar'])) ? get_user_avatar($group_row['group_avatar'], $group_row['group_avatar_type'], $group_row['group_avatar_width'], $group_row['group_avatar_height'], 'GROUP_AVATAR') : '<img src="' . $phpbb_root_path . 'adm/images/no_avatar.gif" alt="" />'; + $avatar_img = (!empty($group_row['group_avatar'])) ? get_user_avatar($group_row['group_avatar'], $group_row['group_avatar_type'], $group_row['group_avatar_width'], $group_row['group_avatar_height'], 'GROUP_AVATAR') : '<img src="' . $phpbb_admin_path . 'images/no_avatar.gif" alt="" />'; $template->assign_vars(array( 'GROUP_NAME' => ($group_type == GROUP_SPECIAL) ? $user->lang['G_' . $group_name] : $group_name, @@ -730,7 +730,7 @@ class ucp_groups 'GROUP_CLOSED' => $type_closed, 'GROUP_HIDDEN' => $type_hidden, - 'U_SWATCH' => append_sid("{$phpbb_root_path}adm/swatch.$phpEx", 'form=ucp&name=group_colour'), + 'U_SWATCH' => append_sid("{$phpbb_admin_path}swatch.$phpEx", 'form=ucp&name=group_colour'), 'S_UCP_ACTION' => $this->u_action . "&action=$action&g=$group_id", 'L_AVATAR_EXPLAIN' => phpbb_avatar_explanation_string(), )); diff --git a/phpBB/includes/ucp/ucp_pm_viewmessage.php b/phpBB/includes/ucp/ucp_pm_viewmessage.php index c85b05f144..a1001cfa74 100644 --- a/phpBB/includes/ucp/ucp_pm_viewmessage.php +++ b/phpBB/includes/ucp/ucp_pm_viewmessage.php @@ -241,7 +241,6 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) 'U_ICQ' => ($user_info['user_icq']) ? 'http://www.icq.com/people/' . urlencode($user_info['user_icq']) . '/' : '', 'U_AIM' => ($user_info['user_aim'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contact&action=aim&u=' . $author_id) : '', 'U_YIM' => ($user_info['user_yim']) ? 'http://edit.yahoo.com/config/send_webmesg?.target=' . urlencode($user_info['user_yim']) . '&.src=pg' : '', - 'U_MSN' => ($user_info['user_msnm'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contact&action=msnm&u=' . $author_id) : '', 'U_JABBER' => ($user_info['user_jabber'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contact&action=jabber&u=' . $author_id) : '', 'U_DELETE' => ($auth->acl_get('u_pm_delete')) ? "$url&mode=compose&action=delete&f=$folder_id&p=" . $message_row['msg_id'] : '', diff --git a/phpBB/includes/ucp/ucp_prefs.php b/phpBB/includes/ucp/ucp_prefs.php index 2228bc7931..23892c2c8c 100644 --- a/phpBB/includes/ucp/ucp_prefs.php +++ b/phpBB/includes/ucp/ucp_prefs.php @@ -132,6 +132,36 @@ class ucp_prefs $dateformat_options .= '>' . $user->lang['CUSTOM_DATEFORMAT'] . '</option>'; $timezone_selects = phpbb_timezone_select($user, $data['tz'], true); + + // check if there are any user-selectable languages + $sql = 'SELECT COUNT(lang_id) as languages_count + FROM ' . LANG_TABLE; + $result = $db->sql_query($sql); + if ($db->sql_fetchfield('languages_count') > 1) + { + $s_more_languages = true; + } + else + { + $s_more_languages = false; + } + $db->sql_freeresult($result); + + // check if there are any user-selectable styles + $sql = 'SELECT COUNT(style_id) as styles_count + FROM ' . STYLES_TABLE . ' + WHERE style_active = 1'; + $result = $db->sql_query($sql); + if ($db->sql_fetchfield('styles_count') > 1) + { + $s_more_styles = true; + } + else + { + $s_more_styles = false; + } + $db->sql_freeresult($result); + $template->assign_vars(array( 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', @@ -152,6 +182,9 @@ class ucp_prefs 'DEFAULT_DATEFORMAT' => $config['default_dateformat'], 'A_DEFAULT_DATEFORMAT' => addslashes($config['default_dateformat']), + 'S_MORE_LANGUAGES' => $s_more_languages, + 'S_MORE_STYLES' => $s_more_styles, + 'S_LANG_OPTIONS' => language_select($data['lang']), 'S_STYLE_OPTIONS' => ($config['override_user_style']) ? '' : style_select($data['style']), 'S_TZ_OPTIONS' => $timezone_selects['tz_select'], diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php index 89bf20a30f..c1ad9955b6 100644 --- a/phpBB/includes/ucp/ucp_profile.php +++ b/phpBB/includes/ucp/ucp_profile.php @@ -251,6 +251,11 @@ class ucp_profile break; case 'profile_info': + // Do not display profile information panel if not authed to do so + if (!$auth->acl_get('u_chgprofileinfo')) + { + trigger_error('NO_AUTH_PROFILEINFO'); + } include($phpbb_root_path . 'includes/functions_profile_fields.' . $phpEx); @@ -261,7 +266,6 @@ class ucp_profile $data = array( 'icq' => request_var('icq', $user->data['user_icq']), 'aim' => request_var('aim', $user->data['user_aim']), - 'msn' => request_var('msn', $user->data['user_msnm']), 'yim' => request_var('yim', $user->data['user_yim']), 'jabber' => utf8_normalize_nfc(request_var('jabber', $user->data['user_jabber'], true)), 'website' => request_var('website', $user->data['user_website']), @@ -294,7 +298,6 @@ class ucp_profile array('string', true, 3, 15), array('match', true, '#^[0-9]+$#i')), 'aim' => array('string', true, 3, 255), - 'msn' => array('string', true, 5, 255), 'jabber' => array( array('string', true, 5, 255), array('jabber')), @@ -346,7 +349,6 @@ class ucp_profile $sql_ary = array( 'user_icq' => $data['icq'], 'user_aim' => $data['aim'], - 'user_msnm' => $data['msn'], 'user_yim' => $data['yim'], 'user_jabber' => $data['jabber'], 'user_website' => $data['website'], @@ -418,7 +420,6 @@ class ucp_profile 'ICQ' => $data['icq'], 'YIM' => $data['yim'], 'AIM' => $data['aim'], - 'MSN' => $data['msn'], 'JABBER' => $data['jabber'], 'WEBSITE' => $data['website'], 'LOCATION' => $data['location'], diff --git a/phpBB/index.php b/phpBB/index.php index 66e1b2114b..845d0f0c02 100644 --- a/phpBB/index.php +++ b/phpBB/index.php @@ -17,48 +17,12 @@ define('IN_PHPBB', true); $phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './'; $phpEx = substr(strrchr(__FILE__, '.'), 1); include($phpbb_root_path . 'common.' . $phpEx); +include($phpbb_root_path . 'includes/functions_display.' . $phpEx); // Start session management $user->session_begin(); $auth->acl($user->data); -$user->setup(); - -// Handle the display of extension front pages -if ($ext = $request->variable('ext', '')) -{ - $class = 'phpbb_ext_' . str_replace('/', '_', $ext) . '_controller'; - - if (!$phpbb_extension_manager->available($ext)) - { - send_status_line(404, 'Not Found'); - trigger_error($user->lang('EXTENSION_DOES_NOT_EXIST', $ext)); - } - else if (!$phpbb_extension_manager->enabled($ext)) - { - send_status_line(404, 'Not Found'); - trigger_error($user->lang('EXTENSION_DISABLED', $ext)); - } - else if (!class_exists($class)) - { - send_status_line(404, 'Not Found'); - trigger_error($user->lang('EXTENSION_CONTROLLER_MISSING', $ext)); - } - - $controller = new $class; - - if (!($controller instanceof phpbb_extension_controller_interface)) - { - send_status_line(500, 'Internal Server Error'); - trigger_error($user->lang('EXTENSION_CLASS_WRONG_TYPE', $class)); - } - - $controller->handle(); - exit_handler(); -} - -include($phpbb_root_path . 'includes/functions_display.' . $phpEx); - -$user->add_lang('viewforum'); +$user->setup('viewforum'); display_forums('', $config['load_moderators']); diff --git a/phpBB/install/convertors/convert_phpbb20.php b/phpBB/install/convertors/convert_phpbb20.php index 68acea02b3..6792f4ff9c 100644 --- a/phpBB/install/convertors/convert_phpbb20.php +++ b/phpBB/install/convertors/convert_phpbb20.php @@ -24,6 +24,8 @@ if (!defined('IN_PHPBB')) include($phpbb_root_path . 'config.' . $phpEx); unset($dbpasswd); +$dbms = phpbb_convert_30_dbms_to_31($dbms); + /** * $convertor_data provides some basic information about this convertor which is * used on the initial list of convertors and to populate the default settings @@ -894,7 +896,6 @@ if (!$get_info) array('user_occ', 'users.user_occ', array('function1' => 'phpbb_set_encoding')), array('user_website', 'users.user_website', 'validate_website'), array('user_jabber', '', ''), - array('user_msnm', 'users.user_msnm', array('function1' => 'phpbb_set_encoding')), array('user_yim', 'users.user_yim', array('function1' => 'phpbb_set_encoding')), array('user_aim', 'users.user_aim', array('function1' => 'phpbb_set_encoding')), array('user_icq', 'users.user_icq', array('function1' => 'phpbb_set_encoding')), diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php index 899394cd08..4a61d189a3 100644 --- a/phpBB/install/database_update.php +++ b/phpBB/install/database_update.php @@ -73,16 +73,20 @@ if (!defined('PHPBB_INSTALLED') || empty($dbms) || empty($acm_type)) die("Please read: <a href='../docs/INSTALL.html'>INSTALL.html</a> before attempting to update."); } +// In case $phpbb_adm_relative_path is not set (in case of an update), use the default. +$phpbb_adm_relative_path = (isset($phpbb_adm_relative_path)) ? $phpbb_adm_relative_path : 'adm/'; +$phpbb_admin_path = (defined('PHPBB_ADMIN_PATH')) ? PHPBB_ADMIN_PATH : $phpbb_root_path . $phpbb_adm_relative_path; + // Include files require($phpbb_root_path . 'includes/class_loader.' . $phpEx); require($phpbb_root_path . 'includes/functions.' . $phpEx); +require($phpbb_root_path . 'includes/functions_container.' . $phpEx); phpbb_require_updated('includes/functions_content.' . $phpEx, true); require($phpbb_root_path . 'includes/functions_admin.' . $phpEx); require($phpbb_root_path . 'includes/constants.' . $phpEx); -require($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx); require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx); phpbb_require_updated('includes/db/db_tools.' . $phpEx); @@ -98,20 +102,17 @@ if (!defined('EXT_TABLE')) define('EXT_TABLE', $table_prefix . 'ext'); } -$phpbb_container = new ContainerBuilder(); -$loader = new YamlFileLoader($phpbb_container, new FileLocator(__DIR__.'/../config')); -$loader->load('services.yml'); +// Setup class loader first +$phpbb_class_loader = new phpbb_class_loader('phpbb_', "{$phpbb_root_path}includes/", ".$phpEx"); +$phpbb_class_loader->register(); +$phpbb_class_loader_ext = new phpbb_class_loader('phpbb_ext_', "{$phpbb_root_path}ext/", ".$phpEx"); +$phpbb_class_loader_ext->register(); -// We must include the DI processor class files because the class loader -// is not yet set up -require($phpbb_root_path . 'includes/di/processor/interface.' . $phpEx); -require($phpbb_root_path . 'includes/di/processor/config.' . $phpEx); -$processor = new phpbb_di_processor_config($phpbb_root_path . 'config.' . $phpEx, $phpbb_root_path, $phpEx); -$processor->process($phpbb_container); +// Set up container +$phpbb_container = phpbb_create_default_container($phpbb_root_path, $phpEx); -// Setup class loader first -$phpbb_class_loader = $phpbb_container->get('class_loader'); -$phpbb_class_loader_ext = $phpbb_container->get('class_loader.ext'); +$phpbb_class_loader->set_cache($phpbb_container->get('cache.driver')); +$phpbb_class_loader_ext->set_cache($phpbb_container->get('cache.driver')); // set up caching $cache = $phpbb_container->get('cache'); @@ -123,13 +124,6 @@ $user = $phpbb_container->get('user'); $auth = $phpbb_container->get('auth'); $db = $phpbb_container->get('dbal.conn'); -$ids = array_keys($phpbb_container->findTaggedServiceIds('container.processor')); -foreach ($ids as $id) -{ - $processor = $phpbb_container->get($id); - $processor->process($phpbb_container); -} - // make sure request_var uses this request instance request_var('', 0, false, false, $request); // "dependency injection" for a function @@ -139,7 +133,8 @@ if (file_exists($phpbb_root_path . 'includes/hooks/index.' . $phpEx)) require($phpbb_root_path . 'includes/hooks/index.' . $phpEx); $phpbb_hook = new phpbb_hook(array('exit_handler', 'phpbb_user_session_handler', 'append_sid', array('template', 'display'))); - foreach ($cache->obtain_hooks() as $hook) + $phpbb_hook_finder = $phpbb_container->get('hook_finder'); + foreach ($phpbb_hook_finder->find() as $hook) { @include($phpbb_root_path . 'includes/hooks/' . $hook . '.' . $phpEx); } @@ -192,7 +187,7 @@ include($phpbb_root_path . 'language/' . $language . '/install.' . $phpEx); $inline_update = (request_var('type', 0)) ? true : false; // To let set_config() calls succeed, we need to make the config array available globally -$config = new phpbb_config_db($db, $cache->get_driver(), CONFIG_TABLE); +$config = new phpbb_config_db($db, $phpbb_container->get('cache.driver'), CONFIG_TABLE); set_config(null, null, null, $config); set_config_count(null, null, null, $config); @@ -230,7 +225,7 @@ if ($has_global && !$ga_forum_id) <title><?php echo $lang['UPDATING_TO_LATEST_STABLE']; ?></title> - <link href="../adm/style/admin.css" rel="stylesheet" type="text/css" media="screen" /> + <link href="<?php echo htmlspecialchars($phpbb_admin_path); ?>style/admin.css" rel="stylesheet" type="text/css" media="screen" /> </head> @@ -280,7 +275,7 @@ header('Content-type: text/html; charset=UTF-8'); <title><?php echo $lang['UPDATING_TO_LATEST_STABLE']; ?></title> -<link href="../adm/style/admin.css" rel="stylesheet" type="text/css" media="screen" /> +<link href="<?php echo htmlspecialchars($phpbb_admin_path); ?>style/admin.css" rel="stylesheet" type="text/css" media="screen" /> </head> @@ -579,7 +574,7 @@ else add_log('admin', 'LOG_UPDATE_DATABASE', $orig_version, $updates_to_version); // Now we purge the session table as well as all cache files -$cache->purge(); +$phpbb_container->get('cache.driver')->purge(); _print_footer(); @@ -816,6 +811,70 @@ function _add_modules($modules_to_install) $_module->remove_cache_file(); } +/** +* Add a new permission, optionally copy permission setting from another +* +* @param auth_admin $auth_admin auth_admin object +* @param phpbb_db_driver $db Database object +* @param string $permission_name Name of the permission to add +* @param bool $is_global True is global, false is local +* @param string $copy_from Optional permission name from which to copy +* @return bool true on success, false on failure +*/ +function _add_permission(auth_admin $auth_admin, phpbb_db_driver $db, $permission_name, $is_global = true, $copy_from = '') +{ + // Only add a permission that don't already exist + if (!empty($auth_admin->acl_options['id'][$permission_name])) + { + return true; + } + + $permission_scope = $is_global ? 'global' : 'local'; + + $result = $auth_admin->acl_add_option(array( + $permission_scope => array($permission_name), + )); + + if (!$result) + { + return $result; + } + + // The permission has been added, now we can copy it if needed + if ($copy_from && isset($auth_admin->acl_options['id'][$copy_from])) + { + $old_id = $auth_admin->acl_options['id'][$copy_from]; + $new_id = $auth_admin->acl_options['id'][$permission_name]; + + $tables = array(ACL_GROUPS_TABLE, ACL_ROLES_DATA_TABLE, ACL_USERS_TABLE); + + foreach ($tables as $table) + { + $sql = 'SELECT * + FROM ' . $table . ' + WHERE auth_option_id = ' . $old_id; + $result = _sql($sql, $errored, $error_ary); + + $sql_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + $row['auth_option_id'] = $new_id; + $sql_ary[] = $row; + } + $db->sql_freeresult($result); + + if (sizeof($sql_ary)) + { + $db->sql_multi_insert($table, $sql_ary); + } + } + + $auth_admin->acl_clear_prefetch(); + } + + return true; +} + /**************************************************************************** * ADD YOUR DATABASE SCHEMA CHANGES HERE * *****************************************************************************/ @@ -1121,9 +1180,12 @@ function database_update_info() 'style_parent_tree' => array('TEXT', ''), ), REPORTS_TABLE => array( - 'reported_post_text' => array('MTEXT_UNI', ''), - 'reported_post_uid' => array('VCHAR:8', ''), - 'reported_post_bitfield' => array('VCHAR:255', ''), + 'reported_post_text' => array('MTEXT_UNI', ''), + 'reported_post_uid' => array('VCHAR:8', ''), + 'reported_post_bitfield' => array('VCHAR:255', ''), + 'reported_post_enable_bbcode' => array('BOOL', 1), + 'reported_post_enable_smilies' => array('BOOL', 1), + 'reported_post_enable_magic_url' => array('BOOL', 1), ), ), 'change_columns' => array( @@ -1134,6 +1196,11 @@ function database_update_info() 'user_timezone' => array('VCHAR:100', ''), ), ), + 'drop_columns' => array( + USERS_TABLE => array( + 'user_msnm', + ), + ), ), ); } @@ -1145,7 +1212,7 @@ function database_update_info() *****************************************************************************/ function change_database_data(&$no_updates, $version) { - global $db, $errored, $error_ary, $config, $phpbb_root_path, $phpEx, $db_tools; + global $db, $db_tools, $errored, $error_ary, $config, $table_prefix, $phpbb_root_path, $phpEx; $update_helpers = new phpbb_update_helpers(); @@ -1462,8 +1529,6 @@ function change_database_data(&$no_updates, $version) ), ); - global $db_tools; - $statements = $db_tools->perform_schema_changes($changes); foreach ($statements as $sql) @@ -2105,26 +2170,41 @@ function change_database_data(&$no_updates, $version) } $db->sql_freeresult($result); - global $db_tools, $table_prefix; - - // Recover from potentially broken Q&A CAPTCHA table on firebird - // Q&A CAPTCHA was uninstallable, so it's safe to remove these - // without data loss + /* + * Due to a bug, vanilla phpbb could not create captcha tables + * in 3.0.8 on firebird. It was possible for board administrators + * to adjust the code to work. If code was manually adjusted by + * board administrators, index names would not be the same as + * what 3.0.9 and newer expect. This code fragment drops captcha + * tables, destroying all entered Q&A captcha configuration, such + * that when Q&A is configured next the respective tables will be + * created with correct index names. + * + * If you wish to preserve your Q&A captcha configuration, you can + * manually rename indexes to the currently expected name: + * phpbb_captcha_questions_lang_iso => phpbb_captcha_questions_lang + * phpbb_captcha_answers_question_id => phpbb_captcha_answers_qid + * + * Again, this needs to be done only if a board was manually modified + * to fix broken captcha code. + * if ($db_tools->sql_layer == 'firebird') { - $tables = array( - $table_prefix . 'captcha_questions', - $table_prefix . 'captcha_answers', - $table_prefix . 'qa_confirm', + $changes = array( + 'drop_tables' => array( + $table_prefix . 'captcha_questions', + $table_prefix . 'captcha_answers', + $table_prefix . 'qa_confirm', + ), ); - foreach ($tables as $table) + $statements = $db_tools->perform_schema_changes($changes); + + foreach ($statements as $sql) { - if ($db_tools->sql_table_exists($table)) - { - $db_tools->sql_table_drop($table); - } + _sql($sql, $errored, $error_ary); } } + */ $no_updates = false; break; @@ -2301,6 +2381,26 @@ function change_database_data(&$no_updates, $version) } } + // Disable receiving pms for bots + $sql = 'SELECT user_id + FROM ' . BOTS_TABLE; + $result = $db->sql_query($sql); + + $bot_user_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $bot_user_ids[] = (int) $row['user_id']; + } + $db->sql_freeresult($result); + + if (!empty($bot_user_ids)) + { + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_allow_pm = 0 + WHERE ' . $db->sql_in_set('user_id', $bot_user_ids); + _sql($sql, $errored, $error_ary); + } + $no_updates = false; break; @@ -2437,6 +2537,12 @@ function change_database_data(&$no_updates, $version) unset($next_legend); } + // Rename styles module to Customise + $sql = 'UPDATE ' . MODULES_TABLE . " + SET module_langname = 'ACP_CAT_CUSTOMISE' + WHERE module_langname = 'ACP_CAT_STYLES'"; + _sql($sql, $errored, $error_ary); + // Install modules $modules_to_install = array( 'position' => array( @@ -2474,10 +2580,67 @@ function change_database_data(&$no_updates, $version) 'auth' => '', 'cat' => 'UCP_PROFILE', ), + // To add a category, the mode and basename must be empty + // The mode is taken from the array key + '' => array( + 'base' => '', + 'class' => 'acp', + 'title' => 'ACP_EXTENSION_MANAGEMENT', + 'auth' => 'acl_a_extensions', + 'cat' => 'ACP_CAT_CUSTOMISE', + ), + 'extensions' => array( + 'base' => 'acp_extensions', + 'class' => 'acp', + 'title' => 'ACP_EXTENSIONS', + 'auth' => 'acl_a_extensions', + 'cat' => 'ACP_EXTENSION_MANAGEMENT', + ), + ); + + _add_modules($modules_to_install); + + // We need a separate array for the new language sub heading + // because it requires another empty key + $modules_to_install = array( + '' => array( + 'base' => '', + 'class' => 'acp', + 'title' => 'ACP_LANGUAGE', + 'auth' => 'acl_a_language', + 'cat' => 'ACP_CAT_CUSTOMISE', + ), ); _add_modules($modules_to_install); + // Move language management to new location in the Customise tab + // First get language module id + $sql = 'SELECT module_id FROM ' . MODULES_TABLE . " + WHERE module_basename = 'acp_language'"; + $result = $db->sql_query($sql); + $language_module_id = $db->sql_fetchfield('module_id'); + $db->sql_freeresult($result); + // Next get language management module id of the one just created + $sql = 'SELECT module_id FROM ' . MODULES_TABLE . " + WHERE module_langname = 'ACP_LANGUAGE'"; + $result = $db->sql_query($sql); + $language_management_module_id = $db->sql_fetchfield('module_id'); + $db->sql_freeresult($result); + + if (!class_exists('acp_modules')) + { + include($phpbb_root_path . 'includes/acp/acp_modules.' . $phpEx); + } + // acp_modules calls adm_back_link, which is undefined at this point + if (!function_exists('adm_back_link')) + { + include($phpbb_root_path . 'includes/functions_acp.' . $phpEx); + } + $module_manager = new acp_modules(); + $module_manager->module_class = 'acp'; + $module_manager->move_module($language_module_id, $language_management_module_id); + $sql = 'DELETE FROM ' . MODULES_TABLE . " WHERE (module_basename = 'styles' OR module_basename = 'acp_styles') AND (module_mode = 'imageset' OR module_mode = 'theme' OR module_mode = 'template')"; _sql($sql, $errored, $error_ary); @@ -2709,8 +2872,6 @@ function change_database_data(&$no_updates, $version) $config->set('display_last_subject', '1'); } - $no_updates = false; - if (!isset($config['assets_version'])) { $config->set('assets_version', '1'); @@ -2739,7 +2900,11 @@ function change_database_data(&$no_updates, $version) set_config('board_timezone', $update_helpers->convert_phpbb30_timezone($config['board_timezone'], $config['board_dst'])); // After we have calculated the timezones we can delete user_dst column from user table. - $db_tools->sql_column_remove(USERS_TABLE, 'user_dst'); + $statements = $db_tools->sql_column_remove(USERS_TABLE, 'user_dst'); + foreach ($statements as $sql) + { + _sql($sql, $errored, $error_ary); + } } if (!isset($config['site_home_url'])) @@ -2748,6 +2913,46 @@ function change_database_data(&$no_updates, $version) $config->set('site_home_text', ''); } + // PHPBB3-10601: Make inbox default. Add basename to ucp's pm category + + // Get the category wanted while checking, at the same time, if this has already been applied + $sql = 'SELECT module_id, module_basename + FROM ' . MODULES_TABLE . " + WHERE module_basename <> 'ucp_pm' AND + module_langname='UCP_PM' + "; + $result = $db->sql_query_limit($sql, 1); + + if ($row = $db->sql_fetchrow($result)) + { + // This update is still not applied. Applying it + + $sql = 'UPDATE ' . MODULES_TABLE . " + SET module_basename = 'ucp_pm' + WHERE module_id = " . (int) $row['module_id']; + + _sql($sql, $errored, $error_ary); + } + $db->sql_freeresult($result); + + + // Add new permissions + include_once($phpbb_root_path . 'includes/acp/auth.' . $phpEx); + $auth_admin = new auth_admin(); + + _add_permission($auth_admin, $db, 'u_chgprofileinfo', true, 'u_sig'); + _add_permission($auth_admin, $db, 'a_extensions', true, 'a_styles'); + + // Update the auth setting for the module + $sql = 'UPDATE ' . MODULES_TABLE . " + SET module_auth = 'acl_u_chgprofileinfo' + WHERE module_class = 'ucp' + AND module_basename = 'ucp_profile' + AND module_mode = 'profile_info'"; + _sql($sql, $errored, $error_ary); + + $no_updates = false; + break; } } diff --git a/phpBB/install/index.php b/phpBB/install/index.php index 753e5eb226..a03fda6395 100644 --- a/phpBB/install/index.php +++ b/phpBB/install/index.php @@ -73,12 +73,15 @@ else } @ini_set('memory_limit', $mem_limit); +// In case $phpbb_adm_relative_path is not set (in case of an update), use the default. +$phpbb_adm_relative_path = (isset($phpbb_adm_relative_path)) ? $phpbb_adm_relative_path : 'adm/'; +$phpbb_admin_path = (defined('PHPBB_ADMIN_PATH')) ? PHPBB_ADMIN_PATH : $phpbb_root_path . $phpbb_adm_relative_path; + // Include essential scripts require($phpbb_root_path . 'includes/class_loader.' . $phpEx); -require($phpbb_root_path . 'includes/di/processor/interface.' . $phpEx); -require($phpbb_root_path . 'includes/di/processor/config.' . $phpEx); require($phpbb_root_path . 'includes/functions.' . $phpEx); +require($phpbb_root_path . 'includes/functions_container.' . $phpEx); phpbb_require_updated('includes/functions_content.' . $phpEx, true); @@ -86,20 +89,17 @@ include($phpbb_root_path . 'includes/functions_admin.' . $phpEx); include($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx); require($phpbb_root_path . 'includes/functions_install.' . $phpEx); -$phpbb_container = new ContainerBuilder(); -$loader = new YamlFileLoader($phpbb_container, new FileLocator(__DIR__.'/../config')); -$loader->load('services.yml'); - -$phpbb_container->setParameter('core.root_path', $phpbb_root_path); -$phpbb_container->setParameter('core.php_ext', $phpEx); +// Setup class loader first +$phpbb_class_loader = new phpbb_class_loader('phpbb_', "{$phpbb_root_path}includes/", ".$phpEx"); +$phpbb_class_loader->register(); +$phpbb_class_loader_ext = new phpbb_class_loader('phpbb_ext_', "{$phpbb_root_path}ext/", ".$phpEx"); +$phpbb_class_loader_ext->register(); -$phpbb_container->setAlias('cache.driver', 'cache.driver.install'); +// Set up container +$phpbb_container = phpbb_create_install_container($phpbb_root_path, $phpEx); -$phpbb_class_loader = $phpbb_container->get('class_loader'); -$phpbb_class_loader_ext = $phpbb_container->get('class_loader.ext'); - -// set up caching -$cache = $phpbb_container->get('cache'); +$phpbb_class_loader->set_cache($phpbb_container->get('cache.driver')); +$phpbb_class_loader_ext->set_cache($phpbb_container->get('cache.driver')); $phpbb_dispatcher = $phpbb_container->get('dispatcher'); $request = $phpbb_container->get('request'); @@ -196,7 +196,8 @@ if (file_exists($phpbb_root_path . 'includes/hooks/index.' . $phpEx)) require($phpbb_root_path . 'includes/hooks/index.' . $phpEx); $phpbb_hook = new phpbb_hook(array('exit_handler', 'phpbb_user_session_handler', 'append_sid', array('template', 'display'))); - foreach ($cache->obtain_hooks() as $hook) + $phpbb_hook_finder = $phpbb_container->get('hook_finder'); + foreach ($phpbb_hook_finder->find() as $hook) { @include($phpbb_root_path . 'includes/hooks/' . $hook . '.' . $phpEx); } @@ -216,9 +217,9 @@ $phpbb_style_path_provider = new phpbb_style_path_provider(); $template = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $phpbb_style_resource_locator, new phpbb_template_context()); $phpbb_style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $phpbb_style_resource_locator, $phpbb_style_path_provider, $template); $phpbb_style->set_ext_dir_prefix('adm/'); -$phpbb_style->set_custom_style('admin', '../adm/style', ''); +$phpbb_style->set_custom_style('admin', $phpbb_admin_path . 'style', array(), ''); $template->assign_var('T_ASSETS_PATH', '../assets'); -$template->assign_var('T_TEMPLATE_PATH', '../adm/style'); +$template->assign_var('T_TEMPLATE_PATH', $phpbb_admin_path . 'style'); $install = new module(); @@ -362,7 +363,7 @@ class module } define('HEADER_INC', true); - global $template, $lang, $stage, $phpbb_root_path; + global $template, $lang, $stage, $phpbb_root_path, $phpbb_admin_path; $template->assign_vars(array( 'L_CHANGE' => $lang['CHANGE'], @@ -371,7 +372,7 @@ class module 'L_SELECT_LANG' => $lang['SELECT_LANG'], 'L_SKIP' => $lang['SKIP'], 'PAGE_TITLE' => $this->get_page_title(), - 'T_IMAGE_PATH' => $phpbb_root_path . 'adm/images/', + 'T_IMAGE_PATH' => htmlspecialchars($phpbb_admin_path) . 'images/', 'S_CONTENT_DIRECTION' => $lang['DIRECTION'], 'S_CONTENT_FLOW_BEGIN' => ($lang['DIRECTION'] == 'ltr') ? 'left' : 'right', @@ -552,7 +553,7 @@ class module */ function error($error, $line, $file, $skip = false) { - global $lang, $db, $template; + global $lang, $db, $template, $phpbb_admin_path; if ($skip) { @@ -574,7 +575,7 @@ class module echo '<head>'; echo '<meta charset="utf-8">'; echo '<title>' . $lang['INST_ERR_FATAL'] . '</title>'; - echo '<link href="../adm/style/admin.css" rel="stylesheet" type="text/css" media="screen" />'; + echo '<link href="' . htmlspecialchars($phpbb_admin_path) . 'style/admin.css" rel="stylesheet" type="text/css" media="screen" />'; echo '</head>'; echo '<body id="errorpage">'; echo '<div id="wrap">'; diff --git a/phpBB/install/install_convert.php b/phpBB/install/install_convert.php index 41de9de44c..15202768b8 100644 --- a/phpBB/install/install_convert.php +++ b/phpBB/install/install_convert.php @@ -121,10 +121,11 @@ class install_convert extends module require($phpbb_root_path . 'config.' . $phpEx); require($phpbb_root_path . 'includes/constants.' . $phpEx); - require($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx); require($phpbb_root_path . 'includes/functions_convert.' . $phpEx); - $db = new $sql_db(); + $dbms = phpbb_convert_30_dbms_to_31($dbms); + + $db = new $dbms(); $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true); unset($dbpasswd); @@ -209,10 +210,11 @@ class install_convert extends module require($phpbb_root_path . 'config.' . $phpEx); require($phpbb_root_path . 'includes/constants.' . $phpEx); - require($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx); require($phpbb_root_path . 'includes/functions_convert.' . $phpEx); - $db = new $sql_db(); + $dbms = phpbb_convert_30_dbms_to_31($dbms); + + $db = new $dbms(); $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true); unset($dbpasswd); @@ -332,10 +334,11 @@ class install_convert extends module require($phpbb_root_path . 'config.' . $phpEx); require($phpbb_root_path . 'includes/constants.' . $phpEx); - require($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx); require($phpbb_root_path . 'includes/functions_convert.' . $phpEx); - $db = new $sql_db(); + $dbms = phpbb_convert_30_dbms_to_31($dbms); + + $db = new $dbms(); $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true); unset($dbpasswd); @@ -425,8 +428,7 @@ class install_convert extends module if ($src_dbms != $dbms || $src_dbhost != $dbhost || $src_dbport != $dbport || $src_dbname != $dbname || $src_dbuser != $dbuser) { - $sql_db = 'dbal_' . $src_dbms; - $src_db = new $sql_db(); + $src_db = new $src_dbms(); $src_db->sql_connect($src_dbhost, $src_dbuser, htmlspecialchars_decode($src_dbpasswd), $src_dbname, $src_dbport, false, true); $same_db = false; } @@ -575,10 +577,11 @@ class install_convert extends module require($phpbb_root_path . 'config.' . $phpEx); require($phpbb_root_path . 'includes/constants.' . $phpEx); - require($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx); require($phpbb_root_path . 'includes/functions_convert.' . $phpEx); - $db = new $sql_db(); + $dbms = phpbb_convert_30_dbms_to_31($dbms); + + $db = new $dbms(); $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true); unset($dbpasswd); @@ -639,12 +642,8 @@ class install_convert extends module $src_db = $same_db = null; if ($convert->src_dbms != $dbms || $convert->src_dbhost != $dbhost || $convert->src_dbport != $dbport || $convert->src_dbname != $dbname || $convert->src_dbuser != $dbuser) { - if ($convert->src_dbms != $dbms) - { - require($phpbb_root_path . 'includes/db/' . $convert->src_dbms . '.' . $phpEx); - } - $sql_db = 'dbal_' . $convert->src_dbms; - $src_db = new $sql_db(); + $dbms = $convert->src_dbms; + $src_db = new $dbms(); $src_db->sql_connect($convert->src_dbhost, $convert->src_dbuser, htmlspecialchars_decode($convert->src_dbpasswd), $convert->src_dbname, $convert->src_dbport, false, true); $same_db = false; } @@ -1539,6 +1538,7 @@ class install_convert extends module function finish_conversion() { global $db, $phpbb_root_path, $phpEx, $convert, $config, $language, $user, $template; + global $cache, $auth; $db->sql_query('DELETE FROM ' . CONFIG_TABLE . " WHERE config_name = 'convert_progress' @@ -1548,7 +1548,7 @@ class install_convert extends module $db->sql_query('DELETE FROM ' . SESSIONS_TABLE); @unlink($phpbb_root_path . 'cache/data_global.' . $phpEx); - cache_moderators(); + phpbb_cache_moderators($db, $cache, $auth); // And finally, add a note to the log add_log('admin', 'LOG_INSTALL_CONVERTED', $convert->convertor_data['forum_name'], $config['version']); diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php index f80b8b5661..1ab9caee0a 100644 --- a/phpBB/install/install_install.php +++ b/phpBB/install/install_install.php @@ -52,12 +52,13 @@ class install_install extends module function main($mode, $sub) { - global $lang, $template, $language, $phpbb_root_path, $cache; + global $lang, $template, $language, $phpbb_root_path, $phpEx; + global $phpbb_container, $cache; switch ($sub) { case 'intro': - $cache->purge(); + $phpbb_container->get('cache.driver')->purge(); $this->page_title = $lang['SUB_INTRO']; @@ -101,6 +102,12 @@ class install_install extends module break; case 'final': + // Create a normal container now + $phpbb_container = phpbb_create_default_container($phpbb_root_path, $phpEx); + + // Sets the global $cache variable + $cache = $phpbb_container->get('cache'); + $this->build_search_index($mode, $sub); $this->add_modules($mode, $sub); $this->add_language($mode, $sub); @@ -1118,11 +1125,8 @@ class install_install extends module $dbms = $available_dbms[$data['dbms']]['DRIVER']; - // Load the appropriate database class if not already loaded - include($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx); - // Instantiate the database - $db = new $sql_db(); + $db = new $dbms(); $db->sql_connect($data['dbhost'], $data['dbuser'], htmlspecialchars_decode($data['dbpasswd']), $data['dbname'], $data['dbport'], false, false); // NOTE: trigger_error does not work here. @@ -1418,11 +1422,8 @@ class install_install extends module $dbms = $available_dbms[$data['dbms']]['DRIVER']; - // Load the appropriate database class if not already loaded - include($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx); - // Instantiate the database - $db = new $sql_db(); + $db = new $dbms(); $db->sql_connect($data['dbhost'], $data['dbuser'], htmlspecialchars_decode($data['dbpasswd']), $data['dbname'], $data['dbport'], false, false); // NOTE: trigger_error does not work here. @@ -1478,8 +1479,14 @@ class install_install extends module foreach ($this->module_categories[$module_class] as $cat_name => $subs) { + $basename = ''; + // Check if this sub-category has a basename. If it has, use it. + if (isset($this->module_categories_basenames[$cat_name])) + { + $basename = $this->module_categories_basenames[$cat_name]; + } $module_data = array( - 'module_basename' => '', + 'module_basename' => $basename, 'module_enabled' => 1, 'module_display' => 1, 'parent_id' => 0, @@ -1507,8 +1514,14 @@ class install_install extends module { foreach ($subs as $level2_name) { + $basename = ''; + // Check if this sub-category has a basename. If it has, use it. + if (isset($this->module_categories_basenames[$level2_name])) + { + $basename = $this->module_categories_basenames[$level2_name]; + } $module_data = array( - 'module_basename' => '', + 'module_basename' => $basename, 'module_enabled' => 1, 'module_display' => 1, 'parent_id' => (int) $categories[$cat_name]['id'], @@ -1772,6 +1785,7 @@ class install_install extends module 'user_timezone' => 'UTC', 'user_dateformat' => $lang['default_dateformat'], 'user_allow_massemail' => 0, + 'user_allow_pm' => 0, ); $user_id = user_add($user_row); @@ -1800,7 +1814,7 @@ class install_install extends module */ function email_admin($mode, $sub) { - global $auth, $config, $db, $lang, $template, $user, $phpbb_root_path, $phpEx; + global $auth, $config, $db, $lang, $template, $user, $phpbb_root_path, $phpbb_admin_path, $phpEx; $this->page_title = $lang['STAGE_FINAL']; @@ -1847,7 +1861,7 @@ class install_install extends module 'TITLE' => $lang['INSTALL_CONGRATS'], 'BODY' => sprintf($lang['INSTALL_CONGRATS_EXPLAIN'], $config['version'], append_sid($phpbb_root_path . 'install/index.' . $phpEx, 'mode=convert&language=' . $data['language']), '../docs/README.html'), 'L_SUBMIT' => $lang['INSTALL_LOGIN'], - 'U_ACTION' => append_sid($phpbb_root_path . 'adm/index.' . $phpEx, 'i=send_statistics&mode=send_statistics'), + 'U_ACTION' => append_sid($phpbb_admin_path . 'index.' . $phpEx, 'i=send_statistics&mode=send_statistics'), )); } @@ -2082,9 +2096,10 @@ class install_install extends module 'ACP_PERMISSION_ROLES', 'ACP_PERMISSION_MASKS', ), - 'ACP_CAT_STYLES' => array( + 'ACP_CAT_CUSTOMISE' => array( 'ACP_STYLE_MANAGEMENT', - 'ACP_STYLE_COMPONENTS', + 'ACP_EXTENSIONS_MANAGEMENT', + 'ACP_LANGUAGE', ), 'ACP_CAT_MAINTENANCE' => array( 'ACP_FORUM_LOGS', @@ -2115,6 +2130,9 @@ class install_install extends module 'UCP_ZEBRA' => null, ), ); + var $module_categories_basenames = array( + 'UCP_PM' => 'ucp_pm', + ); var $module_extras = array( 'acp' => array( diff --git a/phpBB/install/install_update.php b/phpBB/install/install_update.php index 8c044550f3..bfceed6b17 100644 --- a/phpBB/install/install_update.php +++ b/phpBB/install/install_update.php @@ -71,8 +71,8 @@ class install_update extends module function main($mode, $sub) { - global $style, $template, $phpEx, $phpbb_root_path, $user, $db, $config, $cache, $auth, $language; - global $request; + global $phpbb_style, $template, $phpEx, $phpbb_root_path, $user, $db, $config, $cache, $auth, $language; + global $request, $phpbb_admin_path, $phpbb_adm_relative_path; $this->tpl_name = 'install_update'; $this->page_title = 'UPDATE_INSTALLATION'; @@ -83,7 +83,6 @@ class install_update extends module // Init DB require($phpbb_root_path . 'config.' . $phpEx); - require($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx); require($phpbb_root_path . 'includes/constants.' . $phpEx); // Special options for conflicts/modified files @@ -92,7 +91,9 @@ class install_update extends module define('MERGE_NEW_FILE', 3); define('MERGE_MOD_FILE', 4); - $db = new $sql_db(); + $dbms = phpbb_convert_30_dbms_to_31($dbms); + + $db = new $dbms(); // Connect to DB $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, false); @@ -131,7 +132,7 @@ class install_update extends module } // Set custom template again. ;) - $phpbb_style->set_custom_style('admin', '../adm/style', ''); + $phpbb_style->set_custom_style('admin', $phpbb_admin_path . 'style', array(), ''); $template->assign_vars(array( 'S_USER_LANG' => $user->lang['USER_LANG'], @@ -216,7 +217,7 @@ class install_update extends module if ($this->test_update === false) { // Got the updater template itself updated? If so, we are able to directly use it - but only if all three files are present - if (in_array('adm/style/install_update.html', $this->update_info['files'])) + if (in_array($phpbb_adm_relative_path . 'style/install_update.html', $this->update_info['files'])) { $this->tpl_name = '../../install/update/new/adm/style/install_update'; } @@ -493,6 +494,7 @@ class install_update extends module $template->assign_vars(array( 'S_FILE_CHECK' => true, 'S_ALL_UP_TO_DATE' => $all_up_to_date, + 'L_ALL_FILES_UP_TO_DATE' => $user->lang('ALL_FILES_UP_TO_DATE', append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login'), append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login&redirect=' . $phpbb_adm_relative_path . 'index.php%3Fi=send_statistics%26mode=send_statistics')), 'S_VERSION_UP_TO_DATE' => $up_to_date, 'U_ACTION' => append_sid($this->p_master->module_url, "language=$language&mode=$mode&sub=file_check"), 'U_UPDATE_ACTION' => append_sid($this->p_master->module_url, "language=$language&mode=$mode&sub=update_files"), @@ -1077,12 +1079,12 @@ class install_update extends module */ function show_diff(&$update_list) { - global $phpbb_root_path, $template, $user; + global $phpbb_root_path, $template, $user, $phpbb_adm_relative_path; $this->tpl_name = 'install_update_diff'; // Got the diff template itself updated? If so, we are able to directly use it - if (in_array('adm/style/install_update_diff.html', $this->update_info['files'])) + if (in_array($phpbb_adm_relative_path . 'style/install_update_diff.html', $this->update_info['files'])) { $this->tpl_name = '../../install/update/new/adm/style/install_update_diff'; } diff --git a/phpBB/install/schemas/firebird_schema.sql b/phpBB/install/schemas/firebird_schema.sql index 767ce68b4a..b475303fde 100644 --- a/phpBB/install/schemas/firebird_schema.sql +++ b/phpBB/install/schemas/firebird_schema.sql @@ -912,8 +912,11 @@ CREATE TABLE phpbb_reports ( report_time INTEGER DEFAULT 0 NOT NULL, report_text BLOB SUB_TYPE TEXT CHARACTER SET UTF8 DEFAULT '' NOT NULL, reported_post_text BLOB SUB_TYPE TEXT CHARACTER SET UTF8 DEFAULT '' NOT NULL, + reported_post_uid VARCHAR(8) CHARACTER SET NONE DEFAULT '' NOT NULL, reported_post_bitfield VARCHAR(255) CHARACTER SET NONE DEFAULT '' NOT NULL, - reported_post_uid VARCHAR(8) CHARACTER SET NONE DEFAULT '' NOT NULL + reported_post_enable_magic_url INTEGER DEFAULT 1 NOT NULL, + reported_post_enable_smilies INTEGER DEFAULT 1 NOT NULL, + reported_post_enable_bbcode INTEGER DEFAULT 1 NOT NULL );; ALTER TABLE phpbb_reports ADD PRIMARY KEY (report_id);; @@ -1281,7 +1284,6 @@ CREATE TABLE phpbb_users ( user_icq VARCHAR(15) CHARACTER SET NONE DEFAULT '' NOT NULL, user_aim VARCHAR(255) CHARACTER SET UTF8 DEFAULT '' NOT NULL COLLATE UNICODE, user_yim VARCHAR(255) CHARACTER SET UTF8 DEFAULT '' NOT NULL COLLATE UNICODE, - user_msnm VARCHAR(255) CHARACTER SET UTF8 DEFAULT '' NOT NULL COLLATE UNICODE, user_jabber VARCHAR(255) CHARACTER SET UTF8 DEFAULT '' NOT NULL COLLATE UNICODE, user_website VARCHAR(200) CHARACTER SET UTF8 DEFAULT '' NOT NULL COLLATE UNICODE, user_occ BLOB SUB_TYPE TEXT CHARACTER SET UTF8 DEFAULT '' NOT NULL, diff --git a/phpBB/install/schemas/mssql_schema.sql b/phpBB/install/schemas/mssql_schema.sql index 84c975942f..0420738828 100644 --- a/phpBB/install/schemas/mssql_schema.sql +++ b/phpBB/install/schemas/mssql_schema.sql @@ -1111,8 +1111,11 @@ CREATE TABLE [phpbb_reports] ( [report_time] [int] DEFAULT (0) NOT NULL , [report_text] [text] DEFAULT ('') NOT NULL , [reported_post_text] [text] DEFAULT ('') NOT NULL , + [reported_post_uid] [varchar] (8) DEFAULT ('') NOT NULL , [reported_post_bitfield] [varchar] (255) DEFAULT ('') NOT NULL , - [reported_post_uid] [varchar] (8) DEFAULT ('') NOT NULL + [reported_post_enable_magic_url] [int] DEFAULT (1) NOT NULL , + [reported_post_enable_smilies] [int] DEFAULT (1) NOT NULL , + [reported_post_enable_bbcode] [int] DEFAULT (1) NOT NULL ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO @@ -1565,7 +1568,6 @@ CREATE TABLE [phpbb_users] ( [user_icq] [varchar] (15) DEFAULT ('') NOT NULL , [user_aim] [varchar] (255) DEFAULT ('') NOT NULL , [user_yim] [varchar] (255) DEFAULT ('') NOT NULL , - [user_msnm] [varchar] (255) DEFAULT ('') NOT NULL , [user_jabber] [varchar] (255) DEFAULT ('') NOT NULL , [user_website] [varchar] (200) DEFAULT ('') NOT NULL , [user_occ] [varchar] (4000) DEFAULT ('') NOT NULL , diff --git a/phpBB/install/schemas/mysql_40_schema.sql b/phpBB/install/schemas/mysql_40_schema.sql index 8aab949103..18f8560e87 100644 --- a/phpBB/install/schemas/mysql_40_schema.sql +++ b/phpBB/install/schemas/mysql_40_schema.sql @@ -649,8 +649,11 @@ CREATE TABLE phpbb_reports ( report_time int(11) UNSIGNED DEFAULT '0' NOT NULL, report_text mediumblob NOT NULL, reported_post_text mediumblob NOT NULL, - reported_post_bitfield varbinary(255) DEFAULT '' NOT NULL, reported_post_uid varbinary(8) DEFAULT '' NOT NULL, + reported_post_bitfield varbinary(255) DEFAULT '' NOT NULL, + reported_post_enable_magic_url tinyint(1) UNSIGNED DEFAULT '1' NOT NULL, + reported_post_enable_smilies tinyint(1) UNSIGNED DEFAULT '1' NOT NULL, + reported_post_enable_bbcode tinyint(1) UNSIGNED DEFAULT '1' NOT NULL, PRIMARY KEY (report_id), KEY post_id (post_id), KEY pm_id (pm_id) @@ -929,7 +932,6 @@ CREATE TABLE phpbb_users ( user_icq varbinary(15) DEFAULT '' NOT NULL, user_aim blob NOT NULL, user_yim blob NOT NULL, - user_msnm blob NOT NULL, user_jabber blob NOT NULL, user_website blob NOT NULL, user_occ blob NOT NULL, diff --git a/phpBB/install/schemas/mysql_41_schema.sql b/phpBB/install/schemas/mysql_41_schema.sql index 04aef2844a..bc3cfb4249 100644 --- a/phpBB/install/schemas/mysql_41_schema.sql +++ b/phpBB/install/schemas/mysql_41_schema.sql @@ -649,8 +649,11 @@ CREATE TABLE phpbb_reports ( report_time int(11) UNSIGNED DEFAULT '0' NOT NULL, report_text mediumtext NOT NULL, reported_post_text mediumtext NOT NULL, - reported_post_bitfield varchar(255) DEFAULT '' NOT NULL, reported_post_uid varchar(8) DEFAULT '' NOT NULL, + reported_post_bitfield varchar(255) DEFAULT '' NOT NULL, + reported_post_enable_magic_url tinyint(1) UNSIGNED DEFAULT '1' NOT NULL, + reported_post_enable_smilies tinyint(1) UNSIGNED DEFAULT '1' NOT NULL, + reported_post_enable_bbcode tinyint(1) UNSIGNED DEFAULT '1' NOT NULL, PRIMARY KEY (report_id), KEY post_id (post_id), KEY pm_id (pm_id) @@ -929,7 +932,6 @@ CREATE TABLE phpbb_users ( user_icq varchar(15) DEFAULT '' NOT NULL, user_aim varchar(255) DEFAULT '' NOT NULL, user_yim varchar(255) DEFAULT '' NOT NULL, - user_msnm varchar(255) DEFAULT '' NOT NULL, user_jabber varchar(255) DEFAULT '' NOT NULL, user_website varchar(200) DEFAULT '' NOT NULL, user_occ text NOT NULL, diff --git a/phpBB/install/schemas/oracle_schema.sql b/phpBB/install/schemas/oracle_schema.sql index 91f906bc8b..f20b96cd38 100644 --- a/phpBB/install/schemas/oracle_schema.sql +++ b/phpBB/install/schemas/oracle_schema.sql @@ -1216,8 +1216,11 @@ CREATE TABLE phpbb_reports ( report_time number(11) DEFAULT '0' NOT NULL, report_text clob DEFAULT '' , reported_post_text clob DEFAULT '' , - reported_post_bitfield varchar2(255) DEFAULT '' , reported_post_uid varchar2(8) DEFAULT '' , + reported_post_bitfield varchar2(255) DEFAULT '' , + reported_post_enable_magic_url number(1) DEFAULT '1' NOT NULL, + reported_post_enable_smilies number(1) DEFAULT '1' NOT NULL, + reported_post_enable_bbcode number(1) DEFAULT '1' NOT NULL, CONSTRAINT pk_phpbb_reports PRIMARY KEY (report_id) ) / @@ -1677,7 +1680,6 @@ CREATE TABLE phpbb_users ( user_icq varchar2(15) DEFAULT '' , user_aim varchar2(765) DEFAULT '' , user_yim varchar2(765) DEFAULT '' , - user_msnm varchar2(765) DEFAULT '' , user_jabber varchar2(765) DEFAULT '' , user_website varchar2(600) DEFAULT '' , user_occ clob DEFAULT '' , diff --git a/phpBB/install/schemas/postgres_schema.sql b/phpBB/install/schemas/postgres_schema.sql index 619985e0d6..301654bf25 100644 --- a/phpBB/install/schemas/postgres_schema.sql +++ b/phpBB/install/schemas/postgres_schema.sql @@ -855,8 +855,11 @@ CREATE TABLE phpbb_reports ( report_time INT4 DEFAULT '0' NOT NULL CHECK (report_time >= 0), report_text TEXT DEFAULT '' NOT NULL, reported_post_text TEXT DEFAULT '' NOT NULL, - reported_post_bitfield varchar(255) DEFAULT '' NOT NULL, reported_post_uid varchar(8) DEFAULT '' NOT NULL, + reported_post_bitfield varchar(255) DEFAULT '' NOT NULL, + reported_post_enable_magic_url INT2 DEFAULT '1' NOT NULL CHECK (reported_post_enable_magic_url >= 0), + reported_post_enable_smilies INT2 DEFAULT '1' NOT NULL CHECK (reported_post_enable_smilies >= 0), + reported_post_enable_bbcode INT2 DEFAULT '1' NOT NULL CHECK (reported_post_enable_bbcode >= 0), PRIMARY KEY (report_id) ); @@ -1179,7 +1182,6 @@ CREATE TABLE phpbb_users ( user_icq varchar(15) DEFAULT '' NOT NULL, user_aim varchar(255) DEFAULT '' NOT NULL, user_yim varchar(255) DEFAULT '' NOT NULL, - user_msnm varchar(255) DEFAULT '' NOT NULL, user_jabber varchar(255) DEFAULT '' NOT NULL, user_website varchar(200) DEFAULT '' NOT NULL, user_occ varchar(4000) DEFAULT '' NOT NULL, diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index dbb5fd7481..19c00ef9fb 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -387,6 +387,7 @@ INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_chgemail', 1); INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_chggrp', 1); INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_chgname', 1); INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_chgpasswd', 1); +INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_chgprofileinfo', 1); INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_download', 1); INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_hideonline', 1); INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('u_ignoreflood', 1); @@ -453,10 +454,10 @@ INSERT INTO phpbb_forums (forum_name, forum_desc, left_id, right_id, parent_id, INSERT INTO phpbb_forums (forum_name, forum_desc, left_id, right_id, parent_id, forum_type, forum_posts, forum_topics, forum_topics_real, forum_last_post_id, forum_last_poster_id, forum_last_poster_name, forum_last_poster_colour, forum_last_post_subject, forum_last_post_time, forum_link, forum_password, forum_image, forum_rules, forum_rules_link, forum_rules_uid, forum_desc_uid, prune_days, prune_viewed, forum_parents, forum_flags) VALUES ('{L_FORUMS_TEST_FORUM_TITLE}', '{L_FORUMS_TEST_FORUM_DESC}', 2, 3, 1, 1, 1, 1, 1, 1, 2, 'Admin', 'AA0000', '{L_TOPICS_TOPIC_TITLE}', 972086460, '', '', '', '', '', '', '', 0, 0, '', 48); # -- Users / Anonymous user -INSERT INTO phpbb_users (user_type, group_id, username, username_clean, user_regdate, user_password, user_email, user_lang, user_style, user_rank, user_colour, user_posts, user_permissions, user_ip, user_birthday, user_lastpage, user_last_confirm_key, user_post_sortby_type, user_post_sortby_dir, user_topic_sortby_type, user_topic_sortby_dir, user_avatar, user_sig, user_sig_bbcode_uid, user_from, user_icq, user_aim, user_yim, user_msnm, user_jabber, user_website, user_occ, user_interests, user_actkey, user_newpasswd, user_allow_massemail) VALUES (2, 1, 'Anonymous', 'anonymous', 0, '', '', 'en', 1, 0, '', 0, '', '', '', '', '', 't', 'a', 't', 'd', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 0); +INSERT INTO phpbb_users (user_type, group_id, username, username_clean, user_regdate, user_password, user_email, user_lang, user_style, user_rank, user_colour, user_posts, user_permissions, user_ip, user_birthday, user_lastpage, user_last_confirm_key, user_post_sortby_type, user_post_sortby_dir, user_topic_sortby_type, user_topic_sortby_dir, user_avatar, user_sig, user_sig_bbcode_uid, user_from, user_icq, user_aim, user_yim, user_jabber, user_website, user_occ, user_interests, user_actkey, user_newpasswd, user_allow_massemail) VALUES (2, 1, 'Anonymous', 'anonymous', 0, '', '', 'en', 1, 0, '', 0, '', '', '', '', '', 't', 'a', 't', 'd', '', '', '', '', '', '', '', '', '', '', '', '', '', 0); # -- username: Admin password: admin (change this or remove it once everything is working!) -INSERT INTO phpbb_users (user_type, group_id, username, username_clean, user_regdate, user_password, user_email, user_lang, user_style, user_rank, user_colour, user_posts, user_permissions, user_ip, user_birthday, user_lastpage, user_last_confirm_key, user_post_sortby_type, user_post_sortby_dir, user_topic_sortby_type, user_topic_sortby_dir, user_avatar, user_sig, user_sig_bbcode_uid, user_from, user_icq, user_aim, user_yim, user_msnm, user_jabber, user_website, user_occ, user_interests, user_actkey, user_newpasswd) VALUES (3, 5, 'Admin', 'admin', 0, '21232f297a57a5a743894a0e4a801fc3', 'admin@yourdomain.com', 'en', 1, 1, 'AA0000', 1, '', '', '', '', '', 't', 'a', 't', 'd', '', '', '', '', '', '', '', '', '', '', '', '', '', ''); +INSERT INTO phpbb_users (user_type, group_id, username, username_clean, user_regdate, user_password, user_email, user_lang, user_style, user_rank, user_colour, user_posts, user_permissions, user_ip, user_birthday, user_lastpage, user_last_confirm_key, user_post_sortby_type, user_post_sortby_dir, user_topic_sortby_type, user_topic_sortby_dir, user_avatar, user_sig, user_sig_bbcode_uid, user_from, user_icq, user_aim, user_yim, user_jabber, user_website, user_occ, user_interests, user_actkey, user_newpasswd) VALUES (3, 5, 'Admin', 'admin', 0, '21232f297a57a5a743894a0e4a801fc3', 'admin@yourdomain.com', 'en', 1, 1, 'AA0000', 1, '', '', '', '', '', 't', 'a', 't', 'd', '', '', '', '', '', '', '', '', '', '', '', '', ''); # -- Groups INSERT INTO phpbb_groups (group_name, group_type, group_founder_manage, group_colour, group_legend, group_teampage, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('GUESTS', 3, 0, '', 0, 0, '', '', '', 5); @@ -548,7 +549,7 @@ INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 22, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_attach', 'f_bump', 'f_delete', 'f_flash', 'f_icons', 'f_ignoreflood', 'f_sticky', 'f_user_lock', 'f_votechg'); # New Member (u_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 23, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option IN ('u_sendpm', 'u_masspm', 'u_masspm_group'); +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 23, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option LIKE 'u_%' AND auth_option IN ('u_sendpm', 'u_masspm', 'u_masspm_group', 'u_chgprofileinfo'); # New Member (f_) INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 24, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option IN ('f_noapprove'); diff --git a/phpBB/install/schemas/sqlite_schema.sql b/phpBB/install/schemas/sqlite_schema.sql index 1690a7dcab..397cfc139a 100644 --- a/phpBB/install/schemas/sqlite_schema.sql +++ b/phpBB/install/schemas/sqlite_schema.sql @@ -630,8 +630,11 @@ CREATE TABLE phpbb_reports ( report_time INTEGER UNSIGNED NOT NULL DEFAULT '0', report_text mediumtext(16777215) NOT NULL DEFAULT '', reported_post_text mediumtext(16777215) NOT NULL DEFAULT '', + reported_post_uid varchar(8) NOT NULL DEFAULT '', reported_post_bitfield varchar(255) NOT NULL DEFAULT '', - reported_post_uid varchar(8) NOT NULL DEFAULT '' + reported_post_enable_magic_url INTEGER UNSIGNED NOT NULL DEFAULT '1', + reported_post_enable_smilies INTEGER UNSIGNED NOT NULL DEFAULT '1', + reported_post_enable_bbcode INTEGER UNSIGNED NOT NULL DEFAULT '1' ); CREATE INDEX phpbb_reports_post_id ON phpbb_reports (post_id); @@ -903,7 +906,6 @@ CREATE TABLE phpbb_users ( user_icq varchar(15) NOT NULL DEFAULT '', user_aim varchar(255) NOT NULL DEFAULT '', user_yim varchar(255) NOT NULL DEFAULT '', - user_msnm varchar(255) NOT NULL DEFAULT '', user_jabber varchar(255) NOT NULL DEFAULT '', user_website varchar(200) NOT NULL DEFAULT '', user_occ text(65535) NOT NULL DEFAULT '', diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php index a4380486cc..1b99c87938 100644 --- a/phpBB/language/en/acp/board.php +++ b/phpBB/language/en/acp/board.php @@ -449,10 +449,10 @@ $lang = array_merge($lang, array( 'ACP_SECURITY_SETTINGS_EXPLAIN' => 'Here you are able to define session and login related settings.', 'ALL' => 'All', - 'ALLOW_AUTOLOGIN' => 'Allow persistent logins', - 'ALLOW_AUTOLOGIN_EXPLAIN' => 'Determines whether users can autologin when they visit the board.', - 'AUTOLOGIN_LENGTH' => 'Persistent login key expiration length (in days)', - 'AUTOLOGIN_LENGTH_EXPLAIN' => 'Number of days after which persistent login keys are removed or zero to disable.', + 'ALLOW_AUTOLOGIN' => 'Allow "Remember Me" logins', + 'ALLOW_AUTOLOGIN_EXPLAIN' => 'Determines whether users are given "Remember Me" option when they visit the board.', + 'AUTOLOGIN_LENGTH' => '"Remember Me" login key expiration length (in days)', + 'AUTOLOGIN_LENGTH_EXPLAIN' => 'Number of days after which "Remember Me" login keys are removed or zero to disable.', 'BROWSER_VALID' => 'Validate browser', 'BROWSER_VALID_EXPLAIN' => 'Enables browser validation for each session improving security.', 'CHECK_DNSBL' => 'Check IP against DNS Blackhole List', diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php index 5eb10d50b3..427e4f4d98 100644 --- a/phpBB/language/en/acp/common.php +++ b/phpBB/language/en/acp/common.php @@ -59,6 +59,7 @@ $lang = array_merge($lang, array( 'ACP_CAPTCHA' => 'CAPTCHA', + 'ACP_CAT_CUSTOMISE' => 'Customise', 'ACP_CAT_DATABASE' => 'Database', 'ACP_CAT_DOT_MODS' => '.MODs', 'ACP_CAT_FORUMS' => 'Forums', @@ -80,8 +81,10 @@ $lang = array_merge($lang, array( 'ACP_DISALLOW_USERNAMES' => 'Disallow usernames', 'ACP_EMAIL_SETTINGS' => 'Email settings', - 'ACP_EXTENSION_GROUPS' => 'Manage extension groups', - 'ACP_EXTENSIONS' => 'Manage board extensions', + 'ACP_EXTENSION_GROUPS' => 'Manage attachment extension groups', + 'ACP_EXTENSION_MANAGEMENT' => 'Extension management', + 'ACP_EXTENSIONS' => 'Extensions', + 'ACP_FORUM_BASED_PERMISSIONS' => 'Forum based permissions', 'ACP_FORUM_LOGS' => 'Forum logs', @@ -119,7 +122,7 @@ $lang = array_merge($lang, array( 'ACP_MANAGE_ATTACHMENTS' => 'Manage attachments', 'ACP_MANAGE_ATTACHMENTS_EXPLAIN' => 'Here you can list and delete files attached to posts and private messages.', - 'ACP_MANAGE_EXTENSIONS' => 'Manage extensions', + 'ACP_MANAGE_EXTENSIONS' => 'Manage attachment extensions', 'ACP_MANAGE_FORUMS' => 'Manage forums', 'ACP_MANAGE_RANKS' => 'Manage ranks', 'ACP_MANAGE_REASONS' => 'Manage report/denial reasons', @@ -166,7 +169,6 @@ $lang = array_merge($lang, array( 'ACP_SERVER_SETTINGS' => 'Server settings', 'ACP_SIGNATURE_SETTINGS' => 'Signature settings', 'ACP_SMILIES' => 'Smilies', - 'ACP_STYLE_COMPONENTS' => 'Style components', 'ACP_STYLE_MANAGEMENT' => 'Style management', 'ACP_STYLES' => 'Styles', 'ACP_STYLES_CACHE' => 'Purge Cache', diff --git a/phpBB/language/en/acp/permissions_phpbb.php b/phpBB/language/en/acp/permissions_phpbb.php index b142cfd9aa..27ef714f8b 100644 --- a/phpBB/language/en/acp/permissions_phpbb.php +++ b/phpBB/language/en/acp/permissions_phpbb.php @@ -102,6 +102,7 @@ $lang = array_merge($lang, array( 'acl_u_chgemail' => array('lang' => 'Can change email address', 'cat' => 'profile'), 'acl_u_chgavatar' => array('lang' => 'Can change avatar', 'cat' => 'profile'), 'acl_u_chggrp' => array('lang' => 'Can change default usergroup', 'cat' => 'profile'), + 'acl_u_chgprofileinfo' => array('lang' => 'Can change profile field information', 'cat' => 'profile'), 'acl_u_attach' => array('lang' => 'Can attach files', 'cat' => 'post'), 'acl_u_download' => array('lang' => 'Can download files', 'cat' => 'post'), diff --git a/phpBB/language/en/acp/styles.php b/phpBB/language/en/acp/styles.php index e7954ff148..3cb2e741ca 100644 --- a/phpBB/language/en/acp/styles.php +++ b/phpBB/language/en/acp/styles.php @@ -186,7 +186,6 @@ $lang = array_merge($lang, array( 'IMG_ICON_CONTACT_EMAIL' => 'Send email', 'IMG_ICON_CONTACT_ICQ' => 'ICQ', 'IMG_ICON_CONTACT_JABBER' => 'Jabber', - 'IMG_ICON_CONTACT_MSNM' => 'WLM', 'IMG_ICON_CONTACT_PM' => 'Send message', 'IMG_ICON_CONTACT_YAHOO' => 'YIM', 'IMG_ICON_CONTACT_WWW' => 'Website', diff --git a/phpBB/language/en/app.php b/phpBB/language/en/app.php new file mode 100644 index 0000000000..cb56015c30 --- /dev/null +++ b/phpBB/language/en/app.php @@ -0,0 +1,49 @@ +<?php +/** +* +* app [English] +* +* @package language +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* DO NOT CHANGE +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +if (empty($lang) || !is_array($lang)) +{ + $lang = array(); +} + +// DEVELOPERS PLEASE NOTE +// +// All language files should use UTF-8 as their encoding and the files must not contain a BOM. +// +// Placeholders can now contain order information, e.g. instead of +// 'Page %s of %s' you can (and should) write 'Page %1$s of %2$s', this allows +// translators to re-order the output of data while ensuring it remains correct +// +// You do not need this where single placeholders are used, e.g. 'Message %d' is fine +// equally where a string contains only two placeholders which are used to wrap text +// in a url you again do not need to specify an order e.g., 'Click %sHERE%s' is fine +// +// Some characters you may want to copy&paste: +// ’ » “ ” … +// + +$lang = array_merge($lang, array( + 'CONTROLLER_ARGUMENT_VALUE_MISSING' => 'Missing value for argument #%1$s: <strong>%3$s</strong> in class <strong>%2$s</strong>', + 'CONTROLLER_NOT_SPECIFIED' => 'No controller has been specified.', + 'CONTROLLER_NOT_FOUND' => 'The requested page could not be found.', + 'CONTROLLER_METHOD_NOT_SPECIFIED' => 'No method was specified for the controller.', + 'CONTROLLER_SERVICE_NOT_GIVEN' => 'The controller "<strong>%s</strong>" must have a service specified in ./config/routing.yml.', + 'CONTROLLER_SERVICE_UNDEFINED' => 'The service for controller "<strong>%s</strong>" is not defined in ./config/services.yml.', + 'CONTROLLER_RETURN_TYPE_INVALID' => 'The controller object <strong>%s</strong> must return a Symfony\Component\HttpFoundation\Response object.', +)); diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php index 4300ef431a..6cad4136a2 100644 --- a/phpBB/language/en/common.php +++ b/phpBB/language/en/common.php @@ -186,6 +186,8 @@ $lang = array_merge($lang, array( 'ERR_CONNECTING_SERVER' => 'Error connecting to the server.', 'ERR_JAB_AUTH' => 'Could not authorise on Jabber server.', 'ERR_JAB_CONNECT' => 'Could not connect to Jabber server.', + 'ERR_TEMPLATE_EVENT_LOCATION' => 'The specified template event location <em>[%s]</em> is improperly formatted.', + 'ERR_TEMPLATE_COMPILATION' => 'The file could not be compiled: %s', 'ERR_UNABLE_TO_LOGIN' => 'The specified username or password is incorrect.', 'ERR_UNWATCHING' => 'An error occured while trying to unsubscribe.', 'ERR_WATCHING' => 'An error occured while trying to subscribe.', @@ -343,7 +345,7 @@ $lang = array_merge($lang, array( 'LOGIN_EXPLAIN_VIEWONLINE' => 'In order to view the online list you have to be registered and logged in.', 'LOGOUT' => 'Logout', 'LOGOUT_USER' => 'Logout [ %s ]', - 'LOG_ME_IN' => 'Log me on automatically each visit', + 'LOG_ME_IN' => 'Remember me', 'MARK' => 'Mark', 'MARK_ALL' => 'Mark all', @@ -366,7 +368,6 @@ $lang = array_merge($lang, array( 'MODERATORS' => 'Moderators', 'MONTH' => 'Month', 'MOVE' => 'Move', - 'MSNM' => 'WLM', 'NA' => 'N/A', 'NEWEST_USER' => 'Our newest member <strong>%s</strong>', @@ -605,9 +606,11 @@ $lang = array_merge($lang, array( 'SUBJECT' => 'Subject', 'SUBMIT' => 'Submit', + 'TB' => 'TB', 'TERMS_USE' => 'Terms of use', 'TEST_CONNECTION' => 'Test connection', 'THE_TEAM' => 'The team', + 'TIB' => 'TiB', 'TIME' => 'Time', 'TIMEOUT_PROCESSING_REQ' => 'Request timed out.', @@ -623,7 +626,6 @@ $lang = array_merge($lang, array( 'TOO_LONG_INTERESTS' => 'The interests you entered is too long.', 'TOO_LONG_JABBER' => 'The Jabber account name you entered is too long.', 'TOO_LONG_LOCATION' => 'The location you entered is too long.', - 'TOO_LONG_MSN' => 'The WLM name you entered is too long.', 'TOO_LONG_NEW_PASSWORD' => 'The password you entered is too long.', 'TOO_LONG_OCCUPATION' => 'The occupation you entered is too long.', 'TOO_LONG_PASSWORD_CONFIRM' => 'The password confirmation you entered is too long.', @@ -644,7 +646,6 @@ $lang = array_merge($lang, array( 'TOO_SHORT_INTERESTS' => 'The interests you entered is too short.', 'TOO_SHORT_JABBER' => 'The Jabber account name you entered is too short.', 'TOO_SHORT_LOCATION' => 'The location you entered is too short.', - 'TOO_SHORT_MSN' => 'The WLM name you entered is too short.', 'TOO_SHORT_NEW_PASSWORD' => 'The password you entered is too short.', 'TOO_SHORT_OCCUPATION' => 'The occupation you entered is too short.', 'TOO_SHORT_PASSWORD_CONFIRM' => 'The password confirmation you entered is too short.', diff --git a/phpBB/language/en/help_faq.php b/phpBB/language/en/help_faq.php index 5c99f81c06..9500943b88 100644 --- a/phpBB/language/en/help_faq.php +++ b/phpBB/language/en/help_faq.php @@ -43,7 +43,7 @@ $help = array( ), array( 0 => 'Why do I get logged off automatically?', - 1 => 'If you do not check the <em>Log me in automatically</em> box when you login, the board will only keep you logged in for a preset time. This prevents misuse of your account by anyone else. To stay logged in, check the box during login. This is not recommended if you access the board from a shared computer, e.g. library, internet cafe, university computer lab, etc. If you do not see this checkbox, it means the board administrator has disabled this feature.' + 1 => 'If you do not check the <em>Remember me</em> box when you login, the board will only keep you logged in for a preset time. This prevents misuse of your account by anyone else. To stay logged in, check the box during login. This is not recommended if you access the board from a shared computer, e.g. library, internet cafe, university computer lab, etc. If you do not see this checkbox, it means the board administrator has disabled this feature.' ), array( 0 => 'How do I prevent my username appearing in the online user listings?', diff --git a/phpBB/language/en/install.php b/phpBB/language/en/install.php index cb6a17afa2..f7820714e1 100644 --- a/phpBB/language/en/install.php +++ b/phpBB/language/en/install.php @@ -210,7 +210,7 @@ $lang = array_merge($lang, array( <p>phpBB3 supports the following databases:</p> <ul> <li>MySQL 3.23 or above (MySQLi supported)</li> - <li>PostgreSQL 7.3+</li> + <li>PostgreSQL 8.3+</li> <li>SQLite 2.8.2+</li> <li>Firebird 2.1+</li> <li>MS SQL Server 2000 or above (directly or via ODBC)</li> @@ -374,7 +374,7 @@ $lang = array_merge($lang, array( // Updater $lang = array_merge($lang, array( - 'ALL_FILES_UP_TO_DATE' => 'All files are up to date with the latest phpBB version. You should now <a href="../ucp.php?mode=login">login to your board</a> and check if everything is working fine. Do not forget to delete, rename or move your install directory! Please send us updated information about your server and board configurations from the <a href="../ucp.php?mode=login&redirect=adm/index.php%3Fi=send_statistics%26mode=send_statistics">Send statistics</a> module in your ACP.', + 'ALL_FILES_UP_TO_DATE' => 'All files are up to date with the latest phpBB version. You should now <a href="%1$s">login to your board</a> and check if everything is working fine. Do not forget to delete, rename or move your install directory! Please send us updated information about your server and board configurations from the <a href="%2$s">Send statistics</a> module in your ACP.', 'ARCHIVE_FILE' => 'Source file within archive', 'BACK' => 'Back', diff --git a/phpBB/language/en/memberlist.php b/phpBB/language/en/memberlist.php index ec21e8e904..bc5a0c100b 100644 --- a/phpBB/language/en/memberlist.php +++ b/phpBB/language/en/memberlist.php @@ -78,9 +78,6 @@ $lang = array_merge($lang, array( 'IM_JABBER' => 'Please note that users may have selected to not receive unsolicited instant messages.', 'IM_JABBER_SUBJECT' => 'This is an automated message please do not reply! Message from user %1$s at %2$s.', 'IM_MESSAGE' => 'Your message', - 'IM_MSNM' => 'Please note that you need Windows Live Messenger installed to use this.', - 'IM_MSNM_BROWSER' => 'Your browser does not support this.', - 'IM_MSNM_CONNECT' => 'WLM is not connected.\nYou have to connect to WLM to continue.', 'IM_NAME' => 'Your Name', 'IM_NO_DATA' => 'There is no suitable contact information for this user.', 'IM_NO_JABBER' => 'Sorry, direct messaging of Jabber users is not supported on this board. You will need a Jabber client installed on your system to contact the recipient above.', @@ -123,7 +120,6 @@ $lang = array_merge($lang, array( 'SEND_IM' => 'Instant messaging', 'SEND_JABBER_MESSAGE' => 'Send Jabber message', 'SEND_MESSAGE' => 'Message', - 'SEND_MSNM_MESSAGE' => 'Send WLM message', 'SEND_YIM_MESSAGE' => 'Send YIM message', 'SORT_EMAIL' => 'Email', 'SORT_LAST_ACTIVE' => 'Last active', diff --git a/phpBB/language/en/ucp.php b/phpBB/language/en/ucp.php index 705b07b170..2eb34b3713 100644 --- a/phpBB/language/en/ucp.php +++ b/phpBB/language/en/ucp.php @@ -87,7 +87,7 @@ $lang = array_merge($lang, array( 'ATTACHMENTS_EXPLAIN' => 'This is a list of attachments you have made in posts to this board.', 'ATTACHMENTS_DELETED' => 'Attachments successfully deleted.', 'ATTACHMENT_DELETED' => 'Attachment successfully deleted.', - 'AUTOLOGIN_SESSION_KEYS_DELETED'=> 'The selected persistent login keys were successfully deleted.', + 'AUTOLOGIN_SESSION_KEYS_DELETED'=> 'The selected "Remember Me" login keys were successfully deleted.', 'AVATAR_CATEGORY' => 'Category', 'AVATAR_EXPLAIN' => 'Maximum dimensions; width: %1$s, height: %2$s, file size: %3$.2f KiB.', 'AVATAR_FEATURES_DISABLED' => 'The avatar functionality is currently disabled.', @@ -318,6 +318,7 @@ $lang = array_merge($lang, array( 'NO_AUTH_FORWARD_MESSAGE' => 'You are not authorised to forward private messages.', 'NO_AUTH_GROUP_MESSAGE' => 'You are not authorised to send private messages to groups.', 'NO_AUTH_PASSWORD_REMINDER' => 'You are not authorised to request a new password.', + 'NO_AUTH_PROFILEINFO' => 'You are not authorised to change your profile information.', 'NO_AUTH_READ_HOLD_MESSAGE' => 'You are not authorised to read private messages that are on hold.', 'NO_AUTH_READ_MESSAGE' => 'You are not authorised to read private messages.', 'NO_AUTH_READ_REMOVED_MESSAGE' => 'You are not able to read this message because it was removed by the author.', @@ -380,8 +381,8 @@ $lang = array_merge($lang, array( 'PREFERENCES_UPDATED' => 'Your preferences have been updated.', 'PROFILE_INFO_NOTICE' => 'Please note that this information may be viewable to other members. Be careful when including any personal details. Any fields marked with a * must be completed.', 'PROFILE_UPDATED' => 'Your profile has been updated.', - 'PROFILE_AUTOLOGIN_KEYS' => 'The persistent login keys automatically log you in when you visit the board. If you logout, the persistent login key is deleted only on the computer you are using to logout. Here you can see persistent login keys created on other computers you used to access this site.', - 'PROFILE_NO_AUTOLOGIN_KEYS' => 'There are no saved persistent login keys.', + 'PROFILE_AUTOLOGIN_KEYS' => 'The "Remember Me" login keys automatically log you in when you visit the board. If you logout, the remember me login key is deleted only on the computer you are using to logout. Here you can see remember login keys created on other computers you used to access this site.', + 'PROFILE_NO_AUTOLOGIN_KEYS' => 'There are no saved "Remember Me" login keys.', 'RECIPIENT' => 'Recipient', 'RECIPIENTS' => 'Recipients', @@ -454,7 +455,6 @@ $lang = array_merge($lang, array( 'UCP_MAIN_FRONT' => 'Front page', 'UCP_MAIN_SUBSCRIBED' => 'Manage subscriptions', - 'UCP_MSNM' => 'Windows Live Messenger', 'UCP_NO_ATTACHMENTS' => 'You have posted no files.', 'UCP_PREFS' => 'Board preferences', @@ -476,7 +476,7 @@ $lang = array_merge($lang, array( 'UCP_PROFILE_PROFILE_INFO' => 'Edit profile', 'UCP_PROFILE_REG_DETAILS' => 'Edit account settings', 'UCP_PROFILE_SIGNATURE' => 'Edit signature', - 'UCP_PROFILE_AUTOLOGIN_KEYS'=> 'Edit persistent login keys', + 'UCP_PROFILE_AUTOLOGIN_KEYS'=> 'Edit "Remember Me" login keys', 'UCP_USERGROUPS' => 'Usergroups', 'UCP_USERGROUPS_MEMBER' => 'Edit memberships', diff --git a/phpBB/memberlist.php b/phpBB/memberlist.php index d9ba147c70..091379061c 100644 --- a/phpBB/memberlist.php +++ b/phpBB/memberlist.php @@ -287,13 +287,6 @@ switch ($mode) $s_action = ''; break; - case 'msnm': - $lang = 'MSNM'; - $sql_field = 'user_msnm'; - $s_select = 'S_SEND_MSNM'; - $s_action = ''; - break; - case 'jabber': $lang = 'JABBER'; $sql_field = 'user_jabber'; @@ -640,7 +633,6 @@ switch ($mode) 'WWW_IMG' => $user->img('icon_contact_www', $user->lang['WWW']), 'ICQ_IMG' => $user->img('icon_contact_icq', $user->lang['ICQ']), 'AIM_IMG' => $user->img('icon_contact_aim', $user->lang['AIM']), - 'MSN_IMG' => $user->img('icon_contact_msnm', $user->lang['MSNM']), 'YIM_IMG' => $user->img('icon_contact_yahoo', $user->lang['YIM']), 'JABBER_IMG' => $user->img('icon_contact_jabber', $user->lang['JABBER']), 'SEARCH_IMG' => $user->img('icon_user_search', $user->lang['SEARCH']), @@ -649,7 +641,7 @@ switch ($mode) 'S_GROUP_OPTIONS' => $group_options, 'S_CUSTOM_FIELDS' => (isset($profile_fields['row']) && sizeof($profile_fields['row'])) ? true : false, - 'U_USER_ADMIN' => ($auth->acl_get('a_user')) ? append_sid("{$phpbb_root_path}adm/index.$phpEx", 'i=users&mode=overview&u=' . $user_id, true, $user->session_id) : '', + 'U_USER_ADMIN' => ($auth->acl_get('a_user')) ? append_sid("{$phpbb_admin_path}index.$phpEx", 'i=users&mode=overview&u=' . $user_id, true, $user->session_id) : '', 'U_USER_BAN' => ($auth->acl_get('m_ban') && $user_id != $user->data['user_id']) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=ban&mode=user&u=' . $user_id, true, $user->session_id) : '', 'U_MCP_QUEUE' => ($auth->acl_getf_global('m_approve')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue', true, $user->session_id) : '', @@ -984,8 +976,8 @@ switch ($mode) $template_html = 'memberlist_body.html'; // Sorting - $sort_key_text = array('a' => $user->lang['SORT_USERNAME'], 'b' => $user->lang['SORT_LOCATION'], 'c' => $user->lang['SORT_JOINED'], 'd' => $user->lang['SORT_POST_COUNT'], 'f' => $user->lang['WEBSITE'], 'g' => $user->lang['ICQ'], 'h' => $user->lang['AIM'], 'i' => $user->lang['MSNM'], 'j' => $user->lang['YIM'], 'k' => $user->lang['JABBER']); - $sort_key_sql = array('a' => 'u.username_clean', 'b' => 'u.user_from', 'c' => 'u.user_regdate', 'd' => 'u.user_posts', 'f' => 'u.user_website', 'g' => 'u.user_icq', 'h' => 'u.user_aim', 'i' => 'u.user_msnm', 'j' => 'u.user_yim', 'k' => 'u.user_jabber'); + $sort_key_text = array('a' => $user->lang['SORT_USERNAME'], 'b' => $user->lang['SORT_LOCATION'], 'c' => $user->lang['SORT_JOINED'], 'd' => $user->lang['SORT_POST_COUNT'], 'f' => $user->lang['WEBSITE'], 'g' => $user->lang['ICQ'], 'h' => $user->lang['AIM'], 'j' => $user->lang['YIM'], 'k' => $user->lang['JABBER']); + $sort_key_sql = array('a' => 'u.username_clean', 'b' => 'u.user_from', 'c' => 'u.user_regdate', 'd' => 'u.user_posts', 'f' => 'u.user_website', 'g' => 'u.user_icq', 'h' => 'u.user_aim', 'j' => 'u.user_yim', 'k' => 'u.user_jabber'); if ($auth->acl_get('a_user')) { @@ -1028,7 +1020,7 @@ switch ($mode) $select_single = request_var('select_single', false); // Search URL parameters, if any of these are in the URL we do a search - $search_params = array('username', 'email', 'icq', 'aim', 'yahoo', 'msn', 'jabber', 'search_group_id', 'joined_select', 'active_select', 'count_select', 'joined', 'active', 'count', 'ip'); + $search_params = array('username', 'email', 'icq', 'aim', 'yahoo', 'jabber', 'search_group_id', 'joined_select', 'active_select', 'count_select', 'joined', 'active', 'count', 'ip'); // We validate form and field here, only id/class allowed $form = (!preg_match('/^[a-z0-9_-]+$/i', $form)) ? '' : $form; @@ -1040,7 +1032,6 @@ switch ($mode) $icq = request_var('icq', ''); $aim = request_var('aim', ''); $yahoo = request_var('yahoo', ''); - $msn = request_var('msn', ''); $jabber = request_var('jabber', ''); $search_group_id = request_var('search_group_id', 0); @@ -1084,7 +1075,6 @@ switch ($mode) $sql_where .= ($icq) ? ' AND u.user_icq ' . $db->sql_like_expression(str_replace('*', $db->any_char, $icq)) . ' ' : ''; $sql_where .= ($aim) ? ' AND u.user_aim ' . $db->sql_like_expression(str_replace('*', $db->any_char, $aim)) . ' ' : ''; $sql_where .= ($yahoo) ? ' AND u.user_yim ' . $db->sql_like_expression(str_replace('*', $db->any_char, $yahoo)) . ' ' : ''; - $sql_where .= ($msn) ? ' AND u.user_msnm ' . $db->sql_like_expression(str_replace('*', $db->any_char, $msn)) . ' ' : ''; $sql_where .= ($jabber) ? ' AND u.user_jabber ' . $db->sql_like_expression(str_replace('*', $db->any_char, $jabber)) . ' ' : ''; $sql_where .= (is_numeric($count) && isset($find_key_match[$count_select])) ? ' AND u.user_posts ' . $find_key_match[$count_select] . ' ' . (int) $count . ' ' : ''; @@ -1317,7 +1307,6 @@ switch ($mode) 'icq' => array('icq', ''), 'aim' => array('aim', ''), 'yahoo' => array('yahoo', ''), - 'msn' => array('msn', ''), 'jabber' => array('jabber', ''), 'search_group_id' => array('search_group_id', 0), 'joined_select' => array('joined_select', 'lt'), @@ -1449,7 +1438,6 @@ switch ($mode) 'ICQ' => $icq, 'AIM' => $aim, 'YAHOO' => $yahoo, - 'MSNM' => $msn, 'JABBER' => $jabber, 'JOINED' => implode('-', $joined), 'ACTIVE' => implode('-', $active), @@ -1605,7 +1593,6 @@ switch ($mode) 'WWW_IMG' => $user->img('icon_contact_www', $user->lang['WWW']), 'ICQ_IMG' => $user->img('icon_contact_icq', $user->lang['ICQ']), 'AIM_IMG' => $user->img('icon_contact_aim', $user->lang['AIM']), - 'MSN_IMG' => $user->img('icon_contact_msnm', $user->lang['MSNM']), 'YIM_IMG' => $user->img('icon_contact_yahoo', $user->lang['YIM']), 'JABBER_IMG' => $user->img('icon_contact_jabber', $user->lang['JABBER']), 'SEARCH_IMG' => $user->img('icon_user_search', $user->lang['SEARCH']), @@ -1621,7 +1608,6 @@ switch ($mode) 'U_SORT_LOCATION' => $sort_url . '&sk=b&sd=' . (($sort_key == 'b' && $sort_dir == 'a') ? 'd' : 'a'), 'U_SORT_ICQ' => $sort_url . '&sk=g&sd=' . (($sort_key == 'g' && $sort_dir == 'a') ? 'd' : 'a'), 'U_SORT_AIM' => $sort_url . '&sk=h&sd=' . (($sort_key == 'h' && $sort_dir == 'a') ? 'd' : 'a'), - 'U_SORT_MSN' => $sort_url . '&sk=i&sd=' . (($sort_key == 'i' && $sort_dir == 'a') ? 'd' : 'a'), 'U_SORT_YIM' => $sort_url . '&sk=j&sd=' . (($sort_key == 'j' && $sort_dir == 'a') ? 'd' : 'a'), 'U_SORT_ACTIVE' => ($auth->acl_get('u_viewonline')) ? $sort_url . '&sk=l&sd=' . (($sort_key == 'l' && $sort_dir == 'a') ? 'd' : 'a') : '', 'U_SORT_RANK' => $sort_url . '&sk=m&sd=' . (($sort_key == 'm' && $sort_dir == 'a') ? 'd' : 'a'), @@ -1748,14 +1734,12 @@ function show_profile($data, $user_notes_enabled = false, $warn_user_enabled = f 'U_ICQ' => ($data['user_icq']) ? 'http://www.icq.com/people/' . urlencode($data['user_icq']) . '/' : '', 'U_AIM' => ($data['user_aim'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contact&action=aim&u=' . $user_id) : '', 'U_YIM' => ($data['user_yim']) ? 'http://edit.yahoo.com/config/send_webmesg?.target=' . urlencode($data['user_yim']) . '&.src=pg' : '', - 'U_MSN' => ($data['user_msnm'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contact&action=msnm&u=' . $user_id) : '', 'U_JABBER' => ($data['user_jabber'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contact&action=jabber&u=' . $user_id) : '', 'LOCATION' => ($data['user_from']) ? $data['user_from'] : '', 'USER_ICQ' => $data['user_icq'], 'USER_AIM' => $data['user_aim'], 'USER_YIM' => $data['user_yim'], - 'USER_MSN' => $data['user_msnm'], 'USER_JABBER' => $data['user_jabber'], 'USER_JABBER_IMG' => ($data['user_jabber']) ? $user->img('icon_contact_jabber', $data['user_jabber']) : '', diff --git a/phpBB/posting.php b/phpBB/posting.php index 2d3cb9ab44..d32f7e33d9 100644 --- a/phpBB/posting.php +++ b/phpBB/posting.php @@ -1116,8 +1116,9 @@ if ($submit || $preview || $refresh) $captcha->reset(); } - // Check the permissions for post approval. Moderators are not affected. - if ((!$auth->acl_get('f_noapprove', $data['forum_id']) && !$auth->acl_get('m_approve', $data['forum_id']) && empty($data['force_approved_state'])) || (isset($data['force_approved_state']) && !$data['force_approved_state'])) + // Check the permissions for post approval. + // Moderators must go through post approval like ordinary users. + if ((!$auth->acl_get('f_noapprove', $data['forum_id']) && empty($data['force_approved_state'])) || (isset($data['force_approved_state']) && !$data['force_approved_state'])) { meta_refresh(10, $redirect_url); $message = ($mode == 'edit') ? $user->lang['POST_EDITED_MOD'] : $user->lang['POST_STORED_MOD']; diff --git a/phpBB/report.php b/phpBB/report.php index d792b8df6a..be38bad2f3 100644 --- a/phpBB/report.php +++ b/phpBB/report.php @@ -71,11 +71,14 @@ if ($post_id) trigger_error('POST_NOT_EXIST'); } - $forum_id = (int) $report_data['forum_id']; - $topic_id = (int) $report_data['topic_id']; - $reported_post_text = $report_data['post_text']; - $reported_post_bitfield = $report_data['bbcode_bitfield']; - $reported_post_uid = $report_data['bbcode_uid']; + $forum_id = (int) $report_data['forum_id']; + $topic_id = (int) $report_data['topic_id']; + $reported_post_text = $report_data['post_text']; + $reported_post_bitfield = $report_data['bbcode_bitfield']; + $reported_post_uid = $report_data['bbcode_uid']; + $reported_post_enable_bbcode = $report_data['enable_bbcode']; + $reported_post_enable_smilies = $report_data['enable_smilies']; + $reported_post_enable_magic_url = $report_data['enable_magic_url']; $sql = 'SELECT * FROM ' . FORUMS_TABLE . ' @@ -134,9 +137,11 @@ else trigger_error($message); } - $reported_post_text = $report_data['message_text']; - $reported_post_bitfield = $report_data['bbcode_bitfield']; - $reported_post_uid = $report_data['bbcode_uid']; + $reported_post_text = $report_data['message_text']; + $reported_post_bitfield = $report_data['bbcode_bitfield']; + $reported_post_enable_bbcode = $report_data['reported_post_enable_bbcode']; + $reported_post_enable_smilies = $report_data['reported_post_enable_smilies']; + $reported_post_enable_magic_url = $report_data['reported_post_enable_magic_url']; } // Submit report? @@ -155,17 +160,20 @@ if ($submit && $reason_id) } $sql_ary = array( - 'reason_id' => (int) $reason_id, - 'post_id' => $post_id, - 'pm_id' => $pm_id, - 'user_id' => (int) $user->data['user_id'], - 'user_notify' => (int) $user_notify, - 'report_closed' => 0, - 'report_time' => (int) time(), - 'report_text' => (string) $report_text, - 'reported_post_text' => $reported_post_text, - 'reported_post_uid' => $reported_post_uid, - 'reported_post_bitfield'=> $reported_post_bitfield, + 'reason_id' => (int) $reason_id, + 'post_id' => $post_id, + 'pm_id' => $pm_id, + 'user_id' => (int) $user->data['user_id'], + 'user_notify' => (int) $user_notify, + 'report_closed' => 0, + 'report_time' => (int) time(), + 'report_text' => (string) $report_text, + 'reported_post_text' => $reported_post_text, + 'reported_post_uid' => $reported_post_uid, + 'reported_post_bitfield' => $reported_post_bitfield, + 'reported_post_enable_bbcode' => $reported_post_enable_bbcode, + 'reported_post_enable_smilies' => $reported_post_enable_smilies, + 'reported_post_enable_magic_url' => $reported_post_enable_magic_url, ); $sql = 'INSERT INTO ' . REPORTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); diff --git a/phpBB/styles/prosilver/template/ajax.js b/phpBB/styles/prosilver/template/ajax.js index fa31d3268f..8583fb565c 100644 --- a/phpBB/styles/prosilver/template/ajax.js +++ b/phpBB/styles/prosilver/template/ajax.js @@ -2,17 +2,103 @@ "use strict"; +/** +* Close popup alert after a specified delay +* +* @param int Delay in ms until darkenwrapper's click event is triggered +*/ +phpbb.closeDarkenWrapper = function(delay) { + setTimeout(function() { + $('#darkenwrapper').trigger('click'); + }, delay); +}; + +// This callback will mark all forum icons read +phpbb.addAjaxCallback('mark_forums_read', function(res) { + var readTitle = res.NO_UNREAD_POSTS; + var unreadTitle = res.UNREAD_POSTS; + var iconsArray = { + 'forum_unread': 'forum_read', + 'forum_unread_subforum': 'forum_read_subforum', + 'forum_unread_locked': 'forum_read_locked' + }; + + $('li.row').find('dl[class*="forum_unread"]').each(function() { + var $this = $(this); + + $.each(iconsArray, function(unreadClass, readClass) { + if ($this.hasClass(unreadClass)) { + $this.removeClass(unreadClass).addClass(readClass); + } + }); + $this.children('dt[title="' + unreadTitle + '"]').attr('title', readTitle); + }); + + // Mark subforums read + $('a.subforum[class*="unread"]').removeClass('unread').addClass('read'); + + // Update mark forums read links + $('[data-ajax="mark_forums_read"]').attr('href', res.U_MARK_FORUMS); + + phpbb.closeDarkenWrapper(3000); +}); + +// This callback will mark all topic icons read +phpbb.addAjaxCallback('mark_topics_read', function(res) { + var readTitle = res.NO_UNREAD_POSTS; + var unreadTitle = res.UNREAD_POSTS; + var iconsArray = { + 'global_unread': 'global_read', + 'announce_unread': 'announce_read', + 'sticky_unread': 'sticky_read', + 'topic_unread': 'topic_read' + }; + var iconsState = ['', '_hot', '_hot_mine', '_locked', '_locked_mine', '_mine']; + var unreadClassSelectors = ''; + var classMap = {}; + var classNames = []; + + $.each(iconsArray, function(unreadClass, readClass) { + $.each(iconsState, function(key, value) { + // Only topics can be hot + if ((value == '_hot' || value == '_hot_mine') && unreadClass != 'topic_unread') { + return true; + } + classMap[unreadClass + value] = readClass + value; + classNames.push(unreadClass + value); + }); + }); + + unreadClassSelectors = '.' + classNames.join(',.'); + + $('li.row').find(unreadClassSelectors).each(function() { + var $this = $(this); + $.each(classMap, function(unreadClass, readClass) { + if ($this.hasClass(unreadClass)) { + $this.removeClass(unreadClass).addClass(readClass); + } + }); + $this.children('dt[title="' + unreadTitle + '"]').attr('title', readTitle); + }); + + // Remove link to first unread post + $('a').has('span.icon_topic_newest').remove(); + + // Update mark topics read links + $('[data-ajax="mark_topics_read"]').attr('href', res.U_MARK_TOPICS); + + phpbb.closeDarkenWrapper(3000); +}); + // This callback finds the post from the delete link, and removes it. -phpbb.add_ajax_callback('post_delete', function() { +phpbb.addAjaxCallback('post_delete', function() { var el = $(this), - post_id; - - if (el.attr('data-refresh') === undefined) - { - post_id = el[0].href.split('&p=')[1]; - var post = el.parents('#p' + post_id).css('pointer-events', 'none'); - if (post.hasClass('bg1') || post.hasClass('bg2')) - { + postId; + + if (el.attr('data-refresh') === undefined) { + postId = el[0].href.split('&p=')[1]; + var post = el.parents('#p' + postId).css('pointer-events', 'none'); + if (post.hasClass('bg1') || post.hasClass('bg2')) { var posts1 = post.nextAll('.bg1'); post.nextAll('.bg2').removeClass('bg2').addClass('bg1'); posts1.removeClass('bg1').addClass('bg2'); @@ -24,7 +110,7 @@ phpbb.add_ajax_callback('post_delete', function() { }); // This callback removes the approve / disapprove div or link. -phpbb.add_ajax_callback('post_approve', function(res) { +phpbb.addAjaxCallback('post_approve', function(res) { var remove = (res.approved) ? $(this) : $(this).parents('.post'); $(remove).css('pointer-events', 'none').fadeOut(function() { $(this).remove(); @@ -32,12 +118,12 @@ phpbb.add_ajax_callback('post_approve', function(res) { }); // This removes the parent row of the link or form that fired the callback. -phpbb.add_ajax_callback('row_delete', function() { +phpbb.addAjaxCallback('row_delete', function() { $(this).parents('tr').remove(); }); // This handles friend / foe additions removals. -phpbb.add_ajax_callback('zebra', function(res) { +phpbb.addAjaxCallback('zebra', function(res) { var zebra; if (res.success) { @@ -54,8 +140,7 @@ $('[data-ajax]').each(function() { ajax = $this.attr('data-ajax'), fn; - if (ajax !== 'false') - { + if (ajax !== 'false') { fn = (ajax !== 'true') ? ajax : null; phpbb.ajaxify({ selector: this, @@ -89,12 +174,9 @@ phpbb.ajaxify({ filter: function (data) { var action = $('#quick-mod-select').val(); - if (action === 'make_normal') - { + if (action === 'make_normal') { return $(this).find('select option[value="make_global"]').length > 0; - } - else if (action === 'lock' || action === 'unlock') - { + } else if (action === 'lock' || action === 'unlock') { return true; } diff --git a/phpBB/styles/prosilver/template/forumlist_body.html b/phpBB/styles/prosilver/template/forumlist_body.html index 8762cb0c2e..539ed047c9 100644 --- a/phpBB/styles/prosilver/template/forumlist_body.html +++ b/phpBB/styles/prosilver/template/forumlist_body.html @@ -51,6 +51,7 @@ <!-- IF forumrow.U_UNAPPROVED_TOPICS --><a href="{forumrow.U_UNAPPROVED_TOPICS}">{UNAPPROVED_IMG}</a><!-- ENDIF --> <!-- IF forumrow.LAST_POST_TIME --><dfn>{L_LAST_POST}</dfn> <!-- IF forumrow.S_DISPLAY_SUBJECT --> + <!-- EVENT forumlist_body_last_post_title_prepend --> <a href="{forumrow.U_LAST_POST}" title="{forumrow.LAST_POST_SUBJECT}" class="lastsubject">{forumrow.LAST_POST_SUBJECT_TRUNCATED}</a> <br /> <!-- ENDIF --> {L_POST_BY_AUTHOR} {forumrow.LAST_POSTER_FULL} diff --git a/phpBB/styles/prosilver/template/index_body.html b/phpBB/styles/prosilver/template/index_body.html index 6babbf5997..57ad540a4a 100644 --- a/phpBB/styles/prosilver/template/index_body.html +++ b/phpBB/styles/prosilver/template/index_body.html @@ -8,7 +8,7 @@ <!-- IF S_DISPLAY_SEARCH --> <li><a href="{U_SEARCH_UNANSWERED}">{L_SEARCH_UNANSWERED}</a><!-- IF S_LOAD_UNREADS --> • <a href="{U_SEARCH_UNREAD}">{L_SEARCH_UNREAD}</a><!-- ENDIF --><!-- IF S_USER_LOGGED_IN --> • <a href="{U_SEARCH_NEW}">{L_SEARCH_NEW}</a><!-- ENDIF --> • <a href="{U_SEARCH_ACTIVE_TOPICS}">{L_SEARCH_ACTIVE_TOPICS}</a></li> <!-- ENDIF --> - <!-- IF not S_IS_BOT and U_MARK_FORUMS --><li class="rightside"><a href="{U_MARK_FORUMS}" accesskey="m" data-ajax="true">{L_MARK_FORUMS_READ}</a></li><!-- ENDIF --> + <!-- IF not S_IS_BOT and U_MARK_FORUMS --><li class="rightside"><a href="{U_MARK_FORUMS}" accesskey="m" data-ajax="mark_forums_read" data-overlay="false">{L_MARK_FORUMS_READ}</a></li><!-- ENDIF --> </ul> <!-- ENDIF --> @@ -29,6 +29,8 @@ </form> <!-- ENDIF --> +<!-- EVENT index_body_stat_blocks_before --> + <!-- IF S_DISPLAY_ONLINE_LIST --> <!-- IF U_VIEWONLINE --><h3><a href="{U_VIEWONLINE}">{L_WHO_IS_ONLINE}</a></h3><!-- ELSE --><h3>{L_WHO_IS_ONLINE}</h3><!-- ENDIF --> <p>{TOTAL_USERS_ONLINE} ({L_ONLINE_EXPLAIN})<br />{RECORD_USERS}<br /> <br />{LOGGED_IN_USER_LIST} diff --git a/phpBB/styles/prosilver/template/jumpbox.html b/phpBB/styles/prosilver/template/jumpbox.html index 0060e83b15..dd793fbadc 100644 --- a/phpBB/styles/prosilver/template/jumpbox.html +++ b/phpBB/styles/prosilver/template/jumpbox.html @@ -1,22 +1,23 @@ <!-- IF S_VIEWTOPIC --> - <p></p><p><a href="{U_VIEW_FORUM}" class="left-box {S_CONTENT_FLOW_BEGIN}" accesskey="r">{L_RETURN_TO} {FORUM_NAME}</a></p> + <p></p><p><a href="{U_VIEW_FORUM}" class="left-box arrow-{S_CONTENT_FLOW_BEGIN}" accesskey="r">{L_RETURN_TO} {FORUM_NAME}</a></p> <!-- ELSEIF S_VIEWFORUM --> - <p></p><p><a href="{U_INDEX}" class="left-box {S_CONTENT_FLOW_BEGIN}" accesskey="r">{L_RETURN_TO} {L_INDEX}</a></p> + <p></p><p><a href="{U_INDEX}" class="left-box arrow-{S_CONTENT_FLOW_BEGIN}" accesskey="r">{L_RETURN_TO} {L_INDEX}</a></p> <!-- ELSEIF SEARCH_TOPIC --> - <p></p><p><a class="left-box {S_CONTENT_FLOW_BEGIN}" href="{U_SEARCH_TOPIC}" accesskey="r">{L_RETURN_TO}{L_COLON} {SEARCH_TOPIC}</a></p> + <p></p><p><a class="left-box arrow-{S_CONTENT_FLOW_BEGIN}" href="{U_SEARCH_TOPIC}" accesskey="r">{L_RETURN_TO}{L_COLON} {SEARCH_TOPIC}</a></p> <!-- ELSEIF S_SEARCH_ACTION --> - <p></p><p><a class="left-box {S_CONTENT_FLOW_BEGIN}" href="{U_SEARCH}" title="{L_SEARCH_ADV}" accesskey="r">{L_RETURN_TO_SEARCH_ADV}</a></p> + <p></p><p><a class="left-box arrow-{S_CONTENT_FLOW_BEGIN}" href="{U_SEARCH}" title="{L_SEARCH_ADV}" accesskey="r">{L_RETURN_TO_SEARCH_ADV}</a></p> <!-- ENDIF --> <!-- IF S_DISPLAY_JUMPBOX --> - <form method="post" id="jumpbox" action="{S_JUMPBOX_ACTION}" onsubmit="if(this.f.value == -1){return false;}"> + <form method="get" id="jumpbox" action="{S_JUMPBOX_ACTION}" onsubmit="if(this.f.value == -1){return false;}"> <!-- IF $CUSTOM_FIELDSET_CLASS --> <fieldset class="{$CUSTOM_FIELDSET_CLASS}"> <!-- ELSE --> <fieldset class="jumpbox"> <!-- ENDIF --> + {HIDDEN_FIELDS_FOR_JUMPBOX} <label for="f" accesskey="j"><!-- IF S_IN_MCP and S_MERGE_SELECT -->{L_SELECT_TOPICS_FROM}<!-- ELSEIF S_IN_MCP -->{L_MODERATE_FORUM}<!-- ELSE -->{L_JUMP_TO}<!-- ENDIF -->{L_COLON}</label> <select name="f" id="f" onchange="if(this.options[this.selectedIndex].value != -1){ document.forms['jumpbox'].submit() }"> <!-- BEGIN jumpbox_forums --> diff --git a/phpBB/styles/prosilver/template/mcp_forum.html b/phpBB/styles/prosilver/template/mcp_forum.html index cd4ae69fe7..e559f178f2 100644 --- a/phpBB/styles/prosilver/template/mcp_forum.html +++ b/phpBB/styles/prosilver/template/mcp_forum.html @@ -80,8 +80,8 @@ <!-- ENDIF --> <fieldset class="display-options"> - <!-- IF NEXT_PAGE --><a href="{NEXT_PAGE}" class="right-box {S_CONTENT_FLOW_END}">{L_NEXT}</a><!-- ENDIF --> - <!-- IF PREVIOUS_PAGE --><a href="{PREVIOUS_PAGE}" class="left-box {S_CONTENT_FLOW_BEGIN}">{L_PREVIOUS}</a><!-- ENDIF --> + <!-- IF NEXT_PAGE --><a href="{NEXT_PAGE}" class="right-box arrow-{S_CONTENT_FLOW_END}">{L_NEXT}</a><!-- ENDIF --> + <!-- IF PREVIOUS_PAGE --><a href="{PREVIOUS_PAGE}" class="left-box arrow-{S_CONTENT_FLOW_BEGIN}">{L_PREVIOUS}</a><!-- ENDIF --> <label>{L_DISPLAY_TOPICS}{L_COLON} {S_SELECT_SORT_DAYS}</label> <label>{L_SORT_BY} {S_SELECT_SORT_KEY}</label> <label>{S_SELECT_SORT_DIR} <input type="submit" name="sort" value="{L_GO}" class="button2" /></label> diff --git a/phpBB/styles/prosilver/template/mcp_logs.html b/phpBB/styles/prosilver/template/mcp_logs.html index 15974802bc..9e4a6f272e 100644 --- a/phpBB/styles/prosilver/template/mcp_logs.html +++ b/phpBB/styles/prosilver/template/mcp_logs.html @@ -54,8 +54,8 @@ <!-- IF .log --> <fieldset class="display-options"> - <!-- IF NEXT_PAGE --><a href="{NEXT_PAGE}" class="right-box {S_CONTENT_FLOW_END}">{L_NEXT}</a><!-- ENDIF --> - <!-- IF PREVIOUS_PAGE --><a href="{PREVIOUS_PAGE}" class="left-box {S_CONTENT_FLOW_BEGIN}">{L_PREVIOUS}</a><!-- ENDIF --> + <!-- IF NEXT_PAGE --><a href="{NEXT_PAGE}" class="right-box arrow-{S_CONTENT_FLOW_END}">{L_NEXT}</a><!-- ENDIF --> + <!-- IF PREVIOUS_PAGE --><a href="{PREVIOUS_PAGE}" class="left-box arrow-{S_CONTENT_FLOW_BEGIN}">{L_PREVIOUS}</a><!-- ENDIF --> <label>{L_DISPLAY_POSTS}{L_COLON} {S_SELECT_SORT_DAYS}</label> <label>{L_SORT_BY} {S_SELECT_SORT_KEY}</label> <label>{S_SELECT_SORT_DIR}</label> diff --git a/phpBB/styles/prosilver/template/mcp_notes_user.html b/phpBB/styles/prosilver/template/mcp_notes_user.html index c7c568657c..3bbbd10f12 100644 --- a/phpBB/styles/prosilver/template/mcp_notes_user.html +++ b/phpBB/styles/prosilver/template/mcp_notes_user.html @@ -95,8 +95,8 @@ <hr /> <fieldset class="display-options"> - <!-- IF NEXT_PAGE --><a href="{NEXT_PAGE}" class="right-box {S_CONTENT_FLOW_END}">{L_NEXT}</a><!-- ENDIF --> - <!-- IF PREVIOUS_PAGE --><a href="{PREVIOUS_PAGE}" class="left-box {S_CONTENT_FLOW_BEGIN}">{L_PREVIOUS}</a><!-- ENDIF --> + <!-- IF NEXT_PAGE --><a href="{NEXT_PAGE}" class="right-box arrow-{S_CONTENT_FLOW_END}">{L_NEXT}</a><!-- ENDIF --> + <!-- IF PREVIOUS_PAGE --><a href="{PREVIOUS_PAGE}" class="left-box arrow-{S_CONTENT_FLOW_BEGIN}">{L_PREVIOUS}</a><!-- ENDIF --> <label>{L_DISPLAY_LOG}{L_COLON} {S_SELECT_SORT_DAYS}</label> <label>{L_SORT_BY} {S_SELECT_SORT_KEY}</label><label>{S_SELECT_SORT_DIR}</label> <input type="submit" name="sort" value="{L_GO}" class="button2" /> diff --git a/phpBB/styles/prosilver/template/mcp_queue.html b/phpBB/styles/prosilver/template/mcp_queue.html index dc8869713d..847151a01e 100644 --- a/phpBB/styles/prosilver/template/mcp_queue.html +++ b/phpBB/styles/prosilver/template/mcp_queue.html @@ -65,8 +65,8 @@ </ul> <fieldset class="display-options"> - <!-- IF NEXT_PAGE --><a href="{NEXT_PAGE}" class="right-box {S_CONTENT_FLOW_END}">{L_NEXT}</a><!-- ENDIF --> - <!-- IF PREVIOUS_PAGE --><a href="{PREVIOUS_PAGE}" class="left-box {S_CONTENT_FLOW_BEGIN}">{L_PREVIOUS}</a><!-- ENDIF --> + <!-- IF NEXT_PAGE --><a href="{NEXT_PAGE}" class="right-box arrow-{S_CONTENT_FLOW_END}">{L_NEXT}</a><!-- ENDIF --> + <!-- IF PREVIOUS_PAGE --><a href="{PREVIOUS_PAGE}" class="left-box arrow-{S_CONTENT_FLOW_BEGIN}">{L_PREVIOUS}</a><!-- ENDIF --> <label>{L_DISPLAY_POSTS}{L_COLON} {S_SELECT_SORT_DAYS}</label> <label>{L_SORT_BY} {S_SELECT_SORT_KEY}</label><label>{S_SELECT_SORT_DIR}</label> <!-- IF TOPIC_ID --><label><input type="checkbox" class="radio" name="t" value="{TOPIC_ID}" checked="checked" /> <strong>{L_ONLY_TOPIC}</strong></label><!-- ENDIF --> diff --git a/phpBB/styles/prosilver/template/mcp_reports.html b/phpBB/styles/prosilver/template/mcp_reports.html index f9a0ec4bd6..ea9a4edd6f 100644 --- a/phpBB/styles/prosilver/template/mcp_reports.html +++ b/phpBB/styles/prosilver/template/mcp_reports.html @@ -68,8 +68,8 @@ </ul> <fieldset class="display-options"> - <!-- IF NEXT_PAGE --><a href="{NEXT_PAGE}" class="right-box {S_CONTENT_FLOW_END}">{L_NEXT}</a><!-- ENDIF --> - <!-- IF PREVIOUS_PAGE --><a href="{PREVIOUS_PAGE}" class="left-box {S_CONTENT_FLOW_BEGIN}">{L_PREVIOUS}</a><!-- ENDIF --> + <!-- IF NEXT_PAGE --><a href="{NEXT_PAGE}" class="right-box arrow-{S_CONTENT_FLOW_END}">{L_NEXT}</a><!-- ENDIF --> + <!-- IF PREVIOUS_PAGE --><a href="{PREVIOUS_PAGE}" class="left-box arrow-{S_CONTENT_FLOW_BEGIN}">{L_PREVIOUS}</a><!-- ENDIF --> <label>{L_DISPLAY_POSTS}{L_COLON} {S_SELECT_SORT_DAYS}</label> <label>{L_SORT_BY} {S_SELECT_SORT_KEY}</label><label>{S_SELECT_SORT_DIR}</label> <!-- IF TOPIC_ID --><label><input type="checkbox" class="radio" name="t" value="{TOPIC_ID}" checked="checked" /> <strong>{L_ONLY_TOPIC}</strong></label><!-- ENDIF --> diff --git a/phpBB/styles/prosilver/template/mcp_whois.html b/phpBB/styles/prosilver/template/mcp_whois.html index 88d3269a71..41a825458d 100644 --- a/phpBB/styles/prosilver/template/mcp_whois.html +++ b/phpBB/styles/prosilver/template/mcp_whois.html @@ -4,11 +4,11 @@ <div class="panel"> <div class="inner"> - <p><a class="{S_CONTENT_FLOW_BEGIN}" href="{U_RETURN_POST}">{L_RETURN_POST}</a></p> + <p><a class="arrow-{S_CONTENT_FLOW_BEGIN}" href="{U_RETURN_POST}">{L_RETURN_POST}</a></p> <div class="postbody"><div class="content"> <pre>{WHOIS}</pre> </div></div> - <p><a class="{S_CONTENT_FLOW_BEGIN}" href="{U_RETURN_POST}">{L_RETURN_POST}</a></p> + <p><a class="arrow-{S_CONTENT_FLOW_BEGIN}" href="{U_RETURN_POST}">{L_RETURN_POST}</a></p> </div> </div> diff --git a/phpBB/styles/prosilver/template/memberlist_body.html b/phpBB/styles/prosilver/template/memberlist_body.html index 273182ec3f..4ba0c5cb2a 100644 --- a/phpBB/styles/prosilver/template/memberlist_body.html +++ b/phpBB/styles/prosilver/template/memberlist_body.html @@ -143,8 +143,8 @@ <!-- IF S_IN_SEARCH_POPUP and not S_SEARCH_USER --> <fieldset class="display-options"> - <!-- IF PREVIOUS_PAGE --><a href="{PREVIOUS_PAGE}" class="left-box {S_CONTENT_FLOW_BEGIN}">{L_PREVIOUS}</a><!-- ENDIF --> - <!-- IF NEXT_PAGE --><a href="{NEXT_PAGE}" class="right-box {S_CONTENT_FLOW_END}">{L_NEXT}</a><!-- ENDIF --> + <!-- IF PREVIOUS_PAGE --><a href="{PREVIOUS_PAGE}" class="left-box arrow-{S_CONTENT_FLOW_BEGIN}">{L_PREVIOUS}</a><!-- ENDIF --> + <!-- IF NEXT_PAGE --><a href="{NEXT_PAGE}" class="right-box arrow-{S_CONTENT_FLOW_END}">{L_NEXT}</a><!-- ENDIF --> <label for="sk">{L_SELECT_SORT_METHOD}{L_COLON} <select name="sk" id="sk">{S_MODE_SELECT}</select></label> <label for="sd">{L_ORDER} <select name="sd" id="sd">{S_ORDER_SELECT}</select> <input type="submit" name="sort" value="{L_SUBMIT}" class="button2" /></label> </fieldset> diff --git a/phpBB/styles/prosilver/template/memberlist_im.html b/phpBB/styles/prosilver/template/memberlist_im.html index 68aed0b3dd..61b4a1469b 100644 --- a/phpBB/styles/prosilver/template/memberlist_im.html +++ b/phpBB/styles/prosilver/template/memberlist_im.html @@ -1,6 +1,5 @@ <!-- INCLUDE simple_header.html --> -<!-- MSNM info from http://www.cdolive.net/ - doesn't seem to work with MSN Messenger --> <h2 class="solo">{L_SEND_IM}</h2> <form method="post" action="{S_IM_ACTION}"> @@ -13,7 +12,7 @@ <fieldset> <dl class="fields2"> <dt><label>{L_IM_RECIPIENT}{L_COLON}</label></dt> - <dd><strong>{USERNAME}</strong><!-- IF S_SEND_ICQ or S_SEND_AIM or S_SEND_MSNM or S_NO_SEND_JABBER --> [ {IM_CONTACT} ]<!-- ENDIF --><!-- IF PRESENCE_IMG --> {PRESENCE_IMG}<!-- ENDIF --></dd> + <dd><strong>{USERNAME}</strong><!-- IF S_SEND_ICQ or S_SEND_AIM or S_NO_SEND_JABBER --> [ {IM_CONTACT} ]<!-- ENDIF --><!-- IF PRESENCE_IMG --> {PRESENCE_IMG}<!-- ENDIF --></dd> </dl> <!-- IF S_SEND_ICQ --> @@ -43,15 +42,6 @@ </dl> <!-- ENDIF --> - <!-- IF S_SEND_MSNM --> - <dl class="fields2"> - <dt> </dt> - <dd><object classid="clsid:B69003B3-C55E-4B48-836C-BC5946FC3B28" codetype="application/x-oleobject" id="objMessengerApp" width="0" height="0"></object></dd> - <dd><a href="#" onclick="add_contact('{A_IM_CONTACT}'); return false;">{L_IM_ADD_CONTACT}</a></dd> - <dd><a href="#" onclick="im_contact('{A_IM_CONTACT}'); return false;">{L_IM_SEND_MESSAGE}</a></dd> - </dl> - <!-- ENDIF --> - <!-- IF S_SEND_JABBER --> <dl class="fields2"> <dt><label for="message">{L_IM_MESSAGE}{L_COLON}</label></dt> @@ -85,74 +75,4 @@ <a href="#" onclick="window.close(); return false;">{L_CLOSE_WINDOW}</a> -<script type="text/javascript"> -// <![CDATA[ - - /** The following will not work with Windows Vista **/ - - var app = document.getElementById('objMessengerApp'); - - /** - * Check whether the browser supports this and whether MSNM is connected - */ - function msn_supported() - { - // Does the browser support the MSNM object? - if (app.MyStatus) - { - // Is MSNM connected? - if (app.MyStatus == 1) - { - alert('{LA_IM_MSNM_CONNECT}'); - return false; - } - } - else - { - alert('{LA_IM_MSNM_BROWSER}'); - return false; - } - return true; - } - - /** - * Add to your contact list - */ - function add_contact(address) - { - if (msn_supported()) - { - // Could return an error while MSNM is connecting, don't want that - try - { - app.AddContact(0, address); - } - catch (e) - { - return; - } - } -} - -/** -* Write IM to contact -*/ -function im_contact(address) -{ - if (msn_supported()) - { - // Could return an error while MSNM is connecting, don't want that - try - { - app.InstantMessage(address); - } - catch (e) - { - return; - } - } -} -// ]]> -</script> - <!-- INCLUDE simple_footer.html --> diff --git a/phpBB/styles/prosilver/template/memberlist_search.html b/phpBB/styles/prosilver/template/memberlist_search.html index 6fed528cea..1ef8710817 100644 --- a/phpBB/styles/prosilver/template/memberlist_search.html +++ b/phpBB/styles/prosilver/template/memberlist_search.html @@ -71,10 +71,6 @@ function insert_single(user) <dt><label for="yahoo">{L_YIM}{L_COLON}</label></dt> <dd><input type="text" name="yahoo" id="yahoo" value="{YAHOO}" class="inputbox" /></dd> </dl> - <dl> - <dt><label for="msn">{L_MSNM}{L_COLON}</label></dt> - <dd><input type="text" name="msn" id="msn" value="{MSNM}" class="inputbox" /></dd> - </dl> </fieldset> <fieldset class="fields1 column2"> diff --git a/phpBB/styles/prosilver/template/memberlist_view.html b/phpBB/styles/prosilver/template/memberlist_view.html index 57cfcb86d9..7f33e70e8f 100644 --- a/phpBB/styles/prosilver/template/memberlist_view.html +++ b/phpBB/styles/prosilver/template/memberlist_view.html @@ -62,7 +62,6 @@ <!-- IF U_EMAIL --><dt>{L_EMAIL_ADDRESS}{L_COLON}</dt> <dd><a href="{U_EMAIL}">{L_SEND_EMAIL_USER} {USERNAME}</a></dd><!-- ENDIF --> <!-- IF U_WWW --><dt>{L_WEBSITE}{L_COLON}</dt> <dd><a href="{U_WWW}" title="{L_VISIT_WEBSITE}{L_COLON} {U_WWW}">{U_WWW}</a></dd><!-- ENDIF --> <!-- IF U_PM --><dt>{L_PM}{L_COLON}</dt> <dd><a href="{U_PM}">{L_SEND_PRIVATE_MESSAGE}</a></dd><!-- ENDIF --> - <!-- IF U_MSN or USER_MSN --><dt>{L_MSNM}{L_COLON}</dt> <dd><!-- IF U_MSN --><a href="{U_MSN}" onclick="popup(this.href, 550, 320); return false;">{L_SEND_MSNM_MESSAGE}</a><!-- ELSE -->{USER_MSN}<!-- ENDIF --></dd><!-- ENDIF --> <!-- IF U_YIM or USER_YIM --><dt>{L_YIM}{L_COLON}</dt> <dd><!-- IF U_YIM --><a href="{U_YIM}" onclick="popup(this.href, 780, 550); return false;">{L_SEND_YIM_MESSAGE}</a><!-- ELSE -->{USER_YIM}<!-- ENDIF --></dd><!-- ENDIF --> <!-- IF U_AIM or USER_AIM --><dt>{L_AIM}{L_COLON}</dt> <dd><!-- IF U_AIM --><a href="{U_AIM}" onclick="popup(this.href, 550, 320); return false;">{L_SEND_AIM_MESSAGE}</a><!-- ELSE -->{USER_AIM}<!-- ENDIF --></dd><!-- ENDIF --> <!-- IF U_ICQ or USER_ICQ --><dt>{L_ICQ}{L_COLON}</dt> <dd><!-- IF U_ICQ --><a href="{U_ICQ}" onclick="popup(this.href, 550, 320); return false;">{L_SEND_ICQ_MESSAGE}</a><!-- ELSE -->{USER_ICQ}<!-- ENDIF --></dd><!-- ENDIF --> diff --git a/phpBB/styles/prosilver/template/message_body.html b/phpBB/styles/prosilver/template/message_body.html index fb6dfce35f..a844246055 100644 --- a/phpBB/styles/prosilver/template/message_body.html +++ b/phpBB/styles/prosilver/template/message_body.html @@ -8,7 +8,7 @@ <div class="inner"> <h2>{MESSAGE_TITLE}</h2> <p>{MESSAGE_TEXT}</p> - <!-- IF SCRIPT_NAME == "search" and not S_BOARD_DISABLED and not S_NO_SEARCH and L_RETURN_TO_SEARCH_ADV --><p><a href="{U_SEARCH}" class="{S_CONTENT_FLOW_BEGIN}">{L_RETURN_TO_SEARCH_ADV}</a></p><!-- ENDIF --> + <!-- IF SCRIPT_NAME == "search" and not S_BOARD_DISABLED and not S_NO_SEARCH and L_RETURN_TO_SEARCH_ADV --><p><a href="{U_SEARCH}" class="arrow-{S_CONTENT_FLOW_BEGIN}">{L_RETURN_TO_SEARCH_ADV}</a></p><!-- ENDIF --> </div> </div> diff --git a/phpBB/styles/prosilver/template/overall_footer.html b/phpBB/styles/prosilver/template/overall_footer.html index 7e43ff2d0a..322d745501 100644 --- a/phpBB/styles/prosilver/template/overall_footer.html +++ b/phpBB/styles/prosilver/template/overall_footer.html @@ -6,7 +6,8 @@ <div class="inner"> <ul class="linklist"> - <li class="icon-home"><!-- IF U_SITE_HOME --><a href="{U_SITE_HOME}">{L_SITE_HOME}</a> <strong>‹</strong> <!-- ENDIF --><a href="{U_INDEX}" accesskey="h">{L_INDEX}</a></li> + <li class="icon-home"><!-- IF U_SITE_HOME --><a href="{U_SITE_HOME}">{L_SITE_HOME}</a> <strong>‹</strong> <!-- ENDIF --><a href="{U_INDEX}" accesskey="h">{L_INDEX}</a> + <!-- EVENT overall_footer_breadcrumb_append --></li> <!-- IF not S_IS_BOT --> <!-- IF U_WATCH_FORUM_LINK --><li <!-- IF S_WATCHING_FORUM -->class="icon-unsubscribe"<!-- ELSE -->class="icon-subscribe"<!-- ENDIF -->><a href="{U_WATCH_FORUM_LINK}" title="{S_WATCH_FORUM_TITLE}" data-ajax="toggle_link" data-toggle-class="icon-<!-- IF not S_WATCHING_FORUM -->unsubscribe<!-- ELSE -->subscribe<!-- ENDIF -->" data-toggle-text="{S_WATCH_FORUM_TOGGLE}" data-toggle-url="{U_WATCH_FORUM_TOGGLE}">{S_WATCH_FORUM_TITLE}</a></li><!-- ENDIF --> <!-- IF U_WATCH_TOPIC --><li <!-- IF S_WATCHING_TOPIC -->class="icon-unsubscribe"<!-- ELSE -->class="icon-subscribe"<!-- ENDIF -->><a href="{U_WATCH_TOPIC}" title="{S_WATCH_TOPIC_TITLE}" data-ajax="toggle_link" data-toggle-class="<!-- IF not S_WATCHING_TOPIC -->icon-unsubscribe<!-- ELSE -->icon-subscribe<!-- ENDIF -->" data-toggle-text="{S_WATCH_TOPIC_TOGGLE}" data-toggle-url="{U_WATCH_TOPIC_TOGGLE}">{S_WATCH_TOPIC_TITLE}</a></li><!-- ENDIF --> @@ -19,8 +20,11 @@ </div> </div> - <div class="copyright">{CREDIT_LINE} + <div class="copyright"> + <!-- EVENT overall_footer_copyright_prepend --> + {CREDIT_LINE} <!-- IF TRANSLATION_INFO --><br />{TRANSLATION_INFO}<!-- ENDIF --> + <!-- EVENT overall_footer_copyright_append --> <!-- IF DEBUG_OUTPUT --><br />{DEBUG_OUTPUT}<!-- ENDIF --> <!-- IF U_ACP --><br /><strong><a href="{U_ACP}">{L_ACP}</a></strong><!-- ENDIF --> </div> @@ -55,5 +59,6 @@ <!-- INCLUDEJS template/ajax.js --> {SCRIPTS} +<!-- EVENT overall_footer_after --> </body> </html> diff --git a/phpBB/styles/prosilver/template/overall_header.html b/phpBB/styles/prosilver/template/overall_header.html index 79a8b07971..97dbc76e43 100644 --- a/phpBB/styles/prosilver/template/overall_header.html +++ b/phpBB/styles/prosilver/template/overall_header.html @@ -84,8 +84,9 @@ <link href="{T_THEME_PATH}/tweaks.css?assets_version={T_ASSETS_VERSION}" rel="stylesheet" type="text/css" media="screen, projection" /> <![endif]--> -</head> +<!-- EVENT overall_header_head_append --> +</head> <body id="phpbb" class="section-{SCRIPT_NAME} {S_CONTENT_DIRECTION}"> <div id="wrap"> @@ -120,7 +121,12 @@ <div class="inner"> <ul class="linklist navlinks"> - <li class="icon-home"><!-- IF U_SITE_HOME --><a href="{U_SITE_HOME}">{L_SITE_HOME}</a> <strong>‹</strong> <!-- ENDIF --><a href="{U_INDEX}" accesskey="h">{L_INDEX}</a> <!-- BEGIN navlinks --> <strong>‹</strong> <a href="{navlinks.U_VIEW_FORUM}">{navlinks.FORUM_NAME}</a><!-- END navlinks --></li> + <!-- DEFINE $MICRODATA = ' itemtype="http://data-vocabulary.org/Breadcrumb" itemscope=""' --> + <li class="icon-home"><!-- IF U_SITE_HOME --><a href="{U_SITE_HOME}"{$MICRODATA}>{L_SITE_HOME}</a> <strong>‹</strong> <!-- ENDIF --> + <a href="{U_INDEX}" accesskey="h"{$MICRODATA}>{L_INDEX}</a> + <!-- BEGIN navlinks --> <strong>‹</strong> <a href="{navlinks.U_VIEW_FORUM}"{$MICRODATA}>{navlinks.FORUM_NAME}</a><!-- END navlinks --> + <!-- EVENT overall_header_breadcrumb_append --> + </li> <!-- IF U_EMAIL_TOPIC --><li class="rightside"><a href="{U_EMAIL_TOPIC}" title="{L_EMAIL_TOPIC}" class="sendemail">{L_EMAIL_TOPIC}</a></li><!-- ENDIF --> <!-- IF U_EMAIL_PM --><li class="rightside"><a href="{U_EMAIL_PM}" title="{L_EMAIL_PM}" class="sendemail">{L_EMAIL_PM}</a></li><!-- ENDIF --> @@ -144,12 +150,14 @@ <!-- ENDIF --> <ul class="linklist rightside"> + <!-- EVENT overall_header_navigation_prepend --> <li class="icon-faq"><a href="{U_FAQ}" title="{L_FAQ_EXPLAIN}">{L_FAQ}</a></li> <!-- IF not S_IS_BOT --> <!-- IF S_DISPLAY_MEMBERLIST --><li class="icon-members"><a href="{U_MEMBERLIST}" title="{L_MEMBERLIST_EXPLAIN}">{L_MEMBERLIST}</a></li><!-- ENDIF --> <!-- IF not S_USER_LOGGED_IN and S_REGISTER_ENABLED and not (S_SHOW_COPPA or S_REGISTRATION) --><li class="icon-register"><a href="{U_REGISTER}">{L_REGISTER}</a></li><!-- ENDIF --> <li class="icon-logout"><a href="{U_LOGIN_LOGOUT}" title="{L_LOGIN_LOGOUT}" accesskey="x">{L_LOGIN_LOGOUT}</a></li> <!-- ENDIF --> + <!-- EVENT overall_header_navigation_append --> </ul> </div> diff --git a/phpBB/styles/prosilver/template/posting_editor.html b/phpBB/styles/prosilver/template/posting_editor.html index c206cc3181..8156968098 100644 --- a/phpBB/styles/prosilver/template/posting_editor.html +++ b/phpBB/styles/prosilver/template/posting_editor.html @@ -165,7 +165,7 @@ <dt><label for="comment_list_{attach_row.ASSOC_INDEX}">{L_FILE_COMMENT}{L_COLON}</label></dt> <dd><textarea name="comment_list[{attach_row.ASSOC_INDEX}]" id="comment_list_{attach_row.ASSOC_INDEX}" rows="1" cols="35" class="inputbox">{attach_row.FILE_COMMENT}</textarea></dd> - <dd><a href="{attach_row.U_VIEW_ATTACHMENT}" class="{S_CONTENT_FLOW_END}">{attach_row.FILENAME}</a></dd> + <dd><a href="{attach_row.U_VIEW_ATTACHMENT}">{attach_row.FILENAME}</a></dd> <dd style="margin-top: 5px;"> <!-- IF S_INLINE_ATTACHMENT_OPTIONS --><input type="button" value="{L_PLACE_INLINE}" onclick="attach_inline({attach_row.ASSOC_INDEX}, '{attach_row.A_FILENAME}');" class="button2" /> <!-- ENDIF --> <input type="submit" name="delete_file[{attach_row.ASSOC_INDEX}]" value="{L_DELETE_FILE}" class="button2" /> @@ -213,6 +213,7 @@ <div class="inner"> <fieldset class="fields1"> + <!-- EVENT posting_editor_options_prepend --> <!-- IF S_BBCODE_ALLOWED --> <div><label for="disable_bbcode"><input type="checkbox" name="disable_bbcode" id="disable_bbcode"{S_BBCODE_CHECKED} /> {L_DISABLE_BBCODE}</label></div> <!-- ENDIF --> diff --git a/phpBB/styles/prosilver/template/search_results.html b/phpBB/styles/prosilver/template/search_results.html index 136ca991b1..62b7c61eb3 100644 --- a/phpBB/styles/prosilver/template/search_results.html +++ b/phpBB/styles/prosilver/template/search_results.html @@ -6,9 +6,9 @@ <!-- IF PHRASE_SEARCH_DISABLED --> <p><strong>{L_PHRASE_SEARCH_DISABLED}</strong></p><!-- ENDIF --> <!-- IF SEARCH_TOPIC --> - <p><a class="{S_CONTENT_FLOW_BEGIN}" href="{U_SEARCH_TOPIC}">{L_RETURN_TO}{L_COLON} {SEARCH_TOPIC}</a></p> + <p><a class="arrow-{S_CONTENT_FLOW_BEGIN}" href="{U_SEARCH_TOPIC}">{L_RETURN_TO}{L_COLON} {SEARCH_TOPIC}</a></p> <!-- ELSE --> - <p><a class="{S_CONTENT_FLOW_BEGIN}" href="{U_SEARCH}" title="{L_SEARCH_ADV}">{L_RETURN_TO_SEARCH_ADV}</a></p> + <p><a class="arrow-{S_CONTENT_FLOW_BEGIN}" href="{U_SEARCH}" title="{L_SEARCH_ADV}">{L_RETURN_TO_SEARCH_ADV}</a></p> <!-- ENDIF --> <!-- IF .pagination or SEARCH_MATCHES or PAGE_NUMBER --> @@ -131,7 +131,7 @@ <!-- IF not searchresults.S_IGNORE_POST --> <ul class="searchresults"> - <li ><a href="{searchresults.U_VIEW_POST}" class="{S_CONTENT_FLOW_END}">{L_JUMP_TO_POST}</a></li> + <li ><a href="{searchresults.U_VIEW_POST}" class="arrow-{S_CONTENT_FLOW_END}">{L_JUMP_TO_POST}</a></li> </ul> <!-- ENDIF --> @@ -150,8 +150,8 @@ <form method="post" action="{S_SEARCH_ACTION}"> <fieldset class="display-options"> - <!-- IF PREVIOUS_PAGE --><a href="{PREVIOUS_PAGE}" class="left-box {S_CONTENT_FLOW_BEGIN}">{L_PREVIOUS}</a><!-- ENDIF --> - <!-- IF NEXT_PAGE --><a href="{NEXT_PAGE}" class="right-box {S_CONTENT_FLOW_END}">{L_NEXT}</a><!-- ENDIF --> + <!-- IF PREVIOUS_PAGE --><a href="{PREVIOUS_PAGE}" class="left-box arrow-{S_CONTENT_FLOW_BEGIN}">{L_PREVIOUS}</a><!-- ENDIF --> + <!-- IF NEXT_PAGE --><a href="{NEXT_PAGE}" class="right-box arrow-{S_CONTENT_FLOW_END}">{L_NEXT}</a><!-- ENDIF --> <!-- IF S_SELECT_SORT_DAYS or S_SELECT_SORT_KEY --> <label><!-- IF S_SHOW_TOPICS -->{L_DISPLAY_POSTS}<!-- ELSE -->{L_SORT_BY}</label><label><!-- ENDIF --> {S_SELECT_SORT_DAYS}<!-- IF S_SELECT_SORT_KEY --></label> <label>{S_SELECT_SORT_KEY}</label> <label>{S_SELECT_SORT_DIR}<!-- ENDIF --> <input type="submit" name="sort" value="{L_GO}" class="button2" /></label> diff --git a/phpBB/styles/prosilver/template/simple_footer.html b/phpBB/styles/prosilver/template/simple_footer.html index 897e50ced7..ec189304fc 100644 --- a/phpBB/styles/prosilver/template/simple_footer.html +++ b/phpBB/styles/prosilver/template/simple_footer.html @@ -10,5 +10,6 @@ <!-- IF S_JQUERY_FALLBACK --><script type="text/javascript">window.jQuery || document.write(unescape('%3Cscript src="{T_ASSETS_PATH}/javascript/jquery.js?assets_version={T_ASSETS_VERSION}" type="text/javascript"%3E%3C/script%3E'));</script><!-- ENDIF --> {SCRIPTS} +<!-- EVENT simple_footer_after --> </body> </html> diff --git a/phpBB/styles/prosilver/template/timezone.js b/phpBB/styles/prosilver/template/timezone.js index da0a2b0bfd..af8206d12d 100644 --- a/phpBB/styles/prosilver/template/timezone.js +++ b/phpBB/styles/prosilver/template/timezone.js @@ -1,19 +1,19 @@ (function($) { // Avoid conflicts with other libraries $('#tz_date').change(function() { - phpbb.timezone_switch_date(false); + phpbb.timezoneSwitchDate(false); }); $('#tz_select_date_suggest').click(function(){ - phpbb.timezone_preselect_select(true); + phpbb.timezonePreselectSelect(true); }); $(document).ready( - phpbb.timezone_enable_date_selection + phpbb.timezoneEnableDateSelection ); $(document).ready( - phpbb.timezone_preselect_select($('#tz_select_date_suggest').attr('data-is-registration') == 'true') + phpbb.timezonePreselectSelect($('#tz_select_date_suggest').attr('data-is-registration') == 'true') ); })(jQuery); // Avoid conflicts with other libraries diff --git a/phpBB/styles/prosilver/template/ucp_attachments.html b/phpBB/styles/prosilver/template/ucp_attachments.html index 8c93547388..478b14ab86 100644 --- a/phpBB/styles/prosilver/template/ucp_attachments.html +++ b/phpBB/styles/prosilver/template/ucp_attachments.html @@ -47,8 +47,8 @@ </ul> <fieldset class="display-options"> - <!-- IF NEXT_PAGE --><a href="{NEXT_PAGE}" class="right-box {S_CONTENT_FLOW_END}">{L_NEXT}</a><!-- ENDIF --> - <!-- IF PREVIOUS_PAGE --><a href="{PREVIOUS_PAGE}" class="left-box {S_CONTENT_FLOW_BEGIN}">{L_PREVIOUS}</a><!-- ENDIF --> + <!-- IF NEXT_PAGE --><a href="{NEXT_PAGE}" class="right-box arrow-{S_CONTENT_FLOW_END}">{L_NEXT}</a><!-- ENDIF --> + <!-- IF PREVIOUS_PAGE --><a href="{PREVIOUS_PAGE}" class="left-box arrow-{S_CONTENT_FLOW_BEGIN}">{L_PREVIOUS}</a><!-- ENDIF --> <label for="sk">{L_SORT_BY}{L_COLON} <select name="sk" id="sk">{S_SORT_OPTIONS}</select></label> <label><select name="sd" id="sd">{S_ORDER_SELECT}</select></label> <input class="button2" type="submit" name="sort" value="{L_SORT}" /> diff --git a/phpBB/styles/prosilver/template/ucp_pm_message_header.html b/phpBB/styles/prosilver/template/ucp_pm_message_header.html index f03b7c2c86..4d48782c10 100644 --- a/phpBB/styles/prosilver/template/ucp_pm_message_header.html +++ b/phpBB/styles/prosilver/template/ucp_pm_message_header.html @@ -18,7 +18,7 @@ <!-- IF TOTAL_MESSAGES or S_VIEW_MESSAGE --> <ul class="linklist"> <li class="rightside pagination"> - <!-- IF S_VIEW_MESSAGE --><a class="{S_CONTENT_FLOW_BEGIN}" href="{U_CURRENT_FOLDER}">{L_RETURN_TO} {CUR_FOLDER_NAME}</a><!-- ENDIF --> + <!-- IF S_VIEW_MESSAGE --><a class="arrow-{S_CONTENT_FLOW_BEGIN}" href="{U_CURRENT_FOLDER}">{L_RETURN_TO} {CUR_FOLDER_NAME}</a><!-- ENDIF --> <!-- IF FOLDER_CUR_MESSAGES neq 0 --> <!-- IF TOTAL_MESSAGES -->{TOTAL_MESSAGES} • <!-- ENDIF --> <!-- IF .pagination --> diff --git a/phpBB/styles/prosilver/template/ucp_pm_viewfolder.html b/phpBB/styles/prosilver/template/ucp_pm_viewfolder.html index cb373dc5b6..96668284eb 100644 --- a/phpBB/styles/prosilver/template/ucp_pm_viewfolder.html +++ b/phpBB/styles/prosilver/template/ucp_pm_viewfolder.html @@ -119,8 +119,8 @@ <!-- IF FOLDER_CUR_MESSAGES neq 0 --> <fieldset class="display-options"> - <!-- IF PREVIOUS_PAGE --><a href="{PREVIOUS_PAGE}" class="left-box {S_CONTENT_FLOW_BEGIN}">{L_PREVIOUS}</a><!-- ENDIF --> - <!-- IF NEXT_PAGE --><a href="{NEXT_PAGE}" class="right-box {S_CONTENT_FLOW_END}">{L_NEXT}</a><!-- ENDIF --> + <!-- IF PREVIOUS_PAGE --><a href="{PREVIOUS_PAGE}" class="left-box arrow-{S_CONTENT_FLOW_BEGIN}">{L_PREVIOUS}</a><!-- ENDIF --> + <!-- IF NEXT_PAGE --><a href="{NEXT_PAGE}" class="right-box arrow-{S_CONTENT_FLOW_END}">{L_NEXT}</a><!-- ENDIF --> <label>{L_DISPLAY}{L_COLON} {S_SELECT_SORT_DAYS}</label> <label>{L_SORT_BY} {S_SELECT_SORT_KEY}</label> <label>{S_SELECT_SORT_DIR} <input type="submit" name="sort" value="{L_GO}" class="button2" /></label> diff --git a/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html b/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html index c456be1090..23665aa252 100644 --- a/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html +++ b/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html @@ -8,8 +8,8 @@ <!-- IF S_DISPLAY_HISTORY and (U_VIEW_PREVIOUS_HISTORY or U_VIEW_NEXT_HISTORY) --> <fieldset class="display-options clearfix"> - <!-- IF U_VIEW_PREVIOUS_HISTORY --><a href="{U_VIEW_PREVIOUS_HISTORY}" class="left-box {S_CONTENT_FLOW_BEGIN}">{L_VIEW_PREVIOUS_HISTORY}</a><!-- ENDIF --> - <!-- IF U_VIEW_NEXT_HISTORY --><a href="{U_VIEW_NEXT_HISTORY}" class="right-box {S_CONTENT_FLOW_END}">{L_VIEW_NEXT_HISTORY}</a><!-- ENDIF --> + <!-- IF U_VIEW_PREVIOUS_HISTORY --><a href="{U_VIEW_PREVIOUS_HISTORY}" class="left-box arrow-{S_CONTENT_FLOW_BEGIN}">{L_VIEW_PREVIOUS_HISTORY}</a><!-- ENDIF --> + <!-- IF U_VIEW_NEXT_HISTORY --><a href="{U_VIEW_NEXT_HISTORY}" class="right-box arrow-{S_CONTENT_FLOW_END}">{L_VIEW_NEXT_HISTORY}</a><!-- ENDIF --> </fieldset> <!-- ENDIF --> @@ -90,13 +90,12 @@ <!-- END custom_fields --> - <!-- IF U_PM or U_EMAIL or U_WWW or U_MSN or U_ICQ or U_YIM or U_AIM or U_JABBER --> + <!-- IF U_PM or U_EMAIL or U_WWW or U_ICQ or U_YIM or U_AIM or U_JABBER --> <dd> <ul class="profile-icons"> <!-- IF U_PM --><li class="pm-icon"><a href="{U_PM}" title="{L_PRIVATE_MESSAGE}"><span>{L_PRIVATE_MESSAGE}</span></a></li><!-- ENDIF --> <!-- IF U_EMAIL --><li class="email-icon"><a href="{U_EMAIL}" title="{L_SEND_EMAIL_USER} {MESSAGE_AUTHOR}"><span>{L_SEND_EMAIL_USER} {MESSAGE_AUTHOR}</span></a></li><!-- ENDIF --> <!-- IF U_WWW --><li class="web-icon"><a href="{U_WWW}" title="{L_VISIT_WEBSITE}{L_COLON} {U_WWW}"><span>{L_WEBSITE}</span></a></li><!-- ENDIF --> - <!-- IF U_MSN --><li class="msnm-icon"><a href="{U_MSN}" onclick="popup(this.href, 550, 320); return false;" title="{L_MSNM}"><span>{L_MSNM}</span></a></li><!-- ENDIF --> <!-- IF U_ICQ --><li class="icq-icon"><a href="{U_ICQ}" onclick="popup(this.href, 550, 320); return false;" title="{L_ICQ}"><span>{L_ICQ}</span></a></li><!-- ENDIF --> <!-- IF U_YIM --><li class="yahoo-icon"><a href="{U_YIM}" onclick="popup(this.href, 780, 550); return false;" title="{L_YIM}"><span>{L_YIM}</span></a></li><!-- ENDIF --> <!-- IF U_AIM --><li class="aim-icon"><a href="{U_AIM}" onclick="popup(this.href, 550, 320); return false;" title="{L_AIM}"><span>{L_AIM}</span></a></li><!-- ENDIF --> @@ -113,8 +112,8 @@ <!-- IF S_VIEW_MESSAGE --> <fieldset class="display-options"> - <!-- IF U_PREVIOUS_PM --><a href="{U_PREVIOUS_PM}" class="left-box {S_CONTENT_FLOW_BEGIN}">{L_VIEW_PREVIOUS_PM}</a><!-- ENDIF --> - <!-- IF U_NEXT_PM --><a href="{U_NEXT_PM}" class="right-box {S_CONTENT_FLOW_END}">{L_VIEW_NEXT_PM}</a><!-- ENDIF --> + <!-- IF U_PREVIOUS_PM --><a href="{U_PREVIOUS_PM}" class="left-box arrow-{S_CONTENT_FLOW_BEGIN}">{L_VIEW_PREVIOUS_PM}</a><!-- ENDIF --> + <!-- IF U_NEXT_PM --><a href="{U_NEXT_PM}" class="right-box arrow-{S_CONTENT_FLOW_END}">{L_VIEW_NEXT_PM}</a><!-- ENDIF --> <!-- IF S_MARK_OPTIONS --><label for="mark_option"><select name="mark_option" id="mark_option">{S_MARK_OPTIONS}</select></label> <input class="button2" type="submit" name="submit_mark" value="{L_GO}" /><!-- ENDIF --> <!-- IF not S_UNREAD and not S_SPECIAL_FOLDER --><label for="dest_folder"><!-- IF S_VIEW_MESSAGE -->{L_MOVE_TO_FOLDER}{L_COLON} <!-- ELSE -->{L_MOVE_MARKED_TO_FOLDER}<!-- ENDIF --> <select name="dest_folder" id="dest_folder">{S_TO_FOLDER_OPTIONS}</select></label> <input class="button2" type="submit" name="move_pm" value="{L_GO}" /><!-- ENDIF --> diff --git a/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html b/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html index a024a170a7..4a8d3da08a 100644 --- a/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html +++ b/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html @@ -9,8 +9,8 @@ <title>{SITENAME} • {PAGE_TITLE}</title> <link href="{T_THEME_PATH}/print.css" rel="stylesheet" type="text/css" /> +<!-- EVENT ucp_pm_viewmessage_print_head_append --> </head> - <body id="phpbb"> <div id="wrap"> <a id="top" accesskey="t"></a> diff --git a/phpBB/styles/prosilver/template/ucp_prefs_personal.html b/phpBB/styles/prosilver/template/ucp_prefs_personal.html index 4382e891fd..50ade02acd 100644 --- a/phpBB/styles/prosilver/template/ucp_prefs_personal.html +++ b/phpBB/styles/prosilver/template/ucp_prefs_personal.html @@ -63,11 +63,13 @@ <label for="popuppm0"><input type="radio" name="popuppm" id="popuppm0" value="0"<!-- IF not S_POPUP_PM --> checked="checked"<!-- ENDIF --> /> {L_NO}</label> </dd> </dl> - <dl> - <dt><label for="lang">{L_BOARD_LANGUAGE}{L_COLON}</label></dt> - <dd><select name="lang" id="lang">{S_LANG_OPTIONS}</select></dd> - </dl> - <!-- IF S_STYLE_OPTIONS --> + <!-- IF S_MORE_LANGUAGES --> + <dl> + <dt><label for="lang">{L_BOARD_LANGUAGE}{L_COLON}</label></dt> + <dd><select name="lang" id="lang">{S_LANG_OPTIONS}</select></dd> + </dl> + <!-- ENDIF --> + <!-- IF S_STYLE_OPTIONS and S_MORE_STYLES --> <dl> <dt><label for="style">{L_BOARD_STYLE}{L_COLON}</label></dt> <dd><select name="style" id="style">{S_STYLE_OPTIONS}</select></dd> diff --git a/phpBB/styles/prosilver/template/ucp_profile_profile_info.html b/phpBB/styles/prosilver/template/ucp_profile_profile_info.html index 03d89e8590..e8c6715de8 100644 --- a/phpBB/styles/prosilver/template/ucp_profile_profile_info.html +++ b/phpBB/styles/prosilver/template/ucp_profile_profile_info.html @@ -19,10 +19,6 @@ <dd><input type="text" name="aim" id="aim" maxlength="255" value="{AIM}" class="inputbox" /></dd> </dl> <dl> - <dt><label for="msn">{L_UCP_MSNM}{L_COLON}</label></dt> - <dd><input type="text" name="msn" id="msn" maxlength="255" value="{MSN}" class="inputbox" /></dd> - </dl> - <dl> <dt><label for="yim">{L_UCP_YIM}{L_COLON}</label></dt> <dd><input type="text" name="yim" id="yim" maxlength="255" value="{YIM}" class="inputbox" /></dd> </dl> diff --git a/phpBB/styles/prosilver/template/ucp_register.html b/phpBB/styles/prosilver/template/ucp_register.html index 47537e9d8b..db95e5ba13 100644 --- a/phpBB/styles/prosilver/template/ucp_register.html +++ b/phpBB/styles/prosilver/template/ucp_register.html @@ -104,7 +104,4 @@ </div> </form> -<script type="text/javascript" src="{T_SUPER_TEMPLATE_PATH}/timezone.js"></script> -<script type="text/javascript">phpbb_preselect_tz_select();</script> - <!-- INCLUDE overall_footer.html --> diff --git a/phpBB/styles/prosilver/template/viewforum_body.html b/phpBB/styles/prosilver/template/viewforum_body.html index 0a818e725b..b47c13d573 100644 --- a/phpBB/styles/prosilver/template/viewforum_body.html +++ b/phpBB/styles/prosilver/template/viewforum_body.html @@ -28,7 +28,7 @@ <!-- IF S_HAS_SUBFORUM --> <!-- IF not S_IS_BOT and U_MARK_FORUMS --> <ul class="linklist"> - <li class="rightside"><a href="{U_MARK_FORUMS}">{L_MARK_SUBFORUMS_READ}</a></li> + <li class="rightside"><a href="{U_MARK_FORUMS}" data-ajax="mark_forums_read" data-overlay="false">{L_MARK_SUBFORUMS_READ}</a></li> </ul> <!-- ENDIF --> <!-- INCLUDE forumlist_body.html --> @@ -57,7 +57,7 @@ <!-- IF .pagination or TOTAL_POSTS or TOTAL_TOPICS --> <div class="pagination"> - <!-- IF not S_IS_BOT and U_MARK_TOPICS --><a href="{U_MARK_TOPICS}" accesskey="m" data-ajax="true">{L_MARK_TOPICS_READ}</a> • <!-- ENDIF --> + <!-- IF not S_IS_BOT and U_MARK_TOPICS --><a href="{U_MARK_TOPICS}" accesskey="m" data-ajax="mark_topics_read" data-overlay="false">{L_MARK_TOPICS_READ}</a> • <!-- ENDIF --> <!-- IF TOTAL_TOPICS -->{TOTAL_TOPICS} • <!-- ENDIF --> <!-- IF .pagination --> <!-- INCLUDE pagination.html --> @@ -189,8 +189,8 @@ <!-- IF S_SELECT_SORT_DAYS and not S_DISPLAY_ACTIVE --> <form method="post" action="{S_FORUM_ACTION}"> <fieldset class="display-options"> - <!-- IF PREVIOUS_PAGE --><a href="{PREVIOUS_PAGE}" class="left-box {S_CONTENT_FLOW_BEGIN}">{L_PREVIOUS}</a><!-- ENDIF --> - <!-- IF NEXT_PAGE --><a href="{NEXT_PAGE}" class="right-box {S_CONTENT_FLOW_END}">{L_NEXT}</a><!-- ENDIF --> + <!-- IF PREVIOUS_PAGE --><a href="{PREVIOUS_PAGE}" class="left-box arrow-{S_CONTENT_FLOW_BEGIN}">{L_PREVIOUS}</a><!-- ENDIF --> + <!-- IF NEXT_PAGE --><a href="{NEXT_PAGE}" class="right-box arrow-{S_CONTENT_FLOW_END}">{L_NEXT}</a><!-- ENDIF --> <!-- IF not S_IS_BOT --> <label>{L_DISPLAY_TOPICS}{L_COLON} {S_SELECT_SORT_DAYS}</label> <label>{L_SORT_BY} {S_SELECT_SORT_KEY}</label> @@ -211,7 +211,7 @@ <!-- IF PAGE_NUMBER or TOTAL_POSTS or TOTAL_TOPICS --> <div class="pagination"> - <!-- IF TOTAL_TOPICS and not S_IS_BOT and U_MARK_TOPICS --><a href="{U_MARK_TOPICS}">{L_MARK_TOPICS_READ}</a> • <!-- ENDIF --> + <!-- IF TOTAL_TOPICS and not S_IS_BOT and U_MARK_TOPICS --><a href="{U_MARK_TOPICS}" data-ajax="mark_topics_read" data-overlay="false">{L_MARK_TOPICS_READ}</a> • <!-- ENDIF --> <!-- IF TOTAL_POSTS and not NEWEST_USER --> {TOTAL_POSTS}<!-- ELSEIF TOTAL_TOPICS and not NEWEST_USER --> {TOTAL_TOPICS} • <!-- ENDIF --> <!-- IF TOTAL_USERS -->{TOTAL_USERS} • <!-- ENDIF --> <!-- IF .pagination --> diff --git a/phpBB/styles/prosilver/template/viewonline_body.html b/phpBB/styles/prosilver/template/viewonline_body.html index 7ae1b6bc58..cb19a40d8f 100644 --- a/phpBB/styles/prosilver/template/viewonline_body.html +++ b/phpBB/styles/prosilver/template/viewonline_body.html @@ -49,7 +49,7 @@ <!-- IF PREVIOUS_PAGE or NEXT_PAGE --> <fieldset class="display-options right-box"> - <!-- IF PREVIOUS_PAGE --><a href="{PREVIOUS_PAGE}" class="{S_CONTENT_FLOW_BEGIN}">{L_PREVIOUS}</a><!-- ELSE -->{L_PREVIOUS}<!-- ENDIF --> • <!-- IF NEXT_PAGE --><a href="{NEXT_PAGE}" class="{S_CONTENT_FLOW_END}">{L_NEXT}</a><!-- ELSE -->{L_NEXT}<!-- ENDIF --> + <!-- IF PREVIOUS_PAGE --><a href="{PREVIOUS_PAGE}" class="arrow-{S_CONTENT_FLOW_BEGIN}">{L_PREVIOUS}</a><!-- ELSE -->{L_PREVIOUS}<!-- ENDIF --> • <!-- IF NEXT_PAGE --><a href="{NEXT_PAGE}" class="arrow-{S_CONTENT_FLOW_END}">{L_NEXT}</a><!-- ELSE -->{L_NEXT}<!-- ENDIF --> </fieldset> <!-- ENDIF --> diff --git a/phpBB/styles/prosilver/template/viewtopic_body.html b/phpBB/styles/prosilver/template/viewtopic_body.html index 9455d10f72..9910be34b0 100644 --- a/phpBB/styles/prosilver/template/viewtopic_body.html +++ b/phpBB/styles/prosilver/template/viewtopic_body.html @@ -1,6 +1,6 @@ <!-- INCLUDE overall_header.html --> <!-- IF U_MCP --><p>[ <a href="{U_MCP}">{L_MCP}</a> ]</p><!-- ENDIF --> -<h2><a href="{U_VIEW_TOPIC}">{TOPIC_TITLE}</a></h2> +<h2><!-- EVENT viewtopic_topic_title_prepend --><a href="{U_VIEW_TOPIC}">{TOPIC_TITLE}</a></h2> <!-- NOTE: remove the style="display: none" when you want to have the forum description on the topic body --> <!-- IF FORUM_DESC --><div style="display: none !important;">{FORUM_DESC}<br /></div><!-- ENDIF --> @@ -216,13 +216,12 @@ <!-- END custom_fields --> <!-- IF not S_IS_BOT --> - <!-- IF postrow.U_PM or postrow.U_EMAIL or postrow.U_WWW or postrow.U_MSN or postrow.U_ICQ or postrow.U_YIM or postrow.U_AIM or postrow.U_JABBER --> + <!-- IF postrow.U_PM or postrow.U_EMAIL or postrow.U_WWW or postrow.U_ICQ or postrow.U_YIM or postrow.U_AIM or postrow.U_JABBER --> <dd> <ul class="profile-icons"> <!-- IF postrow.U_PM --><li class="pm-icon"><a href="{postrow.U_PM}" title="{L_PRIVATE_MESSAGE}"><span>{L_PRIVATE_MESSAGE}</span></a></li><!-- ENDIF --> <!-- IF postrow.U_EMAIL --><li class="email-icon"><a href="{postrow.U_EMAIL}" title="{L_SEND_EMAIL_USER} {postrow.POST_AUTHOR}"><span>{L_SEND_EMAIL_USER} {postrow.POST_AUTHOR}</span></a></li><!-- ENDIF --> <!-- IF postrow.U_WWW --><li class="web-icon"><a href="{postrow.U_WWW}" title="{L_VISIT_WEBSITE}{L_COLON} {postrow.U_WWW}"><span>{L_WEBSITE}</span></a></li><!-- ENDIF --> - <!-- IF postrow.U_MSN --><li class="msnm-icon"><a href="{postrow.U_MSN}" onclick="popup(this.href, 550, 320); return false;" title="{L_MSNM}"><span>{L_MSNM}</span></a></li><!-- ENDIF --> <!-- IF postrow.U_ICQ --><li class="icq-icon"><a href="{postrow.U_ICQ}" onclick="popup(this.href, 550, 320); return false;" title="{L_ICQ}"><span>{L_ICQ}</span></a></li><!-- ENDIF --> <!-- IF postrow.U_YIM --><li class="yahoo-icon"><a href="{postrow.U_YIM}" onclick="popup(this.href, 780, 550); return false;" title="{L_YIM}"><span>{L_YIM}</span></a></li><!-- ENDIF --> <!-- IF postrow.U_AIM --><li class="aim-icon"><a href="{postrow.U_AIM}" onclick="popup(this.href, 550, 320); return false;" title="{L_AIM}"><span>{L_AIM}</span></a></li><!-- ENDIF --> @@ -249,8 +248,8 @@ <form id="viewtopic" method="post" action="{S_TOPIC_ACTION}"> <fieldset class="display-options" style="margin-top: 0; "> - <!-- IF PREVIOUS_PAGE --><a href="{PREVIOUS_PAGE}" class="left-box {S_CONTENT_FLOW_BEGIN}">{L_PREVIOUS}</a><!-- ENDIF --> - <!-- IF NEXT_PAGE --><a href="{NEXT_PAGE}" class="right-box {S_CONTENT_FLOW_END}">{L_NEXT}</a><!-- ENDIF --> + <!-- IF PREVIOUS_PAGE --><a href="{PREVIOUS_PAGE}" class="left-box arrow-{S_CONTENT_FLOW_BEGIN}">{L_PREVIOUS}</a><!-- ENDIF --> + <!-- IF NEXT_PAGE --><a href="{NEXT_PAGE}" class="right-box arrow-{S_CONTENT_FLOW_END}">{L_NEXT}</a><!-- ENDIF --> <!-- IF not S_IS_BOT --> <label>{L_DISPLAY_POSTS}{L_COLON} {S_SELECT_SORT_DAYS}</label> <label>{L_SORT_BY} {S_SELECT_SORT_KEY}</label> <label>{S_SELECT_SORT_DIR} <input type="submit" name="sort" value="{L_GO}" class="button2" /></label> diff --git a/phpBB/styles/prosilver/template/viewtopic_print.html b/phpBB/styles/prosilver/template/viewtopic_print.html index 54676279d2..fd0b2dc3e6 100644 --- a/phpBB/styles/prosilver/template/viewtopic_print.html +++ b/phpBB/styles/prosilver/template/viewtopic_print.html @@ -9,8 +9,8 @@ <title>{SITENAME} • {PAGE_TITLE}</title> <link href="{T_THEME_PATH}/print.css" rel="stylesheet" type="text/css" /> +<!-- EVENT viewtopic_print_head_append --> </head> - <body id="phpbb"> <div id="wrap"> <a id="top" accesskey="t"></a> diff --git a/phpBB/styles/prosilver/theme/bidi.css b/phpBB/styles/prosilver/theme/bidi.css index 5cff0a811b..a43323d879 100644 --- a/phpBB/styles/prosilver/theme/bidi.css +++ b/phpBB/styles/prosilver/theme/bidi.css @@ -786,7 +786,7 @@ padding-right: 11px; padding-left: 0; } -.rtl .imageset.icon_contact_aim, .rtl .imageset.icon_contact_email, .rtl .imageset.icon_contact_icq, .rtl .imageset.icon_contact_jabber, .rtl .imageset.icon_contact_msnm, .rtl .imageset.icon_contact_www, .rtl .imageset.icon_contact_yahoo, .rtl .imageset.icon_post_delete, .rtl .imageset.icon_post_info, .rtl .imageset.icon_post_report, .rtl .imageset.icon_user_warn { +.rtl .imageset.icon_contact_aim, .rtl .imageset.icon_contact_email, .rtl .imageset.icon_contact_icq, .rtl .imageset.icon_contact_jabber, .rtl .imageset.icon_contact_www, .rtl .imageset.icon_contact_yahoo, .rtl .imageset.icon_post_delete, .rtl .imageset.icon_post_info, .rtl .imageset.icon_post_report, .rtl .imageset.icon_user_warn { padding-right: 20px; padding-left: 0; } diff --git a/phpBB/styles/prosilver/theme/buttons.css b/phpBB/styles/prosilver/theme/buttons.css index 543d9d8183..4c147dbc3f 100644 --- a/phpBB/styles/prosilver/theme/buttons.css +++ b/phpBB/styles/prosilver/theme/buttons.css @@ -156,7 +156,6 @@ ul.profile-icons li a:hover { background: none; } .aim-icon, .aim-icon a { background: none top left no-repeat; } .yahoo-icon, .yahoo-icon a { background: none top left no-repeat; } .web-icon, .web-icon a { background: none top left no-repeat; } -.msnm-icon, .msnm-icon a { background: none top left no-repeat; } .icq-icon, .icq-icon a { background: none top left no-repeat; } .jabber-icon, .jabber-icon a { background: none top left no-repeat; } .pm-icon, .pm-icon a { background: none top left no-repeat; } @@ -174,7 +173,6 @@ ul.profile-icons li.email-icon { width: 20px; height: 20px; } ul.profile-icons li.aim-icon { width: 20px; height: 20px; } ul.profile-icons li.yahoo-icon { width: 20px; height: 20px; } ul.profile-icons li.web-icon { width: 20px; height: 20px; } -ul.profile-icons li.msnm-icon { width: 20px; height: 20px; } ul.profile-icons li.icq-icon { width: 20px; height: 20px; } ul.profile-icons li.jabber-icon { width: 20px; height: 20px; } ul.profile-icons li.pm-icon { width: 28px; height: 20px; } diff --git a/phpBB/styles/prosilver/theme/colours.css b/phpBB/styles/prosilver/theme/colours.css index 0a8e011171..c8f41ae81a 100644 --- a/phpBB/styles/prosilver/theme/colours.css +++ b/phpBB/styles/prosilver/theme/colours.css @@ -331,20 +331,20 @@ a.top2 { } /* Arrow links */ -a.up { background-image: url("./images/arrow_up.gif") } -a.down { background-image: url("./images/arrow_down.gif") } -a.left { background-image: url("./images/arrow_left.gif") } -a.right { background-image: url("./images/arrow_right.gif") } +a.arrow-up { background-image: url("./images/arrow_up.gif") } +a.arrow-down { background-image: url("./images/arrow_down.gif") } +a.arrow-left { background-image: url("./images/arrow_left.gif") } +a.arrow-right { background-image: url("./images/arrow_right.gif") } -a.up:hover { +a.arrow-up:hover { background-color: transparent; } -a.left:hover { +a.arrow-left:hover { color: #368AD2; } -a.right:hover { +a.arrow-right:hover { color: #368AD2; } @@ -678,7 +678,6 @@ a.sendemail { .aim-icon, .aim-icon a { background-image: url("./images/icon_contact_aim.gif"); } .yahoo-icon, .yahoo-icon a { background-image: url("./images/icon_contact_yahoo.gif"); } .web-icon, .web-icon a { background-image: url("./images/icon_contact_www.gif"); } -.msnm-icon, .msnm-icon a { background-image: url("./images/icon_contact_msnm.gif"); } .icq-icon, .icq-icon a { background-image: url("./images/icon_contact_icq.gif"); } .jabber-icon, .jabber-icon a { background-image: url("./images/icon_contact_jabber.gif"); } .pm-icon, .pm-icon a { background-image: url("./en/icon_contact_pm.gif"); } diff --git a/phpBB/styles/prosilver/theme/imageset.css b/phpBB/styles/prosilver/theme/imageset.css index cb99e9e715..a85e320f98 100644 --- a/phpBB/styles/prosilver/theme/imageset.css +++ b/phpBB/styles/prosilver/theme/imageset.css @@ -280,11 +280,6 @@ span.imageset { padding-left: 20px; padding-top: 20px; } -.imageset.icon_contact_msnm { - background-image: url("./images/icon_contact_msnm.gif"); - padding-left: 20px; - padding-top: 20px; -} .imageset.icon_contact_www { background-image: url("./images/icon_contact_www.gif"); padding-left: 20px; diff --git a/phpBB/styles/prosilver/theme/links.css b/phpBB/styles/prosilver/theme/links.css index 66c3aed03e..5dc8a13313 100644 --- a/phpBB/styles/prosilver/theme/links.css +++ b/phpBB/styles/prosilver/theme/links.css @@ -145,44 +145,44 @@ a.top2 { } /* Arrow links */ -a.up { background: none no-repeat left center; } -a.down { background: none no-repeat right center; } -a.left { background: none no-repeat 3px 60%; } -a.right { background: none no-repeat 95% 60%; } +a.arrow-up { background: none no-repeat left center; } +a.arrow-down { background: none no-repeat right center; } +a.arrow-left { background: none no-repeat 3px 60%; } +a.arrow-right { background: none no-repeat 95% 60%; } -a.up, a.up:link, a.up:active, a.up:visited { +a.arrow-up, a.arrow-up:link, a.arrow-up:active, a.arrow-up:visited { padding-left: 10px; text-decoration: none; border-bottom-width: 0; } -a.up:hover { +a.arrow-up:hover { background-position: left top; } -a.down, a.down:link, a.down:active, a.down:visited { +a.arrow-down, a.arrow-down:link, a.arrow-down:active, a.arrow-down:visited { padding-right: 10px; } -a.down:hover { +a.arrow-down:hover { background-position: right bottom; text-decoration: none; } -a.left, a.left:active, a.left:visited { +a.arrow-left, a.arrow-left:active, a.arrow-left:visited { padding-left: 12px; } -a.left:hover { +a.arrow-left:hover { text-decoration: none; background-position: 0 60%; } -a.right, a.right:active, a.right:visited { +a.arrow-right, a.arrow-right:active, a.arrow-right:visited { padding-right: 12px; } -a.right:hover { +a.arrow-right:hover { text-decoration: none; background-position: 100% 60%; } diff --git a/phpBB/styles/subsilver2/template/breadcrumbs.html b/phpBB/styles/subsilver2/template/breadcrumbs.html index 73386ed851..09ee9a8606 100644 --- a/phpBB/styles/subsilver2/template/breadcrumbs.html +++ b/phpBB/styles/subsilver2/template/breadcrumbs.html @@ -1,7 +1,9 @@ + <!-- IF $S_MICRODATA --><!-- DEFINE $MICRODATA = ' itemtype="http://data-vocabulary.org/Breadcrumb" itemscope=""' --><!-- ELSE --><!-- DEFINE $MICRODATA = '' --><!-- ENDIF --> <table class="tablebg" width="100%" cellspacing="1" cellpadding="0" style="margin-top: 5px;"> <tr> <td class="row1"> - <p class="breadcrumbs"><!-- IF U_SITE_HOME --><a href="{U_SITE_HOME}">{L_SITE_HOME}</a> <strong>»</strong> <!-- ENDIF --><a href="{U_INDEX}">{L_INDEX}</a><!-- BEGIN navlinks --> » <a href="{navlinks.U_VIEW_FORUM}">{navlinks.FORUM_NAME}</a><!-- END navlinks --></p> + <p class="breadcrumbs"><!-- IF U_SITE_HOME --><a href="{U_SITE_HOME}"{$MICRODATA}>{L_SITE_HOME}</a> <strong>»</strong> <!-- ENDIF --><a href="{U_INDEX}"{$MICRODATA}>{L_INDEX}</a><!-- BEGIN navlinks --> » <a href="{navlinks.U_VIEW_FORUM}"{$MICRODATA}>{navlinks.FORUM_NAME}</a><!-- END navlinks --> + <!-- EVENT overall_header_breadcrumb_append --></p> <p class="datetime">{S_TIMEZONE}</p> </td> </tr> diff --git a/phpBB/styles/subsilver2/template/forumlist_body.html b/phpBB/styles/subsilver2/template/forumlist_body.html index ad505885f6..3e30561f3a 100644 --- a/phpBB/styles/subsilver2/template/forumlist_body.html +++ b/phpBB/styles/subsilver2/template/forumlist_body.html @@ -61,6 +61,7 @@ <td class="row2" align="center" nowrap="nowrap"> <!-- IF forumrow.LAST_POST_TIME --> <!-- IF forumrow.S_DISPLAY_SUBJECT --> + <!-- EVENT forumlist_body_last_post_title_prepend --> <p class="topicdetails"><a href="{forumrow.U_LAST_POST}" title="{forumrow.LAST_POST_SUBJECT}" class="lastsubject">{forumrow.LAST_POST_SUBJECT_TRUNCATED}</a></p> <!-- ENDIF --> <p class="topicdetails"><!-- IF forumrow.U_UNAPPROVED_TOPICS --><a href="{forumrow.U_UNAPPROVED_TOPICS}" class="imageset">{UNAPPROVED_IMG}</a> <!-- ENDIF -->{forumrow.LAST_POST_TIME}</p> diff --git a/phpBB/styles/subsilver2/template/index_body.html b/phpBB/styles/subsilver2/template/index_body.html index af2cefef7a..e07cfda8b3 100644 --- a/phpBB/styles/subsilver2/template/index_body.html +++ b/phpBB/styles/subsilver2/template/index_body.html @@ -18,6 +18,8 @@ <!-- INCLUDE breadcrumbs.html --> +<!-- EVENT index_body_stat_blocks_before --> + <!-- IF S_DISPLAY_ONLINE_LIST --> <br clear="all" /> diff --git a/phpBB/styles/subsilver2/template/jumpbox.html b/phpBB/styles/subsilver2/template/jumpbox.html index f4153d7692..e0603c6a6e 100644 --- a/phpBB/styles/subsilver2/template/jumpbox.html +++ b/phpBB/styles/subsilver2/template/jumpbox.html @@ -1,10 +1,10 @@ <!-- IF S_DISPLAY_JUMPBOX --> - <form method="post" name="jumpbox" action="{S_JUMPBOX_ACTION}" onsubmit="if(document.jumpbox.f.value == -1){return false;}"> + <form method="get" name="jumpbox" action="{S_JUMPBOX_ACTION}" onsubmit="if(document.jumpbox.f.value == -1){return false;}"> <table cellspacing="0" cellpadding="0" border="0"> <tr> - <td nowrap="nowrap"><span class="gensmall"><!-- IF S_IN_MCP and S_MERGE_SELECT -->{L_SELECT_TOPICS_FROM}<!-- ELSEIF S_IN_MCP -->{L_MODERATE_FORUM}<!-- ELSE -->{L_JUMP_TO}<!-- ENDIF -->{L_COLON}</span> <select name="f" onchange="if(this.options[this.selectedIndex].value != -1){ document.forms['jumpbox'].submit() }"> + <td nowrap="nowrap">{HIDDEN_FIELDS_FOR_JUMPBOX}<span class="gensmall"><!-- IF S_IN_MCP and S_MERGE_SELECT -->{L_SELECT_TOPICS_FROM}<!-- ELSEIF S_IN_MCP -->{L_MODERATE_FORUM}<!-- ELSE -->{L_JUMP_TO}<!-- ENDIF -->{L_COLON}</span> <select name="f" onchange="if(this.options[this.selectedIndex].value != -1){ document.forms['jumpbox'].submit() }"> <!-- BEGIN jumpbox_forums --> <!-- IF jumpbox_forums.S_FORUM_COUNT eq 1 --><option value="-1">------------------</option><!-- ENDIF --> diff --git a/phpBB/styles/subsilver2/template/mcp_jumpbox.html b/phpBB/styles/subsilver2/template/mcp_jumpbox.html index 734222bc77..e6ef4ecdad 100644 --- a/phpBB/styles/subsilver2/template/mcp_jumpbox.html +++ b/phpBB/styles/subsilver2/template/mcp_jumpbox.html @@ -1,7 +1,8 @@ <!-- Note: no longer in use... --> -<form name="jumpbox" method="post" action="{S_JUMPBOX_ACTION}"> +<form name="jumpbox" method="get" action="{S_JUMPBOX_ACTION}"> + {HIDDEN_FIELDS_FOR_JUMPBOX} <span class="gensmall">{L_JUMP_TO}{L_COLON}</span> <select name="f" onChange="if(this.options[this.selectedIndex].value != -1 && this.options[this.selectedIndex].value != document.jumpbox.current_f.value){ document.forms['jumpbox'].submit() }"> <!-- IF S_ENABLE_SELECT_ALL --> diff --git a/phpBB/styles/subsilver2/template/memberlist_im.html b/phpBB/styles/subsilver2/template/memberlist_im.html index da1ad661c3..e91a1caf11 100644 --- a/phpBB/styles/subsilver2/template/memberlist_im.html +++ b/phpBB/styles/subsilver2/template/memberlist_im.html @@ -2,8 +2,6 @@ <br clear="all" /> -<!-- MSNM info from http://www.cdolive.net/ - doesn't seem to work with MSN Messenger --> - <form method="post" action="{S_IM_ACTION}"> <table class="tablebg" width="95%" cellspacing="1" cellpadding="4" border="0" align="center"> <tr> @@ -14,7 +12,7 @@ </tr> <tr> <td class="row1"><b class="genmed">{L_IM_RECIPIENT}{L_COLON} </b></td> - <td class="row2"><span class="gen"><b>{USERNAME}</b><!-- IF S_SEND_ICQ or S_SEND_AIM or S_SEND_MSNM or S_NO_SEND_JABBER --> [ {IM_CONTACT} ]<!-- ENDIF --></span> <!-- IF PRESENCE_IMG -->{PRESENCE_IMG}<!-- ENDIF --></td> + <td class="row2"><span class="gen"><b>{USERNAME}</b><!-- IF S_SEND_ICQ or S_SEND_AIM or S_NO_SEND_JABBER --> [ {IM_CONTACT} ]<!-- ENDIF --></span> <!-- IF PRESENCE_IMG -->{PRESENCE_IMG}<!-- ENDIF --></td> </tr> <!-- IF S_SEND_AIM --> @@ -26,85 +24,6 @@ </tr> <!-- ENDIF --> - <!-- IF S_SEND_MSNM --> - <tr> - <td class="row1" colspan="2" align="center"> - <object classid="clsid:B69003B3-C55E-4B48-836C-BC5946FC3B28" codetype="application/x-oleobject" id="objMessengerApp" width="0" height="0"></object> - <script type="text/javascript"> - // <![CDATA[ - var app = document.getElementById('objMessengerApp'); - - /** - * Check whether the browser supports this and whether MSNM is connected - */ - function msn_supported() - { - // Does the browser support the MSNM object? - if (app.MyStatus) - { - // Is MSNM connected? - if (app.MyStatus == 1) - { - alert('{LA_IM_MSNM_CONNECT}'); - return false; - } - } - else - { - alert('{LA_IM_MSNM_BROWSER}'); - return false; - } - return true; - } - - /** - * Add to your contact list - */ - function add_contact(address) - { - if (msn_supported()) - { - // Could return an error while MSNM is connecting, don't want that - try - { - app.AddContact(0, address); - } - catch (e) - { - return; - } - } - } - - /** - * Write IM to contact - */ - function im_contact(address) - { - if (msn_supported()) - { - // Could return an error while MSNM is connecting, don't want that - try - { - app.InstantMessage(address); - } - catch (e) - { - return; - } - } - } - // ]]> - </script> - - <a class="gen" href="#" onclick="add_contact('{A_IM_CONTACT}'); return false;">{L_IM_ADD_CONTACT}</a><br /><a class="gen" href="#" onclick="im_contact('{A_IM_CONTACT}'); return false;">{L_IM_SEND_MESSAGE}</a> - </td> - </tr> - <tr> - <td class="cat" colspan="2" align="center"> </td> - </tr> - <!-- ENDIF --> - <!-- IF S_SEND_JABBER --> <tr> <td class="row1"><b class="genmed">{L_IM_MESSAGE}{L_COLON} </b></td> diff --git a/phpBB/styles/subsilver2/template/memberlist_search.html b/phpBB/styles/subsilver2/template/memberlist_search.html index c0434d8110..fb76cacc79 100644 --- a/phpBB/styles/subsilver2/template/memberlist_search.html +++ b/phpBB/styles/subsilver2/template/memberlist_search.html @@ -102,14 +102,14 @@ <!-- ELSE --> <td colspan="2" class="row1"> </td> <!-- ENDIF --> - <td class="row1"><b class="genmed">{L_MSNM}{L_COLON}</b></td> - <td class="row2"><input class="post" type="text" name="msn" value="{MSNM}" /></td> + <td class="row1"><b class="genmed">{L_JABBER}{L_COLON}</b></td> + <td class="row2"><input class="post" type="text" name="jabber" value="{JABBER}" /></td> </tr> <tr> <td class="row1"><b class="genmed">{L_POSTS}{L_COLON}</b></td> <td class="row2"><select name="count_select">{S_COUNT_OPTIONS}</select> <input class="post" type="text" name="count" value="{COUNT}" /></td> - <td class="row1"><b class="genmed">{L_JABBER}{L_COLON}</b></td> - <td class="row2"><input class="post" type="text" name="jabber" value="{JABBER}" /></td> + <td class="row1"> </td> + <td class="row2"> </td> </tr> <tr> <td class="row1"><b class="genmed">{L_SORT_BY}{L_COLON}</b></td> diff --git a/phpBB/styles/subsilver2/template/memberlist_view.html b/phpBB/styles/subsilver2/template/memberlist_view.html index 464369a7a8..ff22dcc0f7 100644 --- a/phpBB/styles/subsilver2/template/memberlist_view.html +++ b/phpBB/styles/subsilver2/template/memberlist_view.html @@ -117,10 +117,6 @@ </tr> <!-- ENDIF --> <tr> - <td class="gen" nowrap="nowrap" align="{S_CONTENT_FLOW_END}">{L_MSNM}{L_COLON} </td> - <td><!-- IF U_MSN --><a href="{U_MSN}" onclick="popup(this.href, 550, 320); return false" class="imageset">{MSN_IMG}</a><!-- ELSEIF USER_MSN -->{USER_MSN}<!-- ENDIF --></td> - </tr> - <tr> <td class="gen" nowrap="nowrap" align="{S_CONTENT_FLOW_END}">{L_YIM}{L_COLON} </td> <td><!-- IF U_YIM --><a href="{U_YIM}" onclick="popup(this.href, 780, 550); return false" class="imageset">{YIM_IMG}</a><!-- ELSEIF USER_YIM -->{USER_YIM}<!-- ENDIF --></td> </tr> diff --git a/phpBB/styles/subsilver2/template/overall_footer.html b/phpBB/styles/subsilver2/template/overall_footer.html index 24c6f8105c..3a29a0d752 100644 --- a/phpBB/styles/subsilver2/template/overall_footer.html +++ b/phpBB/styles/subsilver2/template/overall_footer.html @@ -3,14 +3,19 @@ <div id="wrapfooter"> <!-- IF U_ACP --><span class="gensmall">[ <a href="{U_ACP}">{L_ACP}</a> ]</span><br /><br /><!-- ENDIF --> - <span class="copyright">{CREDIT_LINE} + <span class="copyright"> + <!-- EVENT overall_footer_copyright_prepend --> + {CREDIT_LINE} <!-- IF TRANSLATION_INFO --><br />{TRANSLATION_INFO}<!-- ENDIF --> + <!-- EVENT overall_footer_copyright_append --> <!-- IF DEBUG_OUTPUT --><br /><bdo dir="ltr">[ {DEBUG_OUTPUT} ]</bdo><!-- ENDIF --></span> </div> <script type="text/javascript" src="{T_JQUERY_LINK}"></script> <!-- IF S_JQUERY_FALLBACK --><script type="text/javascript">window.jQuery || document.write(unescape('%3Cscript src="{T_ASSETS_PATH}/javascript/jquery.js?assets_version={T_ASSETS_VERSION}" type="text/javascript"%3E%3C/script%3E'));</script><!-- ENDIF --> +<script type="text/javascript" src="{T_ASSETS_PATH}/javascript/core.js?assets_version={T_ASSETS_VERSION}"></script> {SCRIPTS} +<!-- EVENT overall_footer_after --> </body> </html> diff --git a/phpBB/styles/subsilver2/template/overall_header.html b/phpBB/styles/subsilver2/template/overall_header.html index e93dd056bf..d5fd20f0fe 100644 --- a/phpBB/styles/subsilver2/template/overall_header.html +++ b/phpBB/styles/subsilver2/template/overall_header.html @@ -129,6 +129,9 @@ function marklist(id, name, state) // ]]> </script> + +<!-- EVENT overall_header_head_append --> + </head> <body class="{S_CONTENT_DIRECTION}"> @@ -195,6 +198,8 @@ function marklist(id, name, state) <br style="clear: both;" /> + <!-- DEFINE $S_MICRODATA = 1 --> <!-- INCLUDE breadcrumbs.html --> + <!-- DEFINE $S_MICRODATA = 0 --> <br /> diff --git a/phpBB/styles/subsilver2/template/posting_body.html b/phpBB/styles/subsilver2/template/posting_body.html index 4c9df6f060..39f8f876ba 100644 --- a/phpBB/styles/subsilver2/template/posting_body.html +++ b/phpBB/styles/subsilver2/template/posting_body.html @@ -257,6 +257,7 @@ </td> <td class="row2"> <table cellpadding="1"> + <!-- EVENT posting_editor_options_prepend --> <!-- IF S_BBCODE_ALLOWED --> <tr> <td><input type="checkbox" class="radio" name="disable_bbcode"{S_BBCODE_CHECKED} /></td> diff --git a/phpBB/styles/subsilver2/template/simple_footer.html b/phpBB/styles/subsilver2/template/simple_footer.html index 38a86c5001..c847bfedcc 100644 --- a/phpBB/styles/subsilver2/template/simple_footer.html +++ b/phpBB/styles/subsilver2/template/simple_footer.html @@ -9,5 +9,6 @@ <!-- IF S_JQUERY_FALLBACK --><script type="text/javascript">window.jQuery || document.write(unescape('%3Cscript src="{T_ASSETS_PATH}/javascript/jquery.js?assets_version={T_ASSETS_VERSION}" type="text/javascript"%3E%3C/script%3E'));</script><!-- ENDIF --> {SCRIPTS} +<!-- EVENT simple_footer_after --> </body> </html> diff --git a/phpBB/styles/subsilver2/template/timezone.js b/phpBB/styles/subsilver2/template/timezone.js index da0a2b0bfd..af8206d12d 100644 --- a/phpBB/styles/subsilver2/template/timezone.js +++ b/phpBB/styles/subsilver2/template/timezone.js @@ -1,19 +1,19 @@ (function($) { // Avoid conflicts with other libraries $('#tz_date').change(function() { - phpbb.timezone_switch_date(false); + phpbb.timezoneSwitchDate(false); }); $('#tz_select_date_suggest').click(function(){ - phpbb.timezone_preselect_select(true); + phpbb.timezonePreselectSelect(true); }); $(document).ready( - phpbb.timezone_enable_date_selection + phpbb.timezoneEnableDateSelection ); $(document).ready( - phpbb.timezone_preselect_select($('#tz_select_date_suggest').attr('data-is-registration') == 'true') + phpbb.timezonePreselectSelect($('#tz_select_date_suggest').attr('data-is-registration') == 'true') ); })(jQuery); // Avoid conflicts with other libraries diff --git a/phpBB/styles/subsilver2/template/ucp_prefs_personal.html b/phpBB/styles/subsilver2/template/ucp_prefs_personal.html index 5a169763fb..9ebc045608 100644 --- a/phpBB/styles/subsilver2/template/ucp_prefs_personal.html +++ b/phpBB/styles/subsilver2/template/ucp_prefs_personal.html @@ -61,11 +61,13 @@ <td class="row1" width="50%"><b class="genmed">{L_POPUP_ON_PM}{L_COLON}</b></td> <td class="row2"><input type="radio" class="radio" name="popuppm" value="1"<!-- IF S_POPUP_PM --> checked="checked"<!-- ENDIF --> /><span class="genmed">{L_YES}</span> <input type="radio" class="radio" name="popuppm" value="0"<!-- IF not S_POPUP_PM --> checked="checked"<!-- ENDIF --> /><span class="genmed">{L_NO}</span></td> </tr> +<!-- IF S_MORE_LANGUAGES --> <tr> <td class="row1" width="50%"><b class="genmed">{L_BOARD_LANGUAGE}{L_COLON}</b></td> <td class="row2"><select name="lang">{S_LANG_OPTIONS}</select></td> </tr> -<!-- IF S_STYLE_OPTIONS --> +<!-- ENDIF --> +<!-- IF S_STYLE_OPTIONS and S_MORE_STYLES --> <tr> <td class="row1" width="50%"><b class="genmed">{L_BOARD_STYLE}{L_COLON}</b></td> <td class="row2"><select name="style">{S_STYLE_OPTIONS}</select></td> diff --git a/phpBB/styles/subsilver2/template/ucp_profile_profile_info.html b/phpBB/styles/subsilver2/template/ucp_profile_profile_info.html index 19259aebc8..69da5f6172 100644 --- a/phpBB/styles/subsilver2/template/ucp_profile_profile_info.html +++ b/phpBB/styles/subsilver2/template/ucp_profile_profile_info.html @@ -21,10 +21,6 @@ <td class="row2"><input class="post" type="text" name="aim" size="30" maxlength="255" value="{AIM}" /></td> </tr> <tr> - <td class="row1" width="35%"><b class="genmed">{L_UCP_MSNM}{L_COLON} </b></td> - <td class="row2"><input class="post" type="text" name="msn" size="30" maxlength="255" value="{MSN}" /></td> -</tr> -<tr> <td class="row1" width="35%"><b class="genmed">{L_UCP_YIM}{L_COLON} </b></td> <td class="row2"><input class="post" type="text" name="yim" size="30" maxlength="255" value="{YIM}" /></td> </tr> diff --git a/phpBB/styles/subsilver2/template/viewtopic_body.html b/phpBB/styles/subsilver2/template/viewtopic_body.html index e2834ffa0b..9e6377022a 100644 --- a/phpBB/styles/subsilver2/template/viewtopic_body.html +++ b/phpBB/styles/subsilver2/template/viewtopic_body.html @@ -15,7 +15,7 @@ <!-- ENDIF --> <div id="pageheader"> - <h2><a class="titles" href="{U_VIEW_TOPIC}">{TOPIC_TITLE}</a></h2> + <h2><!-- EVENT viewtopic_topic_title_prepend --><a class="titles" href="{U_VIEW_TOPIC}">{TOPIC_TITLE}</a></h2> <!-- IF MODERATORS --> <p class="moderators"><!-- IF S_SINGLE_MODERATOR -->{L_MODERATOR}<!-- ELSE -->{L_MODERATORS}<!-- ENDIF -->{L_COLON} {MODERATORS}</p> diff --git a/phpBB/styles/subsilver2/theme/en/stylesheet.css b/phpBB/styles/subsilver2/theme/en/stylesheet.css index 563492d4fc..6ddecf963b 100644 --- a/phpBB/styles/subsilver2/theme/en/stylesheet.css +++ b/phpBB/styles/subsilver2/theme/en/stylesheet.css @@ -19,11 +19,6 @@ padding-left: 72px; padding-top: 20px; } -.imageset.icon_contact_msnm { - background-image: url("./icon_contact_msnm.gif"); - padding-left: 72px; - padding-top: 20px; -} .imageset.icon_contact_pm { background-image: url("./icon_contact_pm.gif"); padding-left: 72px; diff --git a/phpBB/styles/subsilver2/theme/stylesheet.css b/phpBB/styles/subsilver2/theme/stylesheet.css index 977e5c20c6..e7e64eff32 100644 --- a/phpBB/styles/subsilver2/theme/stylesheet.css +++ b/phpBB/styles/subsilver2/theme/stylesheet.css @@ -1008,11 +1008,6 @@ a.imageset { padding-left: 72px; padding-top: 20px; } -.imageset.icon_contact_msnm { - background-image: url("./en/icon_contact_msnm.gif"); - padding-left: 72px; - padding-top: 20px; -} .imageset.icon_contact_pm { background-image: url("./en/icon_contact_pm.gif"); padding-left: 72px; diff --git a/phpBB/viewforum.php b/phpBB/viewforum.php index 83e5d4caa5..5fed514a12 100644 --- a/phpBB/viewforum.php +++ b/phpBB/viewforum.php @@ -181,6 +181,20 @@ if ($mark_read == 'topics') $redirect_url = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id); meta_refresh(3, $redirect_url); + if ($request->is_ajax()) + { + // Tell the ajax script what language vars and URL need to be replaced + $data = array( + 'NO_UNREAD_POSTS' => $user->lang['NO_UNREAD_POSTS'], + 'UNREAD_POSTS' => $user->lang['UNREAD_POSTS'], + 'U_MARK_TOPICS' => ($user->data['is_registered'] || $config['load_anon_lastread']) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'hash=' . generate_link_hash('global') . "&f=$forum_id&mark=topics&mark_time=" . time()) : '', + 'MESSAGE_TITLE' => $user->lang['INFORMATION'], + 'MESSAGE_TEXT' => $user->lang['TOPICS_MARKED'] + ); + $json_response = new phpbb_json_response(); + $json_response->send($data); + } + trigger_error($user->lang['TOPICS_MARKED'] . '<br /><br />' . sprintf($user->lang['RETURN_FORUM'], '<a href="' . $redirect_url . '">', '</a>')); } diff --git a/phpBB/viewonline.php b/phpBB/viewonline.php index 687fef4c6c..6b26a3f5d6 100644 --- a/phpBB/viewonline.php +++ b/phpBB/viewonline.php @@ -216,7 +216,7 @@ while ($row = $db->sql_fetchrow($result)) $location_url = append_sid("{$phpbb_root_path}index.$phpEx"); break; - case 'adm/index': + case $phpbb_adm_relative_path . 'index': $location = $user->lang['ACP']; $location_url = append_sid("{$phpbb_root_path}index.$phpEx"); break; diff --git a/phpBB/viewtopic.php b/phpBB/viewtopic.php index 3fde5b5e03..fcf34a139a 100644 --- a/phpBB/viewtopic.php +++ b/phpBB/viewtopic.php @@ -617,7 +617,6 @@ $template->assign_vars(array( 'WWW_IMG' => $user->img('icon_contact_www', 'VISIT_WEBSITE'), 'ICQ_IMG' => $user->img('icon_contact_icq', 'ICQ'), 'AIM_IMG' => $user->img('icon_contact_aim', 'AIM'), - 'MSN_IMG' => $user->img('icon_contact_msnm', 'MSNM'), 'YIM_IMG' => $user->img('icon_contact_yahoo', 'YIM'), 'JABBER_IMG' => $user->img('icon_contact_jabber', 'JABBER') , 'REPORT_IMG' => $user->img('icon_post_report', 'REPORT_POST'), @@ -1095,7 +1094,6 @@ while ($row = $db->sql_fetchrow($result)) 'icq_status_img' => '', 'icq' => '', 'aim' => '', - 'msn' => '', 'yim' => '', 'jabber' => '', 'search' => '', @@ -1163,7 +1161,6 @@ while ($row = $db->sql_fetchrow($result)) 'profile' => append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=viewprofile&u=$poster_id"), 'www' => $row['user_website'], 'aim' => ($row['user_aim'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=contact&action=aim&u=$poster_id") : '', - 'msn' => ($row['user_msnm'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=contact&action=msnm&u=$poster_id") : '', 'yim' => ($row['user_yim']) ? 'http://edit.yahoo.com/config/send_webmesg?.target=' . urlencode($row['user_yim']) . '&.src=pg' : '', 'jabber' => ($row['user_jabber'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=contact&action=jabber&u=$poster_id") : '', 'search' => ($auth->acl_get('u_search')) ? append_sid("{$phpbb_root_path}search.$phpEx", "author_id=$poster_id&sr=posts") : '', @@ -1353,7 +1350,7 @@ if (sizeof($attach_list)) } $template->assign_vars(array( - 'S_HAS_ATTACHMENTS' => !empty($attachments), + 'S_HAS_ATTACHMENTS' => $topic_data['topic_attachment'], )); $methods = phpbb_gen_download_links('topic_id', $topic_id, $phpbb_root_path, $phpEx); @@ -1585,7 +1582,6 @@ for ($i = 0, $end = sizeof($post_list); $i < $end; ++$i) 'U_WWW' => $user_cache[$poster_id]['www'], 'U_ICQ' => $user_cache[$poster_id]['icq'], 'U_AIM' => $user_cache[$poster_id]['aim'], - 'U_MSN' => $user_cache[$poster_id]['msn'], 'U_YIM' => $user_cache[$poster_id]['yim'], 'U_JABBER' => $user_cache[$poster_id]['jabber'], |