diff options
Diffstat (limited to 'phpBB')
387 files changed, 8608 insertions, 3534 deletions
diff --git a/phpBB/adm/style/acp_attachments.html b/phpBB/adm/style/acp_attachments.html index e1f7f140c9..6129d6a1a5 100644 --- a/phpBB/adm/style/acp_attachments.html +++ b/phpBB/adm/style/acp_attachments.html @@ -37,12 +37,6 @@ <!-- IF S_ATTACHMENT_SETTINGS --> - <!-- IF not S_THUMBNAIL_SUPPORT --> - <div class="errorbox"> - <p>{L_NO_THUMBNAIL_SUPPORT}</p> - </div> - <!-- ENDIF --> - <form id="attachsettings" method="post" action="{U_ACTION}"> <!-- BEGIN options --> <!-- IF options.S_LEGEND --> @@ -329,42 +323,71 @@ <fieldset class="tabulated"> <legend>{L_TITLE}</legend> - <table class="table1 zebra-table fixed-width-table"> - <thead> - <tr> - <th>{L_FILENAME}</th> - <th style="width: 15%;">{L_FILEDATE}</th> - <th style="width: 15%;">{L_FILESIZE}</th> - <th style="width: 15%;">{L_ATTACH_POST_ID}</th> - <th style="width: 15%;">{L_ATTACH_TO_POST}</th> - <th style="width: 15%;">{L_DELETE}</th> - </tr> - </thead> - <tbody> - <!-- BEGIN orphan --> + <div class="pagination top-pagination"> + <!-- IF .pagination or TOTAL_FILES --> + {L_NUMBER_FILES}{L_COLON} {TOTAL_FILES} • {L_TOTAL_SIZE}{L_COLON} {TOTAL_SIZE} + <!-- IF .pagination --> + • <!-- INCLUDE pagination.html --> + <!-- ELSE --> + • {PAGE_NUMBER} + <!-- ENDIF --> + <!-- ENDIF --> + </div> + + <!-- IF .orphan --> + <table class="table1 zebra-table fixed-width-table"> + <thead> <tr> - <td><a href="{orphan.U_FILE}">{orphan.REAL_FILENAME}</a></td> - <td>{orphan.FILETIME}</td> - <td>{orphan.FILESIZE}</td> - <td><strong>{L_ATTACH_ID}{L_COLON} </strong><input type="number" min="0" max="9999999999" name="post_id[{orphan.ATTACH_ID}]" value="{orphan.POST_ID}" style="width: 75%;" /></td> - <td><input type="checkbox" class="radio" name="add[{orphan.ATTACH_ID}]" /></td> - <td><input type="checkbox" class="radio" name="delete[{orphan.ATTACH_ID}]" /></td> + <th>{L_FILENAME}</th> + <th style="width: 15%;">{L_FILEDATE}</th> + <th style="width: 15%;">{L_FILESIZE}</th> + <th style="width: 15%;">{L_ATTACH_POST_ID}</th> + <th style="width: 15%;">{L_ATTACH_TO_POST}</th> + <th style="width: 15%;">{L_DELETE}</th> </tr> - <!-- END orphan --> - <tr class="row4"> - <td colspan="4"> </td> - <td class="small"><a href="#" onclick="marklist('orphan', 'add', true); return false;">{L_MARK_ALL}</a> :: <a href="#" onclick="marklist('orphan', 'add', false); return false;">{L_UNMARK_ALL}</a></td> - <td class="small"><a href="#" onclick="marklist('orphan', 'delete', true); return false;">{L_MARK_ALL}</a> :: <a href="#" onclick="marklist('orphan', 'delete', false); return false;">{L_UNMARK_ALL}</a></td> - </tr> - </tbody> - </table> + </thead> + <tbody> + <!-- BEGIN orphan --> + <tr> + <td><a href="{orphan.U_FILE}">{orphan.REAL_FILENAME}</a></td> + <td>{orphan.FILETIME}</td> + <td>{orphan.FILESIZE}</td> + <td><strong>{L_ATTACH_ID}{L_COLON} </strong><input type="number" min="0" max="9999999999" name="post_id[{orphan.ATTACH_ID}]" value="{orphan.POST_ID}" style="width: 75%;" /></td> + <td><input type="checkbox" class="radio" name="add[{orphan.ATTACH_ID}]" /></td> + <td><input type="checkbox" class="radio" name="delete[{orphan.ATTACH_ID}]" /></td> + </tr> + <!-- END orphan --> + <tr class="row4"> + <td colspan="4"> </td> + <td class="small"><a href="#" onclick="marklist('orphan', 'add', true); return false;">{L_MARK_ALL}</a> :: <a href="#" onclick="marklist('orphan', 'add', false); return false;">{L_UNMARK_ALL}</a></td> + <td class="small"><a href="#" onclick="marklist('orphan', 'delete', true); return false;">{L_MARK_ALL}</a> :: <a href="#" onclick="marklist('orphan', 'delete', false); return false;">{L_UNMARK_ALL}</a></td> + </tr> + </tbody> + </table> + <!-- ELSE --> + <div class="errorbox"> + <p>{L_NO_ATTACHMENTS}</p> + </div> + <!-- ENDIF --> + + <!-- IF TOTAL_FILES --> + <div class="pagination"> + {L_NUMBER_FILES}{L_COLON} {TOTAL_FILES} • {L_TOTAL_SIZE}{L_COLON} {TOTAL_SIZE} + <!-- IF .pagination --> + • <!-- INCLUDE pagination.html --> + <!-- ELSE --> + • {PAGE_NUMBER} + <!-- ENDIF --> + </div> + <!-- ENDIF --> - <br /> + <!-- IF .orphan --> + <p class="submit-buttons"> + <input class="button1" type="submit" id="submit" name="submit" value="{L_SUBMIT}" /> + <input class="button2" type="reset" id="reset" name="reset" value="{L_RESET}" /> + </p> + <!-- ENDIF --> - <p class="submit-buttons"> - <input class="button1" type="submit" id="submit" name="submit" value="{L_SUBMIT}" /> - <input class="button2" type="reset" id="reset" name="reset" value="{L_RESET}" /> - </p> {S_FORM_TOKEN} </fieldset> </form> @@ -398,17 +421,25 @@ </tr> </thead> <tbody> - <!-- BEGIN attachments --> + {% for attachments in attachments %} <tr> <td> - <!-- IF attachments.S_IN_MESSAGE -->{L_EXTENSION_GROUP}{L_COLON} <strong><!-- IF attachments.EXT_GROUP_NAME -->{attachments.EXT_GROUP_NAME}<!-- ELSE -->{L_NO_EXT_GROUP}<!-- ENDIF --></strong><br />{attachments.L_DOWNLOAD_COUNT}<br />{L_IN} {L_PRIVATE_MESSAGE} - <!-- ELSE --><a href="{attachments.U_FILE}" style="font-weight: bold;">{attachments.REAL_FILENAME}</a><br /><!-- IF attachments.COMMENT -->{attachments.COMMENT}<br /><!-- ENDIF -->{attachments.L_DOWNLOAD_COUNT}<br />{L_TOPIC}{L_COLON} <a href="{attachments.U_VIEW_TOPIC}">{attachments.TOPIC_TITLE}</a><!-- ENDIF --> + {{ lang('EXTENSION_GROUP') ~ lang('COLON') }} <strong>{{ attachments.EXT_GROUP_NAME }}</strong> + {% if attachments.S_IN_MESSAGE %} + <br>{{ attachments.L_DOWNLOAD_COUNT }} + <br>{{ lang('IN') }} {{ lang('PRIVATE_MESSAGE') }} + {% else %} + <br><a href="{{ attachments.U_FILE }}"><strong>{{ attachments.REAL_FILENAME }}</strong></a> + {% if attachments.COMMENT %}<br>{{ attachments.COMMENT }}{% endif %} + <br>{{ attachments.L_DOWNLOAD_COUNT }} + <br>{{ lang('TOPIC') ~ lang('COLON') }} <a href="{{ attachments.U_VIEW_TOPIC }}">{{ attachments.TOPIC_TITLE }}</a> + {% endif %} </td> - <td>{attachments.FILETIME}<br />{L_POST_BY_AUTHOR} {attachments.ATTACHMENT_POSTER}</td> - <td class="centered-text">{attachments.FILESIZE}</td> - <td class="centered-text"><input type="checkbox" class="radio" name="delete[{attachments.ATTACH_ID}]" /></td> + <td>{{ attachments.FILETIME }}<br>{{ lang('POST_BY_AUTHOR') }} {{ attachments.ATTACHMENT_POSTER }}</td> + <td class="centered-text">{{ attachments.FILESIZE }}</td> + <td class="centered-text"><input type="checkbox" class="radio" name="delete[{{ attachments.ATTACH_ID }}]" /></td> </tr> - <!-- END attachments --> + {% endfor %} </tbody> </table> <!-- ELSE --> @@ -440,7 +471,7 @@ <input class="button2" type="submit" name="submit" value="{L_DELETE_MARKED}" /><br /> <p class="small"> <a href="#" onclick="marklist('attachments', 'delete', true); return false;">{L_MARK_ALL}</a> • - <a href="#" onclick="marklist('attachments', 'delete', false); return false;">{L_UNMARK_ALL}</a> + <a href="#" onclick="marklist('attachments', 'delete', false); return false;">{L_UNMARK_ALL}</a> </p> </fieldset> <!-- ENDIF --> diff --git a/phpBB/adm/style/acp_database.html b/phpBB/adm/style/acp_database.html index 39f06319f9..cc0b57b411 100644 --- a/phpBB/adm/style/acp_database.html +++ b/phpBB/adm/style/acp_database.html @@ -20,7 +20,6 @@ <p class="submit-buttons"> <input class="button1" type="submit" id="submit" name="submit" value="{L_START_RESTORE}" /> <input class="button2" type="submit" id="delete" name="delete" value="{L_DELETE_BACKUP}" /> - <input class="button2" type="submit" id="download" name="download" value="{L_DOWNLOAD_BACKUP}" /> </p> {S_FORM_TOKEN} </fieldset> @@ -69,13 +68,6 @@ <!-- END methods --></dd> </dl> <dl> - <dt><label for="where">{L_ACTION}{L_COLON}</label></dt> - <dd> - <label><input id="where" type="radio" class="radio" name="where" value="store" checked="checked" /> {L_STORE_LOCAL}</label> - <label><input type="radio" class="radio" name="where" value="download" /> {L_DOWNLOAD}</label> - </dd> - </dl> - <dl> <dt><label for="table">{L_TABLE_SELECT}{L_COLON}</label></dt> <dd><select id="table" name="table[]" size="10" multiple="multiple"> <!-- BEGIN tables --> diff --git a/phpBB/adm/style/acp_ext_list.html b/phpBB/adm/style/acp_ext_list.html index 7ab2608e13..8e2c7452a3 100644 --- a/phpBB/adm/style/acp_ext_list.html +++ b/phpBB/adm/style/acp_ext_list.html @@ -7,7 +7,7 @@ <p>{L_EXTENSIONS_EXPLAIN}</p> <fieldset class="quick"> - <span class="small"><a href="https://www.phpbb.com/go/customise/extensions/3.1" target="_blank">{L_BROWSE_EXTENSIONS_DATABASE}</a> • <a href="{U_VERSIONCHECK_FORCE}">{L_VERSIONCHECK_FORCE_UPDATE_ALL}</a> • <a href="javascript:phpbb.toggleDisplay('version_check_settings');">{L_SETTINGS}</a></span> + <span class="small"><a href="https://www.phpbb.com/go/customise/extensions/3.2" target="_blank">{L_BROWSE_EXTENSIONS_DATABASE}</a> • <a href="{U_VERSIONCHECK_FORCE}">{L_VERSIONCHECK_FORCE_UPDATE_ALL}</a> • <a href="javascript:phpbb.toggleDisplay('version_check_settings');">{L_SETTINGS}</a></span> </fieldset> <form id="version_check_settings" method="post" action="{U_ACTION}" style="display:none"> diff --git a/phpBB/adm/style/acp_groups.html b/phpBB/adm/style/acp_groups.html index 26d7030531..d0096370d9 100644 --- a/phpBB/adm/style/acp_groups.html +++ b/phpBB/adm/style/acp_groups.html @@ -316,7 +316,7 @@ <tbody> <!-- ELSE --> <tr> - <td><strong>{groups.GROUP_NAME}</strong></td> + <td><strong<!-- IF groups.GROUP_COLOR --> style="color: #{groups.GROUP_COLOR}"<!-- ENDIF -->>{groups.GROUP_NAME}</strong></td> <td style="text-align: center;">{groups.TOTAL_MEMBERS}</td> <td style="text-align: center;">{groups.PENDING_MEMBERS}</td> <td style="text-align: center;"><a href="{groups.U_EDIT}">{L_SETTINGS}</a></td> diff --git a/phpBB/adm/style/acp_language.html b/phpBB/adm/style/acp_language.html index f708eb1508..79fef94207 100644 --- a/phpBB/adm/style/acp_language.html +++ b/phpBB/adm/style/acp_language.html @@ -69,7 +69,7 @@ <p>{L_ACP_LANGUAGE_PACKS_EXPLAIN}</p> <fieldset class="quick"> - <span class="small"><a href="https://www.phpbb.com/go/customise/language-packs/3.1" target="_blank">{L_BROWSE_LANGUAGE_PACKS_DATABASE}</a></span> + <span class="small"><a href="https://www.phpbb.com/go/customise/language-packs/3.2" target="_blank">{L_BROWSE_LANGUAGE_PACKS_DATABASE}</a></span> </fieldset> <table class="table1 zebra-table"> diff --git a/phpBB/adm/style/acp_main.html b/phpBB/adm/style/acp_main.html index 9522baa9c2..12477a4b77 100644 --- a/phpBB/adm/style/acp_main.html +++ b/phpBB/adm/style/acp_main.html @@ -153,8 +153,14 @@ <td><strong>{PHP_VERSION_INFO}</strong></td> <!-- IF S_TOTAL_ORPHAN --> <td>{L_NUMBER_ORPHAN}{L_COLON} </td> - <td><strong>{TOTAL_ORPHAN}</strong></td> - <!-- ELSE --> + <td> + <!-- IF TOTAL_ORPHAN > 0 --> + <a href="{U_ATTACH_ORPHAN}" title="{L_MORE_INFORMATION}"><strong>{TOTAL_ORPHAN}</strong></a> + <!-- ELSE --> + <strong>{TOTAL_ORPHAN}</strong> + <!-- ENDIF --> + </td> + <!-- ELSE --> <td> </td> <td> </td> <!-- ENDIF --> diff --git a/phpBB/adm/style/acp_profile.html b/phpBB/adm/style/acp_profile.html index bd3935b464..25bf97efd5 100644 --- a/phpBB/adm/style/acp_profile.html +++ b/phpBB/adm/style/acp_profile.html @@ -238,7 +238,7 @@ <form id="profile_fields" method="post" action="{U_ACTION}"> <fieldset class="quick"> - <input class="text small" type="text" name="field_ident" /> <select name="field_type">{S_TYPE_OPTIONS}</select> + <select name="field_type">{S_TYPE_OPTIONS}</select> <input class="button1" type="submit" name="submit" value="{L_CREATE_NEW_FIELD}" /> <input type="hidden" name="create" value="1" /> {S_FORM_TOKEN} diff --git a/phpBB/adm/style/acp_prune_forums.html b/phpBB/adm/style/acp_prune_forums.html index b8c681ea00..ef3880e851 100644 --- a/phpBB/adm/style/acp_prune_forums.html +++ b/phpBB/adm/style/acp_prune_forums.html @@ -94,7 +94,9 @@ <dd><label><input type="radio" class="radio" name="prune_sticky" value="1" /> {L_YES}</label> <label><input type="radio" class="radio" id="sticky" name="prune_sticky" value="0" checked="checked" /> {L_NO}</label></dd> </dl> - + + <!-- EVENT acp_prune_forums_settings_append --> + <p class="quick"> {S_HIDDEN_FIELDS} {S_FORM_TOKEN} diff --git a/phpBB/adm/style/acp_styles.html b/phpBB/adm/style/acp_styles.html index 43c2f96a65..cfa804090f 100644 --- a/phpBB/adm/style/acp_styles.html +++ b/phpBB/adm/style/acp_styles.html @@ -33,7 +33,7 @@ <!-- IF L_EXPLAIN --><p>{L_EXPLAIN}</p><!-- ENDIF --> <fieldset class="quick"> - <span class="small"><a href="https://www.phpbb.com/go/customise/styles/3.1" target="_blank">{L_BROWSE_STYLES_DATABASE}</a></span> + <span class="small"><a href="https://www.phpbb.com/go/customise/styles/3.2" target="_blank">{L_BROWSE_STYLES_DATABASE}</a></span> </fieldset> <form id="acp_styles" method="post" action="{U_ACTION}"> @@ -96,6 +96,7 @@ <thead> <tr> <th>{L_STYLE_NAME}</th> + <th width="10%" style="white-space: nowrap; text-align: center;">{L_STYLE_PHPBB_VERSION}</th> <!-- IF not STYLES_LIST_HIDE_COUNT --><th width="10%" style="white-space: nowrap; text-align: center;">{L_STYLE_USED_BY}</th><!-- ENDIF --> <th width="25%" style="white-space: nowrap; text-align: center;">{L_ACTIONS}</th> {STYLES_LIST_EXTRA} @@ -129,6 +130,7 @@ <span class="style-path"><br />{L_STYLE_PATH}{L_COLON} {styles_list.STYLE_PATH_FULL}</span> <!-- ENDIF --> </td> + <td class="{$ROW_CLASS} users">{styles_list.STYLE_PHPBB_VERSION}</td> <!-- IF not STYLES_LIST_HIDE_COUNT --> <td class="{$ROW_CLASS} users">{styles_list.USERS}</td> <!-- ENDIF --> @@ -144,7 +146,9 @@ {styles_list.EXTRA} <td class="{$ROW_CLASS} mark" width="20"> <!-- IF styles_list.STYLE_ID --> - <input class="checkbox" type="checkbox" name="ids[]" value="{styles_list.STYLE_ID}" /> + {% if styles_list.STYLE_NAME !== 'prosilver' %} + <input class="checkbox" type="checkbox" name="ids[]" value="{styles_list.STYLE_ID}" /> + {% endif %} <!-- ELSE --> <!-- IF styles_list.COMMENT != '' --> diff --git a/phpBB/adm/style/acp_users_prefs.html b/phpBB/adm/style/acp_users_prefs.html index 61904adc23..484c5b3976 100644 --- a/phpBB/adm/style/acp_users_prefs.html +++ b/phpBB/adm/style/acp_users_prefs.html @@ -33,7 +33,7 @@ <dt><label for="notifymethod">{L_NOTIFY_METHOD}{L_COLON}</label><br /><span>{L_NOTIFY_METHOD_EXPLAIN}</span></dt> <dd><label><input type="radio" class="radio" name="notifymethod" value="0"<!-- IF NOTIFY_EMAIL --> id="notifymethod" checked="checked"<!-- ENDIF --> /> {L_NOTIFY_METHOD_EMAIL}</label> <label><input type="radio" class="radio" name="notifymethod" value="1"<!-- IF NOTIFY_IM --> id="notifymethod" checked="checked"<!-- ENDIF --><!-- IF S_JABBER_DISABLED --> disabled="disabled"<!-- ENDIF --> /> {L_NOTIFY_METHOD_IM}</label> - <label><input type="radio" class="radio" name="notifymethod" value="2"<!-- IF NOTIFY_BOTH --> id="notifymethod" checked="checked"<!-- ENDIF --> /> {L_NOTIFY_METHOD_BOTH}</label></dd> + <label><input type="radio" class="radio" name="notifymethod" value="2"<!-- IF NOTIFY_BOTH --> id="notifymethod" checked="checked"<!-- ENDIF --><!-- IF S_JABBER_DISABLED --> disabled="disabled"<!-- ENDIF --> /> {L_NOTIFY_METHOD_BOTH}</label></dd> </dl> <dl> <dt><label for="notifypm">{L_NOTIFY_ON_PM}{L_COLON}</label></dt> diff --git a/phpBB/adm/style/admin.css b/phpBB/adm/style/admin.css index 41d0ae8d42..7cf6c22236 100644 --- a/phpBB/adm/style/admin.css +++ b/phpBB/adm/style/admin.css @@ -525,7 +525,6 @@ li { padding: 0; border-right: 1px solid #CCCFD3; position: relative; - z-index: 1; } .rtl #menu { @@ -841,6 +840,7 @@ table.zebra-table tbody tr:nth-child(odd) { } .row2 { + word-break: break-all; background-color: #DCEBFE; } @@ -1891,7 +1891,6 @@ li.pagination ul { color: #000; text-align: center; border: 1px solid #AAA; - opacity: .95; } .tooltip span.top { @@ -2461,6 +2460,9 @@ fieldset.permissions .padding { text-align: left; } +.rtl .dropdown li { + text-align: right; +} .wrap .dropdown li, .dropdown.wrap li { white-space: normal; } @@ -2475,6 +2477,10 @@ fieldset.permissions .padding { width: 250px; } +.rtl .roles-options > .dropdown { + right: auto; +} + .roles-options { -webkit-user-select: none; -moz-user-select: none; @@ -2493,6 +2499,10 @@ fieldset.permissions .padding { background: url('../images/arrow_down.gif') no-repeat 245px .7em; } +.rtl .roles-options > span { + background: url('../images/arrow_down.gif') no-repeat 7px .7em; +} + .roles-options li { list-style: none; } diff --git a/phpBB/adm/style/installer_footer.html b/phpBB/adm/style/installer_footer.html index fefa8f6d3f..54e6951a12 100644 --- a/phpBB/adm/style/installer_footer.html +++ b/phpBB/adm/style/installer_footer.html @@ -6,7 +6,9 @@ <div id="page-footer"> <div class="copyright"> - Powered by <a href="https://www.phpbb.com/">phpBB</a>® Forum Software © phpBB Limited + {% if S_COPYRIGHT_HTML %} + {{ CREDIT_LINE }} + {% endif %} </div> </div> </div> diff --git a/phpBB/adm/style/installer_form.html b/phpBB/adm/style/installer_form.html index a38f33c7c2..592d361d1e 100644 --- a/phpBB/adm/style/installer_form.html +++ b/phpBB/adm/style/installer_form.html @@ -1,3 +1,4 @@ +<!-- IF FORM_TITLE --><h1>{FORM_TITLE}</h1><!-- ENDIF --> <form id="<!-- IF FORM_ID -->{FORM_ID}<!-- ELSE -->install_install<!-- ENDIF -->" method="POST" action="{U_ACTION}"> <!-- IF .options --> <!-- IF S_NOT_ONLY_BUTTON_FORM --> @@ -8,9 +9,9 @@ <!-- IF options.S_LEGEND --> <!-- IF not options.S_FIRST_ROW --> </fieldset> - - <fieldset> <!-- ENDIF --> + <fieldset> + <legend>{options.LEGEND}</legend> <!-- ELSE --> <dl> @@ -49,7 +50,7 @@ <fieldset class="submit-buttons"> <legend>{L_SUBMIT}</legend> <!-- BEGIN submit_buttons --> - <input class="button1<!-- IF submit_buttons.DISABLED --> disabled<!-- ENDIF -->" type="submit" name="{submit_buttons.KEY}" value="{submit_buttons.TITLE}"<!-- IF submit_buttons.DISABLED --> disabled="disabled"<!-- ENDIF --> /> + <input class="<!-- IF not submit_buttons.IS_SECONDARY -->button1<!-- ELSE -->button2<!-- ENDIF --><!-- IF submit_buttons.DISABLED --> disabled<!-- ENDIF -->" type="submit" name="{submit_buttons.KEY}" value="{submit_buttons.TITLE}"<!-- IF submit_buttons.DISABLED --> disabled="disabled"<!-- ENDIF --> /> <!-- END submit_buttons --> </fieldset> <!-- ENDIF --> diff --git a/phpBB/adm/style/permission_mask.html b/phpBB/adm/style/permission_mask.html index 017d29d832..c556664b8c 100644 --- a/phpBB/adm/style/permission_mask.html +++ b/phpBB/adm/style/permission_mask.html @@ -41,7 +41,7 @@ <dt style="width: 20%"><label for="role{p_mask.S_ROW_COUNT}{p_mask.f_mask.S_ROW_COUNT}">{L_ROLE}{L_COLON}</label></dt> {% if p_mask.f_mask.role_options %} <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 20%"> - <div class="dropdown-container dropdown-button-control roles-options" data-alt-text="{LA_ROLE_DESCRIPTION}"> + <div class="dropdown-container dropdown-{S_CONTENT_FLOW_END} dropdown-button-control roles-options" data-alt-text="{LA_ROLE_DESCRIPTION}"> <select id="role{p_mask.S_ROW_COUNT}{p_mask.f_mask.S_ROW_COUNT}" name="role[{p_mask.f_mask.UG_ID}][{p_mask.f_mask.FORUM_ID}]">{p_mask.f_mask.S_ROLE_OPTIONS}</select> <span title="Roles" class="button icon-button tools-icon dropdown-trigger dropdown-select">{L_NO_ROLE_ASSIGNED}</span> <div class="dropdown hidden"> diff --git a/phpBB/adm/style/tooltip.js b/phpBB/adm/style/tooltip.js index 8781e2b509..7b7abb11e6 100644 --- a/phpBB/adm/style/tooltip.js +++ b/phpBB/adm/style/tooltip.js @@ -130,10 +130,17 @@ phpbb.positionTooltip = function ($element) { $element = $element.parent(); offset = $element.offset(); - $('#_tooltip_container').css({ - top: offset.top + 30, - left: offset.left - 205 - }); + if ($('body').hasClass('rtl')) { + $('#_tooltip_container').css({ + top: offset.top + 30, + left: offset.left + 255 + }); + } else { + $('#_tooltip_container').css({ + top: offset.top + 30, + left: offset.left - 205 + }); + } }; /** diff --git a/phpBB/assets/javascript/core.js b/phpBB/assets/javascript/core.js index a88719f1df..5218a8c1be 100644 --- a/phpBB/assets/javascript/core.js +++ b/phpBB/assets/javascript/core.js @@ -20,6 +20,13 @@ var phpbbAlertTimer = null; phpbb.isTouch = (window && typeof window.ontouchstart !== 'undefined'); +// Add ajax pre-filter to prevent cross-domain script execution +$.ajaxPrefilter(function(s) { + if (s.crossDomain) { + s.contents.script = false; + } +}); + /** * Display a loading screen * @@ -27,9 +34,9 @@ phpbb.isTouch = (window && typeof window.ontouchstart !== 'undefined'); */ phpbb.loadingIndicator = function() { if (!$loadingIndicator) { - $loadingIndicator = $('<div />', { - id: 'loading_indicator', - class: 'loading_indicator', + $loadingIndicator = $('<div />', { + 'id': 'loading_indicator', + 'class': 'loading_indicator' }); $loadingIndicator.appendTo('#page-footer'); } @@ -179,7 +186,7 @@ phpbb.alert.close = function($alert, fadedark) { phpbb.confirm = function(msg, callback, fadedark) { var $confirmDiv = $('#phpbb_confirm'); $confirmDiv.find('.alert_text').html(msg); - fadedark = fadedark !== 'undefined' ? fadedark : true; + fadedark = typeof fadedark !== 'undefined' ? fadedark : true; $(document).on('keydown.phpbb.alert', function(e) { if (e.keyCode === keymap.ENTER || e.keyCode === keymap.ESC) { @@ -935,9 +942,9 @@ phpbb.addAjaxCallback('alt_text', function() { $anchor.each(function() { var $this = $(this); altText = $this.attr('data-alt-text'); - $this.attr('data-alt-text', $this.text()); - $this.attr('title', $.trim(altText)); - $this.text(altText); + $this.attr('data-alt-text', $.trim($this.text())); + $this.attr('title', altText); + $this.children('span').text(altText); }); }); @@ -1331,6 +1338,7 @@ phpbb.toggleDropdown = function() { $this.css({ marginLeft: 0, left: 0, + marginRight: 0, maxWidth: (windowWidth - 4) + 'px' }); @@ -1642,7 +1650,7 @@ phpbb.lazyLoadAvatars = function loadAvatars() { }); }; -$(window).load(phpbb.lazyLoadAvatars); +$(window).on('load', phpbb.lazyLoadAvatars); /** * Apply code editor to all textarea elements with data-bbcode attribute @@ -1654,7 +1662,7 @@ $(function() { phpbb.registerPageDropdowns(); - $('#color_palette_placeholder').each(function() { + $('[data-orientation]').each(function() { phpbb.registerPalette($(this)); }); diff --git a/phpBB/assets/javascript/jquery.min.js b/phpBB/assets/javascript/jquery.min.js index 73f33fb3aa..e836475870 100644 --- a/phpBB/assets/javascript/jquery.min.js +++ b/phpBB/assets/javascript/jquery.min.js @@ -1,4 +1,5 @@ -/*! jQuery v1.11.0 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ -!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k="".trim,l={},m="1.11.0",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray||function(a){return"array"===n.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return a-parseFloat(a)>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(l.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:k&&!k.call("\ufeff\xa0")?function(a){return null==a?"":k.call(a)}:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||n.guid++,e):void 0},now:function(){return+new Date},support:l}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s="sizzle"+-new Date,t=a.document,u=0,v=0,w=eb(),x=eb(),y=eb(),z=function(a,b){return a===b&&(j=!0),0},A="undefined",B=1<<31,C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=D.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},J="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",K="[\\x20\\t\\r\\n\\f]",L="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",M=L.replace("w","w#"),N="\\["+K+"*("+L+")"+K+"*(?:([*^$|!~]?=)"+K+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+M+")|)|)"+K+"*\\]",O=":("+L+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+N.replace(3,8)+")*)|.*)\\)|)",P=new RegExp("^"+K+"+|((?:^|[^\\\\])(?:\\\\.)*)"+K+"+$","g"),Q=new RegExp("^"+K+"*,"+K+"*"),R=new RegExp("^"+K+"*([>+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(O),U=new RegExp("^"+M+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L.replace("w","w*")+")"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=/'|\\/g,ab=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),bb=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{G.apply(D=H.call(t.childNodes),t.childNodes),D[t.childNodes.length].nodeType}catch(cb){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function db(a,b,d,e){var f,g,h,i,j,m,p,q,u,v;if((b?b.ownerDocument||b:t)!==l&&k(b),b=b||l,d=d||[],!a||"string"!=typeof a)return d;if(1!==(i=b.nodeType)&&9!==i)return[];if(n&&!e){if(f=Z.exec(a))if(h=f[1]){if(9===i){if(g=b.getElementById(h),!g||!g.parentNode)return d;if(g.id===h)return d.push(g),d}else if(b.ownerDocument&&(g=b.ownerDocument.getElementById(h))&&r(b,g)&&g.id===h)return d.push(g),d}else{if(f[2])return G.apply(d,b.getElementsByTagName(a)),d;if((h=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(h)),d}if(c.qsa&&(!o||!o.test(a))){if(q=p=s,u=b,v=9===i&&a,1===i&&"object"!==b.nodeName.toLowerCase()){m=ob(a),(p=b.getAttribute("id"))?q=p.replace(_,"\\$&"):b.setAttribute("id",q),q="[id='"+q+"'] ",j=m.length;while(j--)m[j]=q+pb(m[j]);u=$.test(a)&&mb(b.parentNode)||b,v=m.join(",")}if(v)try{return G.apply(d,u.querySelectorAll(v)),d}catch(w){}finally{p||b.removeAttribute("id")}}}return xb(a.replace(P,"$1"),b,d,e)}function eb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function fb(a){return a[s]=!0,a}function gb(a){var b=l.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function hb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function ib(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||B)-(~a.sourceIndex||B);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function jb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function kb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function lb(a){return fb(function(b){return b=+b,fb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function mb(a){return a&&typeof a.getElementsByTagName!==A&&a}c=db.support={},f=db.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},k=db.setDocument=function(a){var b,e=a?a.ownerDocument||a:t,g=e.defaultView;return e!==l&&9===e.nodeType&&e.documentElement?(l=e,m=e.documentElement,n=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){k()},!1):g.attachEvent&&g.attachEvent("onunload",function(){k()})),c.attributes=gb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=gb(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(e.getElementsByClassName)&&gb(function(a){return a.innerHTML="<div class='a'></div><div class='a i'></div>",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=gb(function(a){return m.appendChild(a).id=s,!e.getElementsByName||!e.getElementsByName(s).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==A&&n){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ab,bb);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ab,bb);return function(a){var c=typeof a.getAttributeNode!==A&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==A?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==A&&n?b.getElementsByClassName(a):void 0},p=[],o=[],(c.qsa=Y.test(e.querySelectorAll))&&(gb(function(a){a.innerHTML="<select t=''><option selected=''></option></select>",a.querySelectorAll("[t^='']").length&&o.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||o.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll(":checked").length||o.push(":checked")}),gb(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&o.push("name"+K+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||o.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),o.push(",.*:")})),(c.matchesSelector=Y.test(q=m.webkitMatchesSelector||m.mozMatchesSelector||m.oMatchesSelector||m.msMatchesSelector))&&gb(function(a){c.disconnectedMatch=q.call(a,"div"),q.call(a,"[s!='']:x"),p.push("!=",O)}),o=o.length&&new RegExp(o.join("|")),p=p.length&&new RegExp(p.join("|")),b=Y.test(m.compareDocumentPosition),r=b||Y.test(m.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},z=b?function(a,b){if(a===b)return j=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===t&&r(t,a)?-1:b===e||b.ownerDocument===t&&r(t,b)?1:i?I.call(i,a)-I.call(i,b):0:4&d?-1:1)}:function(a,b){if(a===b)return j=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],k=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:i?I.call(i,a)-I.call(i,b):0;if(f===g)return ib(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)k.unshift(c);while(h[d]===k[d])d++;return d?ib(h[d],k[d]):h[d]===t?-1:k[d]===t?1:0},e):l},db.matches=function(a,b){return db(a,null,null,b)},db.matchesSelector=function(a,b){if((a.ownerDocument||a)!==l&&k(a),b=b.replace(S,"='$1']"),!(!c.matchesSelector||!n||p&&p.test(b)||o&&o.test(b)))try{var d=q.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return db(b,l,null,[a]).length>0},db.contains=function(a,b){return(a.ownerDocument||a)!==l&&k(a),r(a,b)},db.attr=function(a,b){(a.ownerDocument||a)!==l&&k(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!n):void 0;return void 0!==f?f:c.attributes||!n?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},db.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},db.uniqueSort=function(a){var b,d=[],e=0,f=0;if(j=!c.detectDuplicates,i=!c.sortStable&&a.slice(0),a.sort(z),j){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return i=null,a},e=db.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=db.selectors={cacheLength:50,createPseudo:fb,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ab,bb),a[3]=(a[4]||a[5]||"").replace(ab,bb),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||db.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&db.error(a[0]),a},PSEUDO:function(a){var b,c=!a[5]&&a[2];return V.CHILD.test(a[0])?null:(a[3]&&void 0!==a[4]?a[2]=a[4]:c&&T.test(c)&&(b=ob(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ab,bb).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=w[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&w(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==A&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=db.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),t=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&t){k=q[s]||(q[s]={}),j=k[a]||[],n=j[0]===u&&j[1],m=j[0]===u&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[u,n,m];break}}else if(t&&(j=(b[s]||(b[s]={}))[a])&&j[0]===u)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(t&&((l[s]||(l[s]={}))[a]=[u,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||db.error("unsupported pseudo: "+a);return e[s]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?fb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:fb(function(a){var b=[],c=[],d=g(a.replace(P,"$1"));return d[s]?fb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:fb(function(a){return function(b){return db(a,b).length>0}}),contains:fb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:fb(function(a){return U.test(a||"")||db.error("unsupported lang: "+a),a=a.replace(ab,bb).toLowerCase(),function(b){var c;do if(c=n?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===m},focus:function(a){return a===l.activeElement&&(!l.hasFocus||l.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:lb(function(){return[0]}),last:lb(function(a,b){return[b-1]}),eq:lb(function(a,b,c){return[0>c?c+b:c]}),even:lb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:lb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:lb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:lb(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=jb(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=kb(b);function nb(){}nb.prototype=d.filters=d.pseudos,d.setFilters=new nb;function ob(a,b){var c,e,f,g,h,i,j,k=x[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){(!c||(e=Q.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=R.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(P," ")}),h=h.slice(c.length));for(g in d.filter)!(e=V[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?db.error(a):x(a,i).slice(0)}function pb(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function qb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=v++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[u,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[s]||(b[s]={}),(h=i[d])&&h[0]===u&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function rb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function sb(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function tb(a,b,c,d,e,f){return d&&!d[s]&&(d=tb(d)),e&&!e[s]&&(e=tb(e,f)),fb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||wb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:sb(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=sb(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?I.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=sb(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ub(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],i=g||d.relative[" "],j=g?1:0,k=qb(function(a){return a===b},i,!0),l=qb(function(a){return I.call(b,a)>-1},i,!0),m=[function(a,c,d){return!g&&(d||c!==h)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>j;j++)if(c=d.relative[a[j].type])m=[qb(rb(m),c)];else{if(c=d.filter[a[j].type].apply(null,a[j].matches),c[s]){for(e=++j;f>e;e++)if(d.relative[a[e].type])break;return tb(j>1&&rb(m),j>1&&pb(a.slice(0,j-1).concat({value:" "===a[j-2].type?"*":""})).replace(P,"$1"),c,e>j&&ub(a.slice(j,e)),f>e&&ub(a=a.slice(e)),f>e&&pb(a))}m.push(c)}return rb(m)}function vb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,i,j,k){var m,n,o,p=0,q="0",r=f&&[],s=[],t=h,v=f||e&&d.find.TAG("*",k),w=u+=null==t?1:Math.random()||.1,x=v.length;for(k&&(h=g!==l&&g);q!==x&&null!=(m=v[q]);q++){if(e&&m){n=0;while(o=a[n++])if(o(m,g,i)){j.push(m);break}k&&(u=w)}c&&((m=!o&&m)&&p--,f&&r.push(m))}if(p+=q,c&&q!==p){n=0;while(o=b[n++])o(r,s,g,i);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=E.call(j));s=sb(s)}G.apply(j,s),k&&!f&&s.length>0&&p+b.length>1&&db.uniqueSort(j)}return k&&(u=w,h=t),r};return c?fb(f):f}g=db.compile=function(a,b){var c,d=[],e=[],f=y[a+" "];if(!f){b||(b=ob(a)),c=b.length;while(c--)f=ub(b[c]),f[s]?d.push(f):e.push(f);f=y(a,vb(e,d))}return f};function wb(a,b,c){for(var d=0,e=b.length;e>d;d++)db(a,b[d],c);return c}function xb(a,b,e,f){var h,i,j,k,l,m=ob(a);if(!f&&1===m.length){if(i=m[0]=m[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&c.getById&&9===b.nodeType&&n&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(ab,bb),b)||[])[0],!b)return e;a=a.slice(i.shift().value.length)}h=V.needsContext.test(a)?0:i.length;while(h--){if(j=i[h],d.relative[k=j.type])break;if((l=d.find[k])&&(f=l(j.matches[0].replace(ab,bb),$.test(i[0].type)&&mb(b.parentNode)||b))){if(i.splice(h,1),a=f.length&&pb(i),!a)return G.apply(e,f),e;break}}}return g(a,m)(f,b,!n,e,$.test(a)&&mb(b.parentNode)||b),e}return c.sortStable=s.split("").sort(z).join("")===s,c.detectDuplicates=!!j,k(),c.sortDetached=gb(function(a){return 1&a.compareDocumentPosition(l.createElement("div"))}),gb(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||hb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&gb(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||hb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),gb(function(a){return null==a.getAttribute("disabled")})||hb(J,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),db}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return n.inArray(a,b)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;e>b;b++)if(n.contains(d[b],this))return!0}));for(b=0;e>b;b++)n.find(a,d[b],c);return c=this.pushStack(e>1?n.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=a.document,A=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,B=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:A.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:z,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=z.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return y.find(a);this.length=1,this[0]=d}return this.context=z,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};B.prototype=n.fn,y=n(z);var C=/^(?:parents|prev(?:Until|All))/,D={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!n(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b,c=n(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(n.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?n.inArray(this[0],n(a)):n.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function E(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return E(a,"nextSibling")},prev:function(a){return E(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return n.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(D[a]||(e=n.unique(e)),C.test(a)&&(e=e.reverse())),this.pushStack(e)}});var F=/\S+/g,G={};function H(a){var b=G[a]={};return n.each(a.match(F)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?G[a]||H(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&n.each(arguments,function(a,c){var d;while((d=n.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){if(a===!0?!--n.readyWait:!n.isReady){if(!z.body)return setTimeout(n.ready);n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(z,[n]),n.fn.trigger&&n(z).trigger("ready").off("ready"))}}});function J(){z.addEventListener?(z.removeEventListener("DOMContentLoaded",K,!1),a.removeEventListener("load",K,!1)):(z.detachEvent("onreadystatechange",K),a.detachEvent("onload",K))}function K(){(z.addEventListener||"load"===event.type||"complete"===z.readyState)&&(J(),n.ready())}n.ready.promise=function(b){if(!I)if(I=n.Deferred(),"complete"===z.readyState)setTimeout(n.ready);else if(z.addEventListener)z.addEventListener("DOMContentLoaded",K,!1),a.addEventListener("load",K,!1);else{z.attachEvent("onreadystatechange",K),a.attachEvent("onload",K);var c=!1;try{c=null==a.frameElement&&z.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!n.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}J(),n.ready()}}()}return I.promise(b)};var L="undefined",M;for(M in n(l))break;l.ownLast="0"!==M,l.inlineBlockNeedsLayout=!1,n(function(){var a,b,c=z.getElementsByTagName("body")[0];c&&(a=z.createElement("div"),a.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",b=z.createElement("div"),c.appendChild(a).appendChild(b),typeof b.style.zoom!==L&&(b.style.cssText="border:0;margin:0;width:1px;padding:1px;display:inline;zoom:1",(l.inlineBlockNeedsLayout=3===b.offsetWidth)&&(c.style.zoom=1)),c.removeChild(a),a=b=null)}),function(){var a=z.createElement("div");if(null==l.deleteExpando){l.deleteExpando=!0;try{delete a.test}catch(b){l.deleteExpando=!1}}a=null}(),n.acceptData=function(a){var b=n.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(O,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}n.data(a,b,c)}else c=void 0}return c}function Q(a){var b;for(b in a)if(("data"!==b||!n.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function R(a,b,d,e){if(n.acceptData(a)){var f,g,h=n.expando,i=a.nodeType,j=i?n.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||n.guid++:h),j[k]||(j[k]=i?{}:{toJSON:n.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=n.extend(j[k],b):j[k].data=n.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[n.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[n.camelCase(b)])):f=g,f -}}function S(a,b,c){if(n.acceptData(a)){var d,e,f=a.nodeType,g=f?n.cache:a,h=f?a[n.expando]:n.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){n.isArray(b)?b=b.concat(n.map(b,n.camelCase)):b in d?b=[b]:(b=n.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!Q(d):!n.isEmptyObject(d))return}(c||(delete g[h].data,Q(g[h])))&&(f?n.cleanData([a],!0):l.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}n.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?n.cache[a[n.expando]]:a[n.expando],!!a&&!Q(a)},data:function(a,b,c){return R(a,b,c)},removeData:function(a,b){return S(a,b)},_data:function(a,b,c){return R(a,b,c,!0)},_removeData:function(a,b){return S(a,b,!0)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=n.data(f),1===f.nodeType&&!n._data(f,"parsedAttrs"))){c=g.length;while(c--)d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d]));n._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){n.data(this,a)}):arguments.length>1?this.each(function(){n.data(this,a,b)}):f?P(f,a,n.data(f,a)):void 0},removeData:function(a){return this.each(function(){n.removeData(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=n._data(a,b),c&&(!d||n.isArray(c)?d=n._data(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return n._data(a,c)||n._data(a,c,{empty:n.Callbacks("once memory").add(function(){n._removeData(a,b+"queue"),n._removeData(a,c)})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=n.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=n._data(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var T=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,U=["Top","Right","Bottom","Left"],V=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)},W=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},X=/^(?:checkbox|radio)$/i;!function(){var a=z.createDocumentFragment(),b=z.createElement("div"),c=z.createElement("input");if(b.setAttribute("className","t"),b.innerHTML=" <link/><table></table><a href='/a'>a</a>",l.leadingWhitespace=3===b.firstChild.nodeType,l.tbody=!b.getElementsByTagName("tbody").length,l.htmlSerialize=!!b.getElementsByTagName("link").length,l.html5Clone="<:nav></:nav>"!==z.createElement("nav").cloneNode(!0).outerHTML,c.type="checkbox",c.checked=!0,a.appendChild(c),l.appendChecked=c.checked,b.innerHTML="<textarea>x</textarea>",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,a.appendChild(b),b.innerHTML="<input type='radio' checked='checked' name='t'/>",l.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,l.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){l.noCloneEvent=!1}),b.cloneNode(!0).click()),null==l.deleteExpando){l.deleteExpando=!0;try{delete b.test}catch(d){l.deleteExpando=!1}}a=b=c=null}(),function(){var b,c,d=z.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(l[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),l[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var Y=/^(?:input|select|textarea)$/i,Z=/^key/,$=/^(?:mouse|contextmenu)|click/,_=/^(?:focusinfocus|focusoutblur)$/,ab=/^([^.]*)(?:\.(.+)|)$/;function bb(){return!0}function cb(){return!1}function db(){try{return z.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof n===L||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(F)||[""],h=b.length;while(h--)f=ab.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||"").match(F)||[""],j=b.length;while(j--)if(h=ab.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,m,o=[d||z],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||z,3!==d.nodeType&&8!==d.nodeType&&!_.test(p+n.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[n.expando]?b:new n.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),k=n.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!n.isWindow(d)){for(i=k.delegateType||p,_.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||z)&&o.push(l.defaultView||l.parentWindow||a)}m=0;while((h=o[m++])&&!b.isPropagationStopped())b.type=m>1?i:k.bindType||p,f=(n._data(h,"events")||{})[b.type]&&n._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&n.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&n.acceptData(d)&&g&&d[p]&&!n.isWindow(d)){l=d[g],l&&(d[g]=null),n.event.triggered=p;try{d[p]()}catch(r){}n.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(n._data(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((n.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?n(c,this).index(i)>=0:n.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},fix:function(a){if(a[n.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=$.test(e)?this.mouseHooks:Z.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new n.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=f.srcElement||z),3===a.target.nodeType&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,g.filter?g.filter(a,f):a},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,d,e,f=b.button,g=b.fromElement;return null==a.pageX&&null!=b.clientX&&(d=a.target.ownerDocument||z,e=d.documentElement,c=d.body,a.pageX=b.clientX+(e&&e.scrollLeft||c&&c.scrollLeft||0)-(e&&e.clientLeft||c&&c.clientLeft||0),a.pageY=b.clientY+(e&&e.scrollTop||c&&c.scrollTop||0)-(e&&e.clientTop||c&&c.clientTop||0)),!a.relatedTarget&&g&&(a.relatedTarget=g===a.target?b.toElement:g),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==db()&&this.focus)try{return this.focus(),!1}catch(a){}},delegateType:"focusin"},blur:{trigger:function(){return this===db()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return n.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=n.extend(new n.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?n.event.trigger(e,null,b):n.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},n.removeEvent=z.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]===L&&(a[d]=null),a.detachEvent(d,c))},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&(a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault())?bb:cb):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={isDefaultPrevented:cb,isPropagationStopped:cb,isImmediatePropagationStopped:cb,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=bb,a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=bb,a&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=bb,this.stopPropagation()}},n.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!n.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),l.submitBubbles||(n.event.special.submit={setup:function(){return n.nodeName(this,"form")?!1:void n.event.add(this,"click._submit keypress._submit",function(a){var b=a.target,c=n.nodeName(b,"input")||n.nodeName(b,"button")?b.form:void 0;c&&!n._data(c,"submitBubbles")&&(n.event.add(c,"submit._submit",function(a){a._submit_bubble=!0}),n._data(c,"submitBubbles",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&n.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){return n.nodeName(this,"form")?!1:void n.event.remove(this,"._submit")}}),l.changeBubbles||(n.event.special.change={setup:function(){return Y.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(n.event.add(this,"propertychange._change",function(a){"checked"===a.originalEvent.propertyName&&(this._just_changed=!0)}),n.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),n.event.simulate("change",this,a,!0)})),!1):void n.event.add(this,"beforeactivate._change",function(a){var b=a.target;Y.test(b.nodeName)&&!n._data(b,"changeBubbles")&&(n.event.add(b,"change._change",function(a){!this.parentNode||a.isSimulated||a.isTrigger||n.event.simulate("change",this.parentNode,a,!0)}),n._data(b,"changeBubbles",!0))})},handle:function(a){var b=a.target;return this!==b||a.isSimulated||a.isTrigger||"radio"!==b.type&&"checkbox"!==b.type?a.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return n.event.remove(this,"._change"),!Y.test(this.nodeName)}}),l.focusinBubbles||n.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a),!0)};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=n._data(d,b);e||d.addEventListener(a,c,!0),n._data(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=n._data(d,b)-1;e?n._data(d,b,e):(d.removeEventListener(a,c,!0),n._removeData(d,b))}}}),n.fn.extend({on:function(a,b,c,d,e){var f,g;if("object"==typeof a){"string"!=typeof b&&(c=c||b,b=void 0);for(f in a)this.on(f,b,c,a[f],e);return this}if(null==c&&null==d?(d=b,c=b=void 0):null==d&&("string"==typeof b?(d=c,c=void 0):(d=c,c=b,b=void 0)),d===!1)d=cb;else if(!d)return this;return 1===e&&(g=d,d=function(a){return n().off(a),g.apply(this,arguments)},d.guid=g.guid||(g.guid=n.guid++)),this.each(function(){n.event.add(this,a,d,c,b)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return(b===!1||"function"==typeof b)&&(c=b,b=void 0),c===!1&&(c=cb),this.each(function(){n.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}});function eb(a){var b=fb.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}var fb="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gb=/ jQuery\d+="(?:null|\d+)"/g,hb=new RegExp("<(?:"+fb+")[\\s/>]","i"),ib=/^\s+/,jb=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,kb=/<([\w:]+)/,lb=/<tbody/i,mb=/<|&#?\w+;/,nb=/<(?:script|style|link)/i,ob=/checked\s*(?:[^=]|=\s*.checked.)/i,pb=/^$|\/(?:java|ecma)script/i,qb=/^true\/(.*)/,rb=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,sb={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:l.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},tb=eb(z),ub=tb.appendChild(z.createElement("div"));sb.optgroup=sb.option,sb.tbody=sb.tfoot=sb.colgroup=sb.caption=sb.thead,sb.th=sb.td;function vb(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==L?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==L?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||n.nodeName(d,b)?f.push(d):n.merge(f,vb(d,b));return void 0===b||b&&n.nodeName(a,b)?n.merge([a],f):f}function wb(a){X.test(a.type)&&(a.defaultChecked=a.checked)}function xb(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function yb(a){return a.type=(null!==n.find.attr(a,"type"))+"/"+a.type,a}function zb(a){var b=qb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Ab(a,b){for(var c,d=0;null!=(c=a[d]);d++)n._data(c,"globalEval",!b||n._data(b[d],"globalEval"))}function Bb(a,b){if(1===b.nodeType&&n.hasData(a)){var c,d,e,f=n._data(a),g=n._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)n.event.add(b,c,h[c][d])}g.data&&(g.data=n.extend({},g.data))}}function Cb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!l.noCloneEvent&&b[n.expando]){e=n._data(b);for(d in e.events)n.removeEvent(b,d,e.handle);b.removeAttribute(n.expando)}"script"===c&&b.text!==a.text?(yb(b).text=a.text,zb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),l.html5Clone&&a.innerHTML&&!n.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&X.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}n.extend({clone:function(a,b,c){var d,e,f,g,h,i=n.contains(a.ownerDocument,a);if(l.html5Clone||n.isXMLDoc(a)||!hb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(ub.innerHTML=a.outerHTML,ub.removeChild(f=ub.firstChild)),!(l.noCloneEvent&&l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(d=vb(f),h=vb(a),g=0;null!=(e=h[g]);++g)d[g]&&Cb(e,d[g]);if(b)if(c)for(h=h||vb(a),d=d||vb(f),g=0;null!=(e=h[g]);g++)Bb(e,d[g]);else Bb(a,f);return d=vb(f,"script"),d.length>0&&Ab(d,!i&&vb(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k,m=a.length,o=eb(b),p=[],q=0;m>q;q++)if(f=a[q],f||0===f)if("object"===n.type(f))n.merge(p,f.nodeType?[f]:f);else if(mb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(kb.exec(f)||["",""])[1].toLowerCase(),k=sb[i]||sb._default,h.innerHTML=k[1]+f.replace(jb,"<$1></$2>")+k[2],e=k[0];while(e--)h=h.lastChild;if(!l.leadingWhitespace&&ib.test(f)&&p.push(b.createTextNode(ib.exec(f)[0])),!l.tbody){f="table"!==i||lb.test(f)?"<table>"!==k[1]||lb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)n.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}n.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),l.appendChecked||n.grep(vb(p,"input"),wb),q=0;while(f=p[q++])if((!d||-1===n.inArray(f,d))&&(g=n.contains(f.ownerDocument,f),h=vb(o.appendChild(f),"script"),g&&Ab(h),c)){e=0;while(f=h[e++])pb.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=n.expando,j=n.cache,k=l.deleteExpando,m=n.event.special;null!=(d=a[h]);h++)if((b||n.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)m[e]?n.event.remove(d,e):n.removeEvent(d,e,g.handle);j[f]&&(delete j[f],k?delete d[i]:typeof d.removeAttribute!==L?d.removeAttribute(i):d[i]=null,c.push(f))}}}),n.fn.extend({text:function(a){return W(this,function(a){return void 0===a?n.text(this):this.empty().append((this[0]&&this[0].ownerDocument||z).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=xb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=xb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(vb(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&Ab(vb(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&n.cleanData(vb(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&n.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return W(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(gb,""):void 0;if(!("string"!=typeof a||nb.test(a)||!l.htmlSerialize&&hb.test(a)||!l.leadingWhitespace&&ib.test(a)||sb[(kb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(jb,"<$1></$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(vb(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(vb(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,k=this.length,m=this,o=k-1,p=a[0],q=n.isFunction(p);if(q||k>1&&"string"==typeof p&&!l.checkClone&&ob.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(k&&(i=n.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=n.map(vb(i,"script"),yb),f=g.length;k>j;j++)d=i,j!==o&&(d=n.clone(d,!0,!0),f&&n.merge(g,vb(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,n.map(g,zb),j=0;f>j;j++)d=g[j],pb.test(d.type||"")&&!n._data(d,"globalEval")&&n.contains(h,d)&&(d.src?n._evalUrl&&n._evalUrl(d.src):n.globalEval((d.text||d.textContent||d.innerHTML||"").replace(rb,"")));i=c=null}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=0,e=[],g=n(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),n(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Db,Eb={};function Fb(b,c){var d=n(c.createElement(b)).appendTo(c.body),e=a.getDefaultComputedStyle?a.getDefaultComputedStyle(d[0]).display:n.css(d[0],"display");return d.detach(),e}function Gb(a){var b=z,c=Eb[a];return c||(c=Fb(a,b),"none"!==c&&c||(Db=(Db||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=(Db[0].contentWindow||Db[0].contentDocument).document,b.write(),b.close(),c=Fb(a,b),Db.detach()),Eb[a]=c),c}!function(){var a,b,c=z.createElement("div"),d="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;padding:0;margin:0;border:0";c.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",a=c.getElementsByTagName("a")[0],a.style.cssText="float:left;opacity:.5",l.opacity=/^0.5/.test(a.style.opacity),l.cssFloat=!!a.style.cssFloat,c.style.backgroundClip="content-box",c.cloneNode(!0).style.backgroundClip="",l.clearCloneStyle="content-box"===c.style.backgroundClip,a=c=null,l.shrinkWrapBlocks=function(){var a,c,e,f;if(null==b){if(a=z.getElementsByTagName("body")[0],!a)return;f="border:0;width:0;height:0;position:absolute;top:0;left:-9999px",c=z.createElement("div"),e=z.createElement("div"),a.appendChild(c).appendChild(e),b=!1,typeof e.style.zoom!==L&&(e.style.cssText=d+";width:1px;padding:1px;zoom:1",e.innerHTML="<div></div>",e.firstChild.style.width="5px",b=3!==e.offsetWidth),a.removeChild(c),a=c=e=null}return b}}();var Hb=/^margin/,Ib=new RegExp("^("+T+")(?!px)[a-z%]+$","i"),Jb,Kb,Lb=/^(top|right|bottom|left)$/;a.getComputedStyle?(Jb=function(a){return a.ownerDocument.defaultView.getComputedStyle(a,null)},Kb=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Jb(a),g=c?c.getPropertyValue(b)||c[b]:void 0,c&&(""!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),Ib.test(g)&&Hb.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0===g?g:g+""}):z.documentElement.currentStyle&&(Jb=function(a){return a.currentStyle},Kb=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Jb(a),g=c?c[b]:void 0,null==g&&h&&h[b]&&(g=h[b]),Ib.test(g)&&!Lb.test(b)&&(d=h.left,e=a.runtimeStyle,f=e&&e.left,f&&(e.left=a.currentStyle.left),h.left="fontSize"===b?"1em":g,g=h.pixelLeft+"px",h.left=d,f&&(e.left=f)),void 0===g?g:g+""||"auto"});function Mb(a,b){return{get:function(){var c=a();if(null!=c)return c?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d,e,f,g,h=z.createElement("div"),i="border:0;width:0;height:0;position:absolute;top:0;left:-9999px",j="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;padding:0;margin:0;border:0";h.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",b=h.getElementsByTagName("a")[0],b.style.cssText="float:left;opacity:.5",l.opacity=/^0.5/.test(b.style.opacity),l.cssFloat=!!b.style.cssFloat,h.style.backgroundClip="content-box",h.cloneNode(!0).style.backgroundClip="",l.clearCloneStyle="content-box"===h.style.backgroundClip,b=h=null,n.extend(l,{reliableHiddenOffsets:function(){if(null!=c)return c;var a,b,d,e=z.createElement("div"),f=z.getElementsByTagName("body")[0];if(f)return e.setAttribute("className","t"),e.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",a=z.createElement("div"),a.style.cssText=i,f.appendChild(a).appendChild(e),e.innerHTML="<table><tr><td></td><td>t</td></tr></table>",b=e.getElementsByTagName("td"),b[0].style.cssText="padding:0;margin:0;border:0;display:none",d=0===b[0].offsetHeight,b[0].style.display="",b[1].style.display="none",c=d&&0===b[0].offsetHeight,f.removeChild(a),e=f=null,c},boxSizing:function(){return null==d&&k(),d},boxSizingReliable:function(){return null==e&&k(),e},pixelPosition:function(){return null==f&&k(),f},reliableMarginRight:function(){var b,c,d,e;if(null==g&&a.getComputedStyle){if(b=z.getElementsByTagName("body")[0],!b)return;c=z.createElement("div"),d=z.createElement("div"),c.style.cssText=i,b.appendChild(c).appendChild(d),e=d.appendChild(z.createElement("div")),e.style.cssText=d.style.cssText=j,e.style.marginRight=e.style.width="0",d.style.width="1px",g=!parseFloat((a.getComputedStyle(e,null)||{}).marginRight),b.removeChild(c)}return g}});function k(){var b,c,h=z.getElementsByTagName("body")[0];h&&(b=z.createElement("div"),c=z.createElement("div"),b.style.cssText=i,h.appendChild(b).appendChild(c),c.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:absolute;display:block;padding:1px;border:1px;width:4px;margin-top:1%;top:1%",n.swap(h,null!=h.style.zoom?{zoom:1}:{},function(){d=4===c.offsetWidth}),e=!0,f=!1,g=!0,a.getComputedStyle&&(f="1%"!==(a.getComputedStyle(c,null)||{}).top,e="4px"===(a.getComputedStyle(c,null)||{width:"4px"}).width),h.removeChild(b),c=h=null)}}(),n.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var Nb=/alpha\([^)]*\)/i,Ob=/opacity\s*=\s*([^)]*)/,Pb=/^(none|table(?!-c[ea]).+)/,Qb=new RegExp("^("+T+")(.*)$","i"),Rb=new RegExp("^([+-])=("+T+")","i"),Sb={position:"absolute",visibility:"hidden",display:"block"},Tb={letterSpacing:0,fontWeight:400},Ub=["Webkit","O","Moz","ms"];function Vb(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=Ub.length;while(e--)if(b=Ub[e]+c,b in a)return b;return d}function Wb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=n._data(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&V(d)&&(f[g]=n._data(d,"olddisplay",Gb(d.nodeName)))):f[g]||(e=V(d),(c&&"none"!==c||!e)&&n._data(d,"olddisplay",e?c:n.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}function Xb(a,b,c){var d=Qb.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Yb(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=n.css(a,c+U[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+U[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+U[f]+"Width",!0,e))):(g+=n.css(a,"padding"+U[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+U[f]+"Width",!0,e)));return g}function Zb(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=Jb(a),g=l.boxSizing()&&"border-box"===n.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=Kb(a,b,f),(0>e||null==e)&&(e=a.style[b]),Ib.test(e))return e;d=g&&(l.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Yb(a,b,c||(g?"border":"content"),d,f)+"px"}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Kb(a,"opacity");return""===c?"1":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":l.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;if(b=n.cssProps[h]||(n.cssProps[h]=Vb(i,h)),g=n.cssHooks[b]||n.cssHooks[h],void 0===c)return g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b];if(f=typeof c,"string"===f&&(e=Rb.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(n.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||n.cssNumber[h]||(c+="px"),l.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),!(g&&"set"in g&&void 0===(c=g.set(a,c,d)))))try{i[b]="",i[b]=c}catch(j){}}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=Vb(a.style,h)),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(f=g.get(a,!0,c)),void 0===f&&(f=Kb(a,b,d)),"normal"===f&&b in Tb&&(f=Tb[b]),""===c||c?(e=parseFloat(f),c===!0||n.isNumeric(e)?e||0:f):f}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?0===a.offsetWidth&&Pb.test(n.css(a,"display"))?n.swap(a,Sb,function(){return Zb(a,b,d)}):Zb(a,b,d):void 0},set:function(a,c,d){var e=d&&Jb(a);return Xb(a,c,d?Yb(a,b,d,l.boxSizing()&&"border-box"===n.css(a,"boxSizing",!1,e),e):0)}}}),l.opacity||(n.cssHooks.opacity={get:function(a,b){return Ob.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=n.isNumeric(b)?"alpha(opacity="+100*b+")":"",f=d&&d.filter||c.filter||"";c.zoom=1,(b>=1||""===b)&&""===n.trim(f.replace(Nb,""))&&c.removeAttribute&&(c.removeAttribute("filter"),""===b||d&&!d.filter)||(c.filter=Nb.test(f)?f.replace(Nb,e):f+" "+e)}}),n.cssHooks.marginRight=Mb(l.reliableMarginRight,function(a,b){return b?n.swap(a,{display:"inline-block"},Kb,[a,"marginRight"]):void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+U[d]+b]=f[d]||f[d-2]||f[0];return e}},Hb.test(a)||(n.cssHooks[a+b].set=Xb)}),n.fn.extend({css:function(a,b){return W(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=Jb(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b) -},a,b,arguments.length>1)},show:function(){return Wb(this,!0)},hide:function(){return Wb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){V(this)?n(this).show():n(this).hide()})}});function $b(a,b,c,d,e){return new $b.prototype.init(a,b,c,d,e)}n.Tween=$b,$b.prototype={constructor:$b,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=$b.propHooks[this.prop];return a&&a.get?a.get(this):$b.propHooks._default.get(this)},run:function(a){var b,c=$b.propHooks[this.prop];return this.pos=b=this.options.duration?n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):$b.propHooks._default.set(this),this}},$b.prototype.init.prototype=$b.prototype,$b.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[n.cssProps[a.prop]]||n.cssHooks[a.prop])?n.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},$b.propHooks.scrollTop=$b.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},n.fx=$b.prototype.init,n.fx.step={};var _b,ac,bc=/^(?:toggle|show|hide)$/,cc=new RegExp("^(?:([+-])=|)("+T+")([a-z%]*)$","i"),dc=/queueHooks$/,ec=[jc],fc={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=cc.exec(b),f=e&&e[3]||(n.cssNumber[a]?"":"px"),g=(n.cssNumber[a]||"px"!==f&&+d)&&cc.exec(n.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,n.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function gc(){return setTimeout(function(){_b=void 0}),_b=n.now()}function hc(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=U[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function ic(a,b,c){for(var d,e=(fc[b]||[]).concat(fc["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function jc(a,b,c){var d,e,f,g,h,i,j,k,m=this,o={},p=a.style,q=a.nodeType&&V(a),r=n._data(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,m.always(function(){m.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=n.css(a,"display"),k=Gb(a.nodeName),"none"===j&&(j=k),"inline"===j&&"none"===n.css(a,"float")&&(l.inlineBlockNeedsLayout&&"inline"!==k?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",l.shrinkWrapBlocks()||m.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],bc.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||n.style(a,d)}if(!n.isEmptyObject(o)){r?"hidden"in r&&(q=r.hidden):r=n._data(a,"fxshow",{}),f&&(r.hidden=!q),q?n(a).show():m.done(function(){n(a).hide()}),m.done(function(){var b;n._removeData(a,"fxshow");for(b in o)n.style(a,b,o[b])});for(d in o)g=ic(q?r[d]:0,d,m),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function kc(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function lc(a,b,c){var d,e,f=0,g=ec.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=_b||gc(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:_b||gc(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(kc(k,j.opts.specialEasing);g>f;f++)if(d=ec[f].call(j,a,k,j.opts))return d;return n.map(k,ic,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}n.Animation=n.extend(lc,{tweener:function(a,b){n.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],fc[c]=fc[c]||[],fc[c].unshift(b)},prefilter:function(a,b){b?ec.unshift(a):ec.push(a)}}),n.speed=function(a,b,c){var d=a&&"object"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(V).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=lc(this,n.extend({},a),f);(e||n._data(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=n.timers,g=n._data(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&dc.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=n._data(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each(["toggle","show","hide"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(hc(b,!0),a,d,e)}}),n.each({slideDown:hc("show"),slideUp:hc("hide"),slideToggle:hc("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=n.timers,c=0;for(_b=n.now();c<b.length;c++)a=b[c],a()||b[c]!==a||b.splice(c--,1);b.length||n.fx.stop(),_b=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){ac||(ac=setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){clearInterval(ac),ac=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(a,b){return a=n.fx?n.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},function(){var a,b,c,d,e=z.createElement("div");e.setAttribute("className","t"),e.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",a=e.getElementsByTagName("a")[0],c=z.createElement("select"),d=c.appendChild(z.createElement("option")),b=e.getElementsByTagName("input")[0],a.style.cssText="top:1px",l.getSetAttribute="t"!==e.className,l.style=/top/.test(a.getAttribute("style")),l.hrefNormalized="/a"===a.getAttribute("href"),l.checkOn=!!b.value,l.optSelected=d.selected,l.enctype=!!z.createElement("form").enctype,c.disabled=!0,l.optDisabled=!d.disabled,b=z.createElement("input"),b.setAttribute("value",""),l.input=""===b.getAttribute("value"),b.value="t",b.setAttribute("type","radio"),l.radioValue="t"===b.value,a=b=c=d=e=null}();var mc=/\r/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e?e+="":n.isArray(e)&&(e=n.map(e,function(a){return null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(mc,""):null==c?"":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,"value");return null!=b?b:n.text(a)}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(l.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&n.nodeName(c.parentNode,"optgroup"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)if(d=e[g],n.inArray(n.valHooks.option.get(d),f)>=0)try{d.selected=c=!0}catch(h){d.scrollHeight}else d.selected=!1;return c||(a.selectedIndex=-1),e}}}}),n.each(["radio","checkbox"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>=0:void 0}},l.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var nc,oc,pc=n.expr.attrHandle,qc=/^(?:checked|selected)$/i,rc=l.getSetAttribute,sc=l.input;n.fn.extend({attr:function(a,b){return W(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===L?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),d=n.attrHooks[b]||(n.expr.match.bool.test(b)?oc:nc)),void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void n.removeAttr(a,b))},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(F);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)?sc&&rc||!qc.test(c)?a[d]=!1:a[n.camelCase("default-"+c)]=a[d]=!1:n.attr(a,c,""),a.removeAttribute(rc?c:d)},attrHooks:{type:{set:function(a,b){if(!l.radioValue&&"radio"===b&&n.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),oc={set:function(a,b,c){return b===!1?n.removeAttr(a,c):sc&&rc||!qc.test(c)?a.setAttribute(!rc&&n.propFix[c]||c,c):a[n.camelCase("default-"+c)]=a[c]=!0,c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=pc[b]||n.find.attr;pc[b]=sc&&rc||!qc.test(b)?function(a,b,d){var e,f;return d||(f=pc[b],pc[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,pc[b]=f),e}:function(a,b,c){return c?void 0:a[n.camelCase("default-"+b)]?b.toLowerCase():null}}),sc&&rc||(n.attrHooks.value={set:function(a,b,c){return n.nodeName(a,"input")?void(a.defaultValue=b):nc&&nc.set(a,b,c)}}),rc||(nc={set:function(a,b,c){var d=a.getAttributeNode(c);return d||a.setAttributeNode(d=a.ownerDocument.createAttribute(c)),d.value=b+="","value"===c||b===a.getAttribute(c)?b:void 0}},pc.id=pc.name=pc.coords=function(a,b,c){var d;return c?void 0:(d=a.getAttributeNode(b))&&""!==d.value?d.value:null},n.valHooks.button={get:function(a,b){var c=a.getAttributeNode(b);return c&&c.specified?c.value:void 0},set:nc.set},n.attrHooks.contenteditable={set:function(a,b,c){nc.set(a,""===b?!1:b,c)}},n.each(["width","height"],function(a,b){n.attrHooks[b]={set:function(a,c){return""===c?(a.setAttribute(b,"auto"),c):void 0}}})),l.style||(n.attrHooks.style={get:function(a){return a.style.cssText||void 0},set:function(a,b){return a.style.cssText=b+""}});var tc=/^(?:input|select|textarea|button|object)$/i,uc=/^(?:a|area)$/i;n.fn.extend({prop:function(a,b){return W(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return a=n.propFix[a]||a,this.each(function(){try{this[a]=void 0,delete this[a]}catch(b){}})}}),n.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!n.isXMLDoc(a),f&&(b=n.propFix[b]||b,e=n.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=n.find.attr(a,"tabindex");return b?parseInt(b,10):tc.test(a.nodeName)||uc.test(a.nodeName)&&a.href?0:-1}}}}),l.hrefNormalized||n.each(["href","src"],function(a,b){n.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}),l.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}}),n.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){n.propFix[this.toLowerCase()]=this}),l.enctype||(n.propFix.enctype="encoding");var vc=/[\t\r\n\f]/g;n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j="string"==typeof a&&a;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(F)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(vc," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=n.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j=0===arguments.length||"string"==typeof a&&a;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(F)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(vc," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?n.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(n.isFunction(a)?function(c){n(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=n(this),f=a.match(F)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===L||"boolean"===c)&&(this.className&&n._data(this,"__className__",this.className),this.className=this.className||a===!1?"":n._data(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(vc," ").indexOf(b)>=0)return!0;return!1}}),n.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var wc=n.now(),xc=/\?/,yc=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;n.parseJSON=function(b){if(a.JSON&&a.JSON.parse)return a.JSON.parse(b+"");var c,d=null,e=n.trim(b+"");return e&&!n.trim(e.replace(yc,function(a,b,e,f){return c&&b&&(d=0),0===d?a:(c=e||b,d+=!f-!e,"")}))?Function("return "+e)():n.error("Invalid JSON: "+b)},n.parseXML=function(b){var c,d;if(!b||"string"!=typeof b)return null;try{a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b))}catch(e){c=void 0}return c&&c.documentElement&&!c.getElementsByTagName("parsererror").length||n.error("Invalid XML: "+b),c};var zc,Ac,Bc=/#.*$/,Cc=/([?&])_=[^&]*/,Dc=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Ec=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Fc=/^(?:GET|HEAD)$/,Gc=/^\/\//,Hc=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Ic={},Jc={},Kc="*/".concat("*");try{Ac=location.href}catch(Lc){Ac=z.createElement("a"),Ac.href="",Ac=Ac.href}zc=Hc.exec(Ac.toLowerCase())||[];function Mc(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(F)||[];if(n.isFunction(c))while(d=f[e++])"+"===d.charAt(0)?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Nc(a,b,c,d){var e={},f=a===Jc;function g(h){var i;return e[h]=!0,n.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Oc(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(d in b)void 0!==b[d]&&((e[d]?a:c||(c={}))[d]=b[d]);return c&&n.extend(!0,a,c),a}function Pc(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===e&&(e=a.mimeType||b.getResponseHeader("Content-Type"));if(e)for(g in h)if(h[g]&&h[g].test(e)){i.unshift(g);break}if(i[0]in c)f=i[0];else{for(g in c){if(!i[0]||a.converters[g+" "+i[0]]){f=g;break}d||(d=g)}f=f||d}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Qc(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Ac,type:"GET",isLocal:Ec.test(zc[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Kc,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":n.parseJSON,"text xml":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Oc(Oc(a,n.ajaxSettings),b):Oc(n.ajaxSettings,a)},ajaxPrefilter:Mc(Ic),ajaxTransport:Mc(Jc),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=n.ajaxSetup({},b),l=k.context||k,m=k.context&&(l.nodeType||l.jquery)?n(l):n.event,o=n.Deferred(),p=n.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!j){j={};while(b=Dc.exec(f))j[b[1].toLowerCase()]=b[2]}b=j[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?f:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return i&&i.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||Ac)+"").replace(Bc,"").replace(Gc,zc[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=n.trim(k.dataType||"*").toLowerCase().match(F)||[""],null==k.crossDomain&&(c=Hc.exec(k.url.toLowerCase()),k.crossDomain=!(!c||c[1]===zc[1]&&c[2]===zc[2]&&(c[3]||("http:"===c[1]?"80":"443"))===(zc[3]||("http:"===zc[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=n.param(k.data,k.traditional)),Nc(Ic,k,b,v),2===t)return v;h=k.global,h&&0===n.active++&&n.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!Fc.test(k.type),e=k.url,k.hasContent||(k.data&&(e=k.url+=(xc.test(e)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=Cc.test(e)?e.replace(Cc,"$1_="+wc++):e+(xc.test(e)?"&":"?")+"_="+wc++)),k.ifModified&&(n.lastModified[e]&&v.setRequestHeader("If-Modified-Since",n.lastModified[e]),n.etag[e]&&v.setRequestHeader("If-None-Match",n.etag[e])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",k.contentType),v.setRequestHeader("Accept",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+("*"!==k.dataTypes[0]?", "+Kc+"; q=0.01":""):k.accepts["*"]);for(d in k.headers)v.setRequestHeader(d,k.headers[d]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(d in{success:1,error:1,complete:1})v[d](k[d]);if(i=Nc(Jc,k,b,v)){v.readyState=1,h&&m.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,i.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,c,d){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),i=void 0,f=d||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,c&&(u=Pc(k,v,c)),u=Qc(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(n.lastModified[e]=w),w=v.getResponseHeader("etag"),w&&(n.etag[e]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+"",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,h&&m.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),h&&(m.trigger("ajaxComplete",[v,k]),--n.active||n.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return n.get(a,b,c,"json")},getScript:function(a,b){return n.get(a,void 0,b,"script")}}),n.each(["get","post"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),n.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n._evalUrl=function(a){return n.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){if(n.isFunction(a))return this.each(function(b){n(this).wrapAll(a.call(this,b))});if(this[0]){var b=n(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&1===a.firstChild.nodeType)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return this.each(n.isFunction(a)?function(b){n(this).wrapInner(a.call(this,b))}:function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,"body")||n(this).replaceWith(this.childNodes)}).end()}}),n.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0||!l.reliableHiddenOffsets()&&"none"===(a.style&&a.style.display||n.css(a,"display"))},n.expr.filters.visible=function(a){return!n.expr.filters.hidden(a)};var Rc=/%20/g,Sc=/\[\]$/,Tc=/\r?\n/g,Uc=/^(?:submit|button|image|reset|file)$/i,Vc=/^(?:input|select|textarea|keygen)/i;function Wc(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||Sc.test(a)?d(a,e):Wc(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==n.type(b))d(a,b);else for(e in b)Wc(a+"["+e+"]",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)Wc(c,a[c],b,e);return d.join("&").replace(Rc,"+")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,"elements");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(":disabled")&&Vc.test(this.nodeName)&&!Uc.test(a)&&(this.checked||!X.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(Tc,"\r\n")}}):{name:b.name,value:c.replace(Tc,"\r\n")}}).get()}}),n.ajaxSettings.xhr=void 0!==a.ActiveXObject?function(){return!this.isLocal&&/^(get|post|head|put|delete|options)$/i.test(this.type)&&$c()||_c()}:$c;var Xc=0,Yc={},Zc=n.ajaxSettings.xhr();a.ActiveXObject&&n(a).on("unload",function(){for(var a in Yc)Yc[a](void 0,!0)}),l.cors=!!Zc&&"withCredentials"in Zc,Zc=l.ajax=!!Zc,Zc&&n.ajaxTransport(function(a){if(!a.crossDomain||l.cors){var b;return{send:function(c,d){var e,f=a.xhr(),g=++Xc;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)void 0!==c[e]&&f.setRequestHeader(e,c[e]+"");f.send(a.hasContent&&a.data||null),b=function(c,e){var h,i,j;if(b&&(e||4===f.readyState))if(delete Yc[g],b=void 0,f.onreadystatechange=n.noop,e)4!==f.readyState&&f.abort();else{j={},h=f.status,"string"==typeof f.responseText&&(j.text=f.responseText);try{i=f.statusText}catch(k){i=""}h||!a.isLocal||a.crossDomain?1223===h&&(h=204):h=j.text?200:404}j&&d(h,i,j,f.getAllResponseHeaders())},a.async?4===f.readyState?setTimeout(b):f.onreadystatechange=Yc[g]=b:b()},abort:function(){b&&b(void 0,!0)}}}});function $c(){try{return new a.XMLHttpRequest}catch(b){}}function _c(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}n.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c=z.head||n("head")[0]||z.documentElement;return{send:function(d,e){b=z.createElement("script"),b.async=!0,a.scriptCharset&&(b.charset=a.scriptCharset),b.src=a.url,b.onload=b.onreadystatechange=function(a,c){(c||!b.readyState||/loaded|complete/.test(b.readyState))&&(b.onload=b.onreadystatechange=null,b.parentNode&&b.parentNode.removeChild(b),b=null,c||e(200,"success"))},c.insertBefore(b,c.firstChild)},abort:function(){b&&b.onload(void 0,!0)}}}});var ad=[],bd=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=ad.pop()||n.expando+"_"+wc++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(bd.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&bd.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(bd,"$1"+e):b.jsonp!==!1&&(b.url+=(xc.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||n.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,ad.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),n.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||z;var d=v.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=n.buildFragment([a],b,e),e&&e.length&&n(e).remove(),n.merge([],d.childNodes))};var cd=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&cd)return cd.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=a.slice(h,a.length),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(f="POST"),g.length>0&&n.ajax({url:a,type:f,dataType:"html",data:b}).done(function(a){e=arguments,g.html(d?n("<div>").append(n.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,e||[a.responseText,b,a])}),this},n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};var dd=a.document.documentElement;function ed(a){return n.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.css(a,"left"),j=("absolute"===k||"fixed"===k)&&n.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,n.contains(b,e)?(typeof e.getBoundingClientRect!==L&&(d=e.getBoundingClientRect()),c=ed(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===n.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(c=a.offset()),c.top+=n.css(a[0],"borderTopWidth",!0),c.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-n.css(d,"marginTop",!0),left:b.left-c.left-n.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||dd;while(a&&!n.nodeName(a,"html")&&"static"===n.css(a,"position"))a=a.offsetParent;return a||dd})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);n.fn[a]=function(d){return W(this,function(a,d,e){var f=ed(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?n(f).scrollLeft():e,c?e:n(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=Mb(l.pixelPosition,function(a,c){return c?(c=Kb(a,b),Ib.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return W(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var fd=a.jQuery,gd=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=gd),b&&a.jQuery===n&&(a.jQuery=fd),n},typeof b===L&&(a.jQuery=a.$=n),n}); +/*! jQuery v1.12.4 | (c) jQuery Foundation | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="1.12.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray||function(a){return"array"===n.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(!l.ownFirst)for(b in a)return k.call(a,b);for(b in a);return void 0===b||k.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(h)return h.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=e.call(arguments,2),d=function(){return a.apply(b||this,c.concat(e.call(arguments)))},d.guid=a.guid=a.guid||n.guid++,d):void 0},now:function(){return+new Date},support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+N+")*)|.*)\\)|)",P=new RegExp(L+"+","g"),Q=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),R=new RegExp("^"+L+"*,"+L+"*"),S=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),T=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),U=new RegExp(O),V=new RegExp("^"+M+"$"),W={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,$=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,aa=/'|\\/g,ba=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),ca=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(aa,"\\$&"):b.setAttribute("id",k=u),r=g(a),h=r.length,l=V.test(k)?"#"+k:"[id='"+k+"']";while(h--)r[h]=l+" "+qa(r[h]);s=r.join(","),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(Q,"$1"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ha(a){return a[u]=!0,a}function ia(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function oa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fa.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ia(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\r\\' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ia(function(a){var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",O)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Z.test(o.compareDocumentPosition),t=b||Z.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return ka(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fa.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fa.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fa.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fa.selectors={cacheLength:50,createPseudo:ha,match:W,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ba,ca),a[3]=(a[3]||a[4]||a[5]||"").replace(ba,ca),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fa.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&U.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ba,ca).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fa.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(P," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fa.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,"$1"));return d[u]?ha(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||"")||fa.error("unsupported lang: "+a),a=a.replace(ba,ca).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Y.test(a.nodeName)},input:function(a){return X.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=la(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=ma(b);function pa(){}pa.prototype=d.filters=d.pseudos,d.setFilters=new pa,g=fa.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){c&&!(e=R.exec(h))||(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=S.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(Q," ")}),h=h.slice(c.length));for(g in d.filter)!(e=W[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?fa.error(a):z(a,i).slice(0)};function qa(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(Q,"$1"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ia(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||ja("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ja("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute("disabled")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,y=/^.[^:#\[\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return n.inArray(a,b)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;e>b;b++)if(n.contains(d[b],this))return!0}));for(b=0;e>b;b++)n.find(a,d[b],c);return c=this.pushStack(e>1?n.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,"string"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,"string"==typeof a){if(e="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:B.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}if(f=d.getElementById(e[2]),f&&f.parentNode){if(f.id!==e[2])return A.find(a);this.length=1,this[0]=f}return this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b,c=n(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(n.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?n.inArray(this[0],n(a)):n.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,"parentNode")},parentsUntil:function(a,b,c){return u(a,"parentNode",c)},next:function(a){return F(a,"nextSibling")},prev:function(a){return F(a,"previousSibling")},nextAll:function(a){return u(a,"nextSibling")},prevAll:function(a){return u(a,"previousSibling")},nextUntil:function(a,b,c){return u(a,"nextSibling",c)},prevUntil:function(a,b,c){return u(a,"previousSibling",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return n.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||(e=n.uniqueSort(e)),D.test(a)&&(e=e.reverse())),this.pushStack(e)}});var G=/\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?H(a):n.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h<f.length)f[h].apply(c[0],c[1])===!1&&a.stopOnFalse&&(h=f.length,c=!1)}a.memory||(c=!1),b=!1,e&&(f=c?[]:"")},j={add:function(){return f&&(c&&!b&&(h=f.length-1,g.push(c)),function d(b){n.each(b,function(b,c){n.isFunction(c)?a.unique&&j.has(c)||f.push(c):c&&c.length&&"string"!==n.type(c)&&d(c)})}(arguments),c&&!b&&i()),this},remove:function(){return n.each(arguments,function(a,b){var c;while((c=n.inArray(b,f,c))>-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=!0,c||j.disable(),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler("ready"),n(d).off("ready"))))}});function J(){d.addEventListener?(d.removeEventListener("DOMContentLoaded",K),a.removeEventListener("load",K)):(d.detachEvent("onreadystatechange",K),a.detachEvent("onload",K))}function K(){(d.addEventListener||"load"===a.event.type||"complete"===d.readyState)&&(J(),n.ready())}n.ready.promise=function(b){if(!I)if(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll)a.setTimeout(n.ready);else if(d.addEventListener)d.addEventListener("DOMContentLoaded",K),a.addEventListener("load",K);else{d.attachEvent("onreadystatechange",K),a.attachEvent("onload",K);var c=!1;try{c=null==a.frameElement&&d.documentElement}catch(e){}c&&c.doScroll&&!function f(){if(!n.isReady){try{c.doScroll("left")}catch(b){return a.setTimeout(f,50)}J(),n.ready()}}()}return I.promise(b)},n.ready.promise();var L;for(L in n(l))break;l.ownFirst="0"===L,l.inlineBlockNeedsLayout=!1,n(function(){var a,b,c,e;c=d.getElementsByTagName("body")[0],c&&c.style&&(b=d.createElement("div"),e=d.createElement("div"),e.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(e).appendChild(b),"undefined"!=typeof b.style.zoom&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",l.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(e))}),function(){var a=d.createElement("div");l.deleteExpando=!0;try{delete a.test}catch(b){l.deleteExpando=!1}a=null}();var M=function(a){var b=n.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b},N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(O,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}n.data(a,b,c)}else c=void 0; +}return c}function Q(a){var b;for(b in a)if(("data"!==b||!n.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function R(a,b,d,e){if(M(a)){var f,g,h=n.expando,i=a.nodeType,j=i?n.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||n.guid++:h),j[k]||(j[k]=i?{}:{toJSON:n.noop}),"object"!=typeof b&&"function"!=typeof b||(e?j[k]=n.extend(j[k],b):j[k].data=n.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[n.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[n.camelCase(b)])):f=g,f}}function S(a,b,c){if(M(a)){var d,e,f=a.nodeType,g=f?n.cache:a,h=f?a[n.expando]:n.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){n.isArray(b)?b=b.concat(n.map(b,n.camelCase)):b in d?b=[b]:(b=n.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!Q(d):!n.isEmptyObject(d))return}(c||(delete g[h].data,Q(g[h])))&&(f?n.cleanData([a],!0):l.deleteExpando||g!=g.window?delete g[h]:g[h]=void 0)}}}n.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?n.cache[a[n.expando]]:a[n.expando],!!a&&!Q(a)},data:function(a,b,c){return R(a,b,c)},removeData:function(a,b){return S(a,b)},_data:function(a,b,c){return R(a,b,c,!0)},_removeData:function(a,b){return S(a,b,!0)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=n.data(f),1===f.nodeType&&!n._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));n._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){n.data(this,a)}):arguments.length>1?this.each(function(){n.data(this,a,b)}):f?P(f,a,n.data(f,a)):void 0},removeData:function(a){return this.each(function(){n.removeData(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=n._data(a,b),c&&(!d||n.isArray(c)?d=n._data(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return n._data(a,c)||n._data(a,c,{empty:n.Callbacks("once memory").add(function(){n._removeData(a,b+"queue"),n._removeData(a,c)})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=n.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=n._data(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}}),function(){var a;l.shrinkWrapBlocks=function(){if(null!=a)return a;a=!1;var b,c,e;return c=d.getElementsByTagName("body")[0],c&&c.style?(b=d.createElement("div"),e=d.createElement("div"),e.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(e).appendChild(b),"undefined"!=typeof b.style.zoom&&(b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1",b.appendChild(d.createElement("div")).style.width="5px",a=3!==b.offsetWidth),c.removeChild(e),a):void 0}}();var T=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,U=new RegExp("^(?:([+-])=|)("+T+")([a-z%]*)$","i"),V=["Top","Right","Bottom","Left"],W=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)};function X(a,b,c,d){var e,f=1,g=20,h=d?function(){return d.cur()}:function(){return n.css(a,b,"")},i=h(),j=c&&c[3]||(n.cssNumber[b]?"":"px"),k=(n.cssNumber[b]||"px"!==j&&+i)&&U.exec(n.css(a,b));if(k&&k[3]!==j){j=j||k[3],c=c||[],k=+i||1;do f=f||".5",k/=f,n.style(a,b,k+j);while(f!==(f=h()/i)&&1!==f&&--g)}return c&&(k=+k||+i||0,e=c[1]?k+(c[1]+1)*c[2]:+c[2],d&&(d.unit=j,d.start=k,d.end=e)),e}var Y=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)Y(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},Z=/^(?:checkbox|radio)$/i,$=/<([\w:-]+)/,_=/^$|\/(?:java|ecma)script/i,aa=/^\s+/,ba="abbr|article|aside|audio|bdi|canvas|data|datalist|details|dialog|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|picture|progress|section|summary|template|time|video";function ca(a){var b=ba.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}!function(){var a=d.createElement("div"),b=d.createDocumentFragment(),c=d.createElement("input");a.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",l.leadingWhitespace=3===a.firstChild.nodeType,l.tbody=!a.getElementsByTagName("tbody").length,l.htmlSerialize=!!a.getElementsByTagName("link").length,l.html5Clone="<:nav></:nav>"!==d.createElement("nav").cloneNode(!0).outerHTML,c.type="checkbox",c.checked=!0,b.appendChild(c),l.appendChecked=c.checked,a.innerHTML="<textarea>x</textarea>",l.noCloneChecked=!!a.cloneNode(!0).lastChild.defaultValue,b.appendChild(a),c=d.createElement("input"),c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),a.appendChild(c),l.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,l.noCloneEvent=!!a.addEventListener,a[n.expando]=1,l.attributes=!a.getAttribute(n.expando)}();var da={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:l.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]};da.optgroup=da.option,da.tbody=da.tfoot=da.colgroup=da.caption=da.thead,da.th=da.td;function ea(a,b){var c,d,e=0,f="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||n.nodeName(d,b)?f.push(d):n.merge(f,ea(d,b));return void 0===b||b&&n.nodeName(a,b)?n.merge([a],f):f}function fa(a,b){for(var c,d=0;null!=(c=a[d]);d++)n._data(c,"globalEval",!b||n._data(b[d],"globalEval"))}var ga=/<|&#?\w+;/,ha=/<tbody/i;function ia(a){Z.test(a.type)&&(a.defaultChecked=a.checked)}function ja(a,b,c,d,e){for(var f,g,h,i,j,k,m,o=a.length,p=ca(b),q=[],r=0;o>r;r++)if(g=a[r],g||0===g)if("object"===n.type(g))n.merge(q,g.nodeType?[g]:g);else if(ga.test(g)){i=i||p.appendChild(b.createElement("div")),j=($.exec(g)||["",""])[1].toLowerCase(),m=da[j]||da._default,i.innerHTML=m[1]+n.htmlPrefilter(g)+m[2],f=m[0];while(f--)i=i.lastChild;if(!l.leadingWhitespace&&aa.test(g)&&q.push(b.createTextNode(aa.exec(g)[0])),!l.tbody){g="table"!==j||ha.test(g)?"<table>"!==m[1]||ha.test(g)?0:i:i.firstChild,f=g&&g.childNodes.length;while(f--)n.nodeName(k=g.childNodes[f],"tbody")&&!k.childNodes.length&&g.removeChild(k)}n.merge(q,i.childNodes),i.textContent="";while(i.firstChild)i.removeChild(i.firstChild);i=p.lastChild}else q.push(b.createTextNode(g));i&&p.removeChild(i),l.appendChecked||n.grep(ea(q,"input"),ia),r=0;while(g=q[r++])if(d&&n.inArray(g,d)>-1)e&&e.push(g);else if(h=n.contains(g.ownerDocument,g),i=ea(p.appendChild(g),"script"),h&&fa(i),c){f=0;while(g=i[f++])_.test(g.type||"")&&c.push(g)}return i=null,p}!function(){var b,c,e=d.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(l[b]=c in a)||(e.setAttribute(c,"t"),l[b]=e.attributes[c].expando===!1);e=null}();var ka=/^(?:input|select|textarea)$/i,la=/^key/,ma=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,na=/^(?:focusinfocus|focusoutblur)$/,oa=/^([^.]*)(?:\.(.+)|)/;function pa(){return!0}function qa(){return!1}function ra(){try{return d.activeElement}catch(a){}}function sa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)sa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=qa;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return"undefined"==typeof n||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(G)||[""],h=b.length;while(h--)f=oa.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=oa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,"events"))}},trigger:function(b,c,e,f){var g,h,i,j,l,m,o,p=[e||d],q=k.call(b,"type")?b.type:b,r=k.call(b,"namespace")?b.namespace.split("."):[];if(i=m=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!na.test(q+n.event.triggered)&&(q.indexOf(".")>-1&&(r=q.split("."),q=r.shift(),r.sort()),h=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=r.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:n.makeArray(c,[b]),l=n.event.special[q]||{},f||!l.trigger||l.trigger.apply(e,c)!==!1)){if(!f&&!l.noBubble&&!n.isWindow(e)){for(j=l.delegateType||q,na.test(j+q)||(i=i.parentNode);i;i=i.parentNode)p.push(i),m=i;m===(e.ownerDocument||d)&&p.push(m.defaultView||m.parentWindow||a)}o=0;while((i=p[o++])&&!b.isPropagationStopped())b.type=o>1?j:l.bindType||q,g=(n._data(i,"events")||{})[b.type]&&n._data(i,"handle"),g&&g.apply(i,c),g=h&&i[h],g&&g.apply&&M(i)&&(b.result=g.apply(i,c),b.result===!1&&b.preventDefault());if(b.type=q,!f&&!b.isDefaultPrevented()&&(!l._default||l._default.apply(p.pop(),c)===!1)&&M(e)&&h&&e[q]&&!n.isWindow(e)){m=e[h],m&&(e[h]=null),n.event.triggered=q;try{e[q]()}catch(s){}n.event.triggered=void 0,m&&(e[h]=m)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(n._data(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},fix:function(a){if(a[n.expando])return a;var b,c,e,f=a.type,g=a,h=this.fixHooks[f];h||(this.fixHooks[f]=h=ma.test(f)?this.mouseHooks:la.test(f)?this.keyHooks:{}),e=h.props?this.props.concat(h.props):this.props,a=new n.Event(g),b=e.length;while(b--)c=e[b],a[c]=g[c];return a.target||(a.target=g.srcElement||d),3===a.target.nodeType&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,h.filter?h.filter(a,g):a},props:"altKey bubbles cancelable ctrlKey currentTarget detail eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,e,f,g=b.button,h=b.fromElement;return null==a.pageX&&null!=b.clientX&&(e=a.target.ownerDocument||d,f=e.documentElement,c=e.body,a.pageX=b.clientX+(f&&f.scrollLeft||c&&c.scrollLeft||0)-(f&&f.clientLeft||c&&c.clientLeft||0),a.pageY=b.clientY+(f&&f.scrollTop||c&&c.scrollTop||0)-(f&&f.clientTop||c&&c.clientTop||0)),!a.relatedTarget&&h&&(a.relatedTarget=h===a.target?b.toElement:h),a.which||void 0===g||(a.which=1&g?1:2&g?3:4&g?2:0),a}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==ra()&&this.focus)try{return this.focus(),!1}catch(a){}},delegateType:"focusin"},blur:{trigger:function(){return this===ra()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return n.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c){var d=n.extend(new n.Event,c,{type:a,isSimulated:!0});n.event.trigger(d,null,b),d.isDefaultPrevented()&&c.preventDefault()}},n.removeEvent=d.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c)}:function(a,b,c){var d="on"+b;a.detachEvent&&("undefined"==typeof a[d]&&(a[d]=null),a.detachEvent(d,c))},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?pa:qa):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={constructor:n.Event,isDefaultPrevented:qa,isPropagationStopped:qa,isImmediatePropagationStopped:qa,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=pa,a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=pa,a&&!this.isSimulated&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=pa,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},n.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return e&&(e===d||n.contains(d,e))||(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),l.submit||(n.event.special.submit={setup:function(){return n.nodeName(this,"form")?!1:void n.event.add(this,"click._submit keypress._submit",function(a){var b=a.target,c=n.nodeName(b,"input")||n.nodeName(b,"button")?n.prop(b,"form"):void 0;c&&!n._data(c,"submit")&&(n.event.add(c,"submit._submit",function(a){a._submitBubble=!0}),n._data(c,"submit",!0))})},postDispatch:function(a){a._submitBubble&&(delete a._submitBubble,this.parentNode&&!a.isTrigger&&n.event.simulate("submit",this.parentNode,a))},teardown:function(){return n.nodeName(this,"form")?!1:void n.event.remove(this,"._submit")}}),l.change||(n.event.special.change={setup:function(){return ka.test(this.nodeName)?("checkbox"!==this.type&&"radio"!==this.type||(n.event.add(this,"propertychange._change",function(a){"checked"===a.originalEvent.propertyName&&(this._justChanged=!0)}),n.event.add(this,"click._change",function(a){this._justChanged&&!a.isTrigger&&(this._justChanged=!1),n.event.simulate("change",this,a)})),!1):void n.event.add(this,"beforeactivate._change",function(a){var b=a.target;ka.test(b.nodeName)&&!n._data(b,"change")&&(n.event.add(b,"change._change",function(a){!this.parentNode||a.isSimulated||a.isTrigger||n.event.simulate("change",this.parentNode,a)}),n._data(b,"change",!0))})},handle:function(a){var b=a.target;return this!==b||a.isSimulated||a.isTrigger||"radio"!==b.type&&"checkbox"!==b.type?a.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return n.event.remove(this,"._change"),!ka.test(this.nodeName)}}),l.focusin||n.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a))};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=n._data(d,b);e||d.addEventListener(a,c,!0),n._data(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=n._data(d,b)-1;e?n._data(d,b,e):(d.removeEventListener(a,c,!0),n._removeData(d,b))}}}),n.fn.extend({on:function(a,b,c,d){return sa(this,a,b,c,d)},one:function(a,b,c,d){return sa(this,a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return b!==!1&&"function"!=typeof b||(c=b,b=void 0),c===!1&&(c=qa),this.each(function(){n.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}});var ta=/ jQuery\d+="(?:null|\d+)"/g,ua=new RegExp("<(?:"+ba+")[\\s/>]","i"),va=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,wa=/<script|<style|<link/i,xa=/checked\s*(?:[^=]|=\s*.checked.)/i,ya=/^true\/(.*)/,za=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,Aa=ca(d),Ba=Aa.appendChild(d.createElement("div"));function Ca(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function Da(a){return a.type=(null!==n.find.attr(a,"type"))+"/"+a.type,a}function Ea(a){var b=ya.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Fa(a,b){if(1===b.nodeType&&n.hasData(a)){var c,d,e,f=n._data(a),g=n._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)n.event.add(b,c,h[c][d])}g.data&&(g.data=n.extend({},g.data))}}function Ga(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!l.noCloneEvent&&b[n.expando]){e=n._data(b);for(d in e.events)n.removeEvent(b,d,e.handle);b.removeAttribute(n.expando)}"script"===c&&b.text!==a.text?(Da(b).text=a.text,Ea(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),l.html5Clone&&a.innerHTML&&!n.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&Z.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}}function Ha(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);if(r||o>1&&"string"==typeof q&&!l.checkClone&&xa.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),Ha(f,b,c,d)});if(o&&(k=ja(b,a[0].ownerDocument,!1,a,d),e=k.firstChild,1===k.childNodes.length&&(k=e),e||d)){for(i=n.map(ea(k,"script"),Da),h=i.length;o>m;m++)g=k,m!==p&&(g=n.clone(g,!0,!0),h&&n.merge(i,ea(g,"script"))),c.call(a[m],g,m);if(h)for(j=i[i.length-1].ownerDocument,n.map(i,Ea),m=0;h>m;m++)g=i[m],_.test(g.type||"")&&!n._data(g,"globalEval")&&n.contains(j,g)&&(g.src?n._evalUrl&&n._evalUrl(g.src):n.globalEval((g.text||g.textContent||g.innerHTML||"").replace(za,"")));k=e=null}return a}function Ia(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(ea(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&fa(ea(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(va,"<$1></$2>")},clone:function(a,b,c){var d,e,f,g,h,i=n.contains(a.ownerDocument,a);if(l.html5Clone||n.isXMLDoc(a)||!ua.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(Ba.innerHTML=a.outerHTML,Ba.removeChild(f=Ba.firstChild)),!(l.noCloneEvent&&l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(d=ea(f),h=ea(a),g=0;null!=(e=h[g]);++g)d[g]&&Ga(e,d[g]);if(b)if(c)for(h=h||ea(a),d=d||ea(f),g=0;null!=(e=h[g]);g++)Fa(e,d[g]);else Fa(a,f);return d=ea(f,"script"),d.length>0&&fa(d,!i&&ea(a,"script")),d=h=e=null,f},cleanData:function(a,b){for(var d,e,f,g,h=0,i=n.expando,j=n.cache,k=l.attributes,m=n.event.special;null!=(d=a[h]);h++)if((b||M(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)m[e]?n.event.remove(d,e):n.removeEvent(d,e,g.handle);j[f]&&(delete j[f],k||"undefined"==typeof d.removeAttribute?d[i]=void 0:d.removeAttribute(i),c.push(f))}}}),n.fn.extend({domManip:Ha,detach:function(a){return Ia(this,a,!0)},remove:function(a){return Ia(this,a)},text:function(a){return Y(this,function(a){return void 0===a?n.text(this):this.empty().append((this[0]&&this[0].ownerDocument||d).createTextNode(a))},null,a,arguments.length)},append:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.appendChild(a)}})},prepend:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&n.cleanData(ea(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&n.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return Y(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(ta,""):void 0;if("string"==typeof a&&!wa.test(a)&&(l.htmlSerialize||!ua.test(a))&&(l.leadingWhitespace||!aa.test(a))&&!da[($.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ea(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ha(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(ea(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=0,e=[],f=n(a),h=f.length-1;h>=d;d++)c=d===h?this:this.clone(!0),n(f[d])[b](c),g.apply(e,c.get());return this.pushStack(e)}});var Ja,Ka={HTML:"block",BODY:"block"};function La(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function Ma(a){var b=d,c=Ka[a];return c||(c=La(a,b),"none"!==c&&c||(Ja=(Ja||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=(Ja[0].contentWindow||Ja[0].contentDocument).document,b.write(),b.close(),c=La(a,b),Ja.detach()),Ka[a]=c),c}var Na=/^margin/,Oa=new RegExp("^("+T+")(?!px)[a-z%]+$","i"),Pa=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e},Qa=d.documentElement;!function(){var b,c,e,f,g,h,i=d.createElement("div"),j=d.createElement("div");if(j.style){j.style.cssText="float:left;opacity:.5",l.opacity="0.5"===j.style.opacity,l.cssFloat=!!j.style.cssFloat,j.style.backgroundClip="content-box",j.cloneNode(!0).style.backgroundClip="",l.clearCloneStyle="content-box"===j.style.backgroundClip,i=d.createElement("div"),i.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",j.innerHTML="",i.appendChild(j),l.boxSizing=""===j.style.boxSizing||""===j.style.MozBoxSizing||""===j.style.WebkitBoxSizing,n.extend(l,{reliableHiddenOffsets:function(){return null==b&&k(),f},boxSizingReliable:function(){return null==b&&k(),e},pixelMarginRight:function(){return null==b&&k(),c},pixelPosition:function(){return null==b&&k(),b},reliableMarginRight:function(){return null==b&&k(),g},reliableMarginLeft:function(){return null==b&&k(),h}});function k(){var k,l,m=d.documentElement;m.appendChild(i),j.style.cssText="-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%",b=e=h=!1,c=g=!0,a.getComputedStyle&&(l=a.getComputedStyle(j),b="1%"!==(l||{}).top,h="2px"===(l||{}).marginLeft,e="4px"===(l||{width:"4px"}).width,j.style.marginRight="50%",c="4px"===(l||{marginRight:"4px"}).marginRight,k=j.appendChild(d.createElement("div")),k.style.cssText=j.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",k.style.marginRight=k.style.width="0",j.style.width="1px",g=!parseFloat((a.getComputedStyle(k)||{}).marginRight),j.removeChild(k)),j.style.display="none",f=0===j.getClientRects().length,f&&(j.style.display="",j.innerHTML="<table><tr><td></td><td>t</td></tr></table>",j.childNodes[0].style.borderCollapse="separate",k=j.getElementsByTagName("td"),k[0].style.cssText="margin:0;border:0;padding:0;display:none",f=0===k[0].offsetHeight,f&&(k[0].style.display="",k[1].style.display="none",f=0===k[0].offsetHeight)),m.removeChild(i)}}}();var Ra,Sa,Ta=/^(top|right|bottom|left)$/;a.getComputedStyle?(Ra=function(b){var c=b.ownerDocument.defaultView;return c&&c.opener||(c=a),c.getComputedStyle(b)},Sa=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ra(a),g=c?c.getPropertyValue(b)||c[b]:void 0,""!==g&&void 0!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),c&&!l.pixelMarginRight()&&Oa.test(g)&&Na.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f),void 0===g?g:g+""}):Qa.currentStyle&&(Ra=function(a){return a.currentStyle},Sa=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ra(a),g=c?c[b]:void 0,null==g&&h&&h[b]&&(g=h[b]),Oa.test(g)&&!Ta.test(b)&&(d=h.left,e=a.runtimeStyle,f=e&&e.left,f&&(e.left=a.currentStyle.left),h.left="fontSize"===b?"1em":g,g=h.pixelLeft+"px",h.left=d,f&&(e.left=f)),void 0===g?g:g+""||"auto"});function Ua(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}var Va=/alpha\([^)]*\)/i,Wa=/opacity\s*=\s*([^)]*)/i,Xa=/^(none|table(?!-c[ea]).+)/,Ya=new RegExp("^("+T+")(.*)$","i"),Za={position:"absolute",visibility:"hidden",display:"block"},$a={letterSpacing:"0",fontWeight:"400"},_a=["Webkit","O","Moz","ms"],ab=d.createElement("div").style;function bb(a){if(a in ab)return a;var b=a.charAt(0).toUpperCase()+a.slice(1),c=_a.length;while(c--)if(a=_a[c]+b,a in ab)return a}function cb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=n._data(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&W(d)&&(f[g]=n._data(d,"olddisplay",Ma(d.nodeName)))):(e=W(d),(c&&"none"!==c||!e)&&n._data(d,"olddisplay",e?c:n.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}function db(a,b,c){var d=Ya.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function eb(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=n.css(a,c+V[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+V[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+V[f]+"Width",!0,e))):(g+=n.css(a,"padding"+V[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+V[f]+"Width",!0,e)));return g}function fb(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=Ra(a),g=l.boxSizing&&"border-box"===n.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=Sa(a,b,f),(0>e||null==e)&&(e=a.style[b]),Oa.test(e))return e;d=g&&(l.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+eb(a,b,c||(g?"border":"content"),d,f)+"px"}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Sa(a,"opacity");return""===c?"1":c}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":l.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;if(b=n.cssProps[h]||(n.cssProps[h]=bb(h)||h),g=n.cssHooks[b]||n.cssHooks[h],void 0===c)return g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b];if(f=typeof c,"string"===f&&(e=U.exec(c))&&e[1]&&(c=X(a,b,e),f="number"),null!=c&&c===c&&("number"===f&&(c+=e&&e[3]||(n.cssNumber[h]?"":"px")),l.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),!(g&&"set"in g&&void 0===(c=g.set(a,c,d)))))try{i[b]=c}catch(j){}}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=bb(h)||h),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(f=g.get(a,!0,c)),void 0===f&&(f=Sa(a,b,d)),"normal"===f&&b in $a&&(f=$a[b]),""===c||c?(e=parseFloat(f),c===!0||isFinite(e)?e||0:f):f}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?Xa.test(n.css(a,"display"))&&0===a.offsetWidth?Pa(a,Za,function(){return fb(a,b,d)}):fb(a,b,d):void 0},set:function(a,c,d){var e=d&&Ra(a);return db(a,c,d?eb(a,b,d,l.boxSizing&&"border-box"===n.css(a,"boxSizing",!1,e),e):0)}}}),l.opacity||(n.cssHooks.opacity={get:function(a,b){return Wa.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=n.isNumeric(b)?"alpha(opacity="+100*b+")":"",f=d&&d.filter||c.filter||"";c.zoom=1,(b>=1||""===b)&&""===n.trim(f.replace(Va,""))&&c.removeAttribute&&(c.removeAttribute("filter"),""===b||d&&!d.filter)||(c.filter=Va.test(f)?f.replace(Va,e):f+" "+e)}}),n.cssHooks.marginRight=Ua(l.reliableMarginRight,function(a,b){return b?Pa(a,{display:"inline-block"},Sa,[a,"marginRight"]):void 0}),n.cssHooks.marginLeft=Ua(l.reliableMarginLeft,function(a,b){return b?(parseFloat(Sa(a,"marginLeft"))||(n.contains(a.ownerDocument,a)?a.getBoundingClientRect().left-Pa(a,{ +marginLeft:0},function(){return a.getBoundingClientRect().left}):0))+"px":void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+V[d]+b]=f[d]||f[d-2]||f[0];return e}},Na.test(a)||(n.cssHooks[a+b].set=db)}),n.fn.extend({css:function(a,b){return Y(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=Ra(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)},a,b,arguments.length>1)},show:function(){return cb(this,!0)},hide:function(){return cb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){W(this)?n(this).show():n(this).hide()})}});function gb(a,b,c,d,e){return new gb.prototype.init(a,b,c,d,e)}n.Tween=gb,gb.prototype={constructor:gb,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||n.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=gb.propHooks[this.prop];return a&&a.get?a.get(this):gb.propHooks._default.get(this)},run:function(a){var b,c=gb.propHooks[this.prop];return this.options.duration?this.pos=b=n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):gb.propHooks._default.set(this),this}},gb.prototype.init.prototype=gb.prototype,gb.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[n.cssProps[a.prop]]&&!n.cssHooks[a.prop]?a.elem[a.prop]=a.now:n.style(a.elem,a.prop,a.now+a.unit)}}},gb.propHooks.scrollTop=gb.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},n.fx=gb.prototype.init,n.fx.step={};var hb,ib,jb=/^(?:toggle|show|hide)$/,kb=/queueHooks$/;function lb(){return a.setTimeout(function(){hb=void 0}),hb=n.now()}function mb(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=V[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function nb(a,b,c){for(var d,e=(qb.tweeners[b]||[]).concat(qb.tweeners["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function ob(a,b,c){var d,e,f,g,h,i,j,k,m=this,o={},p=a.style,q=a.nodeType&&W(a),r=n._data(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,m.always(function(){m.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=n.css(a,"display"),k="none"===j?n._data(a,"olddisplay")||Ma(a.nodeName):j,"inline"===k&&"none"===n.css(a,"float")&&(l.inlineBlockNeedsLayout&&"inline"!==Ma(a.nodeName)?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",l.shrinkWrapBlocks()||m.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],jb.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(o))"inline"===("none"===j?Ma(a.nodeName):j)&&(p.display=j);else{r?"hidden"in r&&(q=r.hidden):r=n._data(a,"fxshow",{}),f&&(r.hidden=!q),q?n(a).show():m.done(function(){n(a).hide()}),m.done(function(){var b;n._removeData(a,"fxshow");for(b in o)n.style(a,b,o[b])});for(d in o)g=nb(q?r[d]:0,d,m),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function pb(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function qb(a,b,c){var d,e,f=0,g=qb.prefilters.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=hb||lb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{},easing:n.easing._default},c),originalProperties:b,originalOptions:c,startTime:hb||lb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?(h.notifyWith(a,[j,1,0]),h.resolveWith(a,[j,b])):h.rejectWith(a,[j,b]),this}}),k=j.props;for(pb(k,j.opts.specialEasing);g>f;f++)if(d=qb.prefilters[f].call(j,a,k,j.opts))return n.isFunction(d.stop)&&(n._queueHooks(j.elem,j.opts.queue).stop=n.proxy(d.stop,d)),d;return n.map(k,nb,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}n.Animation=n.extend(qb,{tweeners:{"*":[function(a,b){var c=this.createTween(a,b);return X(c.elem,a,U.exec(b),c),c}]},tweener:function(a,b){n.isFunction(a)?(b=a,a=["*"]):a=a.match(G);for(var c,d=0,e=a.length;e>d;d++)c=a[d],qb.tweeners[c]=qb.tweeners[c]||[],qb.tweeners[c].unshift(b)},prefilters:[ob],prefilter:function(a,b){b?qb.prefilters.unshift(a):qb.prefilters.push(a)}}),n.speed=function(a,b,c){var d=a&&"object"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,null!=d.queue&&d.queue!==!0||(d.queue="fx"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(W).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=qb(this,n.extend({},a),f);(e||n._data(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=n.timers,g=n._data(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&kb.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));!b&&c||n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=n._data(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each(["toggle","show","hide"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(mb(b,!0),a,d,e)}}),n.each({slideDown:mb("show"),slideUp:mb("hide"),slideToggle:mb("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=n.timers,c=0;for(hb=n.now();c<b.length;c++)a=b[c],a()||b[c]!==a||b.splice(c--,1);b.length||n.fx.stop(),hb=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){ib||(ib=a.setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){a.clearInterval(ib),ib=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(b,c){return b=n.fx?n.fx.speeds[b]||b:b,c=c||"fx",this.queue(c,function(c,d){var e=a.setTimeout(c,b);d.stop=function(){a.clearTimeout(e)}})},function(){var a,b=d.createElement("input"),c=d.createElement("div"),e=d.createElement("select"),f=e.appendChild(d.createElement("option"));c=d.createElement("div"),c.setAttribute("className","t"),c.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",a=c.getElementsByTagName("a")[0],b.setAttribute("type","checkbox"),c.appendChild(b),a=c.getElementsByTagName("a")[0],a.style.cssText="top:1px",l.getSetAttribute="t"!==c.className,l.style=/top/.test(a.getAttribute("style")),l.hrefNormalized="/a"===a.getAttribute("href"),l.checkOn=!!b.value,l.optSelected=f.selected,l.enctype=!!d.createElement("form").enctype,e.disabled=!0,l.optDisabled=!f.disabled,b=d.createElement("input"),b.setAttribute("value",""),l.input=""===b.getAttribute("value"),b.value="t",b.setAttribute("type","radio"),l.radioValue="t"===b.value}();var rb=/\r/g,sb=/[\x20\t\r\n\f]+/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e?e+="":n.isArray(e)&&(e=n.map(e,function(a){return null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(rb,""):null==c?"":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,"value");return null!=b?b:n.trim(n.text(a)).replace(sb," ")}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],(c.selected||i===e)&&(l.optDisabled?!c.disabled:null===c.getAttribute("disabled"))&&(!c.parentNode.disabled||!n.nodeName(c.parentNode,"optgroup"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)if(d=e[g],n.inArray(n.valHooks.option.get(d),f)>-1)try{d.selected=c=!0}catch(h){d.scrollHeight}else d.selected=!1;return c||(a.selectedIndex=-1),e}}}}),n.each(["radio","checkbox"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>-1:void 0}},l.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var tb,ub,vb=n.expr.attrHandle,wb=/^(?:checked|selected)$/i,xb=l.getSetAttribute,yb=l.input;n.fn.extend({attr:function(a,b){return Y(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),e=n.attrHooks[b]||(n.expr.match.bool.test(b)?ub:tb)),void 0!==c?null===c?void n.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=n.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!l.radioValue&&"radio"===b&&n.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(G);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)?yb&&xb||!wb.test(c)?a[d]=!1:a[n.camelCase("default-"+c)]=a[d]=!1:n.attr(a,c,""),a.removeAttribute(xb?c:d)}}),ub={set:function(a,b,c){return b===!1?n.removeAttr(a,c):yb&&xb||!wb.test(c)?a.setAttribute(!xb&&n.propFix[c]||c,c):a[n.camelCase("default-"+c)]=a[c]=!0,c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=vb[b]||n.find.attr;yb&&xb||!wb.test(b)?vb[b]=function(a,b,d){var e,f;return d||(f=vb[b],vb[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,vb[b]=f),e}:vb[b]=function(a,b,c){return c?void 0:a[n.camelCase("default-"+b)]?b.toLowerCase():null}}),yb&&xb||(n.attrHooks.value={set:function(a,b,c){return n.nodeName(a,"input")?void(a.defaultValue=b):tb&&tb.set(a,b,c)}}),xb||(tb={set:function(a,b,c){var d=a.getAttributeNode(c);return d||a.setAttributeNode(d=a.ownerDocument.createAttribute(c)),d.value=b+="","value"===c||b===a.getAttribute(c)?b:void 0}},vb.id=vb.name=vb.coords=function(a,b,c){var d;return c?void 0:(d=a.getAttributeNode(b))&&""!==d.value?d.value:null},n.valHooks.button={get:function(a,b){var c=a.getAttributeNode(b);return c&&c.specified?c.value:void 0},set:tb.set},n.attrHooks.contenteditable={set:function(a,b,c){tb.set(a,""===b?!1:b,c)}},n.each(["width","height"],function(a,b){n.attrHooks[b]={set:function(a,c){return""===c?(a.setAttribute(b,"auto"),c):void 0}}})),l.style||(n.attrHooks.style={get:function(a){return a.style.cssText||void 0},set:function(a,b){return a.style.cssText=b+""}});var zb=/^(?:input|select|textarea|button|object)$/i,Ab=/^(?:a|area)$/i;n.fn.extend({prop:function(a,b){return Y(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return a=n.propFix[a]||a,this.each(function(){try{this[a]=void 0,delete this[a]}catch(b){}})}}),n.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&n.isXMLDoc(a)||(b=n.propFix[b]||b,e=n.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=n.find.attr(a,"tabindex");return b?parseInt(b,10):zb.test(a.nodeName)||Ab.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),l.hrefNormalized||n.each(["href","src"],function(a,b){n.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}),l.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),n.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){n.propFix[this.toLowerCase()]=this}),l.enctype||(n.propFix.enctype="encoding");var Bb=/[\t\r\n\f]/g;function Cb(a){return n.attr(a,"class")||""}n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,Cb(this)))});if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=Cb(c),d=1===c.nodeType&&(" "+e+" ").replace(Bb," ")){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=n.trim(d),e!==h&&n.attr(c,"class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,Cb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=Cb(c),d=1===c.nodeType&&(" "+e+" ").replace(Bb," ")){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=n.trim(d),e!==h&&n.attr(c,"class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):n.isFunction(a)?this.each(function(c){n(this).toggleClass(a.call(this,c,Cb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=n(this),f=a.match(G)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=Cb(this),b&&n._data(this,"__className__",b),n.attr(this,"class",b||a===!1?"":n._data(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+Cb(c)+" ").replace(Bb," ").indexOf(b)>-1)return!0;return!1}}),n.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Db=a.location,Eb=n.now(),Fb=/\?/,Gb=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;n.parseJSON=function(b){if(a.JSON&&a.JSON.parse)return a.JSON.parse(b+"");var c,d=null,e=n.trim(b+"");return e&&!n.trim(e.replace(Gb,function(a,b,e,f){return c&&b&&(d=0),0===d?a:(c=e||b,d+=!f-!e,"")}))?Function("return "+e)():n.error("Invalid JSON: "+b)},n.parseXML=function(b){var c,d;if(!b||"string"!=typeof b)return null;try{a.DOMParser?(d=new a.DOMParser,c=d.parseFromString(b,"text/xml")):(c=new a.ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b))}catch(e){c=void 0}return c&&c.documentElement&&!c.getElementsByTagName("parsererror").length||n.error("Invalid XML: "+b),c};var Hb=/#.*$/,Ib=/([?&])_=[^&]*/,Jb=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Kb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Lb=/^(?:GET|HEAD)$/,Mb=/^\/\//,Nb=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Ob={},Pb={},Qb="*/".concat("*"),Rb=Db.href,Sb=Nb.exec(Rb.toLowerCase())||[];function Tb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(G)||[];if(n.isFunction(c))while(d=f[e++])"+"===d.charAt(0)?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Ub(a,b,c,d){var e={},f=a===Pb;function g(h){var i;return e[h]=!0,n.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Vb(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(d in b)void 0!==b[d]&&((e[d]?a:c||(c={}))[d]=b[d]);return c&&n.extend(!0,a,c),a}function Wb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===e&&(e=a.mimeType||b.getResponseHeader("Content-Type"));if(e)for(g in h)if(h[g]&&h[g].test(e)){i.unshift(g);break}if(i[0]in c)f=i[0];else{for(g in c){if(!i[0]||a.converters[g+" "+i[0]]){f=g;break}d||(d=g)}f=f||d}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Xb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Rb,type:"GET",isLocal:Kb.test(Sb[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Qb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":n.parseJSON,"text xml":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Vb(Vb(a,n.ajaxSettings),b):Vb(n.ajaxSettings,a)},ajaxPrefilter:Tb(Ob),ajaxTransport:Tb(Pb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var d,e,f,g,h,i,j,k,l=n.ajaxSetup({},c),m=l.context||l,o=l.context&&(m.nodeType||m.jquery)?n(m):n.event,p=n.Deferred(),q=n.Callbacks("once memory"),r=l.statusCode||{},s={},t={},u=0,v="canceled",w={readyState:0,getResponseHeader:function(a){var b;if(2===u){if(!k){k={};while(b=Jb.exec(g))k[b[1].toLowerCase()]=b[2]}b=k[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===u?g:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return u||(a=t[c]=t[c]||a,s[a]=b),this},overrideMimeType:function(a){return u||(l.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>u)for(b in a)r[b]=[r[b],a[b]];else w.always(a[w.status]);return this},abort:function(a){var b=a||v;return j&&j.abort(b),y(0,b),this}};if(p.promise(w).complete=q.add,w.success=w.done,w.error=w.fail,l.url=((b||l.url||Rb)+"").replace(Hb,"").replace(Mb,Sb[1]+"//"),l.type=c.method||c.type||l.method||l.type,l.dataTypes=n.trim(l.dataType||"*").toLowerCase().match(G)||[""],null==l.crossDomain&&(d=Nb.exec(l.url.toLowerCase()),l.crossDomain=!(!d||d[1]===Sb[1]&&d[2]===Sb[2]&&(d[3]||("http:"===d[1]?"80":"443"))===(Sb[3]||("http:"===Sb[1]?"80":"443")))),l.data&&l.processData&&"string"!=typeof l.data&&(l.data=n.param(l.data,l.traditional)),Ub(Ob,l,c,w),2===u)return w;i=n.event&&l.global,i&&0===n.active++&&n.event.trigger("ajaxStart"),l.type=l.type.toUpperCase(),l.hasContent=!Lb.test(l.type),f=l.url,l.hasContent||(l.data&&(f=l.url+=(Fb.test(f)?"&":"?")+l.data,delete l.data),l.cache===!1&&(l.url=Ib.test(f)?f.replace(Ib,"$1_="+Eb++):f+(Fb.test(f)?"&":"?")+"_="+Eb++)),l.ifModified&&(n.lastModified[f]&&w.setRequestHeader("If-Modified-Since",n.lastModified[f]),n.etag[f]&&w.setRequestHeader("If-None-Match",n.etag[f])),(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&w.setRequestHeader("Content-Type",l.contentType),w.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+("*"!==l.dataTypes[0]?", "+Qb+"; q=0.01":""):l.accepts["*"]);for(e in l.headers)w.setRequestHeader(e,l.headers[e]);if(l.beforeSend&&(l.beforeSend.call(m,w,l)===!1||2===u))return w.abort();v="abort";for(e in{success:1,error:1,complete:1})w[e](l[e]);if(j=Ub(Pb,l,c,w)){if(w.readyState=1,i&&o.trigger("ajaxSend",[w,l]),2===u)return w;l.async&&l.timeout>0&&(h=a.setTimeout(function(){w.abort("timeout")},l.timeout));try{u=1,j.send(s,y)}catch(x){if(!(2>u))throw x;y(-1,x)}}else y(-1,"No Transport");function y(b,c,d,e){var k,s,t,v,x,y=c;2!==u&&(u=2,h&&a.clearTimeout(h),j=void 0,g=e||"",w.readyState=b>0?4:0,k=b>=200&&300>b||304===b,d&&(v=Wb(l,w,d)),v=Xb(l,v,w,k),k?(l.ifModified&&(x=w.getResponseHeader("Last-Modified"),x&&(n.lastModified[f]=x),x=w.getResponseHeader("etag"),x&&(n.etag[f]=x)),204===b||"HEAD"===l.type?y="nocontent":304===b?y="notmodified":(y=v.state,s=v.data,t=v.error,k=!t)):(t=y,!b&&y||(y="error",0>b&&(b=0))),w.status=b,w.statusText=(c||y)+"",k?p.resolveWith(m,[s,y,w]):p.rejectWith(m,[w,y,t]),w.statusCode(r),r=void 0,i&&o.trigger(k?"ajaxSuccess":"ajaxError",[w,l,k?s:t]),q.fireWith(m,[w,y]),i&&(o.trigger("ajaxComplete",[w,l]),--n.active||n.event.trigger("ajaxStop")))}return w},getJSON:function(a,b,c){return n.get(a,b,c,"json")},getScript:function(a,b){return n.get(a,void 0,b,"script")}}),n.each(["get","post"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax(n.extend({url:a,type:b,dataType:e,data:c,success:d},n.isPlainObject(a)&&a))}}),n._evalUrl=function(a){return n.ajax({url:a,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){if(n.isFunction(a))return this.each(function(b){n(this).wrapAll(a.call(this,b))});if(this[0]){var b=n(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&1===a.firstChild.nodeType)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return n.isFunction(a)?this.each(function(b){n(this).wrapInner(a.call(this,b))}):this.each(function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,"body")||n(this).replaceWith(this.childNodes)}).end()}});function Yb(a){return a.style&&a.style.display||n.css(a,"display")}function Zb(a){if(!n.contains(a.ownerDocument||d,a))return!0;while(a&&1===a.nodeType){if("none"===Yb(a)||"hidden"===a.type)return!0;a=a.parentNode}return!1}n.expr.filters.hidden=function(a){return l.reliableHiddenOffsets()?a.offsetWidth<=0&&a.offsetHeight<=0&&!a.getClientRects().length:Zb(a)},n.expr.filters.visible=function(a){return!n.expr.filters.hidden(a)};var $b=/%20/g,_b=/\[\]$/,ac=/\r?\n/g,bc=/^(?:submit|button|image|reset|file)$/i,cc=/^(?:input|select|textarea|keygen)/i;function dc(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||_b.test(a)?d(a,e):dc(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==n.type(b))d(a,b);else for(e in b)dc(a+"["+e+"]",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)dc(c,a[c],b,e);return d.join("&").replace($b,"+")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,"elements");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(":disabled")&&cc.test(this.nodeName)&&!bc.test(a)&&(this.checked||!Z.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(ac,"\r\n")}}):{name:b.name,value:c.replace(ac,"\r\n")}}).get()}}),n.ajaxSettings.xhr=void 0!==a.ActiveXObject?function(){return this.isLocal?ic():d.documentMode>8?hc():/^(get|post|head|put|delete|options)$/i.test(this.type)&&hc()||ic()}:hc;var ec=0,fc={},gc=n.ajaxSettings.xhr();a.attachEvent&&a.attachEvent("onunload",function(){for(var a in fc)fc[a](void 0,!0)}),l.cors=!!gc&&"withCredentials"in gc,gc=l.ajax=!!gc,gc&&n.ajaxTransport(function(b){if(!b.crossDomain||l.cors){var c;return{send:function(d,e){var f,g=b.xhr(),h=++ec;if(g.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(f in b.xhrFields)g[f]=b.xhrFields[f];b.mimeType&&g.overrideMimeType&&g.overrideMimeType(b.mimeType),b.crossDomain||d["X-Requested-With"]||(d["X-Requested-With"]="XMLHttpRequest");for(f in d)void 0!==d[f]&&g.setRequestHeader(f,d[f]+"");g.send(b.hasContent&&b.data||null),c=function(a,d){var f,i,j;if(c&&(d||4===g.readyState))if(delete fc[h],c=void 0,g.onreadystatechange=n.noop,d)4!==g.readyState&&g.abort();else{j={},f=g.status,"string"==typeof g.responseText&&(j.text=g.responseText);try{i=g.statusText}catch(k){i=""}f||!b.isLocal||b.crossDomain?1223===f&&(f=204):f=j.text?200:404}j&&e(f,i,j,g.getAllResponseHeaders())},b.async?4===g.readyState?a.setTimeout(c):g.onreadystatechange=fc[h]=c:c()},abort:function(){c&&c(void 0,!0)}}}});function hc(){try{return new a.XMLHttpRequest}catch(b){}}function ic(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}n.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c=d.head||n("head")[0]||d.documentElement;return{send:function(e,f){b=d.createElement("script"),b.async=!0,a.scriptCharset&&(b.charset=a.scriptCharset),b.src=a.url,b.onload=b.onreadystatechange=function(a,c){(c||!b.readyState||/loaded|complete/.test(b.readyState))&&(b.onload=b.onreadystatechange=null,b.parentNode&&b.parentNode.removeChild(b),b=null,c||f(200,"success"))},c.insertBefore(b,c.firstChild)},abort:function(){b&&b.onload(void 0,!0)}}}});var jc=[],kc=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=jc.pop()||n.expando+"_"+Eb++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(kc.test(b.url)?"url":"string"==typeof b.data&&0===(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&kc.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(kc,"$1"+e):b.jsonp!==!1&&(b.url+=(Fb.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||n.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){void 0===f?n(a).removeProp(e):a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,jc.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),n.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||d;var e=x.exec(a),f=!c&&[];return e?[b.createElement(e[1])]:(e=ja([a],b,f),f&&f.length&&n(f).remove(),n.merge([],e.childNodes))};var lc=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&lc)return lc.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>-1&&(d=n.trim(a.slice(h,a.length)),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&n.ajax({url:a,type:e||"GET",dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?n("<div>").append(n.parseHTML(a)).find(d):a)}).always(c&&function(a,b){g.each(function(){c.apply(this,f||[a.responseText,b,a])})}),this},n.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};function mc(a){return n.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.css(a,"left"),j=("absolute"===k||"fixed"===k)&&n.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,n.extend({},h))),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,n.contains(b,e)?("undefined"!=typeof e.getBoundingClientRect&&(d=e.getBoundingClientRect()),c=mc(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===n.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(c=a.offset()),c.top+=n.css(a[0],"borderTopWidth",!0),c.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-n.css(d,"marginTop",!0),left:b.left-c.left-n.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent;while(a&&!n.nodeName(a,"html")&&"static"===n.css(a,"position"))a=a.offsetParent;return a||Qa})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);n.fn[a]=function(d){return Y(this,function(a,d,e){var f=mc(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?n(f).scrollLeft():e,c?e:n(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=Ua(l.pixelPosition,function(a,c){return c?(c=Sa(a,b),Oa.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({ +padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return Y(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.extend({bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var nc=a.jQuery,oc=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=oc),b&&a.jQuery===n&&(a.jQuery=nc),n},b||(a.jQuery=a.$=n),n}); diff --git a/phpBB/assets/javascript/plupload.js b/phpBB/assets/javascript/plupload.js index 8b3543880f..fab1ca6d7c 100644 --- a/phpBB/assets/javascript/plupload.js +++ b/phpBB/assets/javascript/plupload.js @@ -21,7 +21,9 @@ phpbb.plupload.initialize = function() { // Only execute if Plupload initialized successfully. phpbb.plupload.uploader.bind('Init', function() { phpbb.plupload.form = $(phpbb.plupload.config.form_hook)[0]; - phpbb.plupload.rowTpl = $('#attach-row-tpl')[0].outerHTML; + let $attachRowTemplate = $('#attach-row-tpl'); + $attachRowTemplate.removeClass('attach-row-tpl'); + phpbb.plupload.rowTpl = $attachRowTemplate[0].outerHTML; // Hide the basic upload panel and remove the attach row template. $('#attach-row-tpl, #attach-panel-basic').remove(); @@ -211,7 +213,7 @@ phpbb.plupload.updateHiddenData = function(row, attach, index) { .attr('type', 'hidden') .attr('name', 'attachment_data[' + index + '][' + key + ']') .attr('value', attach[key]); - $('textarea', row).after(input); + $(row).append(input); } }; diff --git a/phpBB/assets/plupload/plupload.full.min.js b/phpBB/assets/plupload/plupload.full.min.js index 3d01e66083..a58489dc64 100644 --- a/phpBB/assets/plupload/plupload.full.min.js +++ b/phpBB/assets/plupload/plupload.full.min.js @@ -1,6 +1,6 @@ /** * mOxie - multi-runtime File API & XMLHttpRequest L2 Polyfill - * v1.5.5 + * v1.5.7 * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. @@ -8,15 +8,15 @@ * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing * - * Date: 2017-08-26 + * Date: 2017-11-03 */ -!function(e,t){var i=function(){var e={};return t.apply(e,arguments),e.moxie};"function"==typeof define&&define.amd?define("moxie",[],i):"object"==typeof module&&module.exports?module.exports=i():e.moxie=i()}(this||window,function(){!function(e,t){"use strict";function i(e,t){for(var i,n=[],r=0;r<e.length;++r){if(i=s[e[r]]||o(e[r]),!i)throw"module definition dependecy not found: "+e[r];n.push(i)}t.apply(null,n)}function n(e,n,r){if("string"!=typeof e)throw"invalid module definition, module id must be defined and be a string";if(n===t)throw"invalid module definition, dependencies must be specified";if(r===t)throw"invalid module definition, definition function must be specified";i(n,function(){s[e]=r.apply(null,arguments)})}function r(e){return!!s[e]}function o(t){for(var i=e,n=t.split(/[.\/]/),r=0;r<n.length;++r){if(!i[n[r]])return;i=i[n[r]]}return i}function a(i){for(var n=0;n<i.length;n++){for(var r=e,o=i[n],a=o.split(/[.\/]/),u=0;u<a.length-1;++u)r[a[u]]===t&&(r[a[u]]={}),r=r[a[u]];r[a[a.length-1]]=s[o]}}var s={};n("moxie/core/utils/Basic",[],function(){function e(e){var t;return e===t?"undefined":null===e?"null":e.nodeType?"node":{}.toString.call(e).match(/\s([a-z|A-Z]+)/)[1].toLowerCase()}function t(){return s(!1,!1,arguments)}function i(){return s(!0,!1,arguments)}function n(){return s(!1,!0,arguments)}function r(){return s(!0,!0,arguments)}function o(t){switch(e(t)){case"array":return s(!1,!0,[[],t]);case"object":return s(!1,!0,[{},t]);default:return t}}function a(i){switch(e(i)){case"array":return Array.prototype.slice.call(i);case"object":return t({},i)}return i}function s(t,i,n){var r,o=n[0];return c(n,function(n,u){u>0&&c(n,function(n,u){var c=-1!==h(e(n),["array","object"]);return n===r||t&&o[u]===r?!0:(c&&i&&(n=a(n)),e(o[u])===e(n)&&c?s(t,i,[o[u],n]):o[u]=n,void 0)})}),o}function u(e,t){function i(){this.constructor=e}for(var n in t)({}).hasOwnProperty.call(t,n)&&(e[n]=t[n]);return i.prototype=t.prototype,e.prototype=new i,e.super=t.prototype,e}function c(e,t){var i,n,r,o;if(e){try{i=e.length}catch(a){i=o}if(i===o||"number"!=typeof i){for(n in e)if(e.hasOwnProperty(n)&&t(e[n],n)===!1)return}else for(r=0;i>r;r++)if(t(e[r],r)===!1)return}}function l(t){var i;if(!t||"object"!==e(t))return!0;for(i in t)return!1;return!0}function d(t,i){function n(r){"function"===e(t[r])&&t[r](function(e){++r<o&&!e?n(r):i(e)})}var r=0,o=t.length;"function"!==e(i)&&(i=function(){}),t&&t.length||i(),n(r)}function m(e,t){var i=0,n=e.length,r=new Array(n);c(e,function(e,o){e(function(e){if(e)return t(e);var a=[].slice.call(arguments);a.shift(),r[o]=a,i++,i===n&&(r.unshift(null),t.apply(this,r))})})}function h(e,t){if(t){if(Array.prototype.indexOf)return Array.prototype.indexOf.call(t,e);for(var i=0,n=t.length;n>i;i++)if(t[i]===e)return i}return-1}function f(t,i){var n=[];"array"!==e(t)&&(t=[t]),"array"!==e(i)&&(i=[i]);for(var r in t)-1===h(t[r],i)&&n.push(t[r]);return n.length?n:!1}function p(e,t){var i=[];return c(e,function(e){-1!==h(e,t)&&i.push(e)}),i.length?i:null}function g(e){var t,i=[];for(t=0;t<e.length;t++)i[t]=e[t];return i}function x(e){return e?String.prototype.trim?String.prototype.trim.call(e):e.toString().replace(/^\s*/,"").replace(/\s*$/,""):e}function v(e){if("string"!=typeof e)return e;var t,i={t:1099511627776,g:1073741824,m:1048576,k:1024};return e=/^([0-9\.]+)([tmgk]?)$/.exec(e.toLowerCase().replace(/[^0-9\.tmkg]/g,"")),t=e[2],e=+e[1],i.hasOwnProperty(t)&&(e*=i[t]),Math.floor(e)}function w(e){var t=[].slice.call(arguments,1);return e.replace(/%([a-z])/g,function(e,i){var n=t.shift();switch(i){case"s":return n+"";case"d":return parseInt(n,10);case"f":return parseFloat(n);case"c":return"";default:return n}})}function y(e,t){var i=this;setTimeout(function(){e.call(i)},t||1)}var E=function(){var e=0;return function(t){var i,n=(new Date).getTime().toString(32);for(i=0;5>i;i++)n+=Math.floor(65535*Math.random()).toString(32);return(t||"o_")+n+(e++).toString(32)}}();return{guid:E,typeOf:e,extend:t,extendIf:i,extendImmutable:n,extendImmutableIf:r,clone:o,inherit:u,each:c,isEmptyObj:l,inSeries:d,inParallel:m,inArray:h,arrayDiff:f,arrayIntersect:p,toArray:g,trim:x,sprintf:w,parseSizeStr:v,delay:y}}),n("moxie/core/utils/Encode",[],function(){var e=function(e){return unescape(encodeURIComponent(e))},t=function(e){return decodeURIComponent(escape(e))},i=function(e,i){if("function"==typeof window.atob)return i?t(window.atob(e)):window.atob(e);var n,r,o,a,s,u,c,l,d="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",m=0,h=0,f="",p=[];if(!e)return e;e+="";do a=d.indexOf(e.charAt(m++)),s=d.indexOf(e.charAt(m++)),u=d.indexOf(e.charAt(m++)),c=d.indexOf(e.charAt(m++)),l=a<<18|s<<12|u<<6|c,n=255&l>>16,r=255&l>>8,o=255&l,p[h++]=64==u?String.fromCharCode(n):64==c?String.fromCharCode(n,r):String.fromCharCode(n,r,o);while(m<e.length);return f=p.join(""),i?t(f):f},n=function(t,i){if(i&&(t=e(t)),"function"==typeof window.btoa)return window.btoa(t);var n,r,o,a,s,u,c,l,d="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",m=0,h=0,f="",p=[];if(!t)return t;do n=t.charCodeAt(m++),r=t.charCodeAt(m++),o=t.charCodeAt(m++),l=n<<16|r<<8|o,a=63&l>>18,s=63&l>>12,u=63&l>>6,c=63&l,p[h++]=d.charAt(a)+d.charAt(s)+d.charAt(u)+d.charAt(c);while(m<t.length);f=p.join("");var g=t.length%3;return(g?f.slice(0,g-3):f)+"===".slice(g||3)};return{utf8_encode:e,utf8_decode:t,atob:i,btoa:n}}),n("moxie/core/utils/Env",["moxie/core/utils/Basic"],function(e){function i(e,t,i){var n=0,r=0,o=0,a={dev:-6,alpha:-5,a:-5,beta:-4,b:-4,RC:-3,rc:-3,"#":-2,p:1,pl:1},s=function(e){return e=(""+e).replace(/[_\-+]/g,"."),e=e.replace(/([^.\d]+)/g,".$1.").replace(/\.{2,}/g,"."),e.length?e.split("."):[-8]},u=function(e){return e?isNaN(e)?a[e]||-7:parseInt(e,10):0};for(e=s(e),t=s(t),r=Math.max(e.length,t.length),n=0;r>n;n++)if(e[n]!=t[n]){if(e[n]=u(e[n]),t[n]=u(t[n]),e[n]<t[n]){o=-1;break}if(e[n]>t[n]){o=1;break}}if(!i)return o;switch(i){case">":case"gt":return o>0;case">=":case"ge":return o>=0;case"<=":case"le":return 0>=o;case"==":case"=":case"eq":return 0===o;case"<>":case"!=":case"ne":return 0!==o;case"":case"<":case"lt":return 0>o;default:return null}}var n=function(e){var t="",i="?",n="function",r="undefined",o="object",a="name",s="version",u={has:function(e,t){return-1!==t.toLowerCase().indexOf(e.toLowerCase())},lowerize:function(e){return e.toLowerCase()}},c={rgx:function(){for(var t,i,a,s,u,c,l,d=0,m=arguments;d<m.length;d+=2){var h=m[d],f=m[d+1];if(typeof t===r){t={};for(s in f)u=f[s],typeof u===o?t[u[0]]=e:t[u]=e}for(i=a=0;i<h.length;i++)if(c=h[i].exec(this.getUA())){for(s=0;s<f.length;s++)l=c[++a],u=f[s],typeof u===o&&u.length>0?2==u.length?t[u[0]]=typeof u[1]==n?u[1].call(this,l):u[1]:3==u.length?t[u[0]]=typeof u[1]!==n||u[1].exec&&u[1].test?l?l.replace(u[1],u[2]):e:l?u[1].call(this,l,u[2]):e:4==u.length&&(t[u[0]]=l?u[3].call(this,l.replace(u[1],u[2])):e):t[u]=l?l:e;break}if(c)break}return t},str:function(t,n){for(var r in n)if(typeof n[r]===o&&n[r].length>0){for(var a=0;a<n[r].length;a++)if(u.has(n[r][a],t))return r===i?e:r}else if(u.has(n[r],t))return r===i?e:r;return t}},l={browser:{oldsafari:{major:{1:["/8","/1","/3"],2:"/4","?":"/"},version:{"1.0":"/8",1.2:"/1",1.3:"/3","2.0":"/412","2.0.2":"/416","2.0.3":"/417","2.0.4":"/419","?":"/"}}},device:{sprint:{model:{"Evo Shift 4G":"7373KT"},vendor:{HTC:"APA",Sprint:"Sprint"}}},os:{windows:{version:{ME:"4.90","NT 3.11":"NT3.51","NT 4.0":"NT4.0",2000:"NT 5.0",XP:["NT 5.1","NT 5.2"],Vista:"NT 6.0",7:"NT 6.1",8:"NT 6.2",8.1:"NT 6.3",RT:"ARM"}}}},d={browser:[[/(opera\smini)\/([\w\.-]+)/i,/(opera\s[mobiletab]+).+version\/([\w\.-]+)/i,/(opera).+version\/([\w\.]+)/i,/(opera)[\/\s]+([\w\.]+)/i],[a,s],[/\s(opr)\/([\w\.]+)/i],[[a,"Opera"],s],[/(kindle)\/([\w\.]+)/i,/(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?([\w\.]+)*/i,/(avant\s|iemobile|slim|baidu)(?:browser)?[\/\s]?([\w\.]*)/i,/(?:ms|\()(ie)\s([\w\.]+)/i,/(rekonq)\/([\w\.]+)*/i,/(chromium|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi)\/([\w\.-]+)/i],[a,s],[/(trident).+rv[:\s]([\w\.]+).+like\sgecko/i],[[a,"IE"],s],[/(edge)\/((\d+)?[\w\.]+)/i],[a,s],[/(yabrowser)\/([\w\.]+)/i],[[a,"Yandex"],s],[/(comodo_dragon)\/([\w\.]+)/i],[[a,/_/g," "],s],[/(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?([\w\.]+)/i,/(uc\s?browser|qqbrowser)[\/\s]?([\w\.]+)/i],[a,s],[/(dolfin)\/([\w\.]+)/i],[[a,"Dolphin"],s],[/((?:android.+)crmo|crios)\/([\w\.]+)/i],[[a,"Chrome"],s],[/XiaoMi\/MiuiBrowser\/([\w\.]+)/i],[s,[a,"MIUI Browser"]],[/android.+version\/([\w\.]+)\s+(?:mobile\s?safari|safari)/i],[s,[a,"Android Browser"]],[/FBAV\/([\w\.]+);/i],[s,[a,"Facebook"]],[/version\/([\w\.]+).+?mobile\/\w+\s(safari)/i],[s,[a,"Mobile Safari"]],[/version\/([\w\.]+).+?(mobile\s?safari|safari)/i],[s,a],[/webkit.+?(mobile\s?safari|safari)(\/[\w\.]+)/i],[a,[s,c.str,l.browser.oldsafari.version]],[/(konqueror)\/([\w\.]+)/i,/(webkit|khtml)\/([\w\.]+)/i],[a,s],[/(navigator|netscape)\/([\w\.-]+)/i],[[a,"Netscape"],s],[/(swiftfox)/i,/(icedragon|iceweasel|camino|chimera|fennec|maemo\sbrowser|minimo|conkeror)[\/\s]?([\w\.\+]+)/i,/(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix)\/([\w\.-]+)/i,/(mozilla)\/([\w\.]+).+rv\:.+gecko\/\d+/i,/(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf)[\/\s]?([\w\.]+)/i,/(links)\s\(([\w\.]+)/i,/(gobrowser)\/?([\w\.]+)*/i,/(ice\s?browser)\/v?([\w\._]+)/i,/(mosaic)[\/\s]([\w\.]+)/i],[a,s]],engine:[[/windows.+\sedge\/([\w\.]+)/i],[s,[a,"EdgeHTML"]],[/(presto)\/([\w\.]+)/i,/(webkit|trident|netfront|netsurf|amaya|lynx|w3m)\/([\w\.]+)/i,/(khtml|tasman|links)[\/\s]\(?([\w\.]+)/i,/(icab)[\/\s]([23]\.[\d\.]+)/i],[a,s],[/rv\:([\w\.]+).*(gecko)/i],[s,a]],os:[[/microsoft\s(windows)\s(vista|xp)/i],[a,s],[/(windows)\snt\s6\.2;\s(arm)/i,/(windows\sphone(?:\sos)*|windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)/i],[a,[s,c.str,l.os.windows.version]],[/(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i],[[a,"Windows"],[s,c.str,l.os.windows.version]],[/\((bb)(10);/i],[[a,"BlackBerry"],s],[/(blackberry)\w*\/?([\w\.]+)*/i,/(tizen)[\/\s]([\w\.]+)/i,/(android|webos|palm\os|qnx|bada|rim\stablet\sos|meego|contiki)[\/\s-]?([\w\.]+)*/i,/linux;.+(sailfish);/i],[a,s],[/(symbian\s?os|symbos|s60(?=;))[\/\s-]?([\w\.]+)*/i],[[a,"Symbian"],s],[/\((series40);/i],[a],[/mozilla.+\(mobile;.+gecko.+firefox/i],[[a,"Firefox OS"],s],[/(nintendo|playstation)\s([wids3portablevu]+)/i,/(mint)[\/\s\(]?(\w+)*/i,/(mageia|vectorlinux)[;\s]/i,/(joli|[kxln]?ubuntu|debian|[open]*suse|gentoo|arch|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk|linpus)[\/\s-]?([\w\.-]+)*/i,/(hurd|linux)\s?([\w\.]+)*/i,/(gnu)\s?([\w\.]+)*/i],[a,s],[/(cros)\s[\w]+\s([\w\.]+\w)/i],[[a,"Chromium OS"],s],[/(sunos)\s?([\w\.]+\d)*/i],[[a,"Solaris"],s],[/\s([frentopc-]{0,4}bsd|dragonfly)\s?([\w\.]+)*/i],[a,s],[/(ip[honead]+)(?:.*os\s*([\w]+)*\slike\smac|;\sopera)/i],[[a,"iOS"],[s,/_/g,"."]],[/(mac\sos\sx)\s?([\w\s\.]+\w)*/i,/(macintosh|mac(?=_powerpc)\s)/i],[[a,"Mac OS"],[s,/_/g,"."]],[/((?:open)?solaris)[\/\s-]?([\w\.]+)*/i,/(haiku)\s(\w+)/i,/(aix)\s((\d)(?=\.|\)|\s)[\w\.]*)*/i,/(plan\s9|minix|beos|os\/2|amigaos|morphos|risc\sos|openvms)/i,/(unix)\s?([\w\.]+)*/i],[a,s]]},m=function(e){var i=e||(window&&window.navigator&&window.navigator.userAgent?window.navigator.userAgent:t);this.getBrowser=function(){return c.rgx.apply(this,d.browser)},this.getEngine=function(){return c.rgx.apply(this,d.engine)},this.getOS=function(){return c.rgx.apply(this,d.os)},this.getResult=function(){return{ua:this.getUA(),browser:this.getBrowser(),engine:this.getEngine(),os:this.getOS()}},this.getUA=function(){return i},this.setUA=function(e){return i=e,this},this.setUA(i)};return m}(),r=function(){var i={access_global_ns:function(){return!!window.moxie},define_property:function(){return!1}(),create_canvas:function(){var e=document.createElement("canvas"),t=!(!e.getContext||!e.getContext("2d"));return i.create_canvas=t,t},return_response_type:function(t){try{if(-1!==e.inArray(t,["","text","document"]))return!0;if(window.XMLHttpRequest){var i=new XMLHttpRequest;if(i.open("get","/"),"responseType"in i)return i.responseType=t,i.responseType!==t?!1:!0}}catch(n){}return!1},use_blob_uri:function(){var e=window.URL;return e&&"createObjectURL"in e&&"revokeObjectURL"in e}(),use_data_uri:function(){var e=new Image;return e.onload=function(){i.use_data_uri=1===e.width&&1===e.height},setTimeout(function(){e.src="data:image/gif;base64,R0lGODlhAQABAIAAAP8AAAAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=="},1),!1}(),use_data_uri_over32kb:function(){return i.use_data_uri&&("IE"!==a.browser||a.version>=9)},use_data_uri_of:function(e){return i.use_data_uri&&33e3>e||i.use_data_uri_over32kb()},use_fileinput:function(){if(navigator.userAgent.match(/(Android (1.0|1.1|1.5|1.6|2.0|2.1))|(Windows Phone (OS 7|8.0))|(XBLWP)|(ZuneWP)|(w(eb)?OSBrowser)|(webOS)|(Kindle\/(1.0|2.0|2.5|3.0))/))return!1;var e=document.createElement("input");return e.setAttribute("type","file"),i.use_fileinput=!e.disabled},use_webgl:function(){var e,n=document.createElement("canvas"),r=null;try{r=n.getContext("webgl")||n.getContext("experimental-webgl")}catch(o){}return r||(r=null),e=!!r,i.use_webgl=e,n=t,e}};return function(t){var n=[].slice.call(arguments);return n.shift(),"function"===e.typeOf(i[t])?i[t].apply(this,n):!!i[t]}}(),o=(new n).getResult(),a={can:r,uaParser:n,browser:o.browser.name,version:o.browser.version,os:o.os.name,osVersion:o.os.version,verComp:i,swf_url:"../flash/Moxie.swf",xap_url:"../silverlight/Moxie.xap",global_event_dispatcher:"moxie.core.EventTarget.instance.dispatchEvent"};return a.OS=a.os,a}),n("moxie/core/Exceptions",["moxie/core/utils/Basic"],function(e){function t(e,t){var i;for(i in e)if(e[i]===t)return i;return null}return{RuntimeError:function(){function i(e,i){this.code=e,this.name=t(n,e),this.message=this.name+(i||": RuntimeError "+this.code)}var n={NOT_INIT_ERR:1,EXCEPTION_ERR:3,NOT_SUPPORTED_ERR:9,JS_ERR:4};return e.extend(i,n),i.prototype=Error.prototype,i}(),OperationNotAllowedException:function(){function t(e){this.code=e,this.name="OperationNotAllowedException"}return e.extend(t,{NOT_ALLOWED_ERR:1}),t.prototype=Error.prototype,t}(),ImageError:function(){function i(e){this.code=e,this.name=t(n,e),this.message=this.name+": ImageError "+this.code}var n={WRONG_FORMAT:1,MAX_RESOLUTION_ERR:2,INVALID_META_ERR:3};return e.extend(i,n),i.prototype=Error.prototype,i}(),FileException:function(){function i(e){this.code=e,this.name=t(n,e),this.message=this.name+": FileException "+this.code}var n={NOT_FOUND_ERR:1,SECURITY_ERR:2,ABORT_ERR:3,NOT_READABLE_ERR:4,ENCODING_ERR:5,NO_MODIFICATION_ALLOWED_ERR:6,INVALID_STATE_ERR:7,SYNTAX_ERR:8};return e.extend(i,n),i.prototype=Error.prototype,i}(),DOMException:function(){function i(e){this.code=e,this.name=t(n,e),this.message=this.name+": DOMException "+this.code}var n={INDEX_SIZE_ERR:1,DOMSTRING_SIZE_ERR:2,HIERARCHY_REQUEST_ERR:3,WRONG_DOCUMENT_ERR:4,INVALID_CHARACTER_ERR:5,NO_DATA_ALLOWED_ERR:6,NO_MODIFICATION_ALLOWED_ERR:7,NOT_FOUND_ERR:8,NOT_SUPPORTED_ERR:9,INUSE_ATTRIBUTE_ERR:10,INVALID_STATE_ERR:11,SYNTAX_ERR:12,INVALID_MODIFICATION_ERR:13,NAMESPACE_ERR:14,INVALID_ACCESS_ERR:15,VALIDATION_ERR:16,TYPE_MISMATCH_ERR:17,SECURITY_ERR:18,NETWORK_ERR:19,ABORT_ERR:20,URL_MISMATCH_ERR:21,QUOTA_EXCEEDED_ERR:22,TIMEOUT_ERR:23,INVALID_NODE_TYPE_ERR:24,DATA_CLONE_ERR:25};return e.extend(i,n),i.prototype=Error.prototype,i}(),EventException:function(){function t(e){this.code=e,this.name="EventException"}return e.extend(t,{UNSPECIFIED_EVENT_TYPE_ERR:0}),t.prototype=Error.prototype,t}()}}),n("moxie/core/utils/Dom",["moxie/core/utils/Env"],function(e){var t=function(e){return"string"!=typeof e?e:document.getElementById(e)},i=function(e,t){if(!e.className)return!1;var i=new RegExp("(^|\\s+)"+t+"(\\s+|$)");return i.test(e.className)},n=function(e,t){i(e,t)||(e.className=e.className?e.className.replace(/\s+$/,"")+" "+t:t)},r=function(e,t){if(e.className){var i=new RegExp("(^|\\s+)"+t+"(\\s+|$)");e.className=e.className.replace(i,function(e,t,i){return" "===t&&" "===i?" ":""})}},o=function(e,t){return e.currentStyle?e.currentStyle[t]:window.getComputedStyle?window.getComputedStyle(e,null)[t]:void 0},a=function(t,i){function n(e){var t,i,n=0,r=0;return e&&(i=e.getBoundingClientRect(),t="CSS1Compat"===c.compatMode?c.documentElement:c.body,n=i.left+t.scrollLeft,r=i.top+t.scrollTop),{x:n,y:r}}var r,o,a,s=0,u=0,c=document;if(t=t,i=i||c.body,t&&t.getBoundingClientRect&&"IE"===e.browser&&(!c.documentMode||c.documentMode<8))return o=n(t),a=n(i),{x:o.x-a.x,y:o.y-a.y};for(r=t;r&&r!=i&&r.nodeType;)s+=r.offsetLeft||0,u+=r.offsetTop||0,r=r.offsetParent;for(r=t.parentNode;r&&r!=i&&r.nodeType;)s-=r.scrollLeft||0,u-=r.scrollTop||0,r=r.parentNode;return{x:s,y:u}},s=function(e){return{w:e.offsetWidth||e.clientWidth,h:e.offsetHeight||e.clientHeight}};return{get:t,hasClass:i,addClass:n,removeClass:r,getStyle:o,getPos:a,getSize:s}}),n("moxie/core/EventTarget",["moxie/core/utils/Env","moxie/core/Exceptions","moxie/core/utils/Basic"],function(e,t,i){function n(){this.uid=i.guid()}var r={};return i.extend(n.prototype,{init:function(){this.uid||(this.uid=i.guid("uid_"))},addEventListener:function(e,t,n,o){var a,s=this;return this.hasOwnProperty("uid")||(this.uid=i.guid("uid_")),e=i.trim(e),/\s/.test(e)?(i.each(e.split(/\s+/),function(e){s.addEventListener(e,t,n,o)}),void 0):(e=e.toLowerCase(),n=parseInt(n,10)||0,a=r[this.uid]&&r[this.uid][e]||[],a.push({fn:t,priority:n,scope:o||this}),r[this.uid]||(r[this.uid]={}),r[this.uid][e]=a,void 0)},hasEventListener:function(e){var t;return e?(e=e.toLowerCase(),t=r[this.uid]&&r[this.uid][e]):t=r[this.uid],t?t:!1},removeEventListener:function(e,t){var n,o,a=this;if(e=e.toLowerCase(),/\s/.test(e))return i.each(e.split(/\s+/),function(e){a.removeEventListener(e,t)}),void 0;if(n=r[this.uid]&&r[this.uid][e]){if(t){for(o=n.length-1;o>=0;o--)if(n[o].fn===t){n.splice(o,1);break}}else n=[];n.length||(delete r[this.uid][e],i.isEmptyObj(r[this.uid])&&delete r[this.uid])}},removeAllEventListeners:function(){r[this.uid]&&delete r[this.uid]},dispatchEvent:function(e){var n,o,a,s,u,c={},l=!0;if("string"!==i.typeOf(e)){if(s=e,"string"!==i.typeOf(s.type))throw new t.EventException(t.EventException.UNSPECIFIED_EVENT_TYPE_ERR);e=s.type,s.total!==u&&s.loaded!==u&&(c.total=s.total,c.loaded=s.loaded),c.async=s.async||!1}if(-1!==e.indexOf("::")?function(t){n=t[0],e=t[1]}(e.split("::")):n=this.uid,e=e.toLowerCase(),o=r[n]&&r[n][e]){o.sort(function(e,t){return t.priority-e.priority}),a=[].slice.call(arguments),a.shift(),c.type=e,a.unshift(c);var d=[];i.each(o,function(e){a[0].target=e.scope,c.async?d.push(function(t){setTimeout(function(){t(e.fn.apply(e.scope,a)===!1)},1)}):d.push(function(t){t(e.fn.apply(e.scope,a)===!1)})}),d.length&&i.inSeries(d,function(e){l=!e})}return l},bindOnce:function(e,t,i,n){var r=this;r.bind.call(this,e,function o(){return r.unbind(e,o),t.apply(this,arguments)},i,n)},bind:function(){this.addEventListener.apply(this,arguments)},unbind:function(){this.removeEventListener.apply(this,arguments)},unbindAll:function(){this.removeAllEventListeners.apply(this,arguments)},trigger:function(){return this.dispatchEvent.apply(this,arguments)},handleEventProps:function(e){var t=this;this.bind(e.join(" "),function(e){var t="on"+e.type.toLowerCase();"function"===i.typeOf(this[t])&&this[t].apply(this,arguments)}),i.each(e,function(e){e="on"+e.toLowerCase(e),"undefined"===i.typeOf(t[e])&&(t[e]=null)})}}),n.instance=new n,n}),n("moxie/runtime/Runtime",["moxie/core/utils/Env","moxie/core/utils/Basic","moxie/core/utils/Dom","moxie/core/EventTarget"],function(e,t,i,n){function r(e,n,o,s,u){var c,l=this,d=t.guid(n+"_"),m=u||"browser";e=e||{},a[d]=this,o=t.extend({access_binary:!1,access_image_binary:!1,display_media:!1,do_cors:!1,drag_and_drop:!1,filter_by_extension:!0,resize_image:!1,report_upload_progress:!1,return_response_headers:!1,return_response_type:!1,return_status_code:!0,send_custom_headers:!1,select_file:!1,select_folder:!1,select_multiple:!0,send_binary_string:!1,send_browser_cookies:!0,send_multipart:!0,slice_blob:!1,stream_upload:!1,summon_file_dialog:!1,upload_filesize:!0,use_http_method:!0},o),e.preferred_caps&&(m=r.getMode(s,e.preferred_caps,m)),c=function(){var e={};return{exec:function(t,i,n,r){return c[i]&&(e[t]||(e[t]={context:this,instance:new c[i]}),e[t].instance[n])?e[t].instance[n].apply(this,r):void 0},removeInstance:function(t){delete e[t]},removeAllInstances:function(){var i=this;t.each(e,function(e,n){"function"===t.typeOf(e.instance.destroy)&&e.instance.destroy.call(e.context),i.removeInstance(n)})}}}(),t.extend(this,{initialized:!1,uid:d,type:n,mode:r.getMode(s,e.required_caps,m),shimid:d+"_container",clients:0,options:e,can:function(e,i){var n=arguments[2]||o;if("string"===t.typeOf(e)&&"undefined"===t.typeOf(i)&&(e=r.parseCaps(e)),"object"===t.typeOf(e)){for(var a in e)if(!this.can(a,e[a],n))return!1;return!0}return"function"===t.typeOf(n[e])?n[e].call(this,i):i===n[e]},getShimContainer:function(){var e,n=i.get(this.shimid);return n||(e=i.get(this.options.container)||document.body,n=document.createElement("div"),n.id=this.shimid,n.className="moxie-shim moxie-shim-"+this.type,t.extend(n.style,{position:"absolute",top:"0px",left:"0px",width:"1px",height:"1px",overflow:"hidden"}),e.appendChild(n),e=null),n},getShim:function(){return c},shimExec:function(e,t){var i=[].slice.call(arguments,2);return l.getShim().exec.call(this,this.uid,e,t,i)},exec:function(e,t){var i=[].slice.call(arguments,2);return l[e]&&l[e][t]?l[e][t].apply(this,i):l.shimExec.apply(this,arguments)},destroy:function(){if(l){var e=i.get(this.shimid);e&&e.parentNode.removeChild(e),c&&c.removeAllInstances(),this.unbindAll(),delete a[this.uid],this.uid=null,d=l=c=e=null}}}),this.mode&&e.required_caps&&!this.can(e.required_caps)&&(this.mode=!1)}var o={},a={};return r.order="html5,flash,silverlight,html4",r.getRuntime=function(e){return a[e]?a[e]:!1},r.addConstructor=function(e,t){t.prototype=n.instance,o[e]=t},r.getConstructor=function(e){return o[e]||null},r.getInfo=function(e){var t=r.getRuntime(e);return t?{uid:t.uid,type:t.type,mode:t.mode,can:function(){return t.can.apply(t,arguments)}}:null},r.parseCaps=function(e){var i={};return"string"!==t.typeOf(e)?e||{}:(t.each(e.split(","),function(e){i[e]=!0}),i)},r.can=function(e,t){var i,n,o=r.getConstructor(e);return o?(i=new o({required_caps:t}),n=i.mode,i.destroy(),!!n):!1},r.thatCan=function(e,t){var i=(t||r.order).split(/\s*,\s*/);for(var n in i)if(r.can(i[n],e))return i[n];return null},r.getMode=function(e,i,n){var r=null;if("undefined"===t.typeOf(n)&&(n="browser"),i&&!t.isEmptyObj(e)){if(t.each(i,function(i,n){if(e.hasOwnProperty(n)){var o=e[n](i);if("string"==typeof o&&(o=[o]),r){if(!(r=t.arrayIntersect(r,o)))return r=!1}else r=o}}),r)return-1!==t.inArray(n,r)?n:r[0];if(r===!1)return!1}return n},r.getGlobalEventTarget=function(){if(/^moxie\./.test(e.global_event_dispatcher)&&!e.can("access_global_ns")){var i=t.guid("moxie_event_target_");window[i]=function(e,t){n.instance.dispatchEvent(e,t)},e.global_event_dispatcher=i}return e.global_event_dispatcher},r.capTrue=function(){return!0},r.capFalse=function(){return!1},r.capTest=function(e){return function(){return!!e}},r}),n("moxie/runtime/RuntimeClient",["moxie/core/utils/Env","moxie/core/Exceptions","moxie/core/utils/Basic","moxie/runtime/Runtime"],function(e,t,i,n){return function(){var e;i.extend(this,{connectRuntime:function(r){function o(i){var a,u;return i.length?(a=i.shift().toLowerCase(),(u=n.getConstructor(a))?(e=new u(r),e.bind("Init",function(){e.initialized=!0,setTimeout(function(){e.clients++,s.ruid=e.uid,s.trigger("RuntimeInit",e)},1)}),e.bind("Error",function(){e.destroy(),o(i)}),e.bind("Exception",function(e,i){var n=i.name+"(#"+i.code+")"+(i.message?", from: "+i.message:"");s.trigger("RuntimeError",new t.RuntimeError(t.RuntimeError.EXCEPTION_ERR,n))}),e.mode?(e.init(),void 0):(e.trigger("Error"),void 0)):(o(i),void 0)):(s.trigger("RuntimeError",new t.RuntimeError(t.RuntimeError.NOT_INIT_ERR)),e=null,void 0)}var a,s=this;if("string"===i.typeOf(r)?a=r:"string"===i.typeOf(r.ruid)&&(a=r.ruid),a){if(e=n.getRuntime(a))return s.ruid=a,e.clients++,e;throw new t.RuntimeError(t.RuntimeError.NOT_INIT_ERR)}o((r.runtime_order||n.order).split(/\s*,\s*/))},disconnectRuntime:function(){e&&--e.clients<=0&&e.destroy(),e=null},getRuntime:function(){return e&&e.uid?e:e=null},exec:function(){return e?e.exec.apply(this,arguments):null},can:function(t){return e?e.can(t):!1}})}}),n("moxie/file/Blob",["moxie/core/utils/Basic","moxie/core/utils/Encode","moxie/runtime/RuntimeClient"],function(e,t,i){function n(o,a){function s(t,i,o){var a,s=r[this.uid];return"string"===e.typeOf(s)&&s.length?(a=new n(null,{type:o,size:i-t}),a.detach(s.substr(t,a.size)),a):null}i.call(this),o&&this.connectRuntime(o),a?"string"===e.typeOf(a)&&(a={data:a}):a={},e.extend(this,{uid:a.uid||e.guid("uid_"),ruid:o,size:a.size||0,type:a.type||"",slice:function(e,t,i){return this.isDetached()?s.apply(this,arguments):this.getRuntime().exec.call(this,"Blob","slice",this.getSource(),e,t,i)},getSource:function(){return r[this.uid]?r[this.uid]:null},detach:function(e){if(this.ruid&&(this.getRuntime().exec.call(this,"Blob","destroy"),this.disconnectRuntime(),this.ruid=null),e=e||"","data:"==e.substr(0,5)){var i=e.indexOf(";base64,");this.type=e.substring(5,i),e=t.atob(e.substring(i+8))}this.size=e.length,r[this.uid]=e},isDetached:function(){return!this.ruid&&"string"===e.typeOf(r[this.uid])},destroy:function(){this.detach(),delete r[this.uid]}}),a.data?this.detach(a.data):r[this.uid]=a}var r={};return n}),n("moxie/core/I18n",["moxie/core/utils/Basic"],function(e){var t={};return{addI18n:function(i){return e.extend(t,i)},translate:function(e){return t[e]||e},_:function(e){return this.translate(e)},sprintf:function(t){var i=[].slice.call(arguments,1);return t.replace(/%[a-z]/g,function(){var t=i.shift();return"undefined"!==e.typeOf(t)?t:""})}}}),n("moxie/core/utils/Mime",["moxie/core/utils/Basic","moxie/core/I18n"],function(e,t){var i="application/msword,doc dot,application/pdf,pdf,application/pgp-signature,pgp,application/postscript,ps ai eps,application/rtf,rtf,application/vnd.ms-excel,xls xlb xlt xla,application/vnd.ms-powerpoint,ppt pps pot ppa,application/zip,zip,application/x-shockwave-flash,swf swfl,application/vnd.openxmlformats-officedocument.wordprocessingml.document,docx,application/vnd.openxmlformats-officedocument.wordprocessingml.template,dotx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,xlsx,application/vnd.openxmlformats-officedocument.presentationml.presentation,pptx,application/vnd.openxmlformats-officedocument.presentationml.template,potx,application/vnd.openxmlformats-officedocument.presentationml.slideshow,ppsx,application/x-javascript,js,application/json,json,audio/mpeg,mp3 mpga mpega mp2,audio/x-wav,wav,audio/x-m4a,m4a,audio/ogg,oga ogg,audio/aiff,aiff aif,audio/flac,flac,audio/aac,aac,audio/ac3,ac3,audio/x-ms-wma,wma,image/bmp,bmp,image/gif,gif,image/jpeg,jpg jpeg jpe,image/photoshop,psd,image/png,png,image/svg+xml,svg svgz,image/tiff,tiff tif,text/plain,asc txt text diff log,text/html,htm html xhtml,text/css,css,text/csv,csv,text/rtf,rtf,video/mpeg,mpeg mpg mpe m2v,video/quicktime,qt mov,video/mp4,mp4,video/x-m4v,m4v,video/x-flv,flv,video/x-ms-wmv,wmv,video/avi,avi,video/webm,webm,video/3gpp,3gpp 3gp,video/3gpp2,3g2,video/vnd.rn-realvideo,rv,video/ogg,ogv,video/x-matroska,mkv,application/vnd.oasis.opendocument.formula-template,otf,application/octet-stream,exe",n={mimes:{},extensions:{},addMimeType:function(e){var t,i,n,r=e.split(/,/);for(t=0;t<r.length;t+=2){for(n=r[t+1].split(/ /),i=0;i<n.length;i++)this.mimes[n[i]]=r[t];this.extensions[r[t]]=n}},extList2mimes:function(t,i){var n,r,o,a,s=this,u=[];for(r=0;r<t.length;r++)for(n=t[r].extensions.toLowerCase().split(/\s*,\s*/),o=0;o<n.length;o++){if("*"===n[o])return[];if(a=s.mimes[n[o]],i&&/^\w+$/.test(n[o]))u.push("."+n[o]);else if(a&&-1===e.inArray(a,u))u.push(a);else if(!a)return[]}return u},mimes2exts:function(t){var i=this,n=[];return e.each(t,function(t){if(t=t.toLowerCase(),"*"===t)return n=[],!1;var r=t.match(/^(\w+)\/(\*|\w+)$/);r&&("*"===r[2]?e.each(i.extensions,function(e,t){new RegExp("^"+r[1]+"/").test(t)&&[].push.apply(n,i.extensions[t])}):i.extensions[t]&&[].push.apply(n,i.extensions[t]))}),n},mimes2extList:function(i){var n=[],r=[];return"string"===e.typeOf(i)&&(i=e.trim(i).split(/\s*,\s*/)),r=this.mimes2exts(i),n.push({title:t.translate("Files"),extensions:r.length?r.join(","):"*"}),n},getFileExtension:function(e){var t=e&&e.match(/\.([^.]+)$/);return t?t[1].toLowerCase():""},getFileMime:function(e){return this.mimes[this.getFileExtension(e)]||""}};return n.addMimeType(i),n}),n("moxie/file/FileInput",["moxie/core/utils/Basic","moxie/core/utils/Env","moxie/core/utils/Mime","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/core/EventTarget","moxie/core/I18n","moxie/runtime/Runtime","moxie/runtime/RuntimeClient"],function(e,t,i,n,r,o,a,s,u){function c(t){var o,c,d;if(-1!==e.inArray(e.typeOf(t),["string","node"])&&(t={browse_button:t}),c=n.get(t.browse_button),!c)throw new r.DOMException(r.DOMException.NOT_FOUND_ERR);d={accept:[{title:a.translate("All Files"),extensions:"*"}],multiple:!1,required_caps:!1,container:c.parentNode||document.body},t=e.extend({},d,t),"string"==typeof t.required_caps&&(t.required_caps=s.parseCaps(t.required_caps)),"string"==typeof t.accept&&(t.accept=i.mimes2extList(t.accept)),o=n.get(t.container),o||(o=document.body),"static"===n.getStyle(o,"position")&&(o.style.position="relative"),o=c=null,u.call(this),e.extend(this,{uid:e.guid("uid_"),ruid:null,shimid:null,files:null,init:function(){var i=this;i.bind("RuntimeInit",function(r,o){i.ruid=o.uid,i.shimid=o.shimid,i.bind("Ready",function(){i.trigger("Refresh")},999),i.bind("Refresh",function(){var i,r,a,s,u;a=n.get(t.browse_button),s=n.get(o.shimid),a&&(i=n.getPos(a,n.get(t.container)),r=n.getSize(a),u=parseInt(n.getStyle(a,"z-index"),10)||0,s&&e.extend(s.style,{top:i.y+"px",left:i.x+"px",width:r.w+"px",height:r.h+"px",zIndex:u+1})),s=a=null}),o.exec.call(i,"FileInput","init",t)}),i.connectRuntime(e.extend({},t,{required_caps:{select_file:!0}}))},getOption:function(e){return t[e]},setOption:function(e,n){if(t.hasOwnProperty(e)){var o=t[e];switch(e){case"accept":"string"==typeof n&&(n=i.mimes2extList(n));break;case"container":case"required_caps":throw new r.FileException(r.FileException.NO_MODIFICATION_ALLOWED_ERR)}t[e]=n,this.exec("FileInput","setOption",e,n),this.trigger("OptionChanged",e,n,o)}},disable:function(t){var i=this.getRuntime();i&&this.exec("FileInput","disable","undefined"===e.typeOf(t)?!0:t)},refresh:function(){this.trigger("Refresh")},destroy:function(){var t=this.getRuntime();t&&(t.exec.call(this,"FileInput","destroy"),this.disconnectRuntime()),"array"===e.typeOf(this.files)&&e.each(this.files,function(e){e.destroy()}),this.files=null,this.unbindAll()}}),this.handleEventProps(l)}var l=["ready","change","cancel","mouseenter","mouseleave","mousedown","mouseup"];return c.prototype=o.instance,c}),n("moxie/file/File",["moxie/core/utils/Basic","moxie/core/utils/Mime","moxie/file/Blob"],function(e,t,i){function n(n,r){r||(r={}),i.apply(this,arguments),this.type||(this.type=t.getFileMime(r.name));var o;if(r.name)o=r.name.replace(/\\/g,"/"),o=o.substr(o.lastIndexOf("/")+1);else if(this.type){var a=this.type.split("/")[0];o=e.guid((""!==a?a:"file")+"_"),t.extensions[this.type]&&(o+="."+t.extensions[this.type][0])}e.extend(this,{name:o||e.guid("file_"),relativePath:"",lastModifiedDate:r.lastModifiedDate||(new Date).toLocaleString()})}return n.prototype=i.prototype,n}),n("moxie/file/FileDrop",["moxie/core/I18n","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/core/utils/Basic","moxie/core/utils/Env","moxie/file/File","moxie/runtime/RuntimeClient","moxie/core/EventTarget","moxie/core/utils/Mime"],function(e,t,i,n,r,o,a,s,u){function c(i){var r,o=this;"string"==typeof i&&(i={drop_zone:i}),r={accept:[{title:e.translate("All Files"),extensions:"*"}],required_caps:{drag_and_drop:!0}},i="object"==typeof i?n.extend({},r,i):r,i.container=t.get(i.drop_zone)||document.body,"static"===t.getStyle(i.container,"position")&&(i.container.style.position="relative"),"string"==typeof i.accept&&(i.accept=u.mimes2extList(i.accept)),a.call(o),n.extend(o,{uid:n.guid("uid_"),ruid:null,files:null,init:function(){o.bind("RuntimeInit",function(e,t){o.ruid=t.uid,t.exec.call(o,"FileDrop","init",i),o.dispatchEvent("ready") -}),o.connectRuntime(i)},destroy:function(){var e=this.getRuntime();e&&(e.exec.call(this,"FileDrop","destroy"),this.disconnectRuntime()),this.files=null,this.unbindAll()}}),this.handleEventProps(l)}var l=["ready","dragenter","dragleave","drop","error"];return c.prototype=s.instance,c}),n("moxie/file/FileReader",["moxie/core/utils/Basic","moxie/core/utils/Encode","moxie/core/Exceptions","moxie/core/EventTarget","moxie/file/Blob","moxie/runtime/RuntimeClient"],function(e,t,i,n,r,o){function a(){function n(e,n){if(this.trigger("loadstart"),this.readyState===a.LOADING)return this.trigger("error",new i.DOMException(i.DOMException.INVALID_STATE_ERR)),this.trigger("loadend"),void 0;if(!(n instanceof r))return this.trigger("error",new i.DOMException(i.DOMException.NOT_FOUND_ERR)),this.trigger("loadend"),void 0;if(this.result=null,this.readyState=a.LOADING,n.isDetached()){var o=n.getSource();switch(e){case"readAsText":case"readAsBinaryString":this.result=o;break;case"readAsDataURL":this.result="data:"+n.type+";base64,"+t.btoa(o)}this.readyState=a.DONE,this.trigger("load"),this.trigger("loadend")}else this.connectRuntime(n.ruid),this.exec("FileReader","read",e,n)}o.call(this),e.extend(this,{uid:e.guid("uid_"),readyState:a.EMPTY,result:null,error:null,readAsBinaryString:function(e){n.call(this,"readAsBinaryString",e)},readAsDataURL:function(e){n.call(this,"readAsDataURL",e)},readAsText:function(e){n.call(this,"readAsText",e)},abort:function(){this.result=null,-1===e.inArray(this.readyState,[a.EMPTY,a.DONE])&&(this.readyState===a.LOADING&&(this.readyState=a.DONE),this.exec("FileReader","abort"),this.trigger("abort"),this.trigger("loadend"))},destroy:function(){this.abort(),this.exec("FileReader","destroy"),this.disconnectRuntime(),this.unbindAll()}}),this.handleEventProps(s),this.bind("Error",function(e,t){this.readyState=a.DONE,this.error=t},999),this.bind("Load",function(){this.readyState=a.DONE},999)}var s=["loadstart","progress","load","abort","error","loadend"];return a.EMPTY=0,a.LOADING=1,a.DONE=2,a.prototype=n.instance,a}),n("moxie/core/utils/Url",["moxie/core/utils/Basic"],function(e){var t=function(i,n){var r,o=["source","scheme","authority","userInfo","user","pass","host","port","relative","path","directory","file","query","fragment"],a=o.length,s={http:80,https:443},u={},c=/^(?:([^:\/?#]+):)?(?:\/\/()(?:(?:()(?:([^:@\/]*):?([^:@\/]*))?@)?(\[[\da-fA-F:]+\]|[^:\/?#]*)(?::(\d*))?))?()(?:(()(?:(?:[^?#\/]*\/)*)()(?:[^?#]*))(?:\\?([^#]*))?(?:#(.*))?)/,l=c.exec(i||""),d=/^\/\/\w/.test(i);switch(e.typeOf(n)){case"undefined":n=t(document.location.href,!1);break;case"string":n=t(n,!1)}for(;a--;)l[a]&&(u[o[a]]=l[a]);if(r=!d&&!u.scheme,(d||r)&&(u.scheme=n.scheme),r){u.host=n.host,u.port=n.port;var m="";/^[^\/]/.test(u.path)&&(m=n.path,m=/\/[^\/]*\.[^\/]*$/.test(m)?m.replace(/\/[^\/]+$/,"/"):m.replace(/\/?$/,"/")),u.path=m+(u.path||"")}return u.port||(u.port=s[u.scheme]||80),u.port=parseInt(u.port,10),u.path||(u.path="/"),delete u.source,u},i=function(e){var i={http:80,https:443},n="object"==typeof e?e:t(e);return n.scheme+"://"+n.host+(n.port!==i[n.scheme]?":"+n.port:"")+n.path+(n.query?n.query:"")},n=function(e){function i(e){return[e.scheme,e.host,e.port].join("/")}return"string"==typeof e&&(e=t(e)),i(t())===i(e)};return{parseUrl:t,resolveUrl:i,hasSameOrigin:n}}),n("moxie/runtime/RuntimeTarget",["moxie/core/utils/Basic","moxie/runtime/RuntimeClient","moxie/core/EventTarget"],function(e,t,i){function n(){this.uid=e.guid("uid_"),t.call(this),this.destroy=function(){this.disconnectRuntime(),this.unbindAll()}}return n.prototype=i.instance,n}),n("moxie/file/FileReaderSync",["moxie/core/utils/Basic","moxie/runtime/RuntimeClient","moxie/core/utils/Encode"],function(e,t,i){return function(){function n(e,t){if(!t.isDetached()){var n=this.connectRuntime(t.ruid).exec.call(this,"FileReaderSync","read",e,t);return this.disconnectRuntime(),n}var r=t.getSource();switch(e){case"readAsBinaryString":return r;case"readAsDataURL":return"data:"+t.type+";base64,"+i.btoa(r);case"readAsText":for(var o="",a=0,s=r.length;s>a;a++)o+=String.fromCharCode(r[a]);return o}}t.call(this),e.extend(this,{uid:e.guid("uid_"),readAsBinaryString:function(e){return n.call(this,"readAsBinaryString",e)},readAsDataURL:function(e){return n.call(this,"readAsDataURL",e)},readAsText:function(e){return n.call(this,"readAsText",e)}})}}),n("moxie/xhr/FormData",["moxie/core/Exceptions","moxie/core/utils/Basic","moxie/file/Blob"],function(e,t,i){function n(){var e,n=[];t.extend(this,{append:function(r,o){var a=this,s=t.typeOf(o);o instanceof i?e={name:r,value:o}:"array"===s?(r+="[]",t.each(o,function(e){a.append(r,e)})):"object"===s?t.each(o,function(e,t){a.append(r+"["+t+"]",e)}):"null"===s||"undefined"===s||"number"===s&&isNaN(o)?a.append(r,"false"):n.push({name:r,value:o.toString()})},hasBlob:function(){return!!this.getBlob()},getBlob:function(){return e&&e.value||null},getBlobName:function(){return e&&e.name||null},each:function(i){t.each(n,function(e){i(e.value,e.name)}),e&&i(e.value,e.name)},destroy:function(){e=null,n=[]}})}return n}),n("moxie/xhr/XMLHttpRequest",["moxie/core/utils/Basic","moxie/core/Exceptions","moxie/core/EventTarget","moxie/core/utils/Encode","moxie/core/utils/Url","moxie/runtime/Runtime","moxie/runtime/RuntimeTarget","moxie/file/Blob","moxie/file/FileReaderSync","moxie/xhr/FormData","moxie/core/utils/Env","moxie/core/utils/Mime"],function(e,t,i,n,r,o,a,s,u,c,l,d){function m(){this.uid=e.guid("uid_")}function h(){function i(e,t){return I.hasOwnProperty(e)?1===arguments.length?l.can("define_property")?I[e]:A[e]:(l.can("define_property")?I[e]=t:A[e]=t,void 0):void 0}function u(t){function n(){R&&(R.destroy(),R=null),s.dispatchEvent("loadend"),s=null}function r(r){R.bind("LoadStart",function(e){i("readyState",h.LOADING),s.dispatchEvent("readystatechange"),s.dispatchEvent(e),L&&s.upload.dispatchEvent(e)}),R.bind("Progress",function(e){i("readyState")!==h.LOADING&&(i("readyState",h.LOADING),s.dispatchEvent("readystatechange")),s.dispatchEvent(e)}),R.bind("UploadProgress",function(e){L&&s.upload.dispatchEvent({type:"progress",lengthComputable:!1,total:e.total,loaded:e.loaded})}),R.bind("Load",function(t){i("readyState",h.DONE),i("status",Number(r.exec.call(R,"XMLHttpRequest","getStatus")||0)),i("statusText",f[i("status")]||""),i("response",r.exec.call(R,"XMLHttpRequest","getResponse",i("responseType"))),~e.inArray(i("responseType"),["text",""])?i("responseText",i("response")):"document"===i("responseType")&&i("responseXML",i("response")),U=r.exec.call(R,"XMLHttpRequest","getAllResponseHeaders"),s.dispatchEvent("readystatechange"),i("status")>0?(L&&s.upload.dispatchEvent(t),s.dispatchEvent(t)):(F=!0,s.dispatchEvent("error")),n()}),R.bind("Abort",function(e){s.dispatchEvent(e),n()}),R.bind("Error",function(e){F=!0,i("readyState",h.DONE),s.dispatchEvent("readystatechange"),M=!0,s.dispatchEvent(e),n()}),r.exec.call(R,"XMLHttpRequest","send",{url:x,method:v,async:T,user:w,password:y,headers:S,mimeType:D,encoding:O,responseType:s.responseType,withCredentials:s.withCredentials,options:k},t)}var s=this;E=(new Date).getTime(),R=new a,"string"==typeof k.required_caps&&(k.required_caps=o.parseCaps(k.required_caps)),k.required_caps=e.extend({},k.required_caps,{return_response_type:s.responseType}),t instanceof c&&(k.required_caps.send_multipart=!0),e.isEmptyObj(S)||(k.required_caps.send_custom_headers=!0),B||(k.required_caps.do_cors=!0),k.ruid?r(R.connectRuntime(k)):(R.bind("RuntimeInit",function(e,t){r(t)}),R.bind("RuntimeError",function(e,t){s.dispatchEvent("RuntimeError",t)}),R.connectRuntime(k))}function g(){i("responseText",""),i("responseXML",null),i("response",null),i("status",0),i("statusText",""),E=b=null}var x,v,w,y,E,b,R,_,A=this,I={timeout:0,readyState:h.UNSENT,withCredentials:!1,status:0,statusText:"",responseType:"",responseXML:null,responseText:null,response:null},T=!0,S={},O=null,D=null,N=!1,C=!1,L=!1,M=!1,F=!1,B=!1,P=null,H=null,k={},U="";e.extend(this,I,{uid:e.guid("uid_"),upload:new m,open:function(o,a,s,u,c){var l;if(!o||!a)throw new t.DOMException(t.DOMException.SYNTAX_ERR);if(/[\u0100-\uffff]/.test(o)||n.utf8_encode(o)!==o)throw new t.DOMException(t.DOMException.SYNTAX_ERR);if(~e.inArray(o.toUpperCase(),["CONNECT","DELETE","GET","HEAD","OPTIONS","POST","PUT","TRACE","TRACK"])&&(v=o.toUpperCase()),~e.inArray(v,["CONNECT","TRACE","TRACK"]))throw new t.DOMException(t.DOMException.SECURITY_ERR);if(a=n.utf8_encode(a),l=r.parseUrl(a),B=r.hasSameOrigin(l),x=r.resolveUrl(a),(u||c)&&!B)throw new t.DOMException(t.DOMException.INVALID_ACCESS_ERR);if(w=u||l.user,y=c||l.pass,T=s||!0,T===!1&&(i("timeout")||i("withCredentials")||""!==i("responseType")))throw new t.DOMException(t.DOMException.INVALID_ACCESS_ERR);N=!T,C=!1,S={},g.call(this),i("readyState",h.OPENED),this.dispatchEvent("readystatechange")},setRequestHeader:function(r,o){var a=["accept-charset","accept-encoding","access-control-request-headers","access-control-request-method","connection","content-length","cookie","cookie2","content-transfer-encoding","date","expect","host","keep-alive","origin","referer","te","trailer","transfer-encoding","upgrade","user-agent","via"];if(i("readyState")!==h.OPENED||C)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(/[\u0100-\uffff]/.test(r)||n.utf8_encode(r)!==r)throw new t.DOMException(t.DOMException.SYNTAX_ERR);return r=e.trim(r).toLowerCase(),~e.inArray(r,a)||/^(proxy\-|sec\-)/.test(r)?!1:(S[r]?S[r]+=", "+o:S[r]=o,!0)},hasRequestHeader:function(e){return e&&S[e.toLowerCase()]||!1},getAllResponseHeaders:function(){return U||""},getResponseHeader:function(t){return t=t.toLowerCase(),F||~e.inArray(t,["set-cookie","set-cookie2"])?null:U&&""!==U&&(_||(_={},e.each(U.split(/\r\n/),function(t){var i=t.split(/:\s+/);2===i.length&&(i[0]=e.trim(i[0]),_[i[0].toLowerCase()]={header:i[0],value:e.trim(i[1])})})),_.hasOwnProperty(t))?_[t].header+": "+_[t].value:null},overrideMimeType:function(n){var r,o;if(~e.inArray(i("readyState"),[h.LOADING,h.DONE]))throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(n=e.trim(n.toLowerCase()),/;/.test(n)&&(r=n.match(/^([^;]+)(?:;\scharset\=)?(.*)$/))&&(n=r[1],r[2]&&(o=r[2])),!d.mimes[n])throw new t.DOMException(t.DOMException.SYNTAX_ERR);P=n,H=o},send:function(i,r){if(k="string"===e.typeOf(r)?{ruid:r}:r?r:{},this.readyState!==h.OPENED||C)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(i instanceof s)k.ruid=i.ruid,D=i.type||"application/octet-stream";else if(i instanceof c){if(i.hasBlob()){var o=i.getBlob();k.ruid=o.ruid,D=o.type||"application/octet-stream"}}else"string"==typeof i&&(O="UTF-8",D="text/plain;charset=UTF-8",i=n.utf8_encode(i));this.withCredentials||(this.withCredentials=k.required_caps&&k.required_caps.send_browser_cookies&&!B),L=!N&&this.upload.hasEventListener(),F=!1,M=!i,N||(C=!0),u.call(this,i)},abort:function(){if(F=!0,N=!1,~e.inArray(i("readyState"),[h.UNSENT,h.OPENED,h.DONE]))i("readyState",h.UNSENT);else{if(i("readyState",h.DONE),C=!1,!R)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);R.getRuntime().exec.call(R,"XMLHttpRequest","abort",M),M=!0}},destroy:function(){R&&("function"===e.typeOf(R.destroy)&&R.destroy(),R=null),this.unbindAll(),this.upload&&(this.upload.unbindAll(),this.upload=null)}}),this.handleEventProps(p.concat(["readystatechange"])),this.upload.handleEventProps(p)}var f={100:"Continue",101:"Switching Protocols",102:"Processing",200:"OK",201:"Created",202:"Accepted",203:"Non-Authoritative Information",204:"No Content",205:"Reset Content",206:"Partial Content",207:"Multi-Status",226:"IM Used",300:"Multiple Choices",301:"Moved Permanently",302:"Found",303:"See Other",304:"Not Modified",305:"Use Proxy",306:"Reserved",307:"Temporary Redirect",400:"Bad Request",401:"Unauthorized",402:"Payment Required",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",406:"Not Acceptable",407:"Proxy Authentication Required",408:"Request Timeout",409:"Conflict",410:"Gone",411:"Length Required",412:"Precondition Failed",413:"Request Entity Too Large",414:"Request-URI Too Long",415:"Unsupported Media Type",416:"Requested Range Not Satisfiable",417:"Expectation Failed",422:"Unprocessable Entity",423:"Locked",424:"Failed Dependency",426:"Upgrade Required",500:"Internal Server Error",501:"Not Implemented",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout",505:"HTTP Version Not Supported",506:"Variant Also Negotiates",507:"Insufficient Storage",510:"Not Extended"};m.prototype=i.instance;var p=["loadstart","progress","abort","error","load","timeout","loadend"];return h.UNSENT=0,h.OPENED=1,h.HEADERS_RECEIVED=2,h.LOADING=3,h.DONE=4,h.prototype=i.instance,h}),n("moxie/runtime/Transporter",["moxie/core/utils/Basic","moxie/core/utils/Encode","moxie/runtime/RuntimeClient","moxie/core/EventTarget"],function(e,t,i,n){function r(){function n(){l=d=0,c=this.result=null}function o(t,i){var n=this;u=i,n.bind("TransportingProgress",function(t){d=t.loaded,l>d&&-1===e.inArray(n.state,[r.IDLE,r.DONE])&&a.call(n)},999),n.bind("TransportingComplete",function(){d=l,n.state=r.DONE,c=null,n.result=u.exec.call(n,"Transporter","getAsBlob",t||"")},999),n.state=r.BUSY,n.trigger("TransportingStarted"),a.call(n)}function a(){var e,i=this,n=l-d;m>n&&(m=n),e=t.btoa(c.substr(d,m)),u.exec.call(i,"Transporter","receive",e,l)}var s,u,c,l,d,m;i.call(this),e.extend(this,{uid:e.guid("uid_"),state:r.IDLE,result:null,transport:function(t,i,r){var a=this;if(r=e.extend({chunk_size:204798},r),(s=r.chunk_size%3)&&(r.chunk_size+=3-s),m=r.chunk_size,n.call(this),c=t,l=t.length,"string"===e.typeOf(r)||r.ruid)o.call(a,i,this.connectRuntime(r));else{var u=function(e,t){a.unbind("RuntimeInit",u),o.call(a,i,t)};this.bind("RuntimeInit",u),this.connectRuntime(r)}},abort:function(){var e=this;e.state=r.IDLE,u&&(u.exec.call(e,"Transporter","clear"),e.trigger("TransportingAborted")),n.call(e)},destroy:function(){this.unbindAll(),u=null,this.disconnectRuntime(),n.call(this)}})}return r.IDLE=0,r.BUSY=1,r.DONE=2,r.prototype=n.instance,r}),n("moxie/image/Image",["moxie/core/utils/Basic","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/file/FileReaderSync","moxie/xhr/XMLHttpRequest","moxie/runtime/Runtime","moxie/runtime/RuntimeClient","moxie/runtime/Transporter","moxie/core/utils/Env","moxie/core/EventTarget","moxie/file/Blob","moxie/file/File","moxie/core/utils/Encode"],function(e,t,i,n,r,o,a,s,u,c,l,d,m){function h(){function n(e){try{return e||(e=this.exec("Image","getInfo")),this.size=e.size,this.width=e.width,this.height=e.height,this.type=e.type,this.meta=e.meta,""===this.name&&(this.name=e.name),!0}catch(t){return this.trigger("error",t.code),!1}}function c(t){var n=e.typeOf(t);try{if(t instanceof h){if(!t.size)throw new i.DOMException(i.DOMException.INVALID_STATE_ERR);p.apply(this,arguments)}else if(t instanceof l){if(!~e.inArray(t.type,["image/jpeg","image/png"]))throw new i.ImageError(i.ImageError.WRONG_FORMAT);g.apply(this,arguments)}else if(-1!==e.inArray(n,["blob","file"]))c.call(this,new d(null,t),arguments[1]);else if("string"===n)"data:"===t.substr(0,5)?c.call(this,new l(null,{data:t}),arguments[1]):x.apply(this,arguments);else{if("node"!==n||"img"!==t.nodeName.toLowerCase())throw new i.DOMException(i.DOMException.TYPE_MISMATCH_ERR);c.call(this,t.src,arguments[1])}}catch(r){this.trigger("error",r.code)}}function p(t,i){var n=this.connectRuntime(t.ruid);this.ruid=n.uid,n.exec.call(this,"Image","loadFromImage",t,"undefined"===e.typeOf(i)?!0:i)}function g(t,i){function n(e){r.ruid=e.uid,e.exec.call(r,"Image","loadFromBlob",t)}var r=this;r.name=t.name||"",t.isDetached()?(this.bind("RuntimeInit",function(e,t){n(t)}),i&&"string"==typeof i.required_caps&&(i.required_caps=o.parseCaps(i.required_caps)),this.connectRuntime(e.extend({required_caps:{access_image_binary:!0,resize_image:!0}},i))):n(this.connectRuntime(t.ruid))}function x(e,t){var i,n=this;i=new r,i.open("get",e),i.responseType="blob",i.onprogress=function(e){n.trigger(e)},i.onload=function(){g.call(n,i.response,!0)},i.onerror=function(e){n.trigger(e)},i.onloadend=function(){i.destroy()},i.bind("RuntimeError",function(e,t){n.trigger("RuntimeError",t)}),i.send(null,t)}a.call(this),e.extend(this,{uid:e.guid("uid_"),ruid:null,name:"",size:0,width:0,height:0,type:"",meta:{},clone:function(){this.load.apply(this,arguments)},load:function(){c.apply(this,arguments)},resize:function(t){var n,r,o=this,a={x:0,y:0,width:o.width,height:o.height},s=e.extendIf({width:o.width,height:o.height,type:o.type||"image/jpeg",quality:90,crop:!1,fit:!0,preserveHeaders:!0,resample:"default",multipass:!0},t);try{if(!o.size)throw new i.DOMException(i.DOMException.INVALID_STATE_ERR);if(o.width>h.MAX_RESIZE_WIDTH||o.height>h.MAX_RESIZE_HEIGHT)throw new i.ImageError(i.ImageError.MAX_RESOLUTION_ERR);if(n=o.meta&&o.meta.tiff&&o.meta.tiff.Orientation||1,-1!==e.inArray(n,[5,6,7,8])){var u=s.width;s.width=s.height,s.height=u}if(s.crop){switch(r=Math.max(s.width/o.width,s.height/o.height),t.fit?(a.width=Math.min(Math.ceil(s.width/r),o.width),a.height=Math.min(Math.ceil(s.height/r),o.height),r=s.width/a.width):(a.width=Math.min(s.width,o.width),a.height=Math.min(s.height,o.height),r=1),"boolean"==typeof s.crop&&(s.crop="cc"),s.crop.toLowerCase().replace(/_/,"-")){case"rb":case"right-bottom":a.x=o.width-a.width,a.y=o.height-a.height;break;case"cb":case"center-bottom":a.x=Math.floor((o.width-a.width)/2),a.y=o.height-a.height;break;case"lb":case"left-bottom":a.x=0,a.y=o.height-a.height;break;case"lt":case"left-top":a.x=0,a.y=0;break;case"ct":case"center-top":a.x=Math.floor((o.width-a.width)/2),a.y=0;break;case"rt":case"right-top":a.x=o.width-a.width,a.y=0;break;case"rc":case"right-center":case"right-middle":a.x=o.width-a.width,a.y=Math.floor((o.height-a.height)/2);break;case"lc":case"left-center":case"left-middle":a.x=0,a.y=Math.floor((o.height-a.height)/2);break;case"cc":case"center-center":case"center-middle":default:a.x=Math.floor((o.width-a.width)/2),a.y=Math.floor((o.height-a.height)/2)}a.x=Math.max(a.x,0),a.y=Math.max(a.y,0)}else r=Math.min(s.width/o.width,s.height/o.height),r>1&&!s.fit&&(r=1);this.exec("Image","resize",a,r,s)}catch(c){o.trigger("error",c.code)}},downsize:function(t){var i,n={width:this.width,height:this.height,type:this.type||"image/jpeg",quality:90,crop:!1,fit:!1,preserveHeaders:!0,resample:"default"};i="object"==typeof t?e.extend(n,t):e.extend(n,{width:arguments[0],height:arguments[1],crop:arguments[2],preserveHeaders:arguments[3]}),this.resize(i)},crop:function(e,t,i){this.downsize(e,t,!0,i)},getAsCanvas:function(){if(!u.can("create_canvas"))throw new i.RuntimeError(i.RuntimeError.NOT_SUPPORTED_ERR);return this.exec("Image","getAsCanvas")},getAsBlob:function(e,t){if(!this.size)throw new i.DOMException(i.DOMException.INVALID_STATE_ERR);return this.exec("Image","getAsBlob",e||"image/jpeg",t||90)},getAsDataURL:function(e,t){if(!this.size)throw new i.DOMException(i.DOMException.INVALID_STATE_ERR);return this.exec("Image","getAsDataURL",e||"image/jpeg",t||90)},getAsBinaryString:function(e,t){var i=this.getAsDataURL(e,t);return m.atob(i.substring(i.indexOf("base64,")+7))},embed:function(n,r){function o(t,r){var o=this;if(u.can("create_canvas")){var l=o.getAsCanvas();if(l)return n.appendChild(l),l=null,o.destroy(),c.trigger("embedded"),void 0}var d=o.getAsDataURL(t,r);if(!d)throw new i.ImageError(i.ImageError.WRONG_FORMAT);if(u.can("use_data_uri_of",d.length))n.innerHTML='<img src="'+d+'" width="'+o.width+'" height="'+o.height+'" alt="" />',o.destroy(),c.trigger("embedded");else{var h=new s;h.bind("TransportingComplete",function(){a=c.connectRuntime(this.result.ruid),c.bind("Embedded",function(){e.extend(a.getShimContainer().style,{top:"0px",left:"0px",width:o.width+"px",height:o.height+"px"}),a=null},999),a.exec.call(c,"ImageView","display",this.result.uid,width,height),o.destroy()}),h.transport(m.atob(d.substring(d.indexOf("base64,")+7)),t,{required_caps:{display_media:!0},runtime_order:"flash,silverlight",container:n})}}var a,c=this,l=e.extend({width:this.width,height:this.height,type:this.type||"image/jpeg",quality:90,fit:!0,resample:"nearest"},r);try{if(!(n=t.get(n)))throw new i.DOMException(i.DOMException.INVALID_NODE_TYPE_ERR);if(!this.size)throw new i.DOMException(i.DOMException.INVALID_STATE_ERR);this.width>h.MAX_RESIZE_WIDTH||this.height>h.MAX_RESIZE_HEIGHT;var d=new h;return d.bind("Resize",function(){o.call(this,l.type,l.quality)}),d.bind("Load",function(){this.downsize(l)}),this.meta.thumb&&this.meta.thumb.width>=l.width&&this.meta.thumb.height>=l.height?d.load(this.meta.thumb.data):d.clone(this,!1),d}catch(f){this.trigger("error",f.code)}},destroy:function(){this.ruid&&(this.getRuntime().exec.call(this,"Image","destroy"),this.disconnectRuntime()),this.meta&&this.meta.thumb&&this.meta.thumb.data.destroy(),this.unbindAll()}}),this.handleEventProps(f),this.bind("Load Resize",function(){return n.call(this)},999)}var f=["progress","load","error","resize","embedded"];return h.MAX_RESIZE_WIDTH=8192,h.MAX_RESIZE_HEIGHT=8192,h.prototype=c.instance,h}),n("moxie/runtime/html5/Runtime",["moxie/core/utils/Basic","moxie/core/Exceptions","moxie/runtime/Runtime","moxie/core/utils/Env"],function(e,t,i,n){function o(t){var o=this,u=i.capTest,c=i.capTrue,l=e.extend({access_binary:u(window.FileReader||window.File&&window.File.getAsDataURL),access_image_binary:function(){return o.can("access_binary")&&!!s.Image},display_media:u((n.can("create_canvas")||n.can("use_data_uri_over32kb"))&&r("moxie/image/Image")),do_cors:u(window.XMLHttpRequest&&"withCredentials"in new XMLHttpRequest),drag_and_drop:u(function(){var e=document.createElement("div");return("draggable"in e||"ondragstart"in e&&"ondrop"in e)&&("IE"!==n.browser||n.verComp(n.version,9,">"))}()),filter_by_extension:u(function(){return!("Chrome"===n.browser&&n.verComp(n.version,28,"<")||"IE"===n.browser&&n.verComp(n.version,10,"<")||"Safari"===n.browser&&n.verComp(n.version,7,"<")||"Firefox"===n.browser&&n.verComp(n.version,37,"<"))}()),return_response_headers:c,return_response_type:function(e){return"json"===e&&window.JSON?!0:n.can("return_response_type",e)},return_status_code:c,report_upload_progress:u(window.XMLHttpRequest&&(new XMLHttpRequest).upload),resize_image:function(){return o.can("access_binary")&&n.can("create_canvas")},select_file:function(){return n.can("use_fileinput")&&window.File},select_folder:function(){return o.can("select_file")&&("Chrome"===n.browser&&n.verComp(n.version,21,">=")||"Firefox"===n.browser&&n.verComp(n.version,42,">="))},select_multiple:function(){return!(!o.can("select_file")||"Safari"===n.browser&&"Windows"===n.os||"iOS"===n.os&&n.verComp(n.osVersion,"7.0.0",">")&&n.verComp(n.osVersion,"8.0.0","<"))},send_binary_string:u(window.XMLHttpRequest&&((new XMLHttpRequest).sendAsBinary||window.Uint8Array&&window.ArrayBuffer)),send_custom_headers:u(window.XMLHttpRequest),send_multipart:function(){return!!(window.XMLHttpRequest&&(new XMLHttpRequest).upload&&window.FormData)||o.can("send_binary_string")},slice_blob:u(window.File&&(File.prototype.mozSlice||File.prototype.webkitSlice||File.prototype.slice)),stream_upload:function(){return o.can("slice_blob")&&o.can("send_multipart")},summon_file_dialog:function(){return o.can("select_file")&&!("Firefox"===n.browser&&n.verComp(n.version,4,"<")||"Opera"===n.browser&&n.verComp(n.version,12,"<")||"IE"===n.browser&&n.verComp(n.version,10,"<"))},upload_filesize:c,use_http_method:c},arguments[2]);i.call(this,t,arguments[1]||a,l),e.extend(this,{init:function(){this.trigger("Init")},destroy:function(e){return function(){e.call(o),e=o=null}}(this.destroy)}),e.extend(this.getShim(),s)}var a="html5",s={};return i.addConstructor(a,o),s}),n("moxie/runtime/html5/file/Blob",["moxie/runtime/html5/Runtime","moxie/file/Blob"],function(e,t){function i(){function e(e,t,i){var n;if(!window.File.prototype.slice)return(n=window.File.prototype.webkitSlice||window.File.prototype.mozSlice)?n.call(e,t,i):null;try{return e.slice(),e.slice(t,i)}catch(r){return e.slice(t,i-t)}}this.slice=function(){return new t(this.getRuntime().uid,e.apply(this,arguments))},this.destroy=function(){this.getRuntime().getShim().removeInstance(this.uid)}}return e.Blob=i}),n("moxie/core/utils/Events",["moxie/core/utils/Basic"],function(e){function t(){this.returnValue=!1}function i(){this.cancelBubble=!0}var n={},r="moxie_"+e.guid(),o=function(o,a,s,u){var c,l;a=a.toLowerCase(),o.addEventListener?(c=s,o.addEventListener(a,c,!1)):o.attachEvent&&(c=function(){var e=window.event;e.target||(e.target=e.srcElement),e.preventDefault=t,e.stopPropagation=i,s(e)},o.attachEvent("on"+a,c)),o[r]||(o[r]=e.guid()),n.hasOwnProperty(o[r])||(n[o[r]]={}),l=n[o[r]],l.hasOwnProperty(a)||(l[a]=[]),l[a].push({func:c,orig:s,key:u})},a=function(t,i,o){var a,s;if(i=i.toLowerCase(),t[r]&&n[t[r]]&&n[t[r]][i]){a=n[t[r]][i];for(var u=a.length-1;u>=0&&(a[u].orig!==o&&a[u].key!==o||(t.removeEventListener?t.removeEventListener(i,a[u].func,!1):t.detachEvent&&t.detachEvent("on"+i,a[u].func),a[u].orig=null,a[u].func=null,a.splice(u,1),o===s));u--);if(a.length||delete n[t[r]][i],e.isEmptyObj(n[t[r]])){delete n[t[r]];try{delete t[r]}catch(c){t[r]=s}}}},s=function(t,i){t&&t[r]&&e.each(n[t[r]],function(e,n){a(t,n,i)})};return{addEvent:o,removeEvent:a,removeAllEvents:s}}),n("moxie/runtime/html5/file/FileInput",["moxie/runtime/html5/Runtime","moxie/file/File","moxie/core/utils/Basic","moxie/core/utils/Dom","moxie/core/utils/Events","moxie/core/utils/Mime","moxie/core/utils/Env"],function(e,t,i,n,r,o,a){function s(){var e,s;i.extend(this,{init:function(u){var c,l,d,m,h,f,p=this,g=p.getRuntime();e=u,d=o.extList2mimes(e.accept,g.can("filter_by_extension")),l=g.getShimContainer(),l.innerHTML='<input id="'+g.uid+'" type="file" style="font-size:999px;opacity:0;"'+(e.multiple&&g.can("select_multiple")?"multiple":"")+(e.directory&&g.can("select_folder")?"webkitdirectory directory":"")+(d?' accept="'+d.join(",")+'"':"")+" />",c=n.get(g.uid),i.extend(c.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),m=n.get(e.browse_button),s=n.getStyle(m,"z-index")||"auto",g.can("summon_file_dialog")&&("static"===n.getStyle(m,"position")&&(m.style.position="relative"),r.addEvent(m,"click",function(e){var t=n.get(g.uid);t&&!t.disabled&&t.click(),e.preventDefault()},p.uid),p.bind("Refresh",function(){h=parseInt(s,10)||1,n.get(e.browse_button).style.zIndex=h,this.getRuntime().getShimContainer().style.zIndex=h-1})),f=g.can("summon_file_dialog")?m:l,r.addEvent(f,"mouseover",function(){p.trigger("mouseenter")},p.uid),r.addEvent(f,"mouseout",function(){p.trigger("mouseleave")},p.uid),r.addEvent(f,"mousedown",function(){p.trigger("mousedown")},p.uid),r.addEvent(n.get(e.container),"mouseup",function(){p.trigger("mouseup")},p.uid),(g.can("summon_file_dialog")?c:m).setAttribute("tabindex",-1),c.onchange=function x(){if(p.files=[],i.each(this.files,function(i){var n="";return e.directory&&"."==i.name?!0:(i.webkitRelativePath&&(n="/"+i.webkitRelativePath.replace(/^\//,"")),i=new t(g.uid,i),i.relativePath=n,p.files.push(i),void 0)}),"IE"!==a.browser&&"IEMobile"!==a.browser)this.value="";else{var n=this.cloneNode(!0);this.parentNode.replaceChild(n,this),n.onchange=x}p.files.length&&p.trigger("change")},p.trigger({type:"ready",async:!0}),l=null},setOption:function(e,t){var i=this.getRuntime(),r=n.get(i.uid);switch(e){case"accept":if(t){var a=t.mimes||o.extList2mimes(t,i.can("filter_by_extension"));r.setAttribute("accept",a.join(","))}else r.removeAttribute("accept");break;case"directory":t&&i.can("select_folder")?(r.setAttribute("directory",""),r.setAttribute("webkitdirectory","")):(r.removeAttribute("directory"),r.removeAttribute("webkitdirectory"));break;case"multiple":t&&i.can("select_multiple")?r.setAttribute("multiple",""):r.removeAttribute("multiple")}},disable:function(e){var t,i=this.getRuntime();(t=n.get(i.uid))&&(t.disabled=!!e)},destroy:function(){var t=this.getRuntime(),i=t.getShim(),o=t.getShimContainer(),a=e&&n.get(e.container),u=e&&n.get(e.browse_button);a&&r.removeAllEvents(a,this.uid),u&&(r.removeAllEvents(u,this.uid),u.style.zIndex=s),o&&(r.removeAllEvents(o,this.uid),o.innerHTML=""),i.removeInstance(this.uid),e=o=a=u=i=null}})}return e.FileInput=s}),n("moxie/runtime/html5/file/FileDrop",["moxie/runtime/html5/Runtime","moxie/file/File","moxie/core/utils/Basic","moxie/core/utils/Dom","moxie/core/utils/Events","moxie/core/utils/Mime"],function(e,t,i,n,r,o){function a(){function e(e){if(!e.dataTransfer||!e.dataTransfer.types)return!1;var t=i.toArray(e.dataTransfer.types||[]);return-1!==i.inArray("Files",t)||-1!==i.inArray("public.file-url",t)||-1!==i.inArray("application/x-moz-file",t)}function a(e,i){if(u(e)){var n=new t(f,e);n.relativePath=i||"",p.push(n)}}function s(e){for(var t=[],n=0;n<e.length;n++)[].push.apply(t,e[n].extensions.split(/\s*,\s*/));return-1===i.inArray("*",t)?t:[]}function u(e){if(!g.length)return!0;var t=o.getFileExtension(e.name);return!t||-1!==i.inArray(t,g)}function c(e,t){var n=[];i.each(e,function(e){var t=e.webkitGetAsEntry();t&&(t.isFile?a(e.getAsFile(),t.fullPath):n.push(t))}),n.length?l(n,t):t()}function l(e,t){var n=[];i.each(e,function(e){n.push(function(t){d(e,t)})}),i.inSeries(n,function(){t()})}function d(e,t){e.isFile?e.file(function(i){a(i,e.fullPath),t()},function(){t()}):e.isDirectory?m(e,t):t()}function m(e,t){function i(e){r.readEntries(function(t){t.length?([].push.apply(n,t),i(e)):e()},e)}var n=[],r=e.createReader();i(function(){l(n,t)})}var h,f,p=[],g=[];i.extend(this,{init:function(t){var n,o=this;h=t,f=o.ruid,g=s(h.accept),n=h.container,r.addEvent(n,"dragover",function(t){e(t)&&(t.preventDefault(),t.dataTransfer.dropEffect="copy")},o.uid),r.addEvent(n,"drop",function(t){e(t)&&(t.preventDefault(),p=[],t.dataTransfer.items&&t.dataTransfer.items[0].webkitGetAsEntry?c(t.dataTransfer.items,function(){o.files=p,o.trigger("drop")}):(i.each(t.dataTransfer.files,function(e){a(e)}),o.files=p,o.trigger("drop")))},o.uid),r.addEvent(n,"dragenter",function(){o.trigger("dragenter")},o.uid),r.addEvent(n,"dragleave",function(){o.trigger("dragleave")},o.uid)},destroy:function(){r.removeAllEvents(h&&n.get(h.container),this.uid),f=p=g=h=null,this.getRuntime().getShim().removeInstance(this.uid)}})}return e.FileDrop=a}),n("moxie/runtime/html5/file/FileReader",["moxie/runtime/html5/Runtime","moxie/core/utils/Encode","moxie/core/utils/Basic"],function(e,t,i){function n(){function e(e){return t.atob(e.substring(e.indexOf("base64,")+7))}var n,r=!1;i.extend(this,{read:function(t,o){var a=this;a.result="",n=new window.FileReader,n.addEventListener("progress",function(e){a.trigger(e)}),n.addEventListener("load",function(t){a.result=r?e(n.result):n.result,a.trigger(t)}),n.addEventListener("error",function(e){a.trigger(e,n.error)}),n.addEventListener("loadend",function(e){n=null,a.trigger(e)}),"function"===i.typeOf(n[t])?(r=!1,n[t](o.getSource())):"readAsBinaryString"===t&&(r=!0,n.readAsDataURL(o.getSource()))},abort:function(){n&&n.abort()},destroy:function(){n=null,this.getRuntime().getShim().removeInstance(this.uid)}})}return e.FileReader=n}),n("moxie/runtime/html5/xhr/XMLHttpRequest",["moxie/runtime/html5/Runtime","moxie/core/utils/Basic","moxie/core/utils/Mime","moxie/core/utils/Url","moxie/file/File","moxie/file/Blob","moxie/xhr/FormData","moxie/core/Exceptions","moxie/core/utils/Env"],function(e,t,i,n,r,o,a,s,u){function c(){function e(e,t){var i,n,r=this;i=t.getBlob().getSource(),n=new window.FileReader,n.onload=function(){t.append(t.getBlobName(),new o(null,{type:i.type,data:n.result})),f.send.call(r,e,t)},n.readAsBinaryString(i)}function c(){return!window.XMLHttpRequest||"IE"===u.browser&&u.verComp(u.version,8,"<")?function(){for(var e=["Msxml2.XMLHTTP.6.0","Microsoft.XMLHTTP"],t=0;t<e.length;t++)try{return new ActiveXObject(e[t])}catch(i){}}():new window.XMLHttpRequest}function l(e){var t=e.responseXML,i=e.responseText;return"IE"===u.browser&&i&&t&&!t.documentElement&&/[^\/]+\/[^\+]+\+xml/.test(e.getResponseHeader("Content-Type"))&&(t=new window.ActiveXObject("Microsoft.XMLDOM"),t.async=!1,t.validateOnParse=!1,t.loadXML(i)),t&&("IE"===u.browser&&0!==t.parseError||!t.documentElement||"parsererror"===t.documentElement.tagName)?null:t -}function d(e){var t="----moxieboundary"+(new Date).getTime(),i="--",n="\r\n",r="",a=this.getRuntime();if(!a.can("send_binary_string"))throw new s.RuntimeError(s.RuntimeError.NOT_SUPPORTED_ERR);return m.setRequestHeader("Content-Type","multipart/form-data; boundary="+t),e.each(function(e,a){r+=e instanceof o?i+t+n+'Content-Disposition: form-data; name="'+a+'"; filename="'+unescape(encodeURIComponent(e.name||"blob"))+'"'+n+"Content-Type: "+(e.type||"application/octet-stream")+n+n+e.getSource()+n:i+t+n+'Content-Disposition: form-data; name="'+a+'"'+n+n+unescape(encodeURIComponent(e))+n}),r+=i+t+i+n}var m,h,f=this;t.extend(this,{send:function(i,r){var s=this,l="Mozilla"===u.browser&&u.verComp(u.version,4,">=")&&u.verComp(u.version,7,"<"),f="Android Browser"===u.browser,p=!1;if(h=i.url.replace(/^.+?\/([\w\-\.]+)$/,"$1").toLowerCase(),m=c(),m.open(i.method,i.url,i.async,i.user,i.password),r instanceof o)r.isDetached()&&(p=!0),r=r.getSource();else if(r instanceof a){if(r.hasBlob())if(r.getBlob().isDetached())r=d.call(s,r),p=!0;else if((l||f)&&"blob"===t.typeOf(r.getBlob().getSource())&&window.FileReader)return e.call(s,i,r),void 0;if(r instanceof a){var g=new window.FormData;r.each(function(e,t){e instanceof o?g.append(t,e.getSource()):g.append(t,e)}),r=g}}m.upload?(i.withCredentials&&(m.withCredentials=!0),m.addEventListener("load",function(e){s.trigger(e)}),m.addEventListener("error",function(e){s.trigger(e)}),m.addEventListener("progress",function(e){s.trigger(e)}),m.upload.addEventListener("progress",function(e){s.trigger({type:"UploadProgress",loaded:e.loaded,total:e.total})})):m.onreadystatechange=function(){switch(m.readyState){case 1:break;case 2:break;case 3:var e,t;try{n.hasSameOrigin(i.url)&&(e=m.getResponseHeader("Content-Length")||0),m.responseText&&(t=m.responseText.length)}catch(r){e=t=0}s.trigger({type:"progress",lengthComputable:!!e,total:parseInt(e,10),loaded:t});break;case 4:m.onreadystatechange=function(){};try{if(m.status>=200&&m.status<400){s.trigger("load");break}}catch(r){}s.trigger("error")}},t.isEmptyObj(i.headers)||t.each(i.headers,function(e,t){m.setRequestHeader(t,e)}),""!==i.responseType&&"responseType"in m&&(m.responseType="json"!==i.responseType||u.can("return_response_type","json")?i.responseType:"text"),p?m.sendAsBinary?m.sendAsBinary(r):function(){for(var e=new Uint8Array(r.length),t=0;t<r.length;t++)e[t]=255&r.charCodeAt(t);m.send(e.buffer)}():m.send(r),s.trigger("loadstart")},getStatus:function(){try{if(m)return m.status}catch(e){}return 0},getResponse:function(e){var t=this.getRuntime();try{switch(e){case"blob":var n=new r(t.uid,m.response),o=m.getResponseHeader("Content-Disposition");if(o){var a=o.match(/filename=([\'\"'])([^\1]+)\1/);a&&(h=a[2])}return n.name=h,n.type||(n.type=i.getFileMime(h)),n;case"json":return u.can("return_response_type","json")?m.response:200===m.status&&window.JSON?JSON.parse(m.responseText):null;case"document":return l(m);default:return""!==m.responseText?m.responseText:null}}catch(s){return null}},getAllResponseHeaders:function(){try{return m.getAllResponseHeaders()}catch(e){}return""},abort:function(){m&&m.abort()},destroy:function(){f=h=null,this.getRuntime().getShim().removeInstance(this.uid)}})}return e.XMLHttpRequest=c}),n("moxie/runtime/html5/utils/BinaryReader",["moxie/core/utils/Basic"],function(e){function t(e){e instanceof ArrayBuffer?i.apply(this,arguments):n.apply(this,arguments)}function i(t){var i=new DataView(t);e.extend(this,{readByteAt:function(e){return i.getUint8(e)},writeByteAt:function(e,t){i.setUint8(e,t)},SEGMENT:function(e,n,r){switch(arguments.length){case 2:return t.slice(e,e+n);case 1:return t.slice(e);case 3:if(null===r&&(r=new ArrayBuffer),r instanceof ArrayBuffer){var o=new Uint8Array(this.length()-n+r.byteLength);e>0&&o.set(new Uint8Array(t.slice(0,e)),0),o.set(new Uint8Array(r),e),o.set(new Uint8Array(t.slice(e+n)),e+r.byteLength),this.clear(),t=o.buffer,i=new DataView(t);break}default:return t}},length:function(){return t?t.byteLength:0},clear:function(){i=t=null}})}function n(t){function i(e,i,n){n=3===arguments.length?n:t.length-i-1,t=t.substr(0,i)+e+t.substr(n+i)}e.extend(this,{readByteAt:function(e){return t.charCodeAt(e)},writeByteAt:function(e,t){i(String.fromCharCode(t),e,1)},SEGMENT:function(e,n,r){switch(arguments.length){case 1:return t.substr(e);case 2:return t.substr(e,n);case 3:i(null!==r?r:"",e,n);break;default:return t}},length:function(){return t?t.length:0},clear:function(){t=null}})}return e.extend(t.prototype,{littleEndian:!1,read:function(e,t){var i,n,r;if(e+t>this.length())throw new Error("You are trying to read outside the source boundaries.");for(n=this.littleEndian?0:-8*(t-1),r=0,i=0;t>r;r++)i|=this.readByteAt(e+r)<<Math.abs(n+8*r);return i},write:function(e,t,i){var n,r;if(e>this.length())throw new Error("You are trying to write outside the source boundaries.");for(n=this.littleEndian?0:-8*(i-1),r=0;i>r;r++)this.writeByteAt(e+r,255&t>>Math.abs(n+8*r))},BYTE:function(e){return this.read(e,1)},SHORT:function(e){return this.read(e,2)},LONG:function(e){return this.read(e,4)},SLONG:function(e){var t=this.read(e,4);return t>2147483647?t-4294967296:t},CHAR:function(e){return String.fromCharCode(this.read(e,1))},STRING:function(e,t){return this.asArray("CHAR",e,t).join("")},asArray:function(e,t,i){for(var n=[],r=0;i>r;r++)n[r]=this[e](t+r);return n}}),t}),n("moxie/runtime/html5/image/JPEGHeaders",["moxie/runtime/html5/utils/BinaryReader","moxie/core/Exceptions"],function(e,t){return function i(n){var r,o,a,s=[],u=0;if(r=new e(n),65496!==r.SHORT(0))throw r.clear(),new t.ImageError(t.ImageError.WRONG_FORMAT);for(o=2;o<=r.length();)if(a=r.SHORT(o),a>=65488&&65495>=a)o+=2;else{if(65498===a||65497===a)break;u=r.SHORT(o+2)+2,a>=65505&&65519>=a&&s.push({hex:a,name:"APP"+(15&a),start:o,length:u,segment:r.SEGMENT(o,u)}),o+=u}return r.clear(),{headers:s,restore:function(t){var i,n,r;for(r=new e(t),o=65504==r.SHORT(2)?4+r.SHORT(4):2,n=0,i=s.length;i>n;n++)r.SEGMENT(o,0,s[n].segment),o+=s[n].length;return t=r.SEGMENT(),r.clear(),t},strip:function(t){var n,r,o,a;for(o=new i(t),r=o.headers,o.purge(),n=new e(t),a=r.length;a--;)n.SEGMENT(r[a].start,r[a].length,"");return t=n.SEGMENT(),n.clear(),t},get:function(e){for(var t=[],i=0,n=s.length;n>i;i++)s[i].name===e.toUpperCase()&&t.push(s[i].segment);return t},set:function(e,t){var i,n,r,o=[];for("string"==typeof t?o.push(t):o=t,i=n=0,r=s.length;r>i&&(s[i].name===e.toUpperCase()&&(s[i].segment=o[n],s[i].length=o[n].length,n++),!(n>=o.length));i++);},purge:function(){this.headers=s=[]}}}}),n("moxie/runtime/html5/image/ExifParser",["moxie/core/utils/Basic","moxie/runtime/html5/utils/BinaryReader","moxie/core/Exceptions"],function(e,i,n){function r(o){function a(i,r){var o,a,s,u,c,m,h,f,p=this,g=[],x={},v={1:"BYTE",7:"UNDEFINED",2:"ASCII",3:"SHORT",4:"LONG",5:"RATIONAL",9:"SLONG",10:"SRATIONAL"},w={BYTE:1,UNDEFINED:1,ASCII:1,SHORT:2,LONG:4,RATIONAL:8,SLONG:4,SRATIONAL:8};for(o=p.SHORT(i),a=0;o>a;a++)if(g=[],h=i+2+12*a,s=r[p.SHORT(h)],s!==t){if(u=v[p.SHORT(h+=2)],c=p.LONG(h+=2),m=w[u],!m)throw new n.ImageError(n.ImageError.INVALID_META_ERR);if(h+=4,m*c>4&&(h=p.LONG(h)+d.tiffHeader),h+m*c>=this.length())throw new n.ImageError(n.ImageError.INVALID_META_ERR);"ASCII"!==u?(g=p.asArray(u,h,c),f=1==c?g[0]:g,x[s]=l.hasOwnProperty(s)&&"object"!=typeof f?l[s][f]:f):x[s]=e.trim(p.STRING(h,c).replace(/\0$/,""))}return x}function s(e,t,i){var n,r,o,a=0;if("string"==typeof t){var s=c[e.toLowerCase()];for(var u in s)if(s[u]===t){t=u;break}}n=d[e.toLowerCase()+"IFD"],r=this.SHORT(n);for(var l=0;r>l;l++)if(o=n+12*l+2,this.SHORT(o)==t){a=o+8;break}if(!a)return!1;try{this.write(a,i,4)}catch(m){return!1}return!0}var u,c,l,d,m,h;if(i.call(this,o),c={tiff:{274:"Orientation",270:"ImageDescription",271:"Make",272:"Model",305:"Software",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer"},exif:{36864:"ExifVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",36867:"DateTimeOriginal",33434:"ExposureTime",33437:"FNumber",34855:"ISOSpeedRatings",37377:"ShutterSpeedValue",37378:"ApertureValue",37383:"MeteringMode",37384:"LightSource",37385:"Flash",37386:"FocalLength",41986:"ExposureMode",41987:"WhiteBalance",41990:"SceneCaptureType",41988:"DigitalZoomRatio",41992:"Contrast",41993:"Saturation",41994:"Sharpness"},gps:{0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude"},thumb:{513:"JPEGInterchangeFormat",514:"JPEGInterchangeFormatLength"}},l={ColorSpace:{1:"sRGB",0:"Uncalibrated"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{1:"Daylight",2:"Fliorescent",3:"Tungsten",4:"Flash",9:"Fine weather",10:"Cloudy weather",11:"Shade",12:"Daylight fluorescent (D 5700 - 7100K)",13:"Day white fluorescent (N 4600 -5400K)",14:"Cool white fluorescent (W 3900 - 4500K)",15:"White fluorescent (WW 3200 - 3700K)",17:"Standard light A",18:"Standard light B",19:"Standard light C",20:"D55",21:"D65",22:"D75",23:"D50",24:"ISO studio tungsten",255:"Other"},Flash:{0:"Flash did not fire",1:"Flash fired",5:"Strobe return light not detected",7:"Strobe return light detected",9:"Flash fired, compulsory flash mode",13:"Flash fired, compulsory flash mode, return light not detected",15:"Flash fired, compulsory flash mode, return light detected",16:"Flash did not fire, compulsory flash mode",24:"Flash did not fire, auto mode",25:"Flash fired, auto mode",29:"Flash fired, auto mode, return light not detected",31:"Flash fired, auto mode, return light detected",32:"No flash function",65:"Flash fired, red-eye reduction mode",69:"Flash fired, red-eye reduction mode, return light not detected",71:"Flash fired, red-eye reduction mode, return light detected",73:"Flash fired, compulsory flash mode, red-eye reduction mode",77:"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",79:"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",89:"Flash fired, auto mode, red-eye reduction mode",93:"Flash fired, auto mode, return light not detected, red-eye reduction mode",95:"Flash fired, auto mode, return light detected, red-eye reduction mode"},ExposureMode:{0:"Auto exposure",1:"Manual exposure",2:"Auto bracket"},WhiteBalance:{0:"Auto white balance",1:"Manual white balance"},SceneCaptureType:{0:"Standard",1:"Landscape",2:"Portrait",3:"Night scene"},Contrast:{0:"Normal",1:"Soft",2:"Hard"},Saturation:{0:"Normal",1:"Low saturation",2:"High saturation"},Sharpness:{0:"Normal",1:"Soft",2:"Hard"},GPSLatitudeRef:{N:"North latitude",S:"South latitude"},GPSLongitudeRef:{E:"East longitude",W:"West longitude"}},d={tiffHeader:10},m=d.tiffHeader,u={clear:this.clear},e.extend(this,{read:function(){try{return r.prototype.read.apply(this,arguments)}catch(e){throw new n.ImageError(n.ImageError.INVALID_META_ERR)}},write:function(){try{return r.prototype.write.apply(this,arguments)}catch(e){throw new n.ImageError(n.ImageError.INVALID_META_ERR)}},UNDEFINED:function(){return this.BYTE.apply(this,arguments)},RATIONAL:function(e){return this.LONG(e)/this.LONG(e+4)},SRATIONAL:function(e){return this.SLONG(e)/this.SLONG(e+4)},ASCII:function(e){return this.CHAR(e)},TIFF:function(){return h||null},EXIF:function(){var t=null;if(d.exifIFD){try{t=a.call(this,d.exifIFD,c.exif)}catch(i){return null}if(t.ExifVersion&&"array"===e.typeOf(t.ExifVersion)){for(var n=0,r="";n<t.ExifVersion.length;n++)r+=String.fromCharCode(t.ExifVersion[n]);t.ExifVersion=r}}return t},GPS:function(){var t=null;if(d.gpsIFD){try{t=a.call(this,d.gpsIFD,c.gps)}catch(i){return null}t.GPSVersionID&&"array"===e.typeOf(t.GPSVersionID)&&(t.GPSVersionID=t.GPSVersionID.join("."))}return t},thumb:function(){if(d.IFD1)try{var e=a.call(this,d.IFD1,c.thumb);if("JPEGInterchangeFormat"in e)return this.SEGMENT(d.tiffHeader+e.JPEGInterchangeFormat,e.JPEGInterchangeFormatLength)}catch(t){}return null},setExif:function(e,t){return"PixelXDimension"!==e&&"PixelYDimension"!==e?!1:s.call(this,"exif",e,t)},clear:function(){u.clear(),o=c=l=h=d=u=null}}),65505!==this.SHORT(0)||"EXIF\0"!==this.STRING(4,5).toUpperCase())throw new n.ImageError(n.ImageError.INVALID_META_ERR);if(this.littleEndian=18761==this.SHORT(m),42!==this.SHORT(m+=2))throw new n.ImageError(n.ImageError.INVALID_META_ERR);d.IFD0=d.tiffHeader+this.LONG(m+=2),h=a.call(this,d.IFD0,c.tiff),"ExifIFDPointer"in h&&(d.exifIFD=d.tiffHeader+h.ExifIFDPointer,delete h.ExifIFDPointer),"GPSInfoIFDPointer"in h&&(d.gpsIFD=d.tiffHeader+h.GPSInfoIFDPointer,delete h.GPSInfoIFDPointer),e.isEmptyObj(h)&&(h=null);var f=this.LONG(d.IFD0+12*this.SHORT(d.IFD0)+2);f&&(d.IFD1=d.tiffHeader+f)}return r.prototype=i.prototype,r}),n("moxie/runtime/html5/image/JPEG",["moxie/core/utils/Basic","moxie/core/Exceptions","moxie/runtime/html5/image/JPEGHeaders","moxie/runtime/html5/utils/BinaryReader","moxie/runtime/html5/image/ExifParser"],function(e,t,i,n,r){function o(o){function a(e){var t,i,n=0;for(e||(e=c);n<=e.length();){if(t=e.SHORT(n+=2),t>=65472&&65475>=t)return n+=5,{height:e.SHORT(n),width:e.SHORT(n+=2)};i=e.SHORT(n+=2),n+=i-2}return null}function s(){var e,t,i=d.thumb();return i&&(e=new n(i),t=a(e),e.clear(),t)?(t.data=i,t):null}function u(){d&&l&&c&&(d.clear(),l.purge(),c.clear(),m=l=d=c=null)}var c,l,d,m;if(c=new n(o),65496!==c.SHORT(0))throw new t.ImageError(t.ImageError.WRONG_FORMAT);l=new i(o);try{d=new r(l.get("app1")[0])}catch(h){}m=a.call(this),e.extend(this,{type:"image/jpeg",size:c.length(),width:m&&m.width||0,height:m&&m.height||0,setExif:function(t,i){return d?("object"===e.typeOf(t)?e.each(t,function(e,t){d.setExif(t,e)}):d.setExif(t,i),l.set("app1",d.SEGMENT()),void 0):!1},writeHeaders:function(){return arguments.length?l.restore(arguments[0]):l.restore(o)},stripHeaders:function(e){return l.strip(e)},purge:function(){u.call(this)}}),d&&(this.meta={tiff:d.TIFF(),exif:d.EXIF(),gps:d.GPS(),thumb:s()})}return o}),n("moxie/runtime/html5/image/PNG",["moxie/core/Exceptions","moxie/core/utils/Basic","moxie/runtime/html5/utils/BinaryReader"],function(e,t,i){function n(n){function r(){var e,t;return e=a.call(this,8),"IHDR"==e.type?(t=e.start,{width:s.LONG(t),height:s.LONG(t+=4)}):null}function o(){s&&(s.clear(),n=l=u=c=s=null)}function a(e){var t,i,n,r;return t=s.LONG(e),i=s.STRING(e+=4,4),n=e+=4,r=s.LONG(e+t),{length:t,type:i,start:n,CRC:r}}var s,u,c,l;s=new i(n),function(){var t=0,i=0,n=[35152,20039,3338,6666];for(i=0;i<n.length;i++,t+=2)if(n[i]!=s.SHORT(t))throw new e.ImageError(e.ImageError.WRONG_FORMAT)}(),l=r.call(this),t.extend(this,{type:"image/png",size:s.length(),width:l.width,height:l.height,purge:function(){o.call(this)}}),o.call(this)}return n}),n("moxie/runtime/html5/image/ImageInfo",["moxie/core/utils/Basic","moxie/core/Exceptions","moxie/runtime/html5/image/JPEG","moxie/runtime/html5/image/PNG"],function(e,t,i,n){return function(r){var o,a=[i,n];o=function(){for(var e=0;e<a.length;e++)try{return new a[e](r)}catch(i){}throw new t.ImageError(t.ImageError.WRONG_FORMAT)}(),e.extend(this,{type:"",size:0,width:0,height:0,setExif:function(){},writeHeaders:function(e){return e},stripHeaders:function(e){return e},purge:function(){r=null}}),e.extend(this,o),this.purge=function(){o.purge(),o=null}}}),n("moxie/runtime/html5/image/ResizerCanvas",[],function(){function e(i,n,r){var o=i.width>i.height?"width":"height",a=Math.round(i[o]*n),s=!1;"nearest"!==r&&(.5>n||n>2)&&(n=.5>n?.5:2,s=!0);var u=t(i,n);return s?e(u,a/u[o],r):u}function t(e,t){var i=e.width,n=e.height,r=Math.round(i*t),o=Math.round(n*t),a=document.createElement("canvas");return a.width=r,a.height=o,a.getContext("2d").drawImage(e,0,0,i,n,0,0,r,o),e=null,a}return{scale:e}}),n("moxie/runtime/html5/image/Image",["moxie/runtime/html5/Runtime","moxie/core/utils/Basic","moxie/core/Exceptions","moxie/core/utils/Encode","moxie/file/Blob","moxie/file/File","moxie/runtime/html5/image/ImageInfo","moxie/runtime/html5/image/ResizerCanvas","moxie/core/utils/Mime","moxie/core/utils/Env"],function(e,t,i,n,r,o,a,s,u,c){function l(){function e(){if(!w&&!x)throw new i.ImageError(i.DOMException.INVALID_STATE_ERR);return w||x}function l(){var t=e();return"canvas"==t.nodeName.toLowerCase()?t:(w=document.createElement("canvas"),w.width=t.width,w.height=t.height,w.getContext("2d").drawImage(t,0,0),w)}function d(e){return n.atob(e.substring(e.indexOf("base64,")+7))}function m(e,t){return"data:"+(t||"")+";base64,"+n.btoa(e)}function h(e){var t=this,n=e.substr(0,5);x=new Image,x.onerror=function(){g.call(this),t.trigger("error",i.ImageError.WRONG_FORMAT)},x.onload=function(){t.trigger("load")},x.src="data:"===n||"blob:"===n?e:m(e,E.type)}function f(e,t){var n,r=this;return window.FileReader?(n=new FileReader,n.onload=function(){t.call(r,this.result)},n.onerror=function(){r.trigger("error",i.ImageError.WRONG_FORMAT)},n.readAsDataURL(e),void 0):t.call(this,e.getAsDataURL())}function p(e,i){var n=Math.PI/180,r=document.createElement("canvas"),o=r.getContext("2d"),a=e.width,s=e.height;switch(t.inArray(i,[5,6,7,8])>-1?(r.width=s,r.height=a):(r.width=a,r.height=s),i){case 2:o.translate(a,0),o.scale(-1,1);break;case 3:o.translate(a,s),o.rotate(180*n);break;case 4:o.translate(0,s),o.scale(1,-1);break;case 5:o.rotate(90*n),o.scale(1,-1);break;case 6:o.rotate(90*n),o.translate(0,-s);break;case 7:o.rotate(90*n),o.translate(a,-s),o.scale(-1,1);break;case 8:o.rotate(-90*n),o.translate(-a,0)}return o.drawImage(e,0,0,a,s),r}function g(){v&&(v.purge(),v=null),x&&c.can("use_blob_uri")&&URL.revokeObjectURL(x.src),y=x=w=E=null,R=!1}var x,v,w,y,E,b=this,R=!1,_=!0;t.extend(this,{loadFromBlob:function(e){var t=this.getRuntime(),n=arguments.length>1?arguments[1]:!0;if(!t.can("access_binary"))throw new i.RuntimeError(i.RuntimeError.NOT_SUPPORTED_ERR);E=e,e.isDetached()?(y=e.getSource(),h.call(this,y)):c.can("use_blob_uri")?h.call(this,URL.createObjectURL(e.getSource())):f.call(this,e.getSource(),function(e){n&&(y=d(e)),h.call(this,e)})},loadFromImage:function(e,t){var i=this;i.meta=e.meta,E=new o(null,{name:e.name,size:e.size,type:e.type}),c.can("create_canvas")&&!t?(w=e.getAsCanvas(),setTimeout(function(){i.trigger("load")})):h.call(this,t?y=e.getAsBinaryString():e.getAsDataURL())},getInfo:function(){var t,i=this.getRuntime();return!v&&y&&i.can("access_image_binary")&&(v=new a(y)),t={width:e().width||0,height:e().height||0,type:E.type||u.getFileMime(E.name),size:y&&y.length||E.size||0,name:E.name||"",meta:null},_&&(t.meta=v&&v.meta||this.meta||{},!t.meta||!t.meta.thumb||t.meta.thumb.data instanceof r||(t.meta.thumb.data=new r(null,{type:"image/jpeg",data:t.meta.thumb.data}))),t},resize:function(t,i,n){var r=document.createElement("canvas");if(r.width=t.width,r.height=t.height,r.getContext("2d").drawImage(e(),t.x,t.y,t.width,t.height,0,0,r.width,r.height),w=s.scale(r,i),_=n.preserveHeaders,!_){var o=this.meta&&this.meta.tiff&&this.meta.tiff.Orientation||1;w=p(w,o)}this.width=w.width,this.height=w.height,R=!0,this.trigger("Resize")},getAsCanvas:function(){return w||(w=l()),w.id=this.uid+"_canvas",w},getAsBlob:function(e,t){return e!==this.type?(R=!0,new o(null,{name:E.name||"",type:e,data:b.getAsDataURL(e,t)})):new o(null,{name:E.name||"",type:e,data:b.getAsBinaryString(e,t)})},getAsDataURL:function(e){var t=arguments[1]||90;if(!R&&"data:"===x.src.substr(0,5))return x.src;if(l(),"image/jpeg"!==e)return w.toDataURL("image/png");try{return w.toDataURL("image/jpeg",t/100)}catch(i){return w.toDataURL("image/jpeg")}},getAsBinaryString:function(e,t){if(!R)return y||(y=d(b.getAsDataURL(e,t))),y;if("image/jpeg"!==e)y=d(b.getAsDataURL(e,t));else{var i;t||(t=90),l();try{i=w.toDataURL("image/jpeg",t/100)}catch(n){i=w.toDataURL("image/jpeg")}y=d(i),v&&(y=v.stripHeaders(y),_&&(v.meta&&v.meta.exif&&v.setExif({PixelXDimension:this.width,PixelYDimension:this.height}),y=v.writeHeaders(y)),v.purge(),v=null)}return R=!1,y},destroy:function(){b=null,g.call(this),this.getRuntime().getShim().removeInstance(this.uid)}})}return e.Image=l}),n("moxie/runtime/flash/Runtime",["moxie/core/utils/Basic","moxie/core/utils/Env","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/runtime/Runtime"],function(e,t,i,n,o){function a(){var e;try{e=navigator.plugins["Shockwave Flash"],e=e.description}catch(t){try{e=new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version")}catch(i){e="0.0"}}return e=e.match(/\d+/g),parseFloat(e[0]+"."+e[1])}function s(e){var n=i.get(e);n&&"OBJECT"==n.nodeName&&("IE"===t.browser?(n.style.display="none",function r(){4==n.readyState?u(e):setTimeout(r,10)}()):n.parentNode.removeChild(n))}function u(e){var t=i.get(e);if(t){for(var n in t)"function"==typeof t[n]&&(t[n]=null);t.parentNode.removeChild(t)}}function c(u){var c,m=this;u=e.extend({swf_url:t.swf_url},u),o.call(this,u,l,{access_binary:function(e){return e&&"browser"===m.mode},access_image_binary:function(e){return e&&"browser"===m.mode},display_media:o.capTest(r("moxie/image/Image")),do_cors:o.capTrue,drag_and_drop:!1,report_upload_progress:function(){return"client"===m.mode},resize_image:o.capTrue,return_response_headers:!1,return_response_type:function(t){return"json"===t&&window.JSON?!0:!e.arrayDiff(t,["","text","document"])||"browser"===m.mode},return_status_code:function(t){return"browser"===m.mode||!e.arrayDiff(t,[200,404])},select_file:o.capTrue,select_multiple:o.capTrue,send_binary_string:function(e){return e&&"browser"===m.mode},send_browser_cookies:function(e){return e&&"browser"===m.mode},send_custom_headers:function(e){return e&&"browser"===m.mode},send_multipart:o.capTrue,slice_blob:function(e){return e&&"browser"===m.mode},stream_upload:function(e){return e&&"browser"===m.mode},summon_file_dialog:!1,upload_filesize:function(t){return e.parseSizeStr(t)<=2097152||"client"===m.mode},use_http_method:function(t){return!e.arrayDiff(t,["GET","POST"])}},{access_binary:function(e){return e?"browser":"client"},access_image_binary:function(e){return e?"browser":"client"},report_upload_progress:function(e){return e?"browser":"client"},return_response_type:function(t){return e.arrayDiff(t,["","text","json","document"])?"browser":["client","browser"]},return_status_code:function(t){return e.arrayDiff(t,[200,404])?"browser":["client","browser"]},send_binary_string:function(e){return e?"browser":"client"},send_browser_cookies:function(e){return e?"browser":"client"},send_custom_headers:function(e){return e?"browser":"client"},slice_blob:function(e){return e?"browser":"client"},stream_upload:function(e){return e?"client":"browser"},upload_filesize:function(t){return e.parseSizeStr(t)>=2097152?"client":"browser"}},"client"),a()<11.3&&(this.mode=!1),e.extend(this,{getShim:function(){return i.get(this.uid)},shimExec:function(e,t){var i=[].slice.call(arguments,2);return m.getShim().exec(this.uid,e,t,i)},init:function(){var i,r,a;a=this.getShimContainer(),e.extend(a.style,{position:"absolute",top:"-8px",left:"-8px",width:"9px",height:"9px",overflow:"hidden"}),i='<object id="'+this.uid+'" type="application/x-shockwave-flash" data="'+u.swf_url+'" ',"IE"===t.browser&&(i+='classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" '),i+='width="100%" height="100%" style="outline:0"><param name="movie" value="'+u.swf_url+'" />'+'<param name="flashvars" value="uid='+escape(this.uid)+"&target="+o.getGlobalEventTarget()+'" />'+'<param name="wmode" value="transparent" />'+'<param name="allowscriptaccess" value="always" />'+"</object>","IE"===t.browser?(r=document.createElement("div"),a.appendChild(r),r.outerHTML=i,r=a=null):a.innerHTML=i,c=setTimeout(function(){m&&!m.initialized&&m.trigger("Error",new n.RuntimeError(n.RuntimeError.NOT_INIT_ERR))},5e3)},destroy:function(e){return function(){s(m.uid),e.call(m),clearTimeout(c),u=c=e=m=null}}(this.destroy)},d)}var l="flash",d={};return o.addConstructor(l,c),d}),n("moxie/runtime/flash/file/Blob",["moxie/runtime/flash/Runtime","moxie/file/Blob"],function(e,t){var i={slice:function(e,i,n,r){var o=this.getRuntime();return 0>i?i=Math.max(e.size+i,0):i>0&&(i=Math.min(i,e.size)),0>n?n=Math.max(e.size+n,0):n>0&&(n=Math.min(n,e.size)),e=o.shimExec.call(this,"Blob","slice",i,n,r||""),e&&(e=new t(o.uid,e)),e}};return e.Blob=i}),n("moxie/runtime/flash/file/FileInput",["moxie/runtime/flash/Runtime","moxie/file/File","moxie/core/utils/Dom","moxie/core/utils/Basic"],function(e,t,i,n){var r={init:function(e){var r=this,o=this.getRuntime(),a=i.get(e.browse_button);a&&(a.setAttribute("tabindex",-1),a=null),this.bind("Change",function(){var e=o.shimExec.call(r,"FileInput","getFiles");r.files=[],n.each(e,function(e){r.files.push(new t(o.uid,e))})},999),this.getRuntime().shimExec.call(this,"FileInput","init",{accept:e.accept,multiple:e.multiple}),this.trigger("ready")}};return e.FileInput=r}),n("moxie/runtime/flash/file/FileReader",["moxie/runtime/flash/Runtime","moxie/core/utils/Encode"],function(e,t){function i(e,i){switch(i){case"readAsText":return t.atob(e,"utf8");case"readAsBinaryString":return t.atob(e);case"readAsDataURL":return e}return null}var n={read:function(e,t){var n=this;return n.result="","readAsDataURL"===e&&(n.result="data:"+(t.type||"")+";base64,"),n.bind("Progress",function(t,r){r&&(n.result+=i(r,e))},999),n.getRuntime().shimExec.call(this,"FileReader","readAsBase64",t.uid)}};return e.FileReader=n}),n("moxie/runtime/flash/file/FileReaderSync",["moxie/runtime/flash/Runtime","moxie/core/utils/Encode"],function(e,t){function i(e,i){switch(i){case"readAsText":return t.atob(e,"utf8");case"readAsBinaryString":return t.atob(e);case"readAsDataURL":return e}return null}var n={read:function(e,t){var n,r=this.getRuntime();return(n=r.shimExec.call(this,"FileReaderSync","readAsBase64",t.uid))?("readAsDataURL"===e&&(n="data:"+(t.type||"")+";base64,"+n),i(n,e,t.type)):null}};return e.FileReaderSync=n}),n("moxie/runtime/flash/runtime/Transporter",["moxie/runtime/flash/Runtime","moxie/file/Blob"],function(e,t){var i={getAsBlob:function(e){var i=this.getRuntime(),n=i.shimExec.call(this,"Transporter","getAsBlob",e);return n?new t(i.uid,n):null}};return e.Transporter=i}),n("moxie/runtime/flash/xhr/XMLHttpRequest",["moxie/runtime/flash/Runtime","moxie/core/utils/Basic","moxie/file/Blob","moxie/file/File","moxie/file/FileReaderSync","moxie/runtime/flash/file/FileReaderSync","moxie/xhr/FormData","moxie/runtime/Transporter","moxie/runtime/flash/runtime/Transporter"],function(e,t,i,n,r,o,a,s){var u={send:function(e,n){function r(){e.transport=l.mode,l.shimExec.call(c,"XMLHttpRequest","send",e,n)}function o(e,t){l.shimExec.call(c,"XMLHttpRequest","appendBlob",e,t.uid),n=null,r()}function u(e,t){var i=new s;i.bind("TransportingComplete",function(){t(this.result)}),i.transport(e.getSource(),e.type,{ruid:l.uid})}var c=this,l=c.getRuntime();if(t.isEmptyObj(e.headers)||t.each(e.headers,function(e,t){l.shimExec.call(c,"XMLHttpRequest","setRequestHeader",t,e.toString())}),n instanceof a){var d;if(n.each(function(e,t){e instanceof i?d=t:l.shimExec.call(c,"XMLHttpRequest","append",t,e)}),n.hasBlob()){var m=n.getBlob();m.isDetached()?u(m,function(e){m.destroy(),o(d,e)}):o(d,m)}else n=null,r()}else n instanceof i?n.isDetached()?u(n,function(e){n.destroy(),n=e.uid,r()}):(n=n.uid,r()):r()},getResponse:function(e){var i,o,a=this.getRuntime();if(o=a.shimExec.call(this,"XMLHttpRequest","getResponseAsBlob")){if(o=new n(a.uid,o),"blob"===e)return o;try{if(i=new r,~t.inArray(e,["","text"]))return i.readAsText(o);if("json"===e&&window.JSON)return JSON.parse(i.readAsText(o))}finally{o.destroy()}}return null},abort:function(){var e=this.getRuntime();e.shimExec.call(this,"XMLHttpRequest","abort"),this.dispatchEvent("readystatechange"),this.dispatchEvent("abort")}};return e.XMLHttpRequest=u}),n("moxie/runtime/flash/image/Image",["moxie/runtime/flash/Runtime","moxie/core/utils/Basic","moxie/runtime/Transporter","moxie/file/Blob","moxie/file/FileReaderSync"],function(e,t,i,n,r){var o={loadFromBlob:function(e){function t(e){r.shimExec.call(n,"Image","loadFromBlob",e.uid),n=r=null}var n=this,r=n.getRuntime();if(e.isDetached()){var o=new i;o.bind("TransportingComplete",function(){t(o.result.getSource())}),o.transport(e.getSource(),e.type,{ruid:r.uid})}else t(e.getSource())},loadFromImage:function(e){var t=this.getRuntime();return t.shimExec.call(this,"Image","loadFromImage",e.uid)},getInfo:function(){var e=this.getRuntime(),t=e.shimExec.call(this,"Image","getInfo");return t.meta&&t.meta.thumb&&t.meta.thumb.data&&!(e.meta.thumb.data instanceof n)&&(t.meta.thumb.data=new n(e.uid,t.meta.thumb.data)),t},getAsBlob:function(e,t){var i=this.getRuntime(),r=i.shimExec.call(this,"Image","getAsBlob",e,t);return r?new n(i.uid,r):null},getAsDataURL:function(){var e,t=this.getRuntime(),i=t.Image.getAsBlob.apply(this,arguments);return i?(e=new r,e.readAsDataURL(i)):null}};return e.Image=o}),n("moxie/runtime/silverlight/Runtime",["moxie/core/utils/Basic","moxie/core/utils/Env","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/runtime/Runtime"],function(e,t,i,n,o){function a(e){var t,i,n,r,o,a=!1,s=null,u=0;try{try{s=new ActiveXObject("AgControl.AgControl"),s.IsVersionSupported(e)&&(a=!0),s=null}catch(c){var l=navigator.plugins["Silverlight Plug-In"];if(l){for(t=l.description,"1.0.30226.2"===t&&(t="2.0.30226.2"),i=t.split(".");i.length>3;)i.pop();for(;i.length<4;)i.push(0);for(n=e.split(".");n.length>4;)n.pop();do r=parseInt(n[u],10),o=parseInt(i[u],10),u++;while(u<n.length&&r===o);o>=r&&!isNaN(r)&&(a=!0)}}}catch(d){a=!1}return a}function s(s){var l,d=this;s=e.extend({xap_url:t.xap_url},s),o.call(this,s,u,{access_binary:o.capTrue,access_image_binary:o.capTrue,display_media:o.capTest(r("moxie/image/Image")),do_cors:o.capTrue,drag_and_drop:!1,report_upload_progress:o.capTrue,resize_image:o.capTrue,return_response_headers:function(e){return e&&"client"===d.mode},return_response_type:function(e){return"json"!==e?!0:!!window.JSON},return_status_code:function(t){return"client"===d.mode||!e.arrayDiff(t,[200,404])},select_file:o.capTrue,select_multiple:o.capTrue,send_binary_string:o.capTrue,send_browser_cookies:function(e){return e&&"browser"===d.mode},send_custom_headers:function(e){return e&&"client"===d.mode},send_multipart:o.capTrue,slice_blob:o.capTrue,stream_upload:!0,summon_file_dialog:!1,upload_filesize:o.capTrue,use_http_method:function(t){return"client"===d.mode||!e.arrayDiff(t,["GET","POST"])}},{return_response_headers:function(e){return e?"client":"browser"},return_status_code:function(t){return e.arrayDiff(t,[200,404])?"client":["client","browser"]},send_browser_cookies:function(e){return e?"browser":"client"},send_custom_headers:function(e){return e?"client":"browser"},use_http_method:function(t){return e.arrayDiff(t,["GET","POST"])?"client":["client","browser"]}}),a("2.0.31005.0")&&"Opera"!==t.browser||(this.mode=!1),e.extend(this,{getShim:function(){return i.get(this.uid).content.Moxie},shimExec:function(e,t){var i=[].slice.call(arguments,2);return d.getShim().exec(this.uid,e,t,i)},init:function(){var e;e=this.getShimContainer(),e.innerHTML='<object id="'+this.uid+'" data="data:application/x-silverlight," type="application/x-silverlight-2" width="100%" height="100%" style="outline:none;">'+'<param name="source" value="'+s.xap_url+'"/>'+'<param name="background" value="Transparent"/>'+'<param name="windowless" value="true"/>'+'<param name="enablehtmlaccess" value="true"/>'+'<param name="initParams" value="uid='+this.uid+",target="+o.getGlobalEventTarget()+'"/>'+"</object>",l=setTimeout(function(){d&&!d.initialized&&d.trigger("Error",new n.RuntimeError(n.RuntimeError.NOT_INIT_ERR))},"Windows"!==t.OS?1e4:5e3)},destroy:function(e){return function(){e.call(d),clearTimeout(l),s=l=e=d=null}}(this.destroy)},c)}var u="silverlight",c={};return o.addConstructor(u,s),c}),n("moxie/runtime/silverlight/file/Blob",["moxie/runtime/silverlight/Runtime","moxie/core/utils/Basic","moxie/runtime/flash/file/Blob"],function(e,t,i){return e.Blob=t.extend({},i)}),n("moxie/runtime/silverlight/file/FileInput",["moxie/runtime/silverlight/Runtime","moxie/file/File","moxie/core/utils/Dom","moxie/core/utils/Basic"],function(e,t,i,n){function r(e){for(var t="",i=0;i<e.length;i++)t+=(""!==t?"|":"")+e[i].title+" | *."+e[i].extensions.replace(/,/g,";*."); -return t}var o={init:function(e){var o=this,a=this.getRuntime(),s=i.get(e.browse_button);s&&(s.setAttribute("tabindex",-1),s=null),this.bind("Change",function(){var e=a.shimExec.call(o,"FileInput","getFiles");o.files=[],n.each(e,function(e){o.files.push(new t(a.uid,e))})},999),a.shimExec.call(this,"FileInput","init",r(e.accept),e.multiple),this.trigger("ready")},setOption:function(e,t){"accept"==e&&(t=r(t)),this.getRuntime().shimExec.call(this,"FileInput","setOption",e,t)}};return e.FileInput=o}),n("moxie/runtime/silverlight/file/FileDrop",["moxie/runtime/silverlight/Runtime","moxie/core/utils/Dom","moxie/core/utils/Events"],function(e,t,i){var n={init:function(){var e,n=this,r=n.getRuntime();return e=r.getShimContainer(),i.addEvent(e,"dragover",function(e){e.preventDefault(),e.stopPropagation(),e.dataTransfer.dropEffect="copy"},n.uid),i.addEvent(e,"dragenter",function(e){e.preventDefault();var i=t.get(r.uid).dragEnter(e);i&&e.stopPropagation()},n.uid),i.addEvent(e,"drop",function(e){e.preventDefault();var i=t.get(r.uid).dragDrop(e);i&&e.stopPropagation()},n.uid),r.shimExec.call(this,"FileDrop","init")}};return e.FileDrop=n}),n("moxie/runtime/silverlight/file/FileReader",["moxie/runtime/silverlight/Runtime","moxie/core/utils/Basic","moxie/runtime/flash/file/FileReader"],function(e,t,i){return e.FileReader=t.extend({},i)}),n("moxie/runtime/silverlight/file/FileReaderSync",["moxie/runtime/silverlight/Runtime","moxie/core/utils/Basic","moxie/runtime/flash/file/FileReaderSync"],function(e,t,i){return e.FileReaderSync=t.extend({},i)}),n("moxie/runtime/silverlight/runtime/Transporter",["moxie/runtime/silverlight/Runtime","moxie/core/utils/Basic","moxie/runtime/flash/runtime/Transporter"],function(e,t,i){return e.Transporter=t.extend({},i)}),n("moxie/runtime/silverlight/xhr/XMLHttpRequest",["moxie/runtime/silverlight/Runtime","moxie/core/utils/Basic","moxie/runtime/flash/xhr/XMLHttpRequest","moxie/runtime/silverlight/file/FileReaderSync","moxie/runtime/silverlight/runtime/Transporter"],function(e,t,i){return e.XMLHttpRequest=t.extend({},i)}),n("moxie/runtime/silverlight/image/Image",["moxie/runtime/silverlight/Runtime","moxie/core/utils/Basic","moxie/file/Blob","moxie/runtime/flash/image/Image"],function(e,t,i,n){return e.Image=t.extend({},n,{getInfo:function(){var e=this.getRuntime(),n=["tiff","exif","gps","thumb"],r={meta:{}},o=e.shimExec.call(this,"Image","getInfo");return o.meta&&(t.each(n,function(e){var t,i,n,a,s=o.meta[e];if(s&&s.keys)for(r.meta[e]={},i=0,n=s.keys.length;n>i;i++)t=s.keys[i],a=s[t],a&&(/^(\d|[1-9]\d+)$/.test(a)?a=parseInt(a,10):/^\d*\.\d+$/.test(a)&&(a=parseFloat(a)),r.meta[e][t]=a)}),r.meta&&r.meta.thumb&&r.meta.thumb.data&&!(e.meta.thumb.data instanceof i)&&(r.meta.thumb.data=new i(e.uid,r.meta.thumb.data))),r.width=parseInt(o.width,10),r.height=parseInt(o.height,10),r.size=parseInt(o.size,10),r.type=o.type,r.name=o.name,r},resize:function(e,t,i){this.getRuntime().shimExec.call(this,"Image","resize",e.x,e.y,e.width,e.height,t,i.preserveHeaders,i.resample)}})}),n("moxie/runtime/html4/Runtime",["moxie/core/utils/Basic","moxie/core/Exceptions","moxie/runtime/Runtime","moxie/core/utils/Env"],function(e,t,i,n){function o(t){var o=this,u=i.capTest,c=i.capTrue;i.call(this,t,a,{access_binary:u(window.FileReader||window.File&&File.getAsDataURL),access_image_binary:!1,display_media:u((n.can("create_canvas")||n.can("use_data_uri_over32kb"))&&r("moxie/image/Image")),do_cors:!1,drag_and_drop:!1,filter_by_extension:u(function(){return!("Chrome"===n.browser&&n.verComp(n.version,28,"<")||"IE"===n.browser&&n.verComp(n.version,10,"<")||"Safari"===n.browser&&n.verComp(n.version,7,"<")||"Firefox"===n.browser&&n.verComp(n.version,37,"<"))}()),resize_image:function(){return s.Image&&o.can("access_binary")&&n.can("create_canvas")},report_upload_progress:!1,return_response_headers:!1,return_response_type:function(t){return"json"===t&&window.JSON?!0:!!~e.inArray(t,["text","document",""])},return_status_code:function(t){return!e.arrayDiff(t,[200,404])},select_file:function(){return n.can("use_fileinput")},select_multiple:!1,send_binary_string:!1,send_custom_headers:!1,send_multipart:!0,slice_blob:!1,stream_upload:function(){return o.can("select_file")},summon_file_dialog:function(){return o.can("select_file")&&!("Firefox"===n.browser&&n.verComp(n.version,4,"<")||"Opera"===n.browser&&n.verComp(n.version,12,"<")||"IE"===n.browser&&n.verComp(n.version,10,"<"))},upload_filesize:c,use_http_method:function(t){return!e.arrayDiff(t,["GET","POST"])}}),e.extend(this,{init:function(){this.trigger("Init")},destroy:function(e){return function(){e.call(o),e=o=null}}(this.destroy)}),e.extend(this.getShim(),s)}var a="html4",s={};return i.addConstructor(a,o),s}),n("moxie/runtime/html4/file/FileInput",["moxie/runtime/html4/Runtime","moxie/file/File","moxie/core/utils/Basic","moxie/core/utils/Dom","moxie/core/utils/Events","moxie/core/utils/Mime","moxie/core/utils/Env"],function(e,t,i,n,r,o,a){function s(){function e(){var o,c,d,m,h,f,p=this,g=p.getRuntime();f=i.guid("uid_"),o=g.getShimContainer(),s&&(d=n.get(s+"_form"),d&&(i.extend(d.style,{top:"100%"}),d.firstChild.setAttribute("tabindex",-1))),m=document.createElement("form"),m.setAttribute("id",f+"_form"),m.setAttribute("method","post"),m.setAttribute("enctype","multipart/form-data"),m.setAttribute("encoding","multipart/form-data"),i.extend(m.style,{overflow:"hidden",position:"absolute",top:0,left:0,width:"100%",height:"100%"}),h=document.createElement("input"),h.setAttribute("id",f),h.setAttribute("type","file"),h.setAttribute("accept",l.join(",")),g.can("summon_file_dialog")&&h.setAttribute("tabindex",-1),i.extend(h.style,{fontSize:"999px",opacity:0}),m.appendChild(h),o.appendChild(m),i.extend(h.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),"IE"===a.browser&&a.verComp(a.version,10,"<")&&i.extend(h.style,{filter:"progid:DXImageTransform.Microsoft.Alpha(opacity=0)"}),h.onchange=function(){var i;this.value&&(i=this.files?this.files[0]:{name:this.value},i=new t(g.uid,i),this.onchange=function(){},e.call(p),p.files=[i],h.setAttribute("id",i.uid),m.setAttribute("id",i.uid+"_form"),p.trigger("change"),h=m=null)},g.can("summon_file_dialog")&&(c=n.get(u.browse_button),r.removeEvent(c,"click",p.uid),r.addEvent(c,"click",function(e){h&&!h.disabled&&h.click(),e.preventDefault()},p.uid)),s=f,o=d=c=null}var s,u,c,l=[];i.extend(this,{init:function(t){var i,a=this,s=a.getRuntime();u=t,l=o.extList2mimes(t.accept,s.can("filter_by_extension")),i=s.getShimContainer(),function(){var e,o,l;e=n.get(t.browse_button),c=n.getStyle(e,"z-index")||"auto",s.can("summon_file_dialog")?("static"===n.getStyle(e,"position")&&(e.style.position="relative"),a.bind("Refresh",function(){o=parseInt(c,10)||1,n.get(u.browse_button).style.zIndex=o,this.getRuntime().getShimContainer().style.zIndex=o-1})):e.setAttribute("tabindex",-1),l=s.can("summon_file_dialog")?e:i,r.addEvent(l,"mouseover",function(){a.trigger("mouseenter")},a.uid),r.addEvent(l,"mouseout",function(){a.trigger("mouseleave")},a.uid),r.addEvent(l,"mousedown",function(){a.trigger("mousedown")},a.uid),r.addEvent(n.get(t.container),"mouseup",function(){a.trigger("mouseup")},a.uid),e=null}(),e.call(this),i=null,a.trigger({type:"ready",async:!0})},setOption:function(e,t){var i,r=this.getRuntime();"accept"==e&&(l=t.mimes||o.extList2mimes(t,r.can("filter_by_extension"))),i=n.get(s),i&&i.setAttribute("accept",l.join(","))},disable:function(e){var t;(t=n.get(s))&&(t.disabled=!!e)},destroy:function(){var e=this.getRuntime(),t=e.getShim(),i=e.getShimContainer(),o=u&&n.get(u.container),a=u&&n.get(u.browse_button);o&&r.removeAllEvents(o,this.uid),a&&(r.removeAllEvents(a,this.uid),a.style.zIndex=c),i&&(r.removeAllEvents(i,this.uid),i.innerHTML=""),t.removeInstance(this.uid),s=l=u=i=o=a=t=null}})}return e.FileInput=s}),n("moxie/runtime/html4/file/FileReader",["moxie/runtime/html4/Runtime","moxie/runtime/html5/file/FileReader"],function(e,t){return e.FileReader=t}),n("moxie/runtime/html4/xhr/XMLHttpRequest",["moxie/runtime/html4/Runtime","moxie/core/utils/Basic","moxie/core/utils/Dom","moxie/core/utils/Url","moxie/core/Exceptions","moxie/core/utils/Events","moxie/file/Blob","moxie/xhr/FormData"],function(e,t,i,n,r,o,a,s){function u(){function e(e){var t,n,r,a,s=this,u=!1;if(l){if(t=l.id.replace(/_iframe$/,""),n=i.get(t+"_form")){for(r=n.getElementsByTagName("input"),a=r.length;a--;)switch(r[a].getAttribute("type")){case"hidden":r[a].parentNode.removeChild(r[a]);break;case"file":u=!0}r=[],u||n.parentNode.removeChild(n),n=null}setTimeout(function(){o.removeEvent(l,"load",s.uid),l.parentNode&&l.parentNode.removeChild(l);var t=s.getRuntime().getShimContainer();t.children.length||t.parentNode.removeChild(t),t=l=null,e()},1)}}var u,c,l;t.extend(this,{send:function(d,m){function h(){var i=w.getShimContainer()||document.body,r=document.createElement("div");r.innerHTML='<iframe id="'+f+'_iframe" name="'+f+'_iframe" src="javascript:""" style="display:none"></iframe>',l=r.firstChild,i.appendChild(l),o.addEvent(l,"load",function(){var i;try{i=l.contentWindow.document||l.contentDocument||window.frames[l.id].document,/^4(0[0-9]|1[0-7]|2[2346])\s/.test(i.title)?u=i.title.replace(/^(\d+).*$/,"$1"):(u=200,c=t.trim(i.body.innerHTML),v.trigger({type:"progress",loaded:c.length,total:c.length}),x&&v.trigger({type:"uploadprogress",loaded:x.size||1025,total:x.size||1025}))}catch(r){if(!n.hasSameOrigin(d.url))return e.call(v,function(){v.trigger("error")}),void 0;u=404}e.call(v,function(){v.trigger("load")})},v.uid)}var f,p,g,x,v=this,w=v.getRuntime();if(u=c=null,m instanceof s&&m.hasBlob()){if(x=m.getBlob(),f=x.uid,g=i.get(f),p=i.get(f+"_form"),!p)throw new r.DOMException(r.DOMException.NOT_FOUND_ERR)}else f=t.guid("uid_"),p=document.createElement("form"),p.setAttribute("id",f+"_form"),p.setAttribute("method",d.method),p.setAttribute("enctype","multipart/form-data"),p.setAttribute("encoding","multipart/form-data"),w.getShimContainer().appendChild(p);p.setAttribute("target",f+"_iframe"),m instanceof s&&m.each(function(e,i){if(e instanceof a)g&&g.setAttribute("name",i);else{var n=document.createElement("input");t.extend(n,{type:"hidden",name:i,value:e}),g?p.insertBefore(n,g):p.appendChild(n)}}),p.setAttribute("action",d.url),h(),p.submit(),v.trigger("loadstart")},getStatus:function(){return u},getResponse:function(e){if("json"===e&&"string"===t.typeOf(c)&&window.JSON)try{return JSON.parse(c.replace(/^\s*<pre[^>]*>/,"").replace(/<\/pre>\s*$/,""))}catch(i){return null}return c},abort:function(){var t=this;l&&l.contentWindow&&(l.contentWindow.stop?l.contentWindow.stop():l.contentWindow.document.execCommand?l.contentWindow.document.execCommand("Stop"):l.src="about:blank"),e.call(this,function(){t.dispatchEvent("abort")})},destroy:function(){this.getRuntime().getShim().removeInstance(this.uid)}})}return e.XMLHttpRequest=u}),n("moxie/runtime/html4/image/Image",["moxie/runtime/html4/Runtime","moxie/runtime/html5/image/Image"],function(e,t){return e.Image=t}),a(["moxie/core/utils/Basic","moxie/core/utils/Encode","moxie/core/utils/Env","moxie/core/Exceptions","moxie/core/utils/Dom","moxie/core/EventTarget","moxie/runtime/Runtime","moxie/runtime/RuntimeClient","moxie/file/Blob","moxie/core/I18n","moxie/core/utils/Mime","moxie/file/FileInput","moxie/file/File","moxie/file/FileDrop","moxie/file/FileReader","moxie/core/utils/Url","moxie/runtime/RuntimeTarget","moxie/xhr/FormData","moxie/xhr/XMLHttpRequest","moxie/image/Image","moxie/core/utils/Events","moxie/runtime/html5/image/ResizerCanvas"])}(this)}); +!function(e,t){var i=function(){var e={};return t.apply(e,arguments),e.moxie};"function"==typeof define&&define.amd?define("moxie",[],i):"object"==typeof module&&module.exports?module.exports=i():e.moxie=i()}(this||window,function(){!function(e,t){"use strict";function i(e,t){for(var i,n=[],r=0;r<e.length;++r){if(i=s[e[r]]||o(e[r]),!i)throw"module definition dependecy not found: "+e[r];n.push(i)}t.apply(null,n)}function n(e,n,r){if("string"!=typeof e)throw"invalid module definition, module id must be defined and be a string";if(n===t)throw"invalid module definition, dependencies must be specified";if(r===t)throw"invalid module definition, definition function must be specified";i(n,function(){s[e]=r.apply(null,arguments)})}function r(e){return!!s[e]}function o(t){for(var i=e,n=t.split(/[.\/]/),r=0;r<n.length;++r){if(!i[n[r]])return;i=i[n[r]]}return i}function a(i){for(var n=0;n<i.length;n++){for(var r=e,o=i[n],a=o.split(/[.\/]/),u=0;u<a.length-1;++u)r[a[u]]===t&&(r[a[u]]={}),r=r[a[u]];r[a[a.length-1]]=s[o]}}var s={};n("moxie/core/utils/Basic",[],function(){function e(e){var t;return e===t?"undefined":null===e?"null":e.nodeType?"node":{}.toString.call(e).match(/\s([a-z|A-Z]+)/)[1].toLowerCase()}function t(){return s(!1,!1,arguments)}function i(){return s(!0,!1,arguments)}function n(){return s(!1,!0,arguments)}function r(){return s(!0,!0,arguments)}function o(t){switch(e(t)){case"array":return s(!1,!0,[[],t]);case"object":return s(!1,!0,[{},t]);default:return t}}function a(i){switch(e(i)){case"array":return Array.prototype.slice.call(i);case"object":return t({},i)}return i}function s(t,i,n){var r,o=n[0];return c(n,function(n,u){u>0&&c(n,function(n,u){var c=-1!==h(e(n),["array","object"]);return n===r||t&&o[u]===r?!0:(c&&i&&(n=a(n)),e(o[u])===e(n)&&c?s(t,i,[o[u],n]):o[u]=n,void 0)})}),o}function u(e,t){function i(){this.constructor=e}for(var n in t)({}).hasOwnProperty.call(t,n)&&(e[n]=t[n]);return i.prototype=t.prototype,e.prototype=new i,e.parent=t.prototype,e}function c(e,t){var i,n,r,o;if(e){try{i=e.length}catch(a){i=o}if(i===o||"number"!=typeof i){for(n in e)if(e.hasOwnProperty(n)&&t(e[n],n)===!1)return}else for(r=0;i>r;r++)if(t(e[r],r)===!1)return}}function l(t){var i;if(!t||"object"!==e(t))return!0;for(i in t)return!1;return!0}function d(t,i){function n(r){"function"===e(t[r])&&t[r](function(e){++r<o&&!e?n(r):i(e)})}var r=0,o=t.length;"function"!==e(i)&&(i=function(){}),t&&t.length||i(),n(r)}function m(e,t){var i=0,n=e.length,r=new Array(n);c(e,function(e,o){e(function(e){if(e)return t(e);var a=[].slice.call(arguments);a.shift(),r[o]=a,i++,i===n&&(r.unshift(null),t.apply(this,r))})})}function h(e,t){if(t){if(Array.prototype.indexOf)return Array.prototype.indexOf.call(t,e);for(var i=0,n=t.length;n>i;i++)if(t[i]===e)return i}return-1}function f(t,i){var n=[];"array"!==e(t)&&(t=[t]),"array"!==e(i)&&(i=[i]);for(var r in t)-1===h(t[r],i)&&n.push(t[r]);return n.length?n:!1}function p(e,t){var i=[];return c(e,function(e){-1!==h(e,t)&&i.push(e)}),i.length?i:null}function g(e){var t,i=[];for(t=0;t<e.length;t++)i[t]=e[t];return i}function x(e){return e?String.prototype.trim?String.prototype.trim.call(e):e.toString().replace(/^\s*/,"").replace(/\s*$/,""):e}function v(e){if("string"!=typeof e)return e;var t,i={t:1099511627776,g:1073741824,m:1048576,k:1024};return e=/^([0-9\.]+)([tmgk]?)$/.exec(e.toLowerCase().replace(/[^0-9\.tmkg]/g,"")),t=e[2],e=+e[1],i.hasOwnProperty(t)&&(e*=i[t]),Math.floor(e)}function w(e){var t=[].slice.call(arguments,1);return e.replace(/%([a-z])/g,function(e,i){var n=t.shift();switch(i){case"s":return n+"";case"d":return parseInt(n,10);case"f":return parseFloat(n);case"c":return"";default:return n}})}function y(e,t){var i=this;setTimeout(function(){e.call(i)},t||1)}var E=function(){var e=0;return function(t){var i,n=(new Date).getTime().toString(32);for(i=0;5>i;i++)n+=Math.floor(65535*Math.random()).toString(32);return(t||"o_")+n+(e++).toString(32)}}();return{guid:E,typeOf:e,extend:t,extendIf:i,extendImmutable:n,extendImmutableIf:r,clone:o,inherit:u,each:c,isEmptyObj:l,inSeries:d,inParallel:m,inArray:h,arrayDiff:f,arrayIntersect:p,toArray:g,trim:x,sprintf:w,parseSizeStr:v,delay:y}}),n("moxie/core/utils/Encode",[],function(){var e=function(e){return unescape(encodeURIComponent(e))},t=function(e){return decodeURIComponent(escape(e))},i=function(e,i){if("function"==typeof window.atob)return i?t(window.atob(e)):window.atob(e);var n,r,o,a,s,u,c,l,d="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",m=0,h=0,f="",p=[];if(!e)return e;e+="";do a=d.indexOf(e.charAt(m++)),s=d.indexOf(e.charAt(m++)),u=d.indexOf(e.charAt(m++)),c=d.indexOf(e.charAt(m++)),l=a<<18|s<<12|u<<6|c,n=255&l>>16,r=255&l>>8,o=255&l,p[h++]=64==u?String.fromCharCode(n):64==c?String.fromCharCode(n,r):String.fromCharCode(n,r,o);while(m<e.length);return f=p.join(""),i?t(f):f},n=function(t,i){if(i&&(t=e(t)),"function"==typeof window.btoa)return window.btoa(t);var n,r,o,a,s,u,c,l,d="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",m=0,h=0,f="",p=[];if(!t)return t;do n=t.charCodeAt(m++),r=t.charCodeAt(m++),o=t.charCodeAt(m++),l=n<<16|r<<8|o,a=63&l>>18,s=63&l>>12,u=63&l>>6,c=63&l,p[h++]=d.charAt(a)+d.charAt(s)+d.charAt(u)+d.charAt(c);while(m<t.length);f=p.join("");var g=t.length%3;return(g?f.slice(0,g-3):f)+"===".slice(g||3)};return{utf8_encode:e,utf8_decode:t,atob:i,btoa:n}}),n("moxie/core/utils/Env",["moxie/core/utils/Basic"],function(e){function i(e,t,i){var n=0,r=0,o=0,a={dev:-6,alpha:-5,a:-5,beta:-4,b:-4,RC:-3,rc:-3,"#":-2,p:1,pl:1},s=function(e){return e=(""+e).replace(/[_\-+]/g,"."),e=e.replace(/([^.\d]+)/g,".$1.").replace(/\.{2,}/g,"."),e.length?e.split("."):[-8]},u=function(e){return e?isNaN(e)?a[e]||-7:parseInt(e,10):0};for(e=s(e),t=s(t),r=Math.max(e.length,t.length),n=0;r>n;n++)if(e[n]!=t[n]){if(e[n]=u(e[n]),t[n]=u(t[n]),e[n]<t[n]){o=-1;break}if(e[n]>t[n]){o=1;break}}if(!i)return o;switch(i){case">":case"gt":return o>0;case">=":case"ge":return o>=0;case"<=":case"le":return 0>=o;case"==":case"=":case"eq":return 0===o;case"<>":case"!=":case"ne":return 0!==o;case"":case"<":case"lt":return 0>o;default:return null}}var n=function(e){var t="",i="?",n="function",r="undefined",o="object",a="name",s="version",u={has:function(e,t){return-1!==t.toLowerCase().indexOf(e.toLowerCase())},lowerize:function(e){return e.toLowerCase()}},c={rgx:function(){for(var t,i,a,s,u,c,l,d=0,m=arguments;d<m.length;d+=2){var h=m[d],f=m[d+1];if(typeof t===r){t={};for(s in f)u=f[s],typeof u===o?t[u[0]]=e:t[u]=e}for(i=a=0;i<h.length;i++)if(c=h[i].exec(this.getUA())){for(s=0;s<f.length;s++)l=c[++a],u=f[s],typeof u===o&&u.length>0?2==u.length?t[u[0]]=typeof u[1]==n?u[1].call(this,l):u[1]:3==u.length?t[u[0]]=typeof u[1]!==n||u[1].exec&&u[1].test?l?l.replace(u[1],u[2]):e:l?u[1].call(this,l,u[2]):e:4==u.length&&(t[u[0]]=l?u[3].call(this,l.replace(u[1],u[2])):e):t[u]=l?l:e;break}if(c)break}return t},str:function(t,n){for(var r in n)if(typeof n[r]===o&&n[r].length>0){for(var a=0;a<n[r].length;a++)if(u.has(n[r][a],t))return r===i?e:r}else if(u.has(n[r],t))return r===i?e:r;return t}},l={browser:{oldsafari:{major:{1:["/8","/1","/3"],2:"/4","?":"/"},version:{"1.0":"/8",1.2:"/1",1.3:"/3","2.0":"/412","2.0.2":"/416","2.0.3":"/417","2.0.4":"/419","?":"/"}}},device:{sprint:{model:{"Evo Shift 4G":"7373KT"},vendor:{HTC:"APA",Sprint:"Sprint"}}},os:{windows:{version:{ME:"4.90","NT 3.11":"NT3.51","NT 4.0":"NT4.0",2000:"NT 5.0",XP:["NT 5.1","NT 5.2"],Vista:"NT 6.0",7:"NT 6.1",8:"NT 6.2",8.1:"NT 6.3",RT:"ARM"}}}},d={browser:[[/(opera\smini)\/([\w\.-]+)/i,/(opera\s[mobiletab]+).+version\/([\w\.-]+)/i,/(opera).+version\/([\w\.]+)/i,/(opera)[\/\s]+([\w\.]+)/i],[a,s],[/\s(opr)\/([\w\.]+)/i],[[a,"Opera"],s],[/(kindle)\/([\w\.]+)/i,/(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?([\w\.]+)*/i,/(avant\s|iemobile|slim|baidu)(?:browser)?[\/\s]?([\w\.]*)/i,/(?:ms|\()(ie)\s([\w\.]+)/i,/(rekonq)\/([\w\.]+)*/i,/(chromium|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi)\/([\w\.-]+)/i],[a,s],[/(trident).+rv[:\s]([\w\.]+).+like\sgecko/i],[[a,"IE"],s],[/(edge)\/((\d+)?[\w\.]+)/i],[a,s],[/(yabrowser)\/([\w\.]+)/i],[[a,"Yandex"],s],[/(comodo_dragon)\/([\w\.]+)/i],[[a,/_/g," "],s],[/(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?([\w\.]+)/i,/(uc\s?browser|qqbrowser)[\/\s]?([\w\.]+)/i],[a,s],[/(dolfin)\/([\w\.]+)/i],[[a,"Dolphin"],s],[/((?:android.+)crmo|crios)\/([\w\.]+)/i],[[a,"Chrome"],s],[/XiaoMi\/MiuiBrowser\/([\w\.]+)/i],[s,[a,"MIUI Browser"]],[/android.+version\/([\w\.]+)\s+(?:mobile\s?safari|safari)/i],[s,[a,"Android Browser"]],[/FBAV\/([\w\.]+);/i],[s,[a,"Facebook"]],[/version\/([\w\.]+).+?mobile\/\w+\s(safari)/i],[s,[a,"Mobile Safari"]],[/version\/([\w\.]+).+?(mobile\s?safari|safari)/i],[s,a],[/webkit.+?(mobile\s?safari|safari)(\/[\w\.]+)/i],[a,[s,c.str,l.browser.oldsafari.version]],[/(konqueror)\/([\w\.]+)/i,/(webkit|khtml)\/([\w\.]+)/i],[a,s],[/(navigator|netscape)\/([\w\.-]+)/i],[[a,"Netscape"],s],[/(swiftfox)/i,/(icedragon|iceweasel|camino|chimera|fennec|maemo\sbrowser|minimo|conkeror)[\/\s]?([\w\.\+]+)/i,/(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix)\/([\w\.-]+)/i,/(mozilla)\/([\w\.]+).+rv\:.+gecko\/\d+/i,/(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf)[\/\s]?([\w\.]+)/i,/(links)\s\(([\w\.]+)/i,/(gobrowser)\/?([\w\.]+)*/i,/(ice\s?browser)\/v?([\w\._]+)/i,/(mosaic)[\/\s]([\w\.]+)/i],[a,s]],engine:[[/windows.+\sedge\/([\w\.]+)/i],[s,[a,"EdgeHTML"]],[/(presto)\/([\w\.]+)/i,/(webkit|trident|netfront|netsurf|amaya|lynx|w3m)\/([\w\.]+)/i,/(khtml|tasman|links)[\/\s]\(?([\w\.]+)/i,/(icab)[\/\s]([23]\.[\d\.]+)/i],[a,s],[/rv\:([\w\.]+).*(gecko)/i],[s,a]],os:[[/microsoft\s(windows)\s(vista|xp)/i],[a,s],[/(windows)\snt\s6\.2;\s(arm)/i,/(windows\sphone(?:\sos)*|windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)/i],[a,[s,c.str,l.os.windows.version]],[/(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i],[[a,"Windows"],[s,c.str,l.os.windows.version]],[/\((bb)(10);/i],[[a,"BlackBerry"],s],[/(blackberry)\w*\/?([\w\.]+)*/i,/(tizen)[\/\s]([\w\.]+)/i,/(android|webos|palm\os|qnx|bada|rim\stablet\sos|meego|contiki)[\/\s-]?([\w\.]+)*/i,/linux;.+(sailfish);/i],[a,s],[/(symbian\s?os|symbos|s60(?=;))[\/\s-]?([\w\.]+)*/i],[[a,"Symbian"],s],[/\((series40);/i],[a],[/mozilla.+\(mobile;.+gecko.+firefox/i],[[a,"Firefox OS"],s],[/(nintendo|playstation)\s([wids3portablevu]+)/i,/(mint)[\/\s\(]?(\w+)*/i,/(mageia|vectorlinux)[;\s]/i,/(joli|[kxln]?ubuntu|debian|[open]*suse|gentoo|arch|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk|linpus)[\/\s-]?([\w\.-]+)*/i,/(hurd|linux)\s?([\w\.]+)*/i,/(gnu)\s?([\w\.]+)*/i],[a,s],[/(cros)\s[\w]+\s([\w\.]+\w)/i],[[a,"Chromium OS"],s],[/(sunos)\s?([\w\.]+\d)*/i],[[a,"Solaris"],s],[/\s([frentopc-]{0,4}bsd|dragonfly)\s?([\w\.]+)*/i],[a,s],[/(ip[honead]+)(?:.*os\s*([\w]+)*\slike\smac|;\sopera)/i],[[a,"iOS"],[s,/_/g,"."]],[/(mac\sos\sx)\s?([\w\s\.]+\w)*/i,/(macintosh|mac(?=_powerpc)\s)/i],[[a,"Mac OS"],[s,/_/g,"."]],[/((?:open)?solaris)[\/\s-]?([\w\.]+)*/i,/(haiku)\s(\w+)/i,/(aix)\s((\d)(?=\.|\)|\s)[\w\.]*)*/i,/(plan\s9|minix|beos|os\/2|amigaos|morphos|risc\sos|openvms)/i,/(unix)\s?([\w\.]+)*/i],[a,s]]},m=function(e){var i=e||(window&&window.navigator&&window.navigator.userAgent?window.navigator.userAgent:t);this.getBrowser=function(){return c.rgx.apply(this,d.browser)},this.getEngine=function(){return c.rgx.apply(this,d.engine)},this.getOS=function(){return c.rgx.apply(this,d.os)},this.getResult=function(){return{ua:this.getUA(),browser:this.getBrowser(),engine:this.getEngine(),os:this.getOS()}},this.getUA=function(){return i},this.setUA=function(e){return i=e,this},this.setUA(i)};return m}(),r=function(){var i={access_global_ns:function(){return!!window.moxie},define_property:function(){return!1}(),create_canvas:function(){var e=document.createElement("canvas"),t=!(!e.getContext||!e.getContext("2d"));return i.create_canvas=t,t},return_response_type:function(t){try{if(-1!==e.inArray(t,["","text","document"]))return!0;if(window.XMLHttpRequest){var i=new XMLHttpRequest;if(i.open("get","/"),"responseType"in i)return i.responseType=t,i.responseType!==t?!1:!0}}catch(n){}return!1},use_blob_uri:function(){var e=window.URL;return i.use_blob_uri=e&&"createObjectURL"in e&&"revokeObjectURL"in e&&("IE"!==a.browser||a.verComp(a.version,"11.0.46",">=")),i.use_blob_uri},use_data_uri:function(){var e=new Image;return e.onload=function(){i.use_data_uri=1===e.width&&1===e.height},setTimeout(function(){e.src="data:image/gif;base64,R0lGODlhAQABAIAAAP8AAAAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=="},1),!1}(),use_data_uri_over32kb:function(){return i.use_data_uri&&("IE"!==a.browser||a.version>=9)},use_data_uri_of:function(e){return i.use_data_uri&&33e3>e||i.use_data_uri_over32kb()},use_fileinput:function(){if(navigator.userAgent.match(/(Android (1.0|1.1|1.5|1.6|2.0|2.1))|(Windows Phone (OS 7|8.0))|(XBLWP)|(ZuneWP)|(w(eb)?OSBrowser)|(webOS)|(Kindle\/(1.0|2.0|2.5|3.0))/))return!1;var e=document.createElement("input");return e.setAttribute("type","file"),i.use_fileinput=!e.disabled},use_webgl:function(){var e,n=document.createElement("canvas"),r=null;try{r=n.getContext("webgl")||n.getContext("experimental-webgl")}catch(o){}return r||(r=null),e=!!r,i.use_webgl=e,n=t,e}};return function(t){var n=[].slice.call(arguments);return n.shift(),"function"===e.typeOf(i[t])?i[t].apply(this,n):!!i[t]}}(),o=(new n).getResult(),a={can:r,uaParser:n,browser:o.browser.name,version:o.browser.version,os:o.os.name,osVersion:o.os.version,verComp:i,swf_url:"../flash/Moxie.swf",xap_url:"../silverlight/Moxie.xap",global_event_dispatcher:"moxie.core.EventTarget.instance.dispatchEvent"};return a.OS=a.os,a}),n("moxie/core/Exceptions",["moxie/core/utils/Basic"],function(e){function t(e,t){var i;for(i in e)if(e[i]===t)return i;return null}return{RuntimeError:function(){function i(e,i){this.code=e,this.name=t(n,e),this.message=this.name+(i||": RuntimeError "+this.code)}var n={NOT_INIT_ERR:1,EXCEPTION_ERR:3,NOT_SUPPORTED_ERR:9,JS_ERR:4};return e.extend(i,n),i.prototype=Error.prototype,i}(),OperationNotAllowedException:function(){function t(e){this.code=e,this.name="OperationNotAllowedException"}return e.extend(t,{NOT_ALLOWED_ERR:1}),t.prototype=Error.prototype,t}(),ImageError:function(){function i(e){this.code=e,this.name=t(n,e),this.message=this.name+": ImageError "+this.code}var n={WRONG_FORMAT:1,MAX_RESOLUTION_ERR:2,INVALID_META_ERR:3};return e.extend(i,n),i.prototype=Error.prototype,i}(),FileException:function(){function i(e){this.code=e,this.name=t(n,e),this.message=this.name+": FileException "+this.code}var n={NOT_FOUND_ERR:1,SECURITY_ERR:2,ABORT_ERR:3,NOT_READABLE_ERR:4,ENCODING_ERR:5,NO_MODIFICATION_ALLOWED_ERR:6,INVALID_STATE_ERR:7,SYNTAX_ERR:8};return e.extend(i,n),i.prototype=Error.prototype,i}(),DOMException:function(){function i(e){this.code=e,this.name=t(n,e),this.message=this.name+": DOMException "+this.code}var n={INDEX_SIZE_ERR:1,DOMSTRING_SIZE_ERR:2,HIERARCHY_REQUEST_ERR:3,WRONG_DOCUMENT_ERR:4,INVALID_CHARACTER_ERR:5,NO_DATA_ALLOWED_ERR:6,NO_MODIFICATION_ALLOWED_ERR:7,NOT_FOUND_ERR:8,NOT_SUPPORTED_ERR:9,INUSE_ATTRIBUTE_ERR:10,INVALID_STATE_ERR:11,SYNTAX_ERR:12,INVALID_MODIFICATION_ERR:13,NAMESPACE_ERR:14,INVALID_ACCESS_ERR:15,VALIDATION_ERR:16,TYPE_MISMATCH_ERR:17,SECURITY_ERR:18,NETWORK_ERR:19,ABORT_ERR:20,URL_MISMATCH_ERR:21,QUOTA_EXCEEDED_ERR:22,TIMEOUT_ERR:23,INVALID_NODE_TYPE_ERR:24,DATA_CLONE_ERR:25};return e.extend(i,n),i.prototype=Error.prototype,i}(),EventException:function(){function t(e){this.code=e,this.name="EventException"}return e.extend(t,{UNSPECIFIED_EVENT_TYPE_ERR:0}),t.prototype=Error.prototype,t}()}}),n("moxie/core/utils/Dom",["moxie/core/utils/Env"],function(e){var t=function(e){return"string"!=typeof e?e:document.getElementById(e)},i=function(e,t){if(!e.className)return!1;var i=new RegExp("(^|\\s+)"+t+"(\\s+|$)");return i.test(e.className)},n=function(e,t){i(e,t)||(e.className=e.className?e.className.replace(/\s+$/,"")+" "+t:t)},r=function(e,t){if(e.className){var i=new RegExp("(^|\\s+)"+t+"(\\s+|$)");e.className=e.className.replace(i,function(e,t,i){return" "===t&&" "===i?" ":""})}},o=function(e,t){return e.currentStyle?e.currentStyle[t]:window.getComputedStyle?window.getComputedStyle(e,null)[t]:void 0},a=function(t,i){function n(e){var t,i,n=0,r=0;return e&&(i=e.getBoundingClientRect(),t="CSS1Compat"===c.compatMode?c.documentElement:c.body,n=i.left+t.scrollLeft,r=i.top+t.scrollTop),{x:n,y:r}}var r,o,a,s=0,u=0,c=document;if(t=t,i=i||c.body,t&&t.getBoundingClientRect&&"IE"===e.browser&&(!c.documentMode||c.documentMode<8))return o=n(t),a=n(i),{x:o.x-a.x,y:o.y-a.y};for(r=t;r&&r!=i&&r.nodeType;)s+=r.offsetLeft||0,u+=r.offsetTop||0,r=r.offsetParent;for(r=t.parentNode;r&&r!=i&&r.nodeType;)s-=r.scrollLeft||0,u-=r.scrollTop||0,r=r.parentNode;return{x:s,y:u}},s=function(e){return{w:e.offsetWidth||e.clientWidth,h:e.offsetHeight||e.clientHeight}};return{get:t,hasClass:i,addClass:n,removeClass:r,getStyle:o,getPos:a,getSize:s}}),n("moxie/core/EventTarget",["moxie/core/utils/Env","moxie/core/Exceptions","moxie/core/utils/Basic"],function(e,t,i){function n(){this.uid=i.guid()}var r={};return i.extend(n.prototype,{init:function(){this.uid||(this.uid=i.guid("uid_"))},addEventListener:function(e,t,n,o){var a,s=this;return this.hasOwnProperty("uid")||(this.uid=i.guid("uid_")),e=i.trim(e),/\s/.test(e)?(i.each(e.split(/\s+/),function(e){s.addEventListener(e,t,n,o)}),void 0):(e=e.toLowerCase(),n=parseInt(n,10)||0,a=r[this.uid]&&r[this.uid][e]||[],a.push({fn:t,priority:n,scope:o||this}),r[this.uid]||(r[this.uid]={}),r[this.uid][e]=a,void 0)},hasEventListener:function(e){var t;return e?(e=e.toLowerCase(),t=r[this.uid]&&r[this.uid][e]):t=r[this.uid],t?t:!1},removeEventListener:function(e,t){var n,o,a=this;if(e=e.toLowerCase(),/\s/.test(e))return i.each(e.split(/\s+/),function(e){a.removeEventListener(e,t)}),void 0;if(n=r[this.uid]&&r[this.uid][e]){if(t){for(o=n.length-1;o>=0;o--)if(n[o].fn===t){n.splice(o,1);break}}else n=[];n.length||(delete r[this.uid][e],i.isEmptyObj(r[this.uid])&&delete r[this.uid])}},removeAllEventListeners:function(){r[this.uid]&&delete r[this.uid]},dispatchEvent:function(e){var n,o,a,s,u,c={},l=!0;if("string"!==i.typeOf(e)){if(s=e,"string"!==i.typeOf(s.type))throw new t.EventException(t.EventException.UNSPECIFIED_EVENT_TYPE_ERR);e=s.type,s.total!==u&&s.loaded!==u&&(c.total=s.total,c.loaded=s.loaded),c.async=s.async||!1}if(-1!==e.indexOf("::")?function(t){n=t[0],e=t[1]}(e.split("::")):n=this.uid,e=e.toLowerCase(),o=r[n]&&r[n][e]){o.sort(function(e,t){return t.priority-e.priority}),a=[].slice.call(arguments),a.shift(),c.type=e,a.unshift(c);var d=[];i.each(o,function(e){a[0].target=e.scope,c.async?d.push(function(t){setTimeout(function(){t(e.fn.apply(e.scope,a)===!1)},1)}):d.push(function(t){t(e.fn.apply(e.scope,a)===!1)})}),d.length&&i.inSeries(d,function(e){l=!e})}return l},bindOnce:function(e,t,i,n){var r=this;r.bind.call(this,e,function o(){return r.unbind(e,o),t.apply(this,arguments)},i,n)},bind:function(){this.addEventListener.apply(this,arguments)},unbind:function(){this.removeEventListener.apply(this,arguments)},unbindAll:function(){this.removeAllEventListeners.apply(this,arguments)},trigger:function(){return this.dispatchEvent.apply(this,arguments)},handleEventProps:function(e){var t=this;this.bind(e.join(" "),function(e){var t="on"+e.type.toLowerCase();"function"===i.typeOf(this[t])&&this[t].apply(this,arguments)}),i.each(e,function(e){e="on"+e.toLowerCase(e),"undefined"===i.typeOf(t[e])&&(t[e]=null)})}}),n.instance=new n,n}),n("moxie/runtime/Runtime",["moxie/core/utils/Env","moxie/core/utils/Basic","moxie/core/utils/Dom","moxie/core/EventTarget"],function(e,t,i,n){function r(e,n,o,s,u){var c,l=this,d=t.guid(n+"_"),m=u||"browser";e=e||{},a[d]=this,o=t.extend({access_binary:!1,access_image_binary:!1,display_media:!1,do_cors:!1,drag_and_drop:!1,filter_by_extension:!0,resize_image:!1,report_upload_progress:!1,return_response_headers:!1,return_response_type:!1,return_status_code:!0,send_custom_headers:!1,select_file:!1,select_folder:!1,select_multiple:!0,send_binary_string:!1,send_browser_cookies:!0,send_multipart:!0,slice_blob:!1,stream_upload:!1,summon_file_dialog:!1,upload_filesize:!0,use_http_method:!0},o),e.preferred_caps&&(m=r.getMode(s,e.preferred_caps,m)),c=function(){var e={};return{exec:function(t,i,n,r){return c[i]&&(e[t]||(e[t]={context:this,instance:new c[i]}),e[t].instance[n])?e[t].instance[n].apply(this,r):void 0},removeInstance:function(t){delete e[t]},removeAllInstances:function(){var i=this;t.each(e,function(e,n){"function"===t.typeOf(e.instance.destroy)&&e.instance.destroy.call(e.context),i.removeInstance(n)})}}}(),t.extend(this,{initialized:!1,uid:d,type:n,mode:r.getMode(s,e.required_caps,m),shimid:d+"_container",clients:0,options:e,can:function(e,i){var n=arguments[2]||o;if("string"===t.typeOf(e)&&"undefined"===t.typeOf(i)&&(e=r.parseCaps(e)),"object"===t.typeOf(e)){for(var a in e)if(!this.can(a,e[a],n))return!1;return!0}return"function"===t.typeOf(n[e])?n[e].call(this,i):i===n[e]},getShimContainer:function(){var e,n=i.get(this.shimid);return n||(e=i.get(this.options.container)||document.body,n=document.createElement("div"),n.id=this.shimid,n.className="moxie-shim moxie-shim-"+this.type,t.extend(n.style,{position:"absolute",top:"0px",left:"0px",width:"1px",height:"1px",overflow:"hidden"}),e.appendChild(n),e=null),n},getShim:function(){return c},shimExec:function(e,t){var i=[].slice.call(arguments,2);return l.getShim().exec.call(this,this.uid,e,t,i)},exec:function(e,t){var i=[].slice.call(arguments,2);return l[e]&&l[e][t]?l[e][t].apply(this,i):l.shimExec.apply(this,arguments)},destroy:function(){if(l){var e=i.get(this.shimid);e&&e.parentNode.removeChild(e),c&&c.removeAllInstances(),this.unbindAll(),delete a[this.uid],this.uid=null,d=l=c=e=null}}}),this.mode&&e.required_caps&&!this.can(e.required_caps)&&(this.mode=!1)}var o={},a={};return r.order="html5,flash,silverlight,html4",r.getRuntime=function(e){return a[e]?a[e]:!1},r.addConstructor=function(e,t){t.prototype=n.instance,o[e]=t},r.getConstructor=function(e){return o[e]||null},r.getInfo=function(e){var t=r.getRuntime(e);return t?{uid:t.uid,type:t.type,mode:t.mode,can:function(){return t.can.apply(t,arguments)}}:null},r.parseCaps=function(e){var i={};return"string"!==t.typeOf(e)?e||{}:(t.each(e.split(","),function(e){i[e]=!0}),i)},r.can=function(e,t){var i,n,o=r.getConstructor(e);return o?(i=new o({required_caps:t}),n=i.mode,i.destroy(),!!n):!1},r.thatCan=function(e,t){var i=(t||r.order).split(/\s*,\s*/);for(var n in i)if(r.can(i[n],e))return i[n];return null},r.getMode=function(e,i,n){var r=null;if("undefined"===t.typeOf(n)&&(n="browser"),i&&!t.isEmptyObj(e)){if(t.each(i,function(i,n){if(e.hasOwnProperty(n)){var o=e[n](i);if("string"==typeof o&&(o=[o]),r){if(!(r=t.arrayIntersect(r,o)))return r=!1}else r=o}}),r)return-1!==t.inArray(n,r)?n:r[0];if(r===!1)return!1}return n},r.getGlobalEventTarget=function(){if(/^moxie\./.test(e.global_event_dispatcher)&&!e.can("access_global_ns")){var i=t.guid("moxie_event_target_");window[i]=function(e,t){n.instance.dispatchEvent(e,t)},e.global_event_dispatcher=i}return e.global_event_dispatcher},r.capTrue=function(){return!0},r.capFalse=function(){return!1},r.capTest=function(e){return function(){return!!e}},r}),n("moxie/runtime/RuntimeClient",["moxie/core/utils/Env","moxie/core/Exceptions","moxie/core/utils/Basic","moxie/runtime/Runtime"],function(e,t,i,n){return function(){var e;i.extend(this,{connectRuntime:function(r){function o(i){var a,u;return i.length?(a=i.shift().toLowerCase(),(u=n.getConstructor(a))?(e=new u(r),e.bind("Init",function(){e.initialized=!0,setTimeout(function(){e.clients++,s.ruid=e.uid,s.trigger("RuntimeInit",e)},1)}),e.bind("Error",function(){e.destroy(),o(i)}),e.bind("Exception",function(e,i){var n=i.name+"(#"+i.code+")"+(i.message?", from: "+i.message:"");s.trigger("RuntimeError",new t.RuntimeError(t.RuntimeError.EXCEPTION_ERR,n))}),e.mode?(e.init(),void 0):(e.trigger("Error"),void 0)):(o(i),void 0)):(s.trigger("RuntimeError",new t.RuntimeError(t.RuntimeError.NOT_INIT_ERR)),e=null,void 0)}var a,s=this;if("string"===i.typeOf(r)?a=r:"string"===i.typeOf(r.ruid)&&(a=r.ruid),a){if(e=n.getRuntime(a))return s.ruid=a,e.clients++,e;throw new t.RuntimeError(t.RuntimeError.NOT_INIT_ERR)}o((r.runtime_order||n.order).split(/\s*,\s*/))},disconnectRuntime:function(){e&&--e.clients<=0&&e.destroy(),e=null},getRuntime:function(){return e&&e.uid?e:e=null},exec:function(){return e?e.exec.apply(this,arguments):null},can:function(t){return e?e.can(t):!1}})}}),n("moxie/file/Blob",["moxie/core/utils/Basic","moxie/core/utils/Encode","moxie/runtime/RuntimeClient"],function(e,t,i){function n(o,a){function s(t,i,o){var a,s=r[this.uid];return"string"===e.typeOf(s)&&s.length?(a=new n(null,{type:o,size:i-t}),a.detach(s.substr(t,a.size)),a):null}i.call(this),o&&this.connectRuntime(o),a?"string"===e.typeOf(a)&&(a={data:a}):a={},e.extend(this,{uid:a.uid||e.guid("uid_"),ruid:o,size:a.size||0,type:a.type||"",slice:function(e,t,i){return this.isDetached()?s.apply(this,arguments):this.getRuntime().exec.call(this,"Blob","slice",this.getSource(),e,t,i)},getSource:function(){return r[this.uid]?r[this.uid]:null},detach:function(e){if(this.ruid&&(this.getRuntime().exec.call(this,"Blob","destroy"),this.disconnectRuntime(),this.ruid=null),e=e||"","data:"==e.substr(0,5)){var i=e.indexOf(";base64,");this.type=e.substring(5,i),e=t.atob(e.substring(i+8))}this.size=e.length,r[this.uid]=e},isDetached:function(){return!this.ruid&&"string"===e.typeOf(r[this.uid])},destroy:function(){this.detach(),delete r[this.uid]}}),a.data?this.detach(a.data):r[this.uid]=a}var r={};return n}),n("moxie/core/I18n",["moxie/core/utils/Basic"],function(e){var t={};return{addI18n:function(i){return e.extend(t,i)},translate:function(e){return t[e]||e},_:function(e){return this.translate(e)},sprintf:function(t){var i=[].slice.call(arguments,1);return t.replace(/%[a-z]/g,function(){var t=i.shift();return"undefined"!==e.typeOf(t)?t:""})}}}),n("moxie/core/utils/Mime",["moxie/core/utils/Basic","moxie/core/I18n"],function(e,t){var i="application/msword,doc dot,application/pdf,pdf,application/pgp-signature,pgp,application/postscript,ps ai eps,application/rtf,rtf,application/vnd.ms-excel,xls xlb xlt xla,application/vnd.ms-powerpoint,ppt pps pot ppa,application/zip,zip,application/x-shockwave-flash,swf swfl,application/vnd.openxmlformats-officedocument.wordprocessingml.document,docx,application/vnd.openxmlformats-officedocument.wordprocessingml.template,dotx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,xlsx,application/vnd.openxmlformats-officedocument.presentationml.presentation,pptx,application/vnd.openxmlformats-officedocument.presentationml.template,potx,application/vnd.openxmlformats-officedocument.presentationml.slideshow,ppsx,application/x-javascript,js,application/json,json,audio/mpeg,mp3 mpga mpega mp2,audio/x-wav,wav,audio/x-m4a,m4a,audio/ogg,oga ogg,audio/aiff,aiff aif,audio/flac,flac,audio/aac,aac,audio/ac3,ac3,audio/x-ms-wma,wma,image/bmp,bmp,image/gif,gif,image/jpeg,jpg jpeg jpe,image/photoshop,psd,image/png,png,image/svg+xml,svg svgz,image/tiff,tiff tif,text/plain,asc txt text diff log,text/html,htm html xhtml,text/css,css,text/csv,csv,text/rtf,rtf,video/mpeg,mpeg mpg mpe m2v,video/quicktime,qt mov,video/mp4,mp4,video/x-m4v,m4v,video/x-flv,flv,video/x-ms-wmv,wmv,video/avi,avi,video/webm,webm,video/3gpp,3gpp 3gp,video/3gpp2,3g2,video/vnd.rn-realvideo,rv,video/ogg,ogv,video/x-matroska,mkv,application/vnd.oasis.opendocument.formula-template,otf,application/octet-stream,exe",n={},r={},o=function(e){var t,i,o,a=e.split(/,/);for(t=0;t<a.length;t+=2){for(o=a[t+1].split(/ /),i=0;i<o.length;i++)n[o[i]]=a[t];r[a[t]]=o}},a=function(t,i){var n,r,o,a,s=[];for(r=0;r<t.length;r++)for(n=t[r].extensions.toLowerCase().split(/\s*,\s*/),o=0;o<n.length;o++){if("*"===n[o])return[];if(a=s[n[o]],i&&/^\w+$/.test(n[o]))s.push("."+n[o]);else if(a&&-1===e.inArray(a,s))s.push(a);else if(!a)return[]}return s},s=function(t){var i=[];return e.each(t,function(t){if(t=t.toLowerCase(),"*"===t)return i=[],!1;var n=t.match(/^(\w+)\/(\*|\w+)$/);n&&("*"===n[2]?e.each(r,function(e,t){new RegExp("^"+n[1]+"/").test(t)&&[].push.apply(i,r[t])}):r[t]&&[].push.apply(i,r[t]))}),i},u=function(i){var n=[],r=[];return"string"===e.typeOf(i)&&(i=e.trim(i).split(/\s*,\s*/)),r=s(i),n.push({title:t.translate("Files"),extensions:r.length?r.join(","):"*"}),n},c=function(e){var t=e&&e.match(/\.([^.]+)$/);return t?t[1].toLowerCase():""},l=function(e){return n[c(e)]||""};return o(i),{mimes:n,extensions:r,addMimeType:o,extList2mimes:a,mimes2exts:s,mimes2extList:u,getFileExtension:c,getFileMime:l}}),n("moxie/file/FileInput",["moxie/core/utils/Basic","moxie/core/utils/Env","moxie/core/utils/Mime","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/core/EventTarget","moxie/core/I18n","moxie/runtime/Runtime","moxie/runtime/RuntimeClient"],function(e,t,i,n,r,o,a,s,u){function c(t){var o,c,d;if(-1!==e.inArray(e.typeOf(t),["string","node"])&&(t={browse_button:t}),c=n.get(t.browse_button),!c)throw new r.DOMException(r.DOMException.NOT_FOUND_ERR);d={accept:[{title:a.translate("All Files"),extensions:"*"}],multiple:!1,required_caps:!1,container:c.parentNode||document.body},t=e.extend({},d,t),"string"==typeof t.required_caps&&(t.required_caps=s.parseCaps(t.required_caps)),"string"==typeof t.accept&&(t.accept=i.mimes2extList(t.accept)),o=n.get(t.container),o||(o=document.body),"static"===n.getStyle(o,"position")&&(o.style.position="relative"),o=c=null,u.call(this),e.extend(this,{uid:e.guid("uid_"),ruid:null,shimid:null,files:null,init:function(){var i=this;i.bind("RuntimeInit",function(r,o){i.ruid=o.uid,i.shimid=o.shimid,i.bind("Ready",function(){i.trigger("Refresh")},999),i.bind("Refresh",function(){var i,r,a,s,u;a=n.get(t.browse_button),s=n.get(o.shimid),a&&(i=n.getPos(a,n.get(t.container)),r=n.getSize(a),u=parseInt(n.getStyle(a,"z-index"),10)||0,s&&e.extend(s.style,{top:i.y+"px",left:i.x+"px",width:r.w+"px",height:r.h+"px",zIndex:u+1})),s=a=null}),o.exec.call(i,"FileInput","init",t)}),i.connectRuntime(e.extend({},t,{required_caps:{select_file:!0}}))},getOption:function(e){return t[e]},setOption:function(e,n){if(t.hasOwnProperty(e)){var o=t[e];switch(e){case"accept":"string"==typeof n&&(n=i.mimes2extList(n));break;case"container":case"required_caps":throw new r.FileException(r.FileException.NO_MODIFICATION_ALLOWED_ERR)}t[e]=n,this.exec("FileInput","setOption",e,n),this.trigger("OptionChanged",e,n,o)}},disable:function(t){var i=this.getRuntime();i&&this.exec("FileInput","disable","undefined"===e.typeOf(t)?!0:t)},refresh:function(){this.trigger("Refresh")},destroy:function(){var t=this.getRuntime();t&&(t.exec.call(this,"FileInput","destroy"),this.disconnectRuntime()),"array"===e.typeOf(this.files)&&e.each(this.files,function(e){e.destroy()}),this.files=null,this.unbindAll()}}),this.handleEventProps(l)}var l=["ready","change","cancel","mouseenter","mouseleave","mousedown","mouseup"];return c.prototype=o.instance,c}),n("moxie/file/File",["moxie/core/utils/Basic","moxie/core/utils/Mime","moxie/file/Blob"],function(e,t,i){function n(n,r){r||(r={}),i.apply(this,arguments),this.type||(this.type=t.getFileMime(r.name));var o;if(r.name)o=r.name.replace(/\\/g,"/"),o=o.substr(o.lastIndexOf("/")+1);else if(this.type){var a=this.type.split("/")[0];o=e.guid((""!==a?a:"file")+"_"),t.extensions[this.type]&&(o+="."+t.extensions[this.type][0])}e.extend(this,{name:o||e.guid("file_"),relativePath:"",lastModifiedDate:r.lastModifiedDate||(new Date).toLocaleString()})}return n.prototype=i.prototype,n}),n("moxie/file/FileDrop",["moxie/core/I18n","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/core/utils/Basic","moxie/core/utils/Env","moxie/file/File","moxie/runtime/RuntimeClient","moxie/core/EventTarget","moxie/core/utils/Mime"],function(e,t,i,n,r,o,a,s,u){function c(i){var r,o=this;"string"==typeof i&&(i={drop_zone:i}),r={accept:[{title:e.translate("All Files"),extensions:"*"}],required_caps:{drag_and_drop:!0}},i="object"==typeof i?n.extend({},r,i):r,i.container=t.get(i.drop_zone)||document.body,"static"===t.getStyle(i.container,"position")&&(i.container.style.position="relative"),"string"==typeof i.accept&&(i.accept=u.mimes2extList(i.accept)),a.call(o),n.extend(o,{uid:n.guid("uid_"),ruid:null,files:null,init:function(){o.bind("RuntimeInit",function(e,t){o.ruid=t.uid,t.exec.call(o,"FileDrop","init",i),o.dispatchEvent("ready") +}),o.connectRuntime(i)},destroy:function(){var e=this.getRuntime();e&&(e.exec.call(this,"FileDrop","destroy"),this.disconnectRuntime()),this.files=null,this.unbindAll()}}),this.handleEventProps(l)}var l=["ready","dragenter","dragleave","drop","error"];return c.prototype=s.instance,c}),n("moxie/file/FileReader",["moxie/core/utils/Basic","moxie/core/utils/Encode","moxie/core/Exceptions","moxie/core/EventTarget","moxie/file/Blob","moxie/runtime/RuntimeClient"],function(e,t,i,n,r,o){function a(){function n(e,n){if(this.trigger("loadstart"),this.readyState===a.LOADING)return this.trigger("error",new i.DOMException(i.DOMException.INVALID_STATE_ERR)),this.trigger("loadend"),void 0;if(!(n instanceof r))return this.trigger("error",new i.DOMException(i.DOMException.NOT_FOUND_ERR)),this.trigger("loadend"),void 0;if(this.result=null,this.readyState=a.LOADING,n.isDetached()){var o=n.getSource();switch(e){case"readAsText":case"readAsBinaryString":this.result=o;break;case"readAsDataURL":this.result="data:"+n.type+";base64,"+t.btoa(o)}this.readyState=a.DONE,this.trigger("load"),this.trigger("loadend")}else this.connectRuntime(n.ruid),this.exec("FileReader","read",e,n)}o.call(this),e.extend(this,{uid:e.guid("uid_"),readyState:a.EMPTY,result:null,error:null,readAsBinaryString:function(e){n.call(this,"readAsBinaryString",e)},readAsDataURL:function(e){n.call(this,"readAsDataURL",e)},readAsText:function(e){n.call(this,"readAsText",e)},abort:function(){this.result=null,-1===e.inArray(this.readyState,[a.EMPTY,a.DONE])&&(this.readyState===a.LOADING&&(this.readyState=a.DONE),this.exec("FileReader","abort"),this.trigger("abort"),this.trigger("loadend"))},destroy:function(){this.abort(),this.exec("FileReader","destroy"),this.disconnectRuntime(),this.unbindAll()}}),this.handleEventProps(s),this.bind("Error",function(e,t){this.readyState=a.DONE,this.error=t},999),this.bind("Load",function(){this.readyState=a.DONE},999)}var s=["loadstart","progress","load","abort","error","loadend"];return a.EMPTY=0,a.LOADING=1,a.DONE=2,a.prototype=n.instance,a}),n("moxie/core/utils/Url",["moxie/core/utils/Basic"],function(e){var t=function(i,n){var r,o=["source","scheme","authority","userInfo","user","pass","host","port","relative","path","directory","file","query","fragment"],a=o.length,s={http:80,https:443},u={},c=/^(?:([^:\/?#]+):)?(?:\/\/()(?:(?:()(?:([^:@\/]*):?([^:@\/]*))?@)?(\[[\da-fA-F:]+\]|[^:\/?#]*)(?::(\d*))?))?()(?:(()(?:(?:[^?#\/]*\/)*)()(?:[^?#]*))(?:\\?([^#]*))?(?:#(.*))?)/,l=c.exec(i||""),d=/^\/\/\w/.test(i);switch(e.typeOf(n)){case"undefined":n=t(document.location.href,!1);break;case"string":n=t(n,!1)}for(;a--;)l[a]&&(u[o[a]]=l[a]);if(r=!d&&!u.scheme,(d||r)&&(u.scheme=n.scheme),r){u.host=n.host,u.port=n.port;var m="";/^[^\/]/.test(u.path)&&(m=n.path,m=/\/[^\/]*\.[^\/]*$/.test(m)?m.replace(/\/[^\/]+$/,"/"):m.replace(/\/?$/,"/")),u.path=m+(u.path||"")}return u.port||(u.port=s[u.scheme]||80),u.port=parseInt(u.port,10),u.path||(u.path="/"),delete u.source,u},i=function(e){var i={http:80,https:443},n="object"==typeof e?e:t(e);return n.scheme+"://"+n.host+(n.port!==i[n.scheme]?":"+n.port:"")+n.path+(n.query?n.query:"")},n=function(e){function i(e){return[e.scheme,e.host,e.port].join("/")}return"string"==typeof e&&(e=t(e)),i(t())===i(e)};return{parseUrl:t,resolveUrl:i,hasSameOrigin:n}}),n("moxie/runtime/RuntimeTarget",["moxie/core/utils/Basic","moxie/runtime/RuntimeClient","moxie/core/EventTarget"],function(e,t,i){function n(){this.uid=e.guid("uid_"),t.call(this),this.destroy=function(){this.disconnectRuntime(),this.unbindAll()}}return n.prototype=i.instance,n}),n("moxie/file/FileReaderSync",["moxie/core/utils/Basic","moxie/runtime/RuntimeClient","moxie/core/utils/Encode"],function(e,t,i){return function(){function n(e,t){if(!t.isDetached()){var n=this.connectRuntime(t.ruid).exec.call(this,"FileReaderSync","read",e,t);return this.disconnectRuntime(),n}var r=t.getSource();switch(e){case"readAsBinaryString":return r;case"readAsDataURL":return"data:"+t.type+";base64,"+i.btoa(r);case"readAsText":for(var o="",a=0,s=r.length;s>a;a++)o+=String.fromCharCode(r[a]);return o}}t.call(this),e.extend(this,{uid:e.guid("uid_"),readAsBinaryString:function(e){return n.call(this,"readAsBinaryString",e)},readAsDataURL:function(e){return n.call(this,"readAsDataURL",e)},readAsText:function(e){return n.call(this,"readAsText",e)}})}}),n("moxie/xhr/FormData",["moxie/core/Exceptions","moxie/core/utils/Basic","moxie/file/Blob"],function(e,t,i){function n(){var e,n=[];t.extend(this,{append:function(r,o){var a=this,s=t.typeOf(o);o instanceof i?e={name:r,value:o}:"array"===s?(r+="[]",t.each(o,function(e){a.append(r,e)})):"object"===s?t.each(o,function(e,t){a.append(r+"["+t+"]",e)}):"null"===s||"undefined"===s||"number"===s&&isNaN(o)?a.append(r,"false"):n.push({name:r,value:o.toString()})},hasBlob:function(){return!!this.getBlob()},getBlob:function(){return e&&e.value||null},getBlobName:function(){return e&&e.name||null},each:function(i){t.each(n,function(e){i(e.value,e.name)}),e&&i(e.value,e.name)},destroy:function(){e=null,n=[]}})}return n}),n("moxie/xhr/XMLHttpRequest",["moxie/core/utils/Basic","moxie/core/Exceptions","moxie/core/EventTarget","moxie/core/utils/Encode","moxie/core/utils/Url","moxie/runtime/Runtime","moxie/runtime/RuntimeTarget","moxie/file/Blob","moxie/file/FileReaderSync","moxie/xhr/FormData","moxie/core/utils/Env","moxie/core/utils/Mime"],function(e,t,i,n,r,o,a,s,u,c,l,d){function m(){this.uid=e.guid("uid_")}function h(){function i(e,t){return I.hasOwnProperty(e)?1===arguments.length?l.can("define_property")?I[e]:A[e]:(l.can("define_property")?I[e]=t:A[e]=t,void 0):void 0}function u(t){function n(){_&&(_.destroy(),_=null),s.dispatchEvent("loadend"),s=null}function r(r){_.bind("LoadStart",function(e){i("readyState",h.LOADING),s.dispatchEvent("readystatechange"),s.dispatchEvent(e),L&&s.upload.dispatchEvent(e)}),_.bind("Progress",function(e){i("readyState")!==h.LOADING&&(i("readyState",h.LOADING),s.dispatchEvent("readystatechange")),s.dispatchEvent(e)}),_.bind("UploadProgress",function(e){L&&s.upload.dispatchEvent({type:"progress",lengthComputable:!1,total:e.total,loaded:e.loaded})}),_.bind("Load",function(t){i("readyState",h.DONE),i("status",Number(r.exec.call(_,"XMLHttpRequest","getStatus")||0)),i("statusText",f[i("status")]||""),i("response",r.exec.call(_,"XMLHttpRequest","getResponse",i("responseType"))),~e.inArray(i("responseType"),["text",""])?i("responseText",i("response")):"document"===i("responseType")&&i("responseXML",i("response")),U=r.exec.call(_,"XMLHttpRequest","getAllResponseHeaders"),s.dispatchEvent("readystatechange"),i("status")>0?(L&&s.upload.dispatchEvent(t),s.dispatchEvent(t)):(F=!0,s.dispatchEvent("error")),n()}),_.bind("Abort",function(e){s.dispatchEvent(e),n()}),_.bind("Error",function(e){F=!0,i("readyState",h.DONE),s.dispatchEvent("readystatechange"),M=!0,s.dispatchEvent(e),n()}),r.exec.call(_,"XMLHttpRequest","send",{url:x,method:v,async:T,user:w,password:y,headers:S,mimeType:D,encoding:O,responseType:s.responseType,withCredentials:s.withCredentials,options:k},t)}var s=this;E=(new Date).getTime(),_=new a,"string"==typeof k.required_caps&&(k.required_caps=o.parseCaps(k.required_caps)),k.required_caps=e.extend({},k.required_caps,{return_response_type:s.responseType}),t instanceof c&&(k.required_caps.send_multipart=!0),e.isEmptyObj(S)||(k.required_caps.send_custom_headers=!0),B||(k.required_caps.do_cors=!0),k.ruid?r(_.connectRuntime(k)):(_.bind("RuntimeInit",function(e,t){r(t)}),_.bind("RuntimeError",function(e,t){s.dispatchEvent("RuntimeError",t)}),_.connectRuntime(k))}function g(){i("responseText",""),i("responseXML",null),i("response",null),i("status",0),i("statusText",""),E=b=null}var x,v,w,y,E,b,_,R,A=this,I={timeout:0,readyState:h.UNSENT,withCredentials:!1,status:0,statusText:"",responseType:"",responseXML:null,responseText:null,response:null},T=!0,S={},O=null,D=null,N=!1,C=!1,L=!1,M=!1,F=!1,B=!1,P=null,H=null,k={},U="";e.extend(this,I,{uid:e.guid("uid_"),upload:new m,open:function(o,a,s,u,c){var l;if(!o||!a)throw new t.DOMException(t.DOMException.SYNTAX_ERR);if(/[\u0100-\uffff]/.test(o)||n.utf8_encode(o)!==o)throw new t.DOMException(t.DOMException.SYNTAX_ERR);if(~e.inArray(o.toUpperCase(),["CONNECT","DELETE","GET","HEAD","OPTIONS","POST","PUT","TRACE","TRACK"])&&(v=o.toUpperCase()),~e.inArray(v,["CONNECT","TRACE","TRACK"]))throw new t.DOMException(t.DOMException.SECURITY_ERR);if(a=n.utf8_encode(a),l=r.parseUrl(a),B=r.hasSameOrigin(l),x=r.resolveUrl(a),(u||c)&&!B)throw new t.DOMException(t.DOMException.INVALID_ACCESS_ERR);if(w=u||l.user,y=c||l.pass,T=s||!0,T===!1&&(i("timeout")||i("withCredentials")||""!==i("responseType")))throw new t.DOMException(t.DOMException.INVALID_ACCESS_ERR);N=!T,C=!1,S={},g.call(this),i("readyState",h.OPENED),this.dispatchEvent("readystatechange")},setRequestHeader:function(r,o){var a=["accept-charset","accept-encoding","access-control-request-headers","access-control-request-method","connection","content-length","cookie","cookie2","content-transfer-encoding","date","expect","host","keep-alive","origin","referer","te","trailer","transfer-encoding","upgrade","user-agent","via"];if(i("readyState")!==h.OPENED||C)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(/[\u0100-\uffff]/.test(r)||n.utf8_encode(r)!==r)throw new t.DOMException(t.DOMException.SYNTAX_ERR);return r=e.trim(r).toLowerCase(),~e.inArray(r,a)||/^(proxy\-|sec\-)/.test(r)?!1:(S[r]?S[r]+=", "+o:S[r]=o,!0)},hasRequestHeader:function(e){return e&&S[e.toLowerCase()]||!1},getAllResponseHeaders:function(){return U||""},getResponseHeader:function(t){return t=t.toLowerCase(),F||~e.inArray(t,["set-cookie","set-cookie2"])?null:U&&""!==U&&(R||(R={},e.each(U.split(/\r\n/),function(t){var i=t.split(/:\s+/);2===i.length&&(i[0]=e.trim(i[0]),R[i[0].toLowerCase()]={header:i[0],value:e.trim(i[1])})})),R.hasOwnProperty(t))?R[t].header+": "+R[t].value:null},overrideMimeType:function(n){var r,o;if(~e.inArray(i("readyState"),[h.LOADING,h.DONE]))throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(n=e.trim(n.toLowerCase()),/;/.test(n)&&(r=n.match(/^([^;]+)(?:;\scharset\=)?(.*)$/))&&(n=r[1],r[2]&&(o=r[2])),!d.mimes[n])throw new t.DOMException(t.DOMException.SYNTAX_ERR);P=n,H=o},send:function(i,r){if(k="string"===e.typeOf(r)?{ruid:r}:r?r:{},this.readyState!==h.OPENED||C)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(i instanceof s)k.ruid=i.ruid,D=i.type||"application/octet-stream";else if(i instanceof c){if(i.hasBlob()){var o=i.getBlob();k.ruid=o.ruid,D=o.type||"application/octet-stream"}}else"string"==typeof i&&(O="UTF-8",D="text/plain;charset=UTF-8",i=n.utf8_encode(i));this.withCredentials||(this.withCredentials=k.required_caps&&k.required_caps.send_browser_cookies&&!B),L=!N&&this.upload.hasEventListener(),F=!1,M=!i,N||(C=!0),u.call(this,i)},abort:function(){if(F=!0,N=!1,~e.inArray(i("readyState"),[h.UNSENT,h.OPENED,h.DONE]))i("readyState",h.UNSENT);else{if(i("readyState",h.DONE),C=!1,!_)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);_.getRuntime().exec.call(_,"XMLHttpRequest","abort",M),M=!0}},destroy:function(){_&&("function"===e.typeOf(_.destroy)&&_.destroy(),_=null),this.unbindAll(),this.upload&&(this.upload.unbindAll(),this.upload=null)}}),this.handleEventProps(p.concat(["readystatechange"])),this.upload.handleEventProps(p)}var f={100:"Continue",101:"Switching Protocols",102:"Processing",200:"OK",201:"Created",202:"Accepted",203:"Non-Authoritative Information",204:"No Content",205:"Reset Content",206:"Partial Content",207:"Multi-Status",226:"IM Used",300:"Multiple Choices",301:"Moved Permanently",302:"Found",303:"See Other",304:"Not Modified",305:"Use Proxy",306:"Reserved",307:"Temporary Redirect",400:"Bad Request",401:"Unauthorized",402:"Payment Required",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",406:"Not Acceptable",407:"Proxy Authentication Required",408:"Request Timeout",409:"Conflict",410:"Gone",411:"Length Required",412:"Precondition Failed",413:"Request Entity Too Large",414:"Request-URI Too Long",415:"Unsupported Media Type",416:"Requested Range Not Satisfiable",417:"Expectation Failed",422:"Unprocessable Entity",423:"Locked",424:"Failed Dependency",426:"Upgrade Required",500:"Internal Server Error",501:"Not Implemented",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout",505:"HTTP Version Not Supported",506:"Variant Also Negotiates",507:"Insufficient Storage",510:"Not Extended"};m.prototype=i.instance;var p=["loadstart","progress","abort","error","load","timeout","loadend"];return h.UNSENT=0,h.OPENED=1,h.HEADERS_RECEIVED=2,h.LOADING=3,h.DONE=4,h.prototype=i.instance,h}),n("moxie/runtime/Transporter",["moxie/core/utils/Basic","moxie/core/utils/Encode","moxie/runtime/RuntimeClient","moxie/core/EventTarget"],function(e,t,i,n){function r(){function n(){l=d=0,c=this.result=null}function o(t,i){var n=this;u=i,n.bind("TransportingProgress",function(t){d=t.loaded,l>d&&-1===e.inArray(n.state,[r.IDLE,r.DONE])&&a.call(n)},999),n.bind("TransportingComplete",function(){d=l,n.state=r.DONE,c=null,n.result=u.exec.call(n,"Transporter","getAsBlob",t||"")},999),n.state=r.BUSY,n.trigger("TransportingStarted"),a.call(n)}function a(){var e,i=this,n=l-d;m>n&&(m=n),e=t.btoa(c.substr(d,m)),u.exec.call(i,"Transporter","receive",e,l)}var s,u,c,l,d,m;i.call(this),e.extend(this,{uid:e.guid("uid_"),state:r.IDLE,result:null,transport:function(t,i,r){var a=this;if(r=e.extend({chunk_size:204798},r),(s=r.chunk_size%3)&&(r.chunk_size+=3-s),m=r.chunk_size,n.call(this),c=t,l=t.length,"string"===e.typeOf(r)||r.ruid)o.call(a,i,this.connectRuntime(r));else{var u=function(e,t){a.unbind("RuntimeInit",u),o.call(a,i,t)};this.bind("RuntimeInit",u),this.connectRuntime(r)}},abort:function(){var e=this;e.state=r.IDLE,u&&(u.exec.call(e,"Transporter","clear"),e.trigger("TransportingAborted")),n.call(e)},destroy:function(){this.unbindAll(),u=null,this.disconnectRuntime(),n.call(this)}})}return r.IDLE=0,r.BUSY=1,r.DONE=2,r.prototype=n.instance,r}),n("moxie/image/Image",["moxie/core/utils/Basic","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/file/FileReaderSync","moxie/xhr/XMLHttpRequest","moxie/runtime/Runtime","moxie/runtime/RuntimeClient","moxie/runtime/Transporter","moxie/core/utils/Env","moxie/core/EventTarget","moxie/file/Blob","moxie/file/File","moxie/core/utils/Encode"],function(e,t,i,n,r,o,a,s,u,c,l,d,m){function h(){function n(e){try{return e||(e=this.exec("Image","getInfo")),this.size=e.size,this.width=e.width,this.height=e.height,this.type=e.type,this.meta=e.meta,""===this.name&&(this.name=e.name),!0}catch(t){return this.trigger("error",t.code),!1}}function c(t){var n=e.typeOf(t);try{if(t instanceof h){if(!t.size)throw new i.DOMException(i.DOMException.INVALID_STATE_ERR);p.apply(this,arguments)}else if(t instanceof l){if(!~e.inArray(t.type,["image/jpeg","image/png"]))throw new i.ImageError(i.ImageError.WRONG_FORMAT);g.apply(this,arguments)}else if(-1!==e.inArray(n,["blob","file"]))c.call(this,new d(null,t),arguments[1]);else if("string"===n)"data:"===t.substr(0,5)?c.call(this,new l(null,{data:t}),arguments[1]):x.apply(this,arguments);else{if("node"!==n||"img"!==t.nodeName.toLowerCase())throw new i.DOMException(i.DOMException.TYPE_MISMATCH_ERR);c.call(this,t.src,arguments[1])}}catch(r){this.trigger("error",r.code)}}function p(t,i){var n=this.connectRuntime(t.ruid);this.ruid=n.uid,n.exec.call(this,"Image","loadFromImage",t,"undefined"===e.typeOf(i)?!0:i)}function g(t,i){function n(e){r.ruid=e.uid,e.exec.call(r,"Image","loadFromBlob",t)}var r=this;r.name=t.name||"",t.isDetached()?(this.bind("RuntimeInit",function(e,t){n(t)}),i&&"string"==typeof i.required_caps&&(i.required_caps=o.parseCaps(i.required_caps)),this.connectRuntime(e.extend({required_caps:{access_image_binary:!0,resize_image:!0}},i))):n(this.connectRuntime(t.ruid))}function x(e,t){var i,n=this;i=new r,i.open("get",e),i.responseType="blob",i.onprogress=function(e){n.trigger(e)},i.onload=function(){g.call(n,i.response,!0)},i.onerror=function(e){n.trigger(e)},i.onloadend=function(){i.destroy()},i.bind("RuntimeError",function(e,t){n.trigger("RuntimeError",t)}),i.send(null,t)}a.call(this),e.extend(this,{uid:e.guid("uid_"),ruid:null,name:"",size:0,width:0,height:0,type:"",meta:{},clone:function(){this.load.apply(this,arguments)},load:function(){c.apply(this,arguments)},resize:function(t){var n,r,o=this,a={x:0,y:0,width:o.width,height:o.height},s=e.extendIf({width:o.width,height:o.height,type:o.type||"image/jpeg",quality:90,crop:!1,fit:!0,preserveHeaders:!0,resample:"default",multipass:!0},t);try{if(!o.size)throw new i.DOMException(i.DOMException.INVALID_STATE_ERR);if(o.width>h.MAX_RESIZE_WIDTH||o.height>h.MAX_RESIZE_HEIGHT)throw new i.ImageError(i.ImageError.MAX_RESOLUTION_ERR);if(n=o.meta&&o.meta.tiff&&o.meta.tiff.Orientation||1,-1!==e.inArray(n,[5,6,7,8])){var u=s.width;s.width=s.height,s.height=u}if(s.crop){switch(r=Math.max(s.width/o.width,s.height/o.height),t.fit?(a.width=Math.min(Math.ceil(s.width/r),o.width),a.height=Math.min(Math.ceil(s.height/r),o.height),r=s.width/a.width):(a.width=Math.min(s.width,o.width),a.height=Math.min(s.height,o.height),r=1),"boolean"==typeof s.crop&&(s.crop="cc"),s.crop.toLowerCase().replace(/_/,"-")){case"rb":case"right-bottom":a.x=o.width-a.width,a.y=o.height-a.height;break;case"cb":case"center-bottom":a.x=Math.floor((o.width-a.width)/2),a.y=o.height-a.height;break;case"lb":case"left-bottom":a.x=0,a.y=o.height-a.height;break;case"lt":case"left-top":a.x=0,a.y=0;break;case"ct":case"center-top":a.x=Math.floor((o.width-a.width)/2),a.y=0;break;case"rt":case"right-top":a.x=o.width-a.width,a.y=0;break;case"rc":case"right-center":case"right-middle":a.x=o.width-a.width,a.y=Math.floor((o.height-a.height)/2);break;case"lc":case"left-center":case"left-middle":a.x=0,a.y=Math.floor((o.height-a.height)/2);break;case"cc":case"center-center":case"center-middle":default:a.x=Math.floor((o.width-a.width)/2),a.y=Math.floor((o.height-a.height)/2)}a.x=Math.max(a.x,0),a.y=Math.max(a.y,0)}else r=Math.min(s.width/o.width,s.height/o.height),r>1&&!s.fit&&(r=1);this.exec("Image","resize",a,r,s)}catch(c){o.trigger("error",c.code)}},downsize:function(t){var i,n={width:this.width,height:this.height,type:this.type||"image/jpeg",quality:90,crop:!1,fit:!1,preserveHeaders:!0,resample:"default"};i="object"==typeof t?e.extend(n,t):e.extend(n,{width:arguments[0],height:arguments[1],crop:arguments[2],preserveHeaders:arguments[3]}),this.resize(i)},crop:function(e,t,i){this.downsize(e,t,!0,i)},getAsCanvas:function(){if(!u.can("create_canvas"))throw new i.RuntimeError(i.RuntimeError.NOT_SUPPORTED_ERR);return this.exec("Image","getAsCanvas")},getAsBlob:function(e,t){if(!this.size)throw new i.DOMException(i.DOMException.INVALID_STATE_ERR);return this.exec("Image","getAsBlob",e||"image/jpeg",t||90)},getAsDataURL:function(e,t){if(!this.size)throw new i.DOMException(i.DOMException.INVALID_STATE_ERR);return this.exec("Image","getAsDataURL",e||"image/jpeg",t||90)},getAsBinaryString:function(e,t){var i=this.getAsDataURL(e,t);return m.atob(i.substring(i.indexOf("base64,")+7))},embed:function(n,r){function o(t,r){var o=this;if(u.can("create_canvas")){var l=o.getAsCanvas();if(l)return n.appendChild(l),l=null,o.destroy(),c.trigger("embedded"),void 0}var d=o.getAsDataURL(t,r);if(!d)throw new i.ImageError(i.ImageError.WRONG_FORMAT);if(u.can("use_data_uri_of",d.length))n.innerHTML='<img src="'+d+'" width="'+o.width+'" height="'+o.height+'" alt="" />',o.destroy(),c.trigger("embedded");else{var h=new s;h.bind("TransportingComplete",function(){a=c.connectRuntime(this.result.ruid),c.bind("Embedded",function(){e.extend(a.getShimContainer().style,{top:"0px",left:"0px",width:o.width+"px",height:o.height+"px"}),a=null},999),a.exec.call(c,"ImageView","display",this.result.uid,width,height),o.destroy()}),h.transport(m.atob(d.substring(d.indexOf("base64,")+7)),t,{required_caps:{display_media:!0},runtime_order:"flash,silverlight",container:n})}}var a,c=this,l=e.extend({width:this.width,height:this.height,type:this.type||"image/jpeg",quality:90,fit:!0,resample:"nearest"},r);try{if(!(n=t.get(n)))throw new i.DOMException(i.DOMException.INVALID_NODE_TYPE_ERR);if(!this.size)throw new i.DOMException(i.DOMException.INVALID_STATE_ERR);this.width>h.MAX_RESIZE_WIDTH||this.height>h.MAX_RESIZE_HEIGHT;var d=new h;return d.bind("Resize",function(){o.call(this,l.type,l.quality)}),d.bind("Load",function(){this.downsize(l)}),this.meta.thumb&&this.meta.thumb.width>=l.width&&this.meta.thumb.height>=l.height?d.load(this.meta.thumb.data):d.clone(this,!1),d}catch(f){this.trigger("error",f.code)}},destroy:function(){this.ruid&&(this.getRuntime().exec.call(this,"Image","destroy"),this.disconnectRuntime()),this.meta&&this.meta.thumb&&this.meta.thumb.data.destroy(),this.unbindAll()}}),this.handleEventProps(f),this.bind("Load Resize",function(){return n.call(this)},999)}var f=["progress","load","error","resize","embedded"];return h.MAX_RESIZE_WIDTH=8192,h.MAX_RESIZE_HEIGHT=8192,h.prototype=c.instance,h}),n("moxie/runtime/html5/Runtime",["moxie/core/utils/Basic","moxie/core/Exceptions","moxie/runtime/Runtime","moxie/core/utils/Env"],function(e,t,i,n){function o(t){var o=this,u=i.capTest,c=i.capTrue,l=e.extend({access_binary:u(window.FileReader||window.File&&window.File.getAsDataURL),access_image_binary:function(){return o.can("access_binary")&&!!s.Image},display_media:u((n.can("create_canvas")||n.can("use_data_uri_over32kb"))&&r("moxie/image/Image")),do_cors:u(window.XMLHttpRequest&&"withCredentials"in new XMLHttpRequest),drag_and_drop:u(function(){var e=document.createElement("div");return("draggable"in e||"ondragstart"in e&&"ondrop"in e)&&("IE"!==n.browser||n.verComp(n.version,9,">"))}()),filter_by_extension:u(function(){return!("Chrome"===n.browser&&n.verComp(n.version,28,"<")||"IE"===n.browser&&n.verComp(n.version,10,"<")||"Safari"===n.browser&&n.verComp(n.version,7,"<")||"Firefox"===n.browser&&n.verComp(n.version,37,"<"))}()),return_response_headers:c,return_response_type:function(e){return"json"===e&&window.JSON?!0:n.can("return_response_type",e)},return_status_code:c,report_upload_progress:u(window.XMLHttpRequest&&(new XMLHttpRequest).upload),resize_image:function(){return o.can("access_binary")&&n.can("create_canvas")},select_file:function(){return n.can("use_fileinput")&&window.File},select_folder:function(){return o.can("select_file")&&("Chrome"===n.browser&&n.verComp(n.version,21,">=")||"Firefox"===n.browser&&n.verComp(n.version,42,">="))},select_multiple:function(){return!(!o.can("select_file")||"Safari"===n.browser&&"Windows"===n.os||"iOS"===n.os&&n.verComp(n.osVersion,"7.0.0",">")&&n.verComp(n.osVersion,"8.0.0","<"))},send_binary_string:u(window.XMLHttpRequest&&((new XMLHttpRequest).sendAsBinary||window.Uint8Array&&window.ArrayBuffer)),send_custom_headers:u(window.XMLHttpRequest),send_multipart:function(){return!!(window.XMLHttpRequest&&(new XMLHttpRequest).upload&&window.FormData)||o.can("send_binary_string")},slice_blob:u(window.File&&(File.prototype.mozSlice||File.prototype.webkitSlice||File.prototype.slice)),stream_upload:function(){return o.can("slice_blob")&&o.can("send_multipart")},summon_file_dialog:function(){return o.can("select_file")&&!("Firefox"===n.browser&&n.verComp(n.version,4,"<")||"Opera"===n.browser&&n.verComp(n.version,12,"<")||"IE"===n.browser&&n.verComp(n.version,10,"<"))},upload_filesize:c,use_http_method:c},arguments[2]);i.call(this,t,arguments[1]||a,l),e.extend(this,{init:function(){this.trigger("Init")},destroy:function(e){return function(){e.call(o),e=o=null}}(this.destroy)}),e.extend(this.getShim(),s)}var a="html5",s={};return i.addConstructor(a,o),s}),n("moxie/runtime/html5/file/Blob",["moxie/runtime/html5/Runtime","moxie/file/Blob"],function(e,t){function i(){function e(e,t,i){var n;if(!window.File.prototype.slice)return(n=window.File.prototype.webkitSlice||window.File.prototype.mozSlice)?n.call(e,t,i):null;try{return e.slice(),e.slice(t,i)}catch(r){return e.slice(t,i-t)}}this.slice=function(){return new t(this.getRuntime().uid,e.apply(this,arguments))},this.destroy=function(){this.getRuntime().getShim().removeInstance(this.uid)}}return e.Blob=i}),n("moxie/core/utils/Events",["moxie/core/utils/Basic"],function(e){function t(){this.returnValue=!1}function i(){this.cancelBubble=!0}var n={},r="moxie_"+e.guid(),o=function(o,a,s,u){var c,l;a=a.toLowerCase(),o.addEventListener?(c=s,o.addEventListener(a,c,!1)):o.attachEvent&&(c=function(){var e=window.event;e.target||(e.target=e.srcElement),e.preventDefault=t,e.stopPropagation=i,s(e)},o.attachEvent("on"+a,c)),o[r]||(o[r]=e.guid()),n.hasOwnProperty(o[r])||(n[o[r]]={}),l=n[o[r]],l.hasOwnProperty(a)||(l[a]=[]),l[a].push({func:c,orig:s,key:u})},a=function(t,i,o){var a,s;if(i=i.toLowerCase(),t[r]&&n[t[r]]&&n[t[r]][i]){a=n[t[r]][i];for(var u=a.length-1;u>=0&&(a[u].orig!==o&&a[u].key!==o||(t.removeEventListener?t.removeEventListener(i,a[u].func,!1):t.detachEvent&&t.detachEvent("on"+i,a[u].func),a[u].orig=null,a[u].func=null,a.splice(u,1),o===s));u--);if(a.length||delete n[t[r]][i],e.isEmptyObj(n[t[r]])){delete n[t[r]];try{delete t[r]}catch(c){t[r]=s}}}},s=function(t,i){t&&t[r]&&e.each(n[t[r]],function(e,n){a(t,n,i)})};return{addEvent:o,removeEvent:a,removeAllEvents:s}}),n("moxie/runtime/html5/file/FileInput",["moxie/runtime/html5/Runtime","moxie/file/File","moxie/core/utils/Basic","moxie/core/utils/Dom","moxie/core/utils/Events","moxie/core/utils/Mime","moxie/core/utils/Env"],function(e,t,i,n,r,o,a){function s(){var e,s;i.extend(this,{init:function(u){var c,l,d,m,h,f,p=this,g=p.getRuntime();e=u,d=o.extList2mimes(e.accept,g.can("filter_by_extension")),l=g.getShimContainer(),l.innerHTML='<input id="'+g.uid+'" type="file" style="font-size:999px;opacity:0;"'+(e.multiple&&g.can("select_multiple")?"multiple":"")+(e.directory&&g.can("select_folder")?"webkitdirectory directory":"")+(d?' accept="'+d.join(",")+'"':"")+" />",c=n.get(g.uid),i.extend(c.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),m=n.get(e.browse_button),s=n.getStyle(m,"z-index")||"auto",g.can("summon_file_dialog")&&("static"===n.getStyle(m,"position")&&(m.style.position="relative"),r.addEvent(m,"click",function(e){var t=n.get(g.uid);t&&!t.disabled&&t.click(),e.preventDefault()},p.uid),p.bind("Refresh",function(){h=parseInt(s,10)||1,n.get(e.browse_button).style.zIndex=h,this.getRuntime().getShimContainer().style.zIndex=h-1})),f=g.can("summon_file_dialog")?m:l,r.addEvent(f,"mouseover",function(){p.trigger("mouseenter")},p.uid),r.addEvent(f,"mouseout",function(){p.trigger("mouseleave")},p.uid),r.addEvent(f,"mousedown",function(){p.trigger("mousedown")},p.uid),r.addEvent(n.get(e.container),"mouseup",function(){p.trigger("mouseup")},p.uid),(g.can("summon_file_dialog")?c:m).setAttribute("tabindex",-1),c.onchange=function x(){if(p.files=[],i.each(this.files,function(i){var n="";return e.directory&&"."==i.name?!0:(i.webkitRelativePath&&(n="/"+i.webkitRelativePath.replace(/^\//,"")),i=new t(g.uid,i),i.relativePath=n,p.files.push(i),void 0)}),"IE"!==a.browser&&"IEMobile"!==a.browser)this.value="";else{var n=this.cloneNode(!0);this.parentNode.replaceChild(n,this),n.onchange=x}p.files.length&&p.trigger("change")},p.trigger({type:"ready",async:!0}),l=null},setOption:function(e,t){var i=this.getRuntime(),r=n.get(i.uid);switch(e){case"accept":if(t){var a=t.mimes||o.extList2mimes(t,i.can("filter_by_extension"));r.setAttribute("accept",a.join(","))}else r.removeAttribute("accept");break;case"directory":t&&i.can("select_folder")?(r.setAttribute("directory",""),r.setAttribute("webkitdirectory","")):(r.removeAttribute("directory"),r.removeAttribute("webkitdirectory"));break;case"multiple":t&&i.can("select_multiple")?r.setAttribute("multiple",""):r.removeAttribute("multiple")}},disable:function(e){var t,i=this.getRuntime();(t=n.get(i.uid))&&(t.disabled=!!e)},destroy:function(){var t=this.getRuntime(),i=t.getShim(),o=t.getShimContainer(),a=e&&n.get(e.container),u=e&&n.get(e.browse_button);a&&r.removeAllEvents(a,this.uid),u&&(r.removeAllEvents(u,this.uid),u.style.zIndex=s),o&&(r.removeAllEvents(o,this.uid),o.innerHTML=""),i.removeInstance(this.uid),e=o=a=u=i=null}})}return e.FileInput=s}),n("moxie/runtime/html5/file/FileDrop",["moxie/runtime/html5/Runtime","moxie/file/File","moxie/core/utils/Basic","moxie/core/utils/Dom","moxie/core/utils/Events","moxie/core/utils/Mime"],function(e,t,i,n,r,o){function a(){function e(e){if(!e.dataTransfer||!e.dataTransfer.types)return!1;var t=i.toArray(e.dataTransfer.types||[]);return-1!==i.inArray("Files",t)||-1!==i.inArray("public.file-url",t)||-1!==i.inArray("application/x-moz-file",t)}function a(e,i){if(u(e)){var n=new t(f,e);n.relativePath=i||"",p.push(n)}}function s(e){for(var t=[],n=0;n<e.length;n++)[].push.apply(t,e[n].extensions.split(/\s*,\s*/));return-1===i.inArray("*",t)?t:[]}function u(e){if(!g.length)return!0;var t=o.getFileExtension(e.name);return!t||-1!==i.inArray(t,g)}function c(e,t){var n=[];i.each(e,function(e){var t=e.webkitGetAsEntry();t&&(t.isFile?a(e.getAsFile(),t.fullPath):n.push(t))}),n.length?l(n,t):t()}function l(e,t){var n=[];i.each(e,function(e){n.push(function(t){d(e,t)})}),i.inSeries(n,function(){t()})}function d(e,t){e.isFile?e.file(function(i){a(i,e.fullPath),t()},function(){t()}):e.isDirectory?m(e,t):t()}function m(e,t){function i(e){r.readEntries(function(t){t.length?([].push.apply(n,t),i(e)):e()},e)}var n=[],r=e.createReader();i(function(){l(n,t)})}var h,f,p=[],g=[];i.extend(this,{init:function(t){var n,o=this;h=t,f=o.ruid,g=s(h.accept),n=h.container,r.addEvent(n,"dragover",function(t){e(t)&&(t.preventDefault(),t.dataTransfer.dropEffect="copy")},o.uid),r.addEvent(n,"drop",function(t){e(t)&&(t.preventDefault(),p=[],t.dataTransfer.items&&t.dataTransfer.items[0].webkitGetAsEntry?c(t.dataTransfer.items,function(){o.files=p,o.trigger("drop")}):(i.each(t.dataTransfer.files,function(e){a(e)}),o.files=p,o.trigger("drop")))},o.uid),r.addEvent(n,"dragenter",function(){o.trigger("dragenter")},o.uid),r.addEvent(n,"dragleave",function(){o.trigger("dragleave")},o.uid)},destroy:function(){r.removeAllEvents(h&&n.get(h.container),this.uid),f=p=g=h=null,this.getRuntime().getShim().removeInstance(this.uid)}})}return e.FileDrop=a}),n("moxie/runtime/html5/file/FileReader",["moxie/runtime/html5/Runtime","moxie/core/utils/Encode","moxie/core/utils/Basic"],function(e,t,i){function n(){function e(e){return t.atob(e.substring(e.indexOf("base64,")+7))}var n,r=!1;i.extend(this,{read:function(t,o){var a=this;a.result="",n=new window.FileReader,n.addEventListener("progress",function(e){a.trigger(e)}),n.addEventListener("load",function(t){a.result=r?e(n.result):n.result,a.trigger(t)}),n.addEventListener("error",function(e){a.trigger(e,n.error)}),n.addEventListener("loadend",function(e){n=null,a.trigger(e)}),"function"===i.typeOf(n[t])?(r=!1,n[t](o.getSource())):"readAsBinaryString"===t&&(r=!0,n.readAsDataURL(o.getSource()))},abort:function(){n&&n.abort()},destroy:function(){n=null,this.getRuntime().getShim().removeInstance(this.uid)}})}return e.FileReader=n}),n("moxie/runtime/html5/xhr/XMLHttpRequest",["moxie/runtime/html5/Runtime","moxie/core/utils/Basic","moxie/core/utils/Mime","moxie/core/utils/Url","moxie/file/File","moxie/file/Blob","moxie/xhr/FormData","moxie/core/Exceptions","moxie/core/utils/Env"],function(e,t,i,n,r,o,a,s,u){function c(){function e(e,t){var i,n,r=this;i=t.getBlob().getSource(),n=new window.FileReader,n.onload=function(){t.append(t.getBlobName(),new o(null,{type:i.type,data:n.result})),f.send.call(r,e,t)},n.readAsBinaryString(i)}function c(){return!window.XMLHttpRequest||"IE"===u.browser&&u.verComp(u.version,8,"<")?function(){for(var e=["Msxml2.XMLHTTP.6.0","Microsoft.XMLHTTP"],t=0;t<e.length;t++)try{return new ActiveXObject(e[t])}catch(i){}}():new window.XMLHttpRequest}function l(e){var t=e.responseXML,i=e.responseText;return"IE"===u.browser&&i&&t&&!t.documentElement&&/[^\/]+\/[^\+]+\+xml/.test(e.getResponseHeader("Content-Type"))&&(t=new window.ActiveXObject("Microsoft.XMLDOM"),t.async=!1,t.validateOnParse=!1,t.loadXML(i)),t&&("IE"===u.browser&&0!==t.parseError||!t.documentElement||"parsererror"===t.documentElement.tagName)?null:t +}function d(e){var t="----moxieboundary"+(new Date).getTime(),i="--",n="\r\n",r="",a=this.getRuntime();if(!a.can("send_binary_string"))throw new s.RuntimeError(s.RuntimeError.NOT_SUPPORTED_ERR);return m.setRequestHeader("Content-Type","multipart/form-data; boundary="+t),e.each(function(e,a){r+=e instanceof o?i+t+n+'Content-Disposition: form-data; name="'+a+'"; filename="'+unescape(encodeURIComponent(e.name||"blob"))+'"'+n+"Content-Type: "+(e.type||"application/octet-stream")+n+n+e.getSource()+n:i+t+n+'Content-Disposition: form-data; name="'+a+'"'+n+n+unescape(encodeURIComponent(e))+n}),r+=i+t+i+n}var m,h,f=this;t.extend(this,{send:function(i,r){var s=this,l="Mozilla"===u.browser&&u.verComp(u.version,4,">=")&&u.verComp(u.version,7,"<"),f="Android Browser"===u.browser,p=!1;if(h=i.url.replace(/^.+?\/([\w\-\.]+)$/,"$1").toLowerCase(),m=c(),m.open(i.method,i.url,i.async,i.user,i.password),r instanceof o)r.isDetached()&&(p=!0),r=r.getSource();else if(r instanceof a){if(r.hasBlob())if(r.getBlob().isDetached())r=d.call(s,r),p=!0;else if((l||f)&&"blob"===t.typeOf(r.getBlob().getSource())&&window.FileReader)return e.call(s,i,r),void 0;if(r instanceof a){var g=new window.FormData;r.each(function(e,t){e instanceof o?g.append(t,e.getSource()):g.append(t,e)}),r=g}}m.upload?(i.withCredentials&&(m.withCredentials=!0),m.addEventListener("load",function(e){s.trigger(e)}),m.addEventListener("error",function(e){s.trigger(e)}),m.addEventListener("progress",function(e){s.trigger(e)}),m.upload.addEventListener("progress",function(e){s.trigger({type:"UploadProgress",loaded:e.loaded,total:e.total})})):m.onreadystatechange=function(){switch(m.readyState){case 1:break;case 2:break;case 3:var e,t;try{n.hasSameOrigin(i.url)&&(e=m.getResponseHeader("Content-Length")||0),m.responseText&&(t=m.responseText.length)}catch(r){e=t=0}s.trigger({type:"progress",lengthComputable:!!e,total:parseInt(e,10),loaded:t});break;case 4:m.onreadystatechange=function(){};try{if(m.status>=200&&m.status<400){s.trigger("load");break}}catch(r){}s.trigger("error")}},t.isEmptyObj(i.headers)||t.each(i.headers,function(e,t){m.setRequestHeader(t,e)}),""!==i.responseType&&"responseType"in m&&(m.responseType="json"!==i.responseType||u.can("return_response_type","json")?i.responseType:"text"),p?m.sendAsBinary?m.sendAsBinary(r):function(){for(var e=new Uint8Array(r.length),t=0;t<r.length;t++)e[t]=255&r.charCodeAt(t);m.send(e.buffer)}():m.send(r),s.trigger("loadstart")},getStatus:function(){try{if(m)return m.status}catch(e){}return 0},getResponse:function(e){var t=this.getRuntime();try{switch(e){case"blob":var n=new r(t.uid,m.response),o=m.getResponseHeader("Content-Disposition");if(o){var a=o.match(/filename=([\'\"'])([^\1]+)\1/);a&&(h=a[2])}return n.name=h,n.type||(n.type=i.getFileMime(h)),n;case"json":return u.can("return_response_type","json")?m.response:200===m.status&&window.JSON?JSON.parse(m.responseText):null;case"document":return l(m);default:return""!==m.responseText?m.responseText:null}}catch(s){return null}},getAllResponseHeaders:function(){try{return m.getAllResponseHeaders()}catch(e){}return""},abort:function(){m&&m.abort()},destroy:function(){f=h=null,this.getRuntime().getShim().removeInstance(this.uid)}})}return e.XMLHttpRequest=c}),n("moxie/runtime/html5/utils/BinaryReader",["moxie/core/utils/Basic"],function(e){function t(e){e instanceof ArrayBuffer?i.apply(this,arguments):n.apply(this,arguments)}function i(t){var i=new DataView(t);e.extend(this,{readByteAt:function(e){return i.getUint8(e)},writeByteAt:function(e,t){i.setUint8(e,t)},SEGMENT:function(e,n,r){switch(arguments.length){case 2:return t.slice(e,e+n);case 1:return t.slice(e);case 3:if(null===r&&(r=new ArrayBuffer),r instanceof ArrayBuffer){var o=new Uint8Array(this.length()-n+r.byteLength);e>0&&o.set(new Uint8Array(t.slice(0,e)),0),o.set(new Uint8Array(r),e),o.set(new Uint8Array(t.slice(e+n)),e+r.byteLength),this.clear(),t=o.buffer,i=new DataView(t);break}default:return t}},length:function(){return t?t.byteLength:0},clear:function(){i=t=null}})}function n(t){function i(e,i,n){n=3===arguments.length?n:t.length-i-1,t=t.substr(0,i)+e+t.substr(n+i)}e.extend(this,{readByteAt:function(e){return t.charCodeAt(e)},writeByteAt:function(e,t){i(String.fromCharCode(t),e,1)},SEGMENT:function(e,n,r){switch(arguments.length){case 1:return t.substr(e);case 2:return t.substr(e,n);case 3:i(null!==r?r:"",e,n);break;default:return t}},length:function(){return t?t.length:0},clear:function(){t=null}})}return e.extend(t.prototype,{littleEndian:!1,read:function(e,t){var i,n,r;if(e+t>this.length())throw new Error("You are trying to read outside the source boundaries.");for(n=this.littleEndian?0:-8*(t-1),r=0,i=0;t>r;r++)i|=this.readByteAt(e+r)<<Math.abs(n+8*r);return i},write:function(e,t,i){var n,r;if(e>this.length())throw new Error("You are trying to write outside the source boundaries.");for(n=this.littleEndian?0:-8*(i-1),r=0;i>r;r++)this.writeByteAt(e+r,255&t>>Math.abs(n+8*r))},BYTE:function(e){return this.read(e,1)},SHORT:function(e){return this.read(e,2)},LONG:function(e){return this.read(e,4)},SLONG:function(e){var t=this.read(e,4);return t>2147483647?t-4294967296:t},CHAR:function(e){return String.fromCharCode(this.read(e,1))},STRING:function(e,t){return this.asArray("CHAR",e,t).join("")},asArray:function(e,t,i){for(var n=[],r=0;i>r;r++)n[r]=this[e](t+r);return n}}),t}),n("moxie/runtime/html5/image/JPEGHeaders",["moxie/runtime/html5/utils/BinaryReader","moxie/core/Exceptions"],function(e,t){return function i(n){var r,o,a,s=[],u=0;if(r=new e(n),65496!==r.SHORT(0))throw r.clear(),new t.ImageError(t.ImageError.WRONG_FORMAT);for(o=2;o<=r.length();)if(a=r.SHORT(o),a>=65488&&65495>=a)o+=2;else{if(65498===a||65497===a)break;u=r.SHORT(o+2)+2,a>=65505&&65519>=a&&s.push({hex:a,name:"APP"+(15&a),start:o,length:u,segment:r.SEGMENT(o,u)}),o+=u}return r.clear(),{headers:s,restore:function(t){var i,n,r;for(r=new e(t),o=65504==r.SHORT(2)?4+r.SHORT(4):2,n=0,i=s.length;i>n;n++)r.SEGMENT(o,0,s[n].segment),o+=s[n].length;return t=r.SEGMENT(),r.clear(),t},strip:function(t){var n,r,o,a;for(o=new i(t),r=o.headers,o.purge(),n=new e(t),a=r.length;a--;)n.SEGMENT(r[a].start,r[a].length,"");return t=n.SEGMENT(),n.clear(),t},get:function(e){for(var t=[],i=0,n=s.length;n>i;i++)s[i].name===e.toUpperCase()&&t.push(s[i].segment);return t},set:function(e,t){var i,n,r,o=[];for("string"==typeof t?o.push(t):o=t,i=n=0,r=s.length;r>i&&(s[i].name===e.toUpperCase()&&(s[i].segment=o[n],s[i].length=o[n].length,n++),!(n>=o.length));i++);},purge:function(){this.headers=s=[]}}}}),n("moxie/runtime/html5/image/ExifParser",["moxie/core/utils/Basic","moxie/runtime/html5/utils/BinaryReader","moxie/core/Exceptions"],function(e,i,n){function r(o){function a(i,r){var o,a,s,u,c,m,h,f,p=this,g=[],x={},v={1:"BYTE",7:"UNDEFINED",2:"ASCII",3:"SHORT",4:"LONG",5:"RATIONAL",9:"SLONG",10:"SRATIONAL"},w={BYTE:1,UNDEFINED:1,ASCII:1,SHORT:2,LONG:4,RATIONAL:8,SLONG:4,SRATIONAL:8};for(o=p.SHORT(i),a=0;o>a;a++)if(g=[],h=i+2+12*a,s=r[p.SHORT(h)],s!==t){if(u=v[p.SHORT(h+=2)],c=p.LONG(h+=2),m=w[u],!m)throw new n.ImageError(n.ImageError.INVALID_META_ERR);if(h+=4,m*c>4&&(h=p.LONG(h)+d.tiffHeader),h+m*c>=this.length())throw new n.ImageError(n.ImageError.INVALID_META_ERR);"ASCII"!==u?(g=p.asArray(u,h,c),f=1==c?g[0]:g,x[s]=l.hasOwnProperty(s)&&"object"!=typeof f?l[s][f]:f):x[s]=e.trim(p.STRING(h,c).replace(/\0$/,""))}return x}function s(e,t,i){var n,r,o,a=0;if("string"==typeof t){var s=c[e.toLowerCase()];for(var u in s)if(s[u]===t){t=u;break}}n=d[e.toLowerCase()+"IFD"],r=this.SHORT(n);for(var l=0;r>l;l++)if(o=n+12*l+2,this.SHORT(o)==t){a=o+8;break}if(!a)return!1;try{this.write(a,i,4)}catch(m){return!1}return!0}var u,c,l,d,m,h;if(i.call(this,o),c={tiff:{274:"Orientation",270:"ImageDescription",271:"Make",272:"Model",305:"Software",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer"},exif:{36864:"ExifVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",36867:"DateTimeOriginal",33434:"ExposureTime",33437:"FNumber",34855:"ISOSpeedRatings",37377:"ShutterSpeedValue",37378:"ApertureValue",37383:"MeteringMode",37384:"LightSource",37385:"Flash",37386:"FocalLength",41986:"ExposureMode",41987:"WhiteBalance",41990:"SceneCaptureType",41988:"DigitalZoomRatio",41992:"Contrast",41993:"Saturation",41994:"Sharpness"},gps:{0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude"},thumb:{513:"JPEGInterchangeFormat",514:"JPEGInterchangeFormatLength"}},l={ColorSpace:{1:"sRGB",0:"Uncalibrated"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{1:"Daylight",2:"Fliorescent",3:"Tungsten",4:"Flash",9:"Fine weather",10:"Cloudy weather",11:"Shade",12:"Daylight fluorescent (D 5700 - 7100K)",13:"Day white fluorescent (N 4600 -5400K)",14:"Cool white fluorescent (W 3900 - 4500K)",15:"White fluorescent (WW 3200 - 3700K)",17:"Standard light A",18:"Standard light B",19:"Standard light C",20:"D55",21:"D65",22:"D75",23:"D50",24:"ISO studio tungsten",255:"Other"},Flash:{0:"Flash did not fire",1:"Flash fired",5:"Strobe return light not detected",7:"Strobe return light detected",9:"Flash fired, compulsory flash mode",13:"Flash fired, compulsory flash mode, return light not detected",15:"Flash fired, compulsory flash mode, return light detected",16:"Flash did not fire, compulsory flash mode",24:"Flash did not fire, auto mode",25:"Flash fired, auto mode",29:"Flash fired, auto mode, return light not detected",31:"Flash fired, auto mode, return light detected",32:"No flash function",65:"Flash fired, red-eye reduction mode",69:"Flash fired, red-eye reduction mode, return light not detected",71:"Flash fired, red-eye reduction mode, return light detected",73:"Flash fired, compulsory flash mode, red-eye reduction mode",77:"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",79:"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",89:"Flash fired, auto mode, red-eye reduction mode",93:"Flash fired, auto mode, return light not detected, red-eye reduction mode",95:"Flash fired, auto mode, return light detected, red-eye reduction mode"},ExposureMode:{0:"Auto exposure",1:"Manual exposure",2:"Auto bracket"},WhiteBalance:{0:"Auto white balance",1:"Manual white balance"},SceneCaptureType:{0:"Standard",1:"Landscape",2:"Portrait",3:"Night scene"},Contrast:{0:"Normal",1:"Soft",2:"Hard"},Saturation:{0:"Normal",1:"Low saturation",2:"High saturation"},Sharpness:{0:"Normal",1:"Soft",2:"Hard"},GPSLatitudeRef:{N:"North latitude",S:"South latitude"},GPSLongitudeRef:{E:"East longitude",W:"West longitude"}},d={tiffHeader:10},m=d.tiffHeader,u={clear:this.clear},e.extend(this,{read:function(){try{return r.prototype.read.apply(this,arguments)}catch(e){throw new n.ImageError(n.ImageError.INVALID_META_ERR)}},write:function(){try{return r.prototype.write.apply(this,arguments)}catch(e){throw new n.ImageError(n.ImageError.INVALID_META_ERR)}},UNDEFINED:function(){return this.BYTE.apply(this,arguments)},RATIONAL:function(e){return this.LONG(e)/this.LONG(e+4)},SRATIONAL:function(e){return this.SLONG(e)/this.SLONG(e+4)},ASCII:function(e){return this.CHAR(e)},TIFF:function(){return h||null},EXIF:function(){var t=null;if(d.exifIFD){try{t=a.call(this,d.exifIFD,c.exif)}catch(i){return null}if(t.ExifVersion&&"array"===e.typeOf(t.ExifVersion)){for(var n=0,r="";n<t.ExifVersion.length;n++)r+=String.fromCharCode(t.ExifVersion[n]);t.ExifVersion=r}}return t},GPS:function(){var t=null;if(d.gpsIFD){try{t=a.call(this,d.gpsIFD,c.gps)}catch(i){return null}t.GPSVersionID&&"array"===e.typeOf(t.GPSVersionID)&&(t.GPSVersionID=t.GPSVersionID.join("."))}return t},thumb:function(){if(d.IFD1)try{var e=a.call(this,d.IFD1,c.thumb);if("JPEGInterchangeFormat"in e)return this.SEGMENT(d.tiffHeader+e.JPEGInterchangeFormat,e.JPEGInterchangeFormatLength)}catch(t){}return null},setExif:function(e,t){return"PixelXDimension"!==e&&"PixelYDimension"!==e?!1:s.call(this,"exif",e,t)},clear:function(){u.clear(),o=c=l=h=d=u=null}}),65505!==this.SHORT(0)||"EXIF\0"!==this.STRING(4,5).toUpperCase())throw new n.ImageError(n.ImageError.INVALID_META_ERR);if(this.littleEndian=18761==this.SHORT(m),42!==this.SHORT(m+=2))throw new n.ImageError(n.ImageError.INVALID_META_ERR);d.IFD0=d.tiffHeader+this.LONG(m+=2),h=a.call(this,d.IFD0,c.tiff),"ExifIFDPointer"in h&&(d.exifIFD=d.tiffHeader+h.ExifIFDPointer,delete h.ExifIFDPointer),"GPSInfoIFDPointer"in h&&(d.gpsIFD=d.tiffHeader+h.GPSInfoIFDPointer,delete h.GPSInfoIFDPointer),e.isEmptyObj(h)&&(h=null);var f=this.LONG(d.IFD0+12*this.SHORT(d.IFD0)+2);f&&(d.IFD1=d.tiffHeader+f)}return r.prototype=i.prototype,r}),n("moxie/runtime/html5/image/JPEG",["moxie/core/utils/Basic","moxie/core/Exceptions","moxie/runtime/html5/image/JPEGHeaders","moxie/runtime/html5/utils/BinaryReader","moxie/runtime/html5/image/ExifParser"],function(e,t,i,n,r){function o(o){function a(e){var t,i,n=0;for(e||(e=c);n<=e.length();){if(t=e.SHORT(n+=2),t>=65472&&65475>=t)return n+=5,{height:e.SHORT(n),width:e.SHORT(n+=2)};i=e.SHORT(n+=2),n+=i-2}return null}function s(){var e,t,i=d.thumb();return i&&(e=new n(i),t=a(e),e.clear(),t)?(t.data=i,t):null}function u(){d&&l&&c&&(d.clear(),l.purge(),c.clear(),m=l=d=c=null)}var c,l,d,m;if(c=new n(o),65496!==c.SHORT(0))throw new t.ImageError(t.ImageError.WRONG_FORMAT);l=new i(o);try{d=new r(l.get("app1")[0])}catch(h){}m=a.call(this),e.extend(this,{type:"image/jpeg",size:c.length(),width:m&&m.width||0,height:m&&m.height||0,setExif:function(t,i){return d?("object"===e.typeOf(t)?e.each(t,function(e,t){d.setExif(t,e)}):d.setExif(t,i),l.set("app1",d.SEGMENT()),void 0):!1},writeHeaders:function(){return arguments.length?l.restore(arguments[0]):l.restore(o)},stripHeaders:function(e){return l.strip(e)},purge:function(){u.call(this)}}),d&&(this.meta={tiff:d.TIFF(),exif:d.EXIF(),gps:d.GPS(),thumb:s()})}return o}),n("moxie/runtime/html5/image/PNG",["moxie/core/Exceptions","moxie/core/utils/Basic","moxie/runtime/html5/utils/BinaryReader"],function(e,t,i){function n(n){function r(){var e,t;return e=a.call(this,8),"IHDR"==e.type?(t=e.start,{width:s.LONG(t),height:s.LONG(t+=4)}):null}function o(){s&&(s.clear(),n=l=u=c=s=null)}function a(e){var t,i,n,r;return t=s.LONG(e),i=s.STRING(e+=4,4),n=e+=4,r=s.LONG(e+t),{length:t,type:i,start:n,CRC:r}}var s,u,c,l;s=new i(n),function(){var t=0,i=0,n=[35152,20039,3338,6666];for(i=0;i<n.length;i++,t+=2)if(n[i]!=s.SHORT(t))throw new e.ImageError(e.ImageError.WRONG_FORMAT)}(),l=r.call(this),t.extend(this,{type:"image/png",size:s.length(),width:l.width,height:l.height,purge:function(){o.call(this)}}),o.call(this)}return n}),n("moxie/runtime/html5/image/ImageInfo",["moxie/core/utils/Basic","moxie/core/Exceptions","moxie/runtime/html5/image/JPEG","moxie/runtime/html5/image/PNG"],function(e,t,i,n){return function(r){var o,a=[i,n];o=function(){for(var e=0;e<a.length;e++)try{return new a[e](r)}catch(i){}throw new t.ImageError(t.ImageError.WRONG_FORMAT)}(),e.extend(this,{type:"",size:0,width:0,height:0,setExif:function(){},writeHeaders:function(e){return e},stripHeaders:function(e){return e},purge:function(){r=null}}),e.extend(this,o),this.purge=function(){o.purge(),o=null}}}),n("moxie/runtime/html5/image/ResizerCanvas",[],function(){function e(i,n,r){var o=i.width>i.height?"width":"height",a=Math.round(i[o]*n),s=!1;"nearest"!==r&&(.5>n||n>2)&&(n=.5>n?.5:2,s=!0);var u=t(i,n);return s?e(u,a/u[o],r):u}function t(e,t){var i=e.width,n=e.height,r=Math.round(i*t),o=Math.round(n*t),a=document.createElement("canvas");return a.width=r,a.height=o,a.getContext("2d").drawImage(e,0,0,i,n,0,0,r,o),e=null,a}return{scale:e}}),n("moxie/runtime/html5/image/Image",["moxie/runtime/html5/Runtime","moxie/core/utils/Basic","moxie/core/Exceptions","moxie/core/utils/Encode","moxie/file/Blob","moxie/file/File","moxie/runtime/html5/image/ImageInfo","moxie/runtime/html5/image/ResizerCanvas","moxie/core/utils/Mime","moxie/core/utils/Env"],function(e,t,i,n,r,o,a,s,u){function c(){function e(){if(!v&&!g)throw new i.ImageError(i.DOMException.INVALID_STATE_ERR);return v||g}function c(){var t=e();return"canvas"==t.nodeName.toLowerCase()?t:(v=document.createElement("canvas"),v.width=t.width,v.height=t.height,v.getContext("2d").drawImage(t,0,0),v)}function l(e){return n.atob(e.substring(e.indexOf("base64,")+7))}function d(e,t){return"data:"+(t||"")+";base64,"+n.btoa(e)}function m(e){var t=this;g=new Image,g.onerror=function(){p.call(this),t.trigger("error",i.ImageError.WRONG_FORMAT)},g.onload=function(){t.trigger("load")},g.src="data:"==e.substr(0,5)?e:d(e,y.type)}function h(e,t){var n,r=this;return window.FileReader?(n=new FileReader,n.onload=function(){t.call(r,this.result)},n.onerror=function(){r.trigger("error",i.ImageError.WRONG_FORMAT)},n.readAsDataURL(e),void 0):t.call(this,e.getAsDataURL())}function f(e,i){var n=Math.PI/180,r=document.createElement("canvas"),o=r.getContext("2d"),a=e.width,s=e.height;switch(t.inArray(i,[5,6,7,8])>-1?(r.width=s,r.height=a):(r.width=a,r.height=s),i){case 2:o.translate(a,0),o.scale(-1,1);break;case 3:o.translate(a,s),o.rotate(180*n);break;case 4:o.translate(0,s),o.scale(1,-1);break;case 5:o.rotate(90*n),o.scale(1,-1);break;case 6:o.rotate(90*n),o.translate(0,-s);break;case 7:o.rotate(90*n),o.translate(a,-s),o.scale(-1,1);break;case 8:o.rotate(-90*n),o.translate(-a,0)}return o.drawImage(e,0,0,a,s),r}function p(){x&&(x.purge(),x=null),w=g=v=y=null,b=!1}var g,x,v,w,y,E=this,b=!1,_=!0;t.extend(this,{loadFromBlob:function(e){var t=this.getRuntime(),n=arguments.length>1?arguments[1]:!0;if(!t.can("access_binary"))throw new i.RuntimeError(i.RuntimeError.NOT_SUPPORTED_ERR);return y=e,e.isDetached()?(w=e.getSource(),m.call(this,w),void 0):(h.call(this,e.getSource(),function(e){n&&(w=l(e)),m.call(this,e)}),void 0)},loadFromImage:function(e,t){this.meta=e.meta,y=new o(null,{name:e.name,size:e.size,type:e.type}),m.call(this,t?w=e.getAsBinaryString():e.getAsDataURL())},getInfo:function(){var t,i=this.getRuntime();return!x&&w&&i.can("access_image_binary")&&(x=new a(w)),t={width:e().width||0,height:e().height||0,type:y.type||u.getFileMime(y.name),size:w&&w.length||y.size||0,name:y.name||"",meta:null},_&&(t.meta=x&&x.meta||this.meta||{},!t.meta||!t.meta.thumb||t.meta.thumb.data instanceof r||(t.meta.thumb.data=new r(null,{type:"image/jpeg",data:t.meta.thumb.data}))),t},resize:function(t,i,n){var r=document.createElement("canvas");if(r.width=t.width,r.height=t.height,r.getContext("2d").drawImage(e(),t.x,t.y,t.width,t.height,0,0,r.width,r.height),v=s.scale(r,i),_=n.preserveHeaders,!_){var o=this.meta&&this.meta.tiff&&this.meta.tiff.Orientation||1;v=f(v,o)}this.width=v.width,this.height=v.height,b=!0,this.trigger("Resize")},getAsCanvas:function(){return v||(v=c()),v.id=this.uid+"_canvas",v},getAsBlob:function(e,t){return e!==this.type?(b=!0,new o(null,{name:y.name||"",type:e,data:E.getAsDataURL(e,t)})):new o(null,{name:y.name||"",type:e,data:E.getAsBinaryString(e,t)})},getAsDataURL:function(e){var t=arguments[1]||90;if(!b)return g.src;if(c(),"image/jpeg"!==e)return v.toDataURL("image/png");try{return v.toDataURL("image/jpeg",t/100)}catch(i){return v.toDataURL("image/jpeg")}},getAsBinaryString:function(e,t){if(!b)return w||(w=l(E.getAsDataURL(e,t))),w;if("image/jpeg"!==e)w=l(E.getAsDataURL(e,t));else{var i;t||(t=90),c();try{i=v.toDataURL("image/jpeg",t/100)}catch(n){i=v.toDataURL("image/jpeg")}w=l(i),x&&(w=x.stripHeaders(w),_&&(x.meta&&x.meta.exif&&x.setExif({PixelXDimension:this.width,PixelYDimension:this.height}),w=x.writeHeaders(w)),x.purge(),x=null)}return b=!1,w},destroy:function(){E=null,p.call(this),this.getRuntime().getShim().removeInstance(this.uid)}})}return e.Image=c}),n("moxie/runtime/flash/Runtime",["moxie/core/utils/Basic","moxie/core/utils/Env","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/runtime/Runtime"],function(e,t,i,n,o){function a(){var e;try{e=navigator.plugins["Shockwave Flash"],e=e.description}catch(t){try{e=new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version")}catch(i){e="0.0"}}return e=e.match(/\d+/g),parseFloat(e[0]+"."+e[1])}function s(e){var n=i.get(e);n&&"OBJECT"==n.nodeName&&("IE"===t.browser?(n.style.display="none",function r(){4==n.readyState?u(e):setTimeout(r,10)}()):n.parentNode.removeChild(n))}function u(e){var t=i.get(e);if(t){for(var n in t)"function"==typeof t[n]&&(t[n]=null);t.parentNode.removeChild(t)}}function c(u){var c,m=this;u=e.extend({swf_url:t.swf_url},u),o.call(this,u,l,{access_binary:function(e){return e&&"browser"===m.mode},access_image_binary:function(e){return e&&"browser"===m.mode},display_media:o.capTest(r("moxie/image/Image")),do_cors:o.capTrue,drag_and_drop:!1,report_upload_progress:function(){return"client"===m.mode},resize_image:o.capTrue,return_response_headers:!1,return_response_type:function(t){return"json"===t&&window.JSON?!0:!e.arrayDiff(t,["","text","document"])||"browser"===m.mode},return_status_code:function(t){return"browser"===m.mode||!e.arrayDiff(t,[200,404])},select_file:o.capTrue,select_multiple:o.capTrue,send_binary_string:function(e){return e&&"browser"===m.mode},send_browser_cookies:function(e){return e&&"browser"===m.mode},send_custom_headers:function(e){return e&&"browser"===m.mode},send_multipart:o.capTrue,slice_blob:function(e){return e&&"browser"===m.mode},stream_upload:function(e){return e&&"browser"===m.mode},summon_file_dialog:!1,upload_filesize:function(t){return e.parseSizeStr(t)<=2097152||"client"===m.mode},use_http_method:function(t){return!e.arrayDiff(t,["GET","POST"])}},{access_binary:function(e){return e?"browser":"client"},access_image_binary:function(e){return e?"browser":"client"},report_upload_progress:function(e){return e?"browser":"client"},return_response_type:function(t){return e.arrayDiff(t,["","text","json","document"])?"browser":["client","browser"]},return_status_code:function(t){return e.arrayDiff(t,[200,404])?"browser":["client","browser"]},send_binary_string:function(e){return e?"browser":"client"},send_browser_cookies:function(e){return e?"browser":"client"},send_custom_headers:function(e){return e?"browser":"client"},slice_blob:function(e){return e?"browser":"client"},stream_upload:function(e){return e?"client":"browser"},upload_filesize:function(t){return e.parseSizeStr(t)>=2097152?"client":"browser"}},"client"),a()<11.3&&(this.mode=!1),e.extend(this,{getShim:function(){return i.get(this.uid)},shimExec:function(e,t){var i=[].slice.call(arguments,2);return m.getShim().exec(this.uid,e,t,i)},init:function(){var i,r,a;a=this.getShimContainer(),e.extend(a.style,{position:"absolute",top:"-8px",left:"-8px",width:"9px",height:"9px",overflow:"hidden"}),i='<object id="'+this.uid+'" type="application/x-shockwave-flash" data="'+u.swf_url+'" ',"IE"===t.browser&&(i+='classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" '),i+='width="100%" height="100%" style="outline:0"><param name="movie" value="'+u.swf_url+'" />'+'<param name="flashvars" value="uid='+escape(this.uid)+"&target="+o.getGlobalEventTarget()+'" />'+'<param name="wmode" value="transparent" />'+'<param name="allowscriptaccess" value="always" />'+"</object>","IE"===t.browser?(r=document.createElement("div"),a.appendChild(r),r.outerHTML=i,r=a=null):a.innerHTML=i,c=setTimeout(function(){m&&!m.initialized&&m.trigger("Error",new n.RuntimeError(n.RuntimeError.NOT_INIT_ERR))},5e3)},destroy:function(e){return function(){s(m.uid),e.call(m),clearTimeout(c),u=c=e=m=null}}(this.destroy)},d)}var l="flash",d={};return o.addConstructor(l,c),d}),n("moxie/runtime/flash/file/Blob",["moxie/runtime/flash/Runtime","moxie/file/Blob"],function(e,t){var i={slice:function(e,i,n,r){var o=this.getRuntime();return 0>i?i=Math.max(e.size+i,0):i>0&&(i=Math.min(i,e.size)),0>n?n=Math.max(e.size+n,0):n>0&&(n=Math.min(n,e.size)),e=o.shimExec.call(this,"Blob","slice",i,n,r||""),e&&(e=new t(o.uid,e)),e}};return e.Blob=i}),n("moxie/runtime/flash/file/FileInput",["moxie/runtime/flash/Runtime","moxie/file/File","moxie/core/utils/Dom","moxie/core/utils/Basic"],function(e,t,i,n){var r={init:function(e){var r=this,o=this.getRuntime(),a=i.get(e.browse_button);a&&(a.setAttribute("tabindex",-1),a=null),this.bind("Change",function(){var e=o.shimExec.call(r,"FileInput","getFiles");r.files=[],n.each(e,function(e){r.files.push(new t(o.uid,e))})},999),this.getRuntime().shimExec.call(this,"FileInput","init",{accept:e.accept,multiple:e.multiple}),this.trigger("ready")}};return e.FileInput=r}),n("moxie/runtime/flash/file/FileReader",["moxie/runtime/flash/Runtime","moxie/core/utils/Encode"],function(e,t){function i(e,i){switch(i){case"readAsText":return t.atob(e,"utf8");case"readAsBinaryString":return t.atob(e);case"readAsDataURL":return e}return null}var n={read:function(e,t){var n=this;return n.result="","readAsDataURL"===e&&(n.result="data:"+(t.type||"")+";base64,"),n.bind("Progress",function(t,r){r&&(n.result+=i(r,e))},999),n.getRuntime().shimExec.call(this,"FileReader","readAsBase64",t.uid)}};return e.FileReader=n}),n("moxie/runtime/flash/file/FileReaderSync",["moxie/runtime/flash/Runtime","moxie/core/utils/Encode"],function(e,t){function i(e,i){switch(i){case"readAsText":return t.atob(e,"utf8");case"readAsBinaryString":return t.atob(e);case"readAsDataURL":return e}return null}var n={read:function(e,t){var n,r=this.getRuntime();return(n=r.shimExec.call(this,"FileReaderSync","readAsBase64",t.uid))?("readAsDataURL"===e&&(n="data:"+(t.type||"")+";base64,"+n),i(n,e,t.type)):null}};return e.FileReaderSync=n}),n("moxie/runtime/flash/runtime/Transporter",["moxie/runtime/flash/Runtime","moxie/file/Blob"],function(e,t){var i={getAsBlob:function(e){var i=this.getRuntime(),n=i.shimExec.call(this,"Transporter","getAsBlob",e);return n?new t(i.uid,n):null}};return e.Transporter=i}),n("moxie/runtime/flash/xhr/XMLHttpRequest",["moxie/runtime/flash/Runtime","moxie/core/utils/Basic","moxie/file/Blob","moxie/file/File","moxie/file/FileReaderSync","moxie/runtime/flash/file/FileReaderSync","moxie/xhr/FormData","moxie/runtime/Transporter","moxie/runtime/flash/runtime/Transporter"],function(e,t,i,n,r,o,a,s){var u={send:function(e,n){function r(){e.transport=l.mode,l.shimExec.call(c,"XMLHttpRequest","send",e,n)}function o(e,t){l.shimExec.call(c,"XMLHttpRequest","appendBlob",e,t.uid),n=null,r()}function u(e,t){var i=new s;i.bind("TransportingComplete",function(){t(this.result)}),i.transport(e.getSource(),e.type,{ruid:l.uid})}var c=this,l=c.getRuntime();if(t.isEmptyObj(e.headers)||t.each(e.headers,function(e,t){l.shimExec.call(c,"XMLHttpRequest","setRequestHeader",t,e.toString())}),n instanceof a){var d;if(n.each(function(e,t){e instanceof i?d=t:l.shimExec.call(c,"XMLHttpRequest","append",t,e)}),n.hasBlob()){var m=n.getBlob();m.isDetached()?u(m,function(e){m.destroy(),o(d,e)}):o(d,m)}else n=null,r()}else n instanceof i?n.isDetached()?u(n,function(e){n.destroy(),n=e.uid,r()}):(n=n.uid,r()):r()},getResponse:function(e){var i,o,a=this.getRuntime();if(o=a.shimExec.call(this,"XMLHttpRequest","getResponseAsBlob")){if(o=new n(a.uid,o),"blob"===e)return o;try{if(i=new r,~t.inArray(e,["","text"]))return i.readAsText(o);if("json"===e&&window.JSON)return JSON.parse(i.readAsText(o))}finally{o.destroy()}}return null},abort:function(){var e=this.getRuntime();e.shimExec.call(this,"XMLHttpRequest","abort"),this.dispatchEvent("readystatechange"),this.dispatchEvent("abort")}};return e.XMLHttpRequest=u}),n("moxie/runtime/flash/image/Image",["moxie/runtime/flash/Runtime","moxie/core/utils/Basic","moxie/runtime/Transporter","moxie/file/Blob","moxie/file/FileReaderSync"],function(e,t,i,n,r){var o={loadFromBlob:function(e){function t(e){r.shimExec.call(n,"Image","loadFromBlob",e.uid),n=r=null}var n=this,r=n.getRuntime();if(e.isDetached()){var o=new i;o.bind("TransportingComplete",function(){t(o.result.getSource())}),o.transport(e.getSource(),e.type,{ruid:r.uid})}else t(e.getSource())},loadFromImage:function(e){var t=this.getRuntime();return t.shimExec.call(this,"Image","loadFromImage",e.uid)},getInfo:function(){var e=this.getRuntime(),t=e.shimExec.call(this,"Image","getInfo");return t.meta&&t.meta.thumb&&t.meta.thumb.data&&!(e.meta.thumb.data instanceof n)&&(t.meta.thumb.data=new n(e.uid,t.meta.thumb.data)),t},getAsBlob:function(e,t){var i=this.getRuntime(),r=i.shimExec.call(this,"Image","getAsBlob",e,t);return r?new n(i.uid,r):null},getAsDataURL:function(){var e,t=this.getRuntime(),i=t.Image.getAsBlob.apply(this,arguments);return i?(e=new r,e.readAsDataURL(i)):null}};return e.Image=o}),n("moxie/runtime/silverlight/Runtime",["moxie/core/utils/Basic","moxie/core/utils/Env","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/runtime/Runtime"],function(e,t,i,n,o){function a(e){var t,i,n,r,o,a=!1,s=null,u=0;try{try{s=new ActiveXObject("AgControl.AgControl"),s.IsVersionSupported(e)&&(a=!0),s=null}catch(c){var l=navigator.plugins["Silverlight Plug-In"];if(l){for(t=l.description,"1.0.30226.2"===t&&(t="2.0.30226.2"),i=t.split(".");i.length>3;)i.pop();for(;i.length<4;)i.push(0);for(n=e.split(".");n.length>4;)n.pop();do r=parseInt(n[u],10),o=parseInt(i[u],10),u++;while(u<n.length&&r===o);o>=r&&!isNaN(r)&&(a=!0)}}}catch(d){a=!1}return a}function s(s){var l,d=this;s=e.extend({xap_url:t.xap_url},s),o.call(this,s,u,{access_binary:o.capTrue,access_image_binary:o.capTrue,display_media:o.capTest(r("moxie/image/Image")),do_cors:o.capTrue,drag_and_drop:!1,report_upload_progress:o.capTrue,resize_image:o.capTrue,return_response_headers:function(e){return e&&"client"===d.mode},return_response_type:function(e){return"json"!==e?!0:!!window.JSON},return_status_code:function(t){return"client"===d.mode||!e.arrayDiff(t,[200,404])},select_file:o.capTrue,select_multiple:o.capTrue,send_binary_string:o.capTrue,send_browser_cookies:function(e){return e&&"browser"===d.mode},send_custom_headers:function(e){return e&&"client"===d.mode},send_multipart:o.capTrue,slice_blob:o.capTrue,stream_upload:!0,summon_file_dialog:!1,upload_filesize:o.capTrue,use_http_method:function(t){return"client"===d.mode||!e.arrayDiff(t,["GET","POST"])}},{return_response_headers:function(e){return e?"client":"browser"},return_status_code:function(t){return e.arrayDiff(t,[200,404])?"client":["client","browser"]},send_browser_cookies:function(e){return e?"browser":"client"},send_custom_headers:function(e){return e?"client":"browser"},use_http_method:function(t){return e.arrayDiff(t,["GET","POST"])?"client":["client","browser"]}}),a("2.0.31005.0")&&"Opera"!==t.browser||(this.mode=!1),e.extend(this,{getShim:function(){return i.get(this.uid).content.Moxie},shimExec:function(e,t){var i=[].slice.call(arguments,2);return d.getShim().exec(this.uid,e,t,i)},init:function(){var e;e=this.getShimContainer(),e.innerHTML='<object id="'+this.uid+'" data="data:application/x-silverlight," type="application/x-silverlight-2" width="100%" height="100%" style="outline:none;">'+'<param name="source" value="'+s.xap_url+'"/>'+'<param name="background" value="Transparent"/>'+'<param name="windowless" value="true"/>'+'<param name="enablehtmlaccess" value="true"/>'+'<param name="initParams" value="uid='+this.uid+",target="+o.getGlobalEventTarget()+'"/>'+"</object>",l=setTimeout(function(){d&&!d.initialized&&d.trigger("Error",new n.RuntimeError(n.RuntimeError.NOT_INIT_ERR))},"Windows"!==t.OS?1e4:5e3)},destroy:function(e){return function(){e.call(d),clearTimeout(l),s=l=e=d=null}}(this.destroy)},c)}var u="silverlight",c={};return o.addConstructor(u,s),c}),n("moxie/runtime/silverlight/file/Blob",["moxie/runtime/silverlight/Runtime","moxie/core/utils/Basic","moxie/runtime/flash/file/Blob"],function(e,t,i){return e.Blob=t.extend({},i)}),n("moxie/runtime/silverlight/file/FileInput",["moxie/runtime/silverlight/Runtime","moxie/file/File","moxie/core/utils/Dom","moxie/core/utils/Basic"],function(e,t,i,n){function r(e){for(var t="",i=0;i<e.length;i++)t+=(""!==t?"|":"")+e[i].title+" | *."+e[i].extensions.replace(/,/g,";*.");return t}var o={init:function(e){var o=this,a=this.getRuntime(),s=i.get(e.browse_button);s&&(s.setAttribute("tabindex",-1),s=null),this.bind("Change",function(){var e=a.shimExec.call(o,"FileInput","getFiles"); +o.files=[],n.each(e,function(e){o.files.push(new t(a.uid,e))})},999),a.shimExec.call(this,"FileInput","init",r(e.accept),e.multiple),this.trigger("ready")},setOption:function(e,t){"accept"==e&&(t=r(t)),this.getRuntime().shimExec.call(this,"FileInput","setOption",e,t)}};return e.FileInput=o}),n("moxie/runtime/silverlight/file/FileDrop",["moxie/runtime/silverlight/Runtime","moxie/core/utils/Dom","moxie/core/utils/Events"],function(e,t,i){var n={init:function(){var e,n=this,r=n.getRuntime();return e=r.getShimContainer(),i.addEvent(e,"dragover",function(e){e.preventDefault(),e.stopPropagation(),e.dataTransfer.dropEffect="copy"},n.uid),i.addEvent(e,"dragenter",function(e){e.preventDefault();var i=t.get(r.uid).dragEnter(e);i&&e.stopPropagation()},n.uid),i.addEvent(e,"drop",function(e){e.preventDefault();var i=t.get(r.uid).dragDrop(e);i&&e.stopPropagation()},n.uid),r.shimExec.call(this,"FileDrop","init")}};return e.FileDrop=n}),n("moxie/runtime/silverlight/file/FileReader",["moxie/runtime/silverlight/Runtime","moxie/core/utils/Basic","moxie/runtime/flash/file/FileReader"],function(e,t,i){return e.FileReader=t.extend({},i)}),n("moxie/runtime/silverlight/file/FileReaderSync",["moxie/runtime/silverlight/Runtime","moxie/core/utils/Basic","moxie/runtime/flash/file/FileReaderSync"],function(e,t,i){return e.FileReaderSync=t.extend({},i)}),n("moxie/runtime/silverlight/runtime/Transporter",["moxie/runtime/silverlight/Runtime","moxie/core/utils/Basic","moxie/runtime/flash/runtime/Transporter"],function(e,t,i){return e.Transporter=t.extend({},i)}),n("moxie/runtime/silverlight/xhr/XMLHttpRequest",["moxie/runtime/silverlight/Runtime","moxie/core/utils/Basic","moxie/runtime/flash/xhr/XMLHttpRequest","moxie/runtime/silverlight/file/FileReaderSync","moxie/runtime/silverlight/runtime/Transporter"],function(e,t,i){return e.XMLHttpRequest=t.extend({},i)}),n("moxie/runtime/silverlight/image/Image",["moxie/runtime/silverlight/Runtime","moxie/core/utils/Basic","moxie/file/Blob","moxie/runtime/flash/image/Image"],function(e,t,i,n){return e.Image=t.extend({},n,{getInfo:function(){var e=this.getRuntime(),n=["tiff","exif","gps","thumb"],r={meta:{}},o=e.shimExec.call(this,"Image","getInfo");return o.meta&&(t.each(n,function(e){var t,i,n,a,s=o.meta[e];if(s&&s.keys)for(r.meta[e]={},i=0,n=s.keys.length;n>i;i++)t=s.keys[i],a=s[t],a&&(/^(\d|[1-9]\d+)$/.test(a)?a=parseInt(a,10):/^\d*\.\d+$/.test(a)&&(a=parseFloat(a)),r.meta[e][t]=a)}),r.meta&&r.meta.thumb&&r.meta.thumb.data&&!(e.meta.thumb.data instanceof i)&&(r.meta.thumb.data=new i(e.uid,r.meta.thumb.data))),r.width=parseInt(o.width,10),r.height=parseInt(o.height,10),r.size=parseInt(o.size,10),r.type=o.type,r.name=o.name,r},resize:function(e,t,i){this.getRuntime().shimExec.call(this,"Image","resize",e.x,e.y,e.width,e.height,t,i.preserveHeaders,i.resample)}})}),n("moxie/runtime/html4/Runtime",["moxie/core/utils/Basic","moxie/core/Exceptions","moxie/runtime/Runtime","moxie/core/utils/Env"],function(e,t,i,n){function o(t){var o=this,u=i.capTest,c=i.capTrue;i.call(this,t,a,{access_binary:u(window.FileReader||window.File&&File.getAsDataURL),access_image_binary:!1,display_media:u((n.can("create_canvas")||n.can("use_data_uri_over32kb"))&&r("moxie/image/Image")),do_cors:!1,drag_and_drop:!1,filter_by_extension:u(function(){return!("Chrome"===n.browser&&n.verComp(n.version,28,"<")||"IE"===n.browser&&n.verComp(n.version,10,"<")||"Safari"===n.browser&&n.verComp(n.version,7,"<")||"Firefox"===n.browser&&n.verComp(n.version,37,"<"))}()),resize_image:function(){return s.Image&&o.can("access_binary")&&n.can("create_canvas")},report_upload_progress:!1,return_response_headers:!1,return_response_type:function(t){return"json"===t&&window.JSON?!0:!!~e.inArray(t,["text","document",""])},return_status_code:function(t){return!e.arrayDiff(t,[200,404])},select_file:function(){return n.can("use_fileinput")},select_multiple:!1,send_binary_string:!1,send_custom_headers:!1,send_multipart:!0,slice_blob:!1,stream_upload:function(){return o.can("select_file")},summon_file_dialog:function(){return o.can("select_file")&&!("Firefox"===n.browser&&n.verComp(n.version,4,"<")||"Opera"===n.browser&&n.verComp(n.version,12,"<")||"IE"===n.browser&&n.verComp(n.version,10,"<"))},upload_filesize:c,use_http_method:function(t){return!e.arrayDiff(t,["GET","POST"])}}),e.extend(this,{init:function(){this.trigger("Init")},destroy:function(e){return function(){e.call(o),e=o=null}}(this.destroy)}),e.extend(this.getShim(),s)}var a="html4",s={};return i.addConstructor(a,o),s}),n("moxie/runtime/html4/file/FileInput",["moxie/runtime/html4/Runtime","moxie/file/File","moxie/core/utils/Basic","moxie/core/utils/Dom","moxie/core/utils/Events","moxie/core/utils/Mime","moxie/core/utils/Env"],function(e,t,i,n,r,o,a){function s(){function e(){var o,c,d,m,h,f,p=this,g=p.getRuntime();f=i.guid("uid_"),o=g.getShimContainer(),s&&(d=n.get(s+"_form"),d&&(i.extend(d.style,{top:"100%"}),d.firstChild.setAttribute("tabindex",-1))),m=document.createElement("form"),m.setAttribute("id",f+"_form"),m.setAttribute("method","post"),m.setAttribute("enctype","multipart/form-data"),m.setAttribute("encoding","multipart/form-data"),i.extend(m.style,{overflow:"hidden",position:"absolute",top:0,left:0,width:"100%",height:"100%"}),h=document.createElement("input"),h.setAttribute("id",f),h.setAttribute("type","file"),h.setAttribute("accept",l.join(",")),g.can("summon_file_dialog")&&h.setAttribute("tabindex",-1),i.extend(h.style,{fontSize:"999px",opacity:0}),m.appendChild(h),o.appendChild(m),i.extend(h.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),"IE"===a.browser&&a.verComp(a.version,10,"<")&&i.extend(h.style,{filter:"progid:DXImageTransform.Microsoft.Alpha(opacity=0)"}),h.onchange=function(){var i;this.value&&(i=this.files?this.files[0]:{name:this.value},i=new t(g.uid,i),this.onchange=function(){},e.call(p),p.files=[i],h.setAttribute("id",i.uid),m.setAttribute("id",i.uid+"_form"),p.trigger("change"),h=m=null)},g.can("summon_file_dialog")&&(c=n.get(u.browse_button),r.removeEvent(c,"click",p.uid),r.addEvent(c,"click",function(e){h&&!h.disabled&&h.click(),e.preventDefault()},p.uid)),s=f,o=d=c=null}var s,u,c,l=[];i.extend(this,{init:function(t){var i,a=this,s=a.getRuntime();u=t,l=o.extList2mimes(t.accept,s.can("filter_by_extension")),i=s.getShimContainer(),function(){var e,o,l;e=n.get(t.browse_button),c=n.getStyle(e,"z-index")||"auto",s.can("summon_file_dialog")?("static"===n.getStyle(e,"position")&&(e.style.position="relative"),a.bind("Refresh",function(){o=parseInt(c,10)||1,n.get(u.browse_button).style.zIndex=o,this.getRuntime().getShimContainer().style.zIndex=o-1})):e.setAttribute("tabindex",-1),l=s.can("summon_file_dialog")?e:i,r.addEvent(l,"mouseover",function(){a.trigger("mouseenter")},a.uid),r.addEvent(l,"mouseout",function(){a.trigger("mouseleave")},a.uid),r.addEvent(l,"mousedown",function(){a.trigger("mousedown")},a.uid),r.addEvent(n.get(t.container),"mouseup",function(){a.trigger("mouseup")},a.uid),e=null}(),e.call(this),i=null,a.trigger({type:"ready",async:!0})},setOption:function(e,t){var i,r=this.getRuntime();"accept"==e&&(l=t.mimes||o.extList2mimes(t,r.can("filter_by_extension"))),i=n.get(s),i&&i.setAttribute("accept",l.join(","))},disable:function(e){var t;(t=n.get(s))&&(t.disabled=!!e)},destroy:function(){var e=this.getRuntime(),t=e.getShim(),i=e.getShimContainer(),o=u&&n.get(u.container),a=u&&n.get(u.browse_button);o&&r.removeAllEvents(o,this.uid),a&&(r.removeAllEvents(a,this.uid),a.style.zIndex=c),i&&(r.removeAllEvents(i,this.uid),i.innerHTML=""),t.removeInstance(this.uid),s=l=u=i=o=a=t=null}})}return e.FileInput=s}),n("moxie/runtime/html4/file/FileReader",["moxie/runtime/html4/Runtime","moxie/runtime/html5/file/FileReader"],function(e,t){return e.FileReader=t}),n("moxie/runtime/html4/xhr/XMLHttpRequest",["moxie/runtime/html4/Runtime","moxie/core/utils/Basic","moxie/core/utils/Dom","moxie/core/utils/Url","moxie/core/Exceptions","moxie/core/utils/Events","moxie/file/Blob","moxie/xhr/FormData"],function(e,t,i,n,r,o,a,s){function u(){function e(e){var t,n,r,a,s=this,u=!1;if(l){if(t=l.id.replace(/_iframe$/,""),n=i.get(t+"_form")){for(r=n.getElementsByTagName("input"),a=r.length;a--;)switch(r[a].getAttribute("type")){case"hidden":r[a].parentNode.removeChild(r[a]);break;case"file":u=!0}r=[],u||n.parentNode.removeChild(n),n=null}setTimeout(function(){o.removeEvent(l,"load",s.uid),l.parentNode&&l.parentNode.removeChild(l);var t=s.getRuntime().getShimContainer();t.children.length||t.parentNode.removeChild(t),t=l=null,e()},1)}}var u,c,l;t.extend(this,{send:function(d,m){function h(){var i=w.getShimContainer()||document.body,r=document.createElement("div");r.innerHTML='<iframe id="'+f+'_iframe" name="'+f+'_iframe" src="javascript:""" style="display:none"></iframe>',l=r.firstChild,i.appendChild(l),o.addEvent(l,"load",function(){var i;try{i=l.contentWindow.document||l.contentDocument||window.frames[l.id].document,/^4(0[0-9]|1[0-7]|2[2346])\s/.test(i.title)?u=i.title.replace(/^(\d+).*$/,"$1"):(u=200,c=t.trim(i.body.innerHTML),v.trigger({type:"progress",loaded:c.length,total:c.length}),x&&v.trigger({type:"uploadprogress",loaded:x.size||1025,total:x.size||1025}))}catch(r){if(!n.hasSameOrigin(d.url))return e.call(v,function(){v.trigger("error")}),void 0;u=404}e.call(v,function(){v.trigger("load")})},v.uid)}var f,p,g,x,v=this,w=v.getRuntime();if(u=c=null,m instanceof s&&m.hasBlob()){if(x=m.getBlob(),f=x.uid,g=i.get(f),p=i.get(f+"_form"),!p)throw new r.DOMException(r.DOMException.NOT_FOUND_ERR)}else f=t.guid("uid_"),p=document.createElement("form"),p.setAttribute("id",f+"_form"),p.setAttribute("method",d.method),p.setAttribute("enctype","multipart/form-data"),p.setAttribute("encoding","multipart/form-data"),w.getShimContainer().appendChild(p);p.setAttribute("target",f+"_iframe"),m instanceof s&&m.each(function(e,i){if(e instanceof a)g&&g.setAttribute("name",i);else{var n=document.createElement("input");t.extend(n,{type:"hidden",name:i,value:e}),g?p.insertBefore(n,g):p.appendChild(n)}}),p.setAttribute("action",d.url),h(),p.submit(),v.trigger("loadstart")},getStatus:function(){return u},getResponse:function(e){if("json"===e&&"string"===t.typeOf(c)&&window.JSON)try{return JSON.parse(c.replace(/^\s*<pre[^>]*>/,"").replace(/<\/pre>\s*$/,""))}catch(i){return null}return c},abort:function(){var t=this;l&&l.contentWindow&&(l.contentWindow.stop?l.contentWindow.stop():l.contentWindow.document.execCommand?l.contentWindow.document.execCommand("Stop"):l.src="about:blank"),e.call(this,function(){t.dispatchEvent("abort")})},destroy:function(){this.getRuntime().getShim().removeInstance(this.uid)}})}return e.XMLHttpRequest=u}),n("moxie/runtime/html4/image/Image",["moxie/runtime/html4/Runtime","moxie/runtime/html5/image/Image"],function(e,t){return e.Image=t}),a(["moxie/core/utils/Basic","moxie/core/utils/Encode","moxie/core/utils/Env","moxie/core/Exceptions","moxie/core/utils/Dom","moxie/core/EventTarget","moxie/runtime/Runtime","moxie/runtime/RuntimeClient","moxie/file/Blob","moxie/core/I18n","moxie/core/utils/Mime","moxie/file/FileInput","moxie/file/File","moxie/file/FileDrop","moxie/file/FileReader","moxie/core/utils/Url","moxie/runtime/RuntimeTarget","moxie/xhr/FormData","moxie/xhr/XMLHttpRequest","moxie/image/Image","moxie/core/utils/Events","moxie/runtime/html5/image/ResizerCanvas"])}(this)}); /** * Plupload - multi-runtime File Uploader - * v2.3.3 + * v2.3.6 * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. @@ -24,6 +24,6 @@ return t}var o={init:function(e){var o=this,a=this.getRuntime(),s=i.get(e.browse * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing * - * Date: 2017-08-28 + * Date: 2017-11-03 */ -!function(e,t){var i=function(){var e={};return t.apply(e,arguments),e.plupload};"function"==typeof define&&define.amd?define("plupload",["./moxie"],i):"object"==typeof module&&module.exports?module.exports=i(require("./moxie")):e.plupload=i(e.moxie)}(this||window,function(e){!function(e,t,i){function n(e){function t(e,t,i){var r={chunks:"slice_blob",jpgresize:"send_binary_string",pngresize:"send_binary_string",progress:"report_upload_progress",multi_selection:"select_multiple",dragdrop:"drag_and_drop",drop_element:"drag_and_drop",headers:"send_custom_headers",urlstream_upload:"send_binary_string",canSendBinary:"send_binary",triggerDialog:"summon_file_dialog"};r[e]?n[r[e]]=t:i||(n[e]=t)}var i=e.required_features,n={};return"string"==typeof i?l.each(i.split(/\s*,\s*/),function(e){t(e,!0)}):"object"==typeof i?l.each(i,function(e,i){t(i,e)}):i===!0&&(e.chunk_size&&e.chunk_size>0&&(n.slice_blob=!0),l.isEmptyObj(e.resize)&&e.multipart!==!1||(n.send_binary_string=!0),e.http_method&&(n.use_http_method=e.http_method),l.each(e,function(e,i){t(i,!!e,!0)})),n}var r=window.setTimeout,s={},a=t.core.utils,o=t.runtime.Runtime,l={VERSION:"2.3.3",STOPPED:1,STARTED:2,QUEUED:1,UPLOADING:2,FAILED:4,DONE:5,GENERIC_ERROR:-100,HTTP_ERROR:-200,IO_ERROR:-300,SECURITY_ERROR:-400,INIT_ERROR:-500,FILE_SIZE_ERROR:-600,FILE_EXTENSION_ERROR:-601,FILE_DUPLICATE_ERROR:-602,IMAGE_FORMAT_ERROR:-700,MEMORY_ERROR:-701,IMAGE_DIMENSIONS_ERROR:-702,moxie:t,mimeTypes:a.Mime.mimes,ua:a.Env,typeOf:a.Basic.typeOf,extend:a.Basic.extend,guid:a.Basic.guid,getAll:function(e){var t,i=[];"array"!==l.typeOf(e)&&(e=[e]);for(var n=e.length;n--;)t=l.get(e[n]),t&&i.push(t);return i.length?i:null},get:a.Dom.get,each:a.Basic.each,getPos:a.Dom.getPos,getSize:a.Dom.getSize,xmlEncode:function(e){var t={"<":"lt",">":"gt","&":"amp",'"':"quot","'":"#39"},i=/[<>&\"\']/g;return e?(""+e).replace(i,function(e){return t[e]?"&"+t[e]+";":e}):e},toArray:a.Basic.toArray,inArray:a.Basic.inArray,inSeries:a.Basic.inSeries,addI18n:t.core.I18n.addI18n,translate:t.core.I18n.translate,sprintf:a.Basic.sprintf,isEmptyObj:a.Basic.isEmptyObj,hasClass:a.Dom.hasClass,addClass:a.Dom.addClass,removeClass:a.Dom.removeClass,getStyle:a.Dom.getStyle,addEvent:a.Events.addEvent,removeEvent:a.Events.removeEvent,removeAllEvents:a.Events.removeAllEvents,cleanName:function(e){var t,i;for(i=[/[\300-\306]/g,"A",/[\340-\346]/g,"a",/\307/g,"C",/\347/g,"c",/[\310-\313]/g,"E",/[\350-\353]/g,"e",/[\314-\317]/g,"I",/[\354-\357]/g,"i",/\321/g,"N",/\361/g,"n",/[\322-\330]/g,"O",/[\362-\370]/g,"o",/[\331-\334]/g,"U",/[\371-\374]/g,"u"],t=0;t<i.length;t+=2)e=e.replace(i[t],i[t+1]);return e=e.replace(/\s+/g,"_"),e=e.replace(/[^a-z0-9_\-\.]+/gi,"")},buildUrl:function(e,t){var i="";return l.each(t,function(e,t){i+=(i?"&":"")+encodeURIComponent(t)+"="+encodeURIComponent(e)}),i&&(e+=(e.indexOf("?")>0?"&":"?")+i),e},formatSize:function(e){function t(e,t){return Math.round(e*Math.pow(10,t))/Math.pow(10,t)}if(e===i||/\D/.test(e))return l.translate("N/A");var n=Math.pow(1024,4);return e>n?t(e/n,1)+" "+l.translate("tb"):e>(n/=1024)?t(e/n,1)+" "+l.translate("gb"):e>(n/=1024)?t(e/n,1)+" "+l.translate("mb"):e>1024?Math.round(e/1024)+" "+l.translate("kb"):e+" "+l.translate("b")},parseSize:a.Basic.parseSizeStr,predictRuntime:function(e,t){var i,n;return i=new l.Uploader(e),n=o.thatCan(i.getOption().required_features,t||e.runtimes),i.destroy(),n},addFileFilter:function(e,t){s[e]=t}};l.addFileFilter("mime_types",function(e,t,i){e.length&&!e.regexp.test(t.name)?(this.trigger("Error",{code:l.FILE_EXTENSION_ERROR,message:l.translate("File extension error."),file:t}),i(!1)):i(!0)}),l.addFileFilter("max_file_size",function(e,t,i){var n;e=l.parseSize(e),t.size!==n&&e&&t.size>e?(this.trigger("Error",{code:l.FILE_SIZE_ERROR,message:l.translate("File size error."),file:t}),i(!1)):i(!0)}),l.addFileFilter("prevent_duplicates",function(e,t,i){if(e)for(var n=this.files.length;n--;)if(t.name===this.files[n].name&&t.size===this.files[n].size)return this.trigger("Error",{code:l.FILE_DUPLICATE_ERROR,message:l.translate("Duplicate file error."),file:t}),i(!1),void 0;i(!0)}),l.addFileFilter("prevent_empty",function(e,t,n){e&&!t.size&&t.size!==i?(this.trigger("Error",{code:l.FILE_SIZE_ERROR,message:l.translate("File size error."),file:t}),n(!1)):n(!0)}),l.Uploader=function(e){function a(){var e,t,i=0;if(this.state==l.STARTED){for(t=0;t<D.length;t++)e||D[t].status!=l.QUEUED?i++:(e=D[t],this.trigger("BeforeUpload",e)&&(e.status=l.UPLOADING,this.trigger("UploadFile",e)));i==D.length&&(this.state!==l.STOPPED&&(this.state=l.STOPPED,this.trigger("StateChanged")),this.trigger("UploadComplete",D))}}function u(e){e.percent=e.size>0?Math.ceil(100*(e.loaded/e.size)):100,d()}function d(){var e,t,n,r=0;for(I.reset(),e=0;e<D.length;e++)t=D[e],t.size!==i?(I.size+=t.origSize,n=t.loaded*t.origSize/t.size,(!t.completeTimestamp||t.completeTimestamp>S)&&(r+=n),I.loaded+=n):I.size=i,t.status==l.DONE?I.uploaded++:t.status==l.FAILED?I.failed++:I.queued++;I.size===i?I.percent=D.length>0?Math.ceil(100*(I.uploaded/D.length)):0:(I.bytesPerSec=Math.ceil(r/((+new Date-S||1)/1e3)),I.percent=I.size>0?Math.ceil(100*(I.loaded/I.size)):0)}function c(){var e=F[0]||P[0];return e?e.getRuntime().uid:!1}function f(){this.bind("FilesAdded FilesRemoved",function(e){e.trigger("QueueChanged"),e.refresh()}),this.bind("CancelUpload",b),this.bind("BeforeUpload",m),this.bind("UploadFile",_),this.bind("UploadProgress",E),this.bind("StateChanged",v),this.bind("QueueChanged",d),this.bind("Error",R),this.bind("FileUploaded",y),this.bind("Destroy",z)}function p(e,i){var n=this,r=0,s=[],a={runtime_order:e.runtimes,required_caps:e.required_features,preferred_caps:x,swf_url:e.flash_swf_url,xap_url:e.silverlight_xap_url};l.each(e.runtimes.split(/\s*,\s*/),function(t){e[t]&&(a[t]=e[t])}),e.browse_button&&l.each(e.browse_button,function(i){s.push(function(s){var u=new t.file.FileInput(l.extend({},a,{accept:e.filters.mime_types,name:e.file_data_name,multiple:e.multi_selection,container:e.container,browse_button:i}));u.onready=function(){var e=o.getInfo(this.ruid);l.extend(n.features,{chunks:e.can("slice_blob"),multipart:e.can("send_multipart"),multi_selection:e.can("select_multiple")}),r++,F.push(this),s()},u.onchange=function(){n.addFile(this.files)},u.bind("mouseenter mouseleave mousedown mouseup",function(t){U||(e.browse_button_hover&&("mouseenter"===t.type?l.addClass(i,e.browse_button_hover):"mouseleave"===t.type&&l.removeClass(i,e.browse_button_hover)),e.browse_button_active&&("mousedown"===t.type?l.addClass(i,e.browse_button_active):"mouseup"===t.type&&l.removeClass(i,e.browse_button_active)))}),u.bind("mousedown",function(){n.trigger("Browse")}),u.bind("error runtimeerror",function(){u=null,s()}),u.init()})}),e.drop_element&&l.each(e.drop_element,function(e){s.push(function(i){var s=new t.file.FileDrop(l.extend({},a,{drop_zone:e}));s.onready=function(){var e=o.getInfo(this.ruid);l.extend(n.features,{chunks:e.can("slice_blob"),multipart:e.can("send_multipart"),dragdrop:e.can("drag_and_drop")}),r++,P.push(this),i()},s.ondrop=function(){n.addFile(this.files)},s.bind("error runtimeerror",function(){s=null,i()}),s.init()})}),l.inSeries(s,function(){"function"==typeof i&&i(r)})}function g(e,n,r,s){var a=new t.image.Image;try{a.onload=function(){n.width>this.width&&n.height>this.height&&n.quality===i&&n.preserve_headers&&!n.crop?(this.destroy(),s(e)):a.downsize(n.width,n.height,n.crop,n.preserve_headers)},a.onresize=function(){var t=this.getAsBlob(e.type,n.quality);this.destroy(),s(t)},a.bind("error runtimeerror",function(){this.destroy(),s(e)}),a.load(e,r)}catch(o){s(e)}}function h(e,i,r){function s(e,i,n){var r=O[e];switch(e){case"max_file_size":"max_file_size"===e&&(O.max_file_size=O.filters.max_file_size=i);break;case"chunk_size":(i=l.parseSize(i))&&(O[e]=i,O.send_file_name=!0);break;case"multipart":O[e]=i,i||(O.send_file_name=!0);break;case"http_method":O[e]="PUT"===i.toUpperCase()?"PUT":"POST";break;case"unique_names":O[e]=i,i&&(O.send_file_name=!0);break;case"filters":"array"===l.typeOf(i)&&(i={mime_types:i}),n?l.extend(O.filters,i):O.filters=i,i.mime_types&&("string"===l.typeOf(i.mime_types)&&(i.mime_types=t.core.utils.Mime.mimes2extList(i.mime_types)),i.mime_types.regexp=function(e){var t=[];return l.each(e,function(e){l.each(e.extensions.split(/,/),function(e){/^\s*\*\s*$/.test(e)?t.push("\\.*"):t.push("\\."+e.replace(new RegExp("["+"/^$.*+?|()[]{}\\".replace(/./g,"\\$&")+"]","g"),"\\$&"))})}),new RegExp("("+t.join("|")+")$","i")}(i.mime_types),O.filters.mime_types=i.mime_types);break;case"resize":O.resize=i?l.extend({preserve_headers:!0,crop:!1},i):!1;break;case"prevent_duplicates":O.prevent_duplicates=O.filters.prevent_duplicates=!!i;break;case"container":case"browse_button":case"drop_element":i="container"===e?l.get(i):l.getAll(i);case"runtimes":case"multi_selection":case"flash_swf_url":case"silverlight_xap_url":O[e]=i,n||(u=!0);break;default:O[e]=i}n||a.trigger("OptionChanged",e,i,r)}var a=this,u=!1;"object"==typeof e?l.each(e,function(e,t){s(t,e,r)}):s(e,i,r),r?(O.required_features=n(l.extend({},O)),x=n(l.extend({},O,{required_features:!0}))):u&&(a.trigger("Destroy"),p.call(a,O,function(e){e?(a.runtime=o.getInfo(c()).type,a.trigger("Init",{runtime:a.runtime}),a.trigger("PostInit")):a.trigger("Error",{code:l.INIT_ERROR,message:l.translate("Init error.")})}))}function m(e,t){if(e.settings.unique_names){var i=t.name.match(/\.([^.]+)$/),n="part";i&&(n=i[1]),t.target_name=t.id+"."+n}}function _(e,i){function n(){c-->0?r(s,1e3):(i.loaded=p,e.trigger("Error",{code:l.HTTP_ERROR,message:l.translate("HTTP Error."),file:i,response:T.responseText,status:T.status,responseHeaders:T.getAllResponseHeaders()}))}function s(){var t,n,r={};i.status===l.UPLOADING&&e.state!==l.STOPPED&&(e.settings.send_file_name&&(r.name=i.target_name||i.name),d&&f.chunks&&o.size>d?(n=Math.min(d,o.size-p),t=o.slice(p,p+n)):(n=o.size,t=o),d&&f.chunks&&(e.settings.send_chunk_number?(r.chunk=Math.ceil(p/d),r.chunks=Math.ceil(o.size/d)):(r.offset=p,r.total=o.size)),e.trigger("BeforeChunkUpload",i,r,t,p)&&a(r,t,n))}function a(a,d,g){var m;T=new t.xhr.XMLHttpRequest,T.upload&&(T.upload.onprogress=function(t){i.loaded=Math.min(i.size,p+t.loaded),e.trigger("UploadProgress",i)}),T.onload=function(){return T.status<200&&T.status>=400?(n(),void 0):(c=e.settings.max_retries,g<o.size?(d.destroy(),p+=g,i.loaded=Math.min(p,o.size),e.trigger("ChunkUploaded",i,{offset:i.loaded,total:o.size,response:T.responseText,status:T.status,responseHeaders:T.getAllResponseHeaders()}),"Android Browser"===l.ua.browser&&e.trigger("UploadProgress",i)):i.loaded=i.size,d=m=null,!p||p>=o.size?(i.size!=i.origSize&&(o.destroy(),o=null),e.trigger("UploadProgress",i),i.status=l.DONE,i.completeTimestamp=+new Date,e.trigger("FileUploaded",i,{response:T.responseText,status:T.status,responseHeaders:T.getAllResponseHeaders()})):r(s,1),void 0)},T.onerror=function(){n()},T.onloadend=function(){this.destroy()},e.settings.multipart&&f.multipart?(T.open(e.settings.http_method,u,!0),l.each(e.settings.headers,function(e,t){T.setRequestHeader(t,e)}),m=new t.xhr.FormData,l.each(l.extend(a,e.settings.multipart_params),function(e,t){m.append(t,e)}),m.append(e.settings.file_data_name,d),T.send(m,h)):(u=l.buildUrl(e.settings.url,l.extend(a,e.settings.multipart_params)),T.open(e.settings.http_method,u,!0),l.each(e.settings.headers,function(e,t){T.setRequestHeader(t,e)}),T.hasRequestHeader("Content-Type")||T.setRequestHeader("Content-Type","application/octet-stream"),T.send(d,h))}var o,u=e.settings.url,d=e.settings.chunk_size,c=e.settings.max_retries,f=e.features,p=0,h={runtime_order:e.settings.runtimes,required_caps:e.settings.required_features,preferred_caps:x,swf_url:e.settings.flash_swf_url,xap_url:e.settings.silverlight_xap_url};i.loaded&&(p=i.loaded=d?d*Math.floor(i.loaded/d):0),o=i.getSource(),l.isEmptyObj(e.settings.resize)||-1===l.inArray(o.type,["image/jpeg","image/png"])?s():g(o,e.settings.resize,h,function(e){o=e,i.size=e.size,s()})}function E(e,t){u(t)}function v(e){if(e.state==l.STARTED)S=+new Date;else if(e.state==l.STOPPED)for(var t=e.files.length-1;t>=0;t--)e.files[t].status==l.UPLOADING&&(e.files[t].status=l.QUEUED,d())}function b(){T&&T.abort()}function y(e){d(),r(function(){a.call(e)},1)}function R(e,t){t.code===l.INIT_ERROR?e.destroy():t.code===l.HTTP_ERROR&&(t.file.status=l.FAILED,t.file.completeTimestamp=+new Date,u(t.file),e.state==l.STARTED&&(e.trigger("CancelUpload"),r(function(){a.call(e)},1)))}function z(e){e.stop(),l.each(D,function(e){e.destroy()}),D=[],F.length&&(l.each(F,function(e){e.destroy()}),F=[]),P.length&&(l.each(P,function(e){e.destroy()}),P=[]),x={},U=!1,S=T=null,I.reset()}var O,S,I,T,w=l.guid(),D=[],x={},F=[],P=[],U=!1;O={chunk_size:0,file_data_name:"file",filters:{mime_types:[],max_file_size:0,prevent_duplicates:!1,prevent_empty:!0},flash_swf_url:"js/Moxie.swf",http_method:"POST",max_retries:0,multipart:!0,multi_selection:!0,resize:!1,runtimes:o.order,send_file_name:!0,send_chunk_number:!0,silverlight_xap_url:"js/Moxie.xap"},h.call(this,e,null,!0),I=new l.QueueProgress,l.extend(this,{id:w,uid:w,state:l.STOPPED,features:{},runtime:null,files:D,settings:O,total:I,init:function(){var e,t,i=this;return e=i.getOption("preinit"),"function"==typeof e?e(i):l.each(e,function(e,t){i.bind(t,e)}),f.call(i),l.each(["container","browse_button","drop_element"],function(e){return null===i.getOption(e)?(t={code:l.INIT_ERROR,message:l.sprintf(l.translate("%s specified, but cannot be found."),e)},!1):void 0}),t?i.trigger("Error",t):O.browse_button||O.drop_element?(p.call(i,O,function(e){var t=i.getOption("init");"function"==typeof t?t(i):l.each(t,function(e,t){i.bind(t,e)}),e?(i.runtime=o.getInfo(c()).type,i.trigger("Init",{runtime:i.runtime}),i.trigger("PostInit")):i.trigger("Error",{code:l.INIT_ERROR,message:l.translate("Init error.")})}),void 0):i.trigger("Error",{code:l.INIT_ERROR,message:l.translate("You must specify either browse_button or drop_element.")})},setOption:function(e,t){h.call(this,e,t,!this.runtime)},getOption:function(e){return e?O[e]:O},refresh:function(){F.length&&l.each(F,function(e){e.trigger("Refresh")}),this.trigger("Refresh")},start:function(){this.state!=l.STARTED&&(this.state=l.STARTED,this.trigger("StateChanged"),a.call(this))},stop:function(){this.state!=l.STOPPED&&(this.state=l.STOPPED,this.trigger("StateChanged"),this.trigger("CancelUpload"))},disableBrowse:function(){U=arguments[0]!==i?arguments[0]:!0,F.length&&l.each(F,function(e){e.disable(U)}),this.trigger("DisableBrowse",U)},getFile:function(e){var t;for(t=D.length-1;t>=0;t--)if(D[t].id===e)return D[t]},addFile:function(e,i){function n(e,t){var i=[];l.each(u.settings.filters,function(t,n){s[n]&&i.push(function(i){s[n].call(u,t,e,function(e){i(!e)})})}),l.inSeries(i,t)}function a(e){var s=l.typeOf(e);if(e instanceof t.file.File){if(!e.ruid&&!e.isDetached()){if(!o)return!1;e.ruid=o,e.connectRuntime(o)}a(new l.File(e))}else e instanceof t.file.Blob?(a(e.getSource()),e.destroy()):e instanceof l.File?(i&&(e.name=i),d.push(function(t){n(e,function(i){i||(D.push(e),f.push(e),u.trigger("FileFiltered",e)),r(t,1)})})):-1!==l.inArray(s,["file","blob"])?a(new t.file.File(null,e)):"node"===s&&"filelist"===l.typeOf(e.files)?l.each(e.files,a):"array"===s&&(i=null,l.each(e,a))}var o,u=this,d=[],f=[];o=c(),a(e),d.length&&l.inSeries(d,function(){f.length&&u.trigger("FilesAdded",f)})},removeFile:function(e){for(var t="string"==typeof e?e:e.id,i=D.length-1;i>=0;i--)if(D[i].id===t)return this.splice(i,1)[0]},splice:function(e,t){var n=D.splice(e===i?0:e,t===i?D.length:t),r=!1;return this.state==l.STARTED&&(l.each(n,function(e){return e.status===l.UPLOADING?(r=!0,!1):void 0}),r&&this.stop()),this.trigger("FilesRemoved",n),l.each(n,function(e){e.destroy()}),r&&this.start(),n},dispatchEvent:function(e){var t,i;if(e=e.toLowerCase(),t=this.hasEventListener(e)){t.sort(function(e,t){return t.priority-e.priority}),i=[].slice.call(arguments),i.shift(),i.unshift(this);for(var n=0;n<t.length;n++)if(t[n].fn.apply(t[n].scope,i)===!1)return!1}return!0},bind:function(e,t,i,n){l.Uploader.prototype.bind.call(this,e,t,n,i)},destroy:function(){this.trigger("Destroy"),O=I=null,this.unbindAll()}})},l.Uploader.prototype=t.core.EventTarget.instance,l.File=function(){function e(e){l.extend(this,{id:l.guid(),name:e.name||e.fileName,type:e.type||"",relativePath:e.relativePath||"",size:e.fileSize||e.size,origSize:e.fileSize||e.size,loaded:0,percent:0,status:l.QUEUED,lastModifiedDate:e.lastModifiedDate||(new Date).toLocaleString(),completeTimestamp:0,getNative:function(){var e=this.getSource().getSource();return-1!==l.inArray(l.typeOf(e),["blob","file"])?e:null},getSource:function(){return t[this.id]?t[this.id]:null},destroy:function(){var e=this.getSource();e&&(e.destroy(),delete t[this.id])}}),t[this.id]=e}var t={};return e}(),l.QueueProgress=function(){var e=this;e.size=0,e.loaded=0,e.uploaded=0,e.failed=0,e.queued=0,e.percent=0,e.bytesPerSec=0,e.reset=function(){e.size=e.loaded=e.uploaded=e.failed=e.queued=e.percent=e.bytesPerSec=0}},e.plupload=l}(this,e)});
\ No newline at end of file +!function(e,t){var i=function(){var e={};return t.apply(e,arguments),e.plupload};"function"==typeof define&&define.amd?define("plupload",["./moxie"],i):"object"==typeof module&&module.exports?module.exports=i(require("./moxie")):e.plupload=i(e.moxie)}(this||window,function(e){!function(e,t,i){function n(e){function t(e,t,i){var r={chunks:"slice_blob",jpgresize:"send_binary_string",pngresize:"send_binary_string",progress:"report_upload_progress",multi_selection:"select_multiple",dragdrop:"drag_and_drop",drop_element:"drag_and_drop",headers:"send_custom_headers",urlstream_upload:"send_binary_string",canSendBinary:"send_binary",triggerDialog:"summon_file_dialog"};r[e]?n[r[e]]=t:i||(n[e]=t)}var i=e.required_features,n={};return"string"==typeof i?l.each(i.split(/\s*,\s*/),function(e){t(e,!0)}):"object"==typeof i?l.each(i,function(e,i){t(i,e)}):i===!0&&(e.chunk_size&&e.chunk_size>0&&(n.slice_blob=!0),l.isEmptyObj(e.resize)&&e.multipart!==!1||(n.send_binary_string=!0),e.http_method&&(n.use_http_method=e.http_method),l.each(e,function(e,i){t(i,!!e,!0)})),n}var r=window.setTimeout,s={},a=t.core.utils,o=t.runtime.Runtime,l={VERSION:"2.3.6",STOPPED:1,STARTED:2,QUEUED:1,UPLOADING:2,FAILED:4,DONE:5,GENERIC_ERROR:-100,HTTP_ERROR:-200,IO_ERROR:-300,SECURITY_ERROR:-400,INIT_ERROR:-500,FILE_SIZE_ERROR:-600,FILE_EXTENSION_ERROR:-601,FILE_DUPLICATE_ERROR:-602,IMAGE_FORMAT_ERROR:-700,MEMORY_ERROR:-701,IMAGE_DIMENSIONS_ERROR:-702,moxie:t,mimeTypes:a.Mime.mimes,ua:a.Env,typeOf:a.Basic.typeOf,extend:a.Basic.extend,guid:a.Basic.guid,getAll:function(e){var t,i=[];"array"!==l.typeOf(e)&&(e=[e]);for(var n=e.length;n--;)t=l.get(e[n]),t&&i.push(t);return i.length?i:null},get:a.Dom.get,each:a.Basic.each,getPos:a.Dom.getPos,getSize:a.Dom.getSize,xmlEncode:function(e){var t={"<":"lt",">":"gt","&":"amp",'"':"quot","'":"#39"},i=/[<>&\"\']/g;return e?(""+e).replace(i,function(e){return t[e]?"&"+t[e]+";":e}):e},toArray:a.Basic.toArray,inArray:a.Basic.inArray,inSeries:a.Basic.inSeries,addI18n:t.core.I18n.addI18n,translate:t.core.I18n.translate,sprintf:a.Basic.sprintf,isEmptyObj:a.Basic.isEmptyObj,hasClass:a.Dom.hasClass,addClass:a.Dom.addClass,removeClass:a.Dom.removeClass,getStyle:a.Dom.getStyle,addEvent:a.Events.addEvent,removeEvent:a.Events.removeEvent,removeAllEvents:a.Events.removeAllEvents,cleanName:function(e){var t,i;for(i=[/[\300-\306]/g,"A",/[\340-\346]/g,"a",/\307/g,"C",/\347/g,"c",/[\310-\313]/g,"E",/[\350-\353]/g,"e",/[\314-\317]/g,"I",/[\354-\357]/g,"i",/\321/g,"N",/\361/g,"n",/[\322-\330]/g,"O",/[\362-\370]/g,"o",/[\331-\334]/g,"U",/[\371-\374]/g,"u"],t=0;t<i.length;t+=2)e=e.replace(i[t],i[t+1]);return e=e.replace(/\s+/g,"_"),e=e.replace(/[^a-z0-9_\-\.]+/gi,"")},buildUrl:function(e,t){var i="";return l.each(t,function(e,t){i+=(i?"&":"")+encodeURIComponent(t)+"="+encodeURIComponent(e)}),i&&(e+=(e.indexOf("?")>0?"&":"?")+i),e},formatSize:function(e){function t(e,t){return Math.round(e*Math.pow(10,t))/Math.pow(10,t)}if(e===i||/\D/.test(e))return l.translate("N/A");var n=Math.pow(1024,4);return e>n?t(e/n,1)+" "+l.translate("tb"):e>(n/=1024)?t(e/n,1)+" "+l.translate("gb"):e>(n/=1024)?t(e/n,1)+" "+l.translate("mb"):e>1024?Math.round(e/1024)+" "+l.translate("kb"):e+" "+l.translate("b")},parseSize:a.Basic.parseSizeStr,predictRuntime:function(e,t){var i,n;return i=new l.Uploader(e),n=o.thatCan(i.getOption().required_features,t||e.runtimes),i.destroy(),n},addFileFilter:function(e,t){s[e]=t}};l.addFileFilter("mime_types",function(e,t,i){e.length&&!e.regexp.test(t.name)?(this.trigger("Error",{code:l.FILE_EXTENSION_ERROR,message:l.translate("File extension error."),file:t}),i(!1)):i(!0)}),l.addFileFilter("max_file_size",function(e,t,i){var n;e=l.parseSize(e),t.size!==n&&e&&t.size>e?(this.trigger("Error",{code:l.FILE_SIZE_ERROR,message:l.translate("File size error."),file:t}),i(!1)):i(!0)}),l.addFileFilter("prevent_duplicates",function(e,t,i){if(e)for(var n=this.files.length;n--;)if(t.name===this.files[n].name&&t.size===this.files[n].size)return this.trigger("Error",{code:l.FILE_DUPLICATE_ERROR,message:l.translate("Duplicate file error."),file:t}),i(!1),void 0;i(!0)}),l.addFileFilter("prevent_empty",function(e,t,n){e&&!t.size&&t.size!==i?(this.trigger("Error",{code:l.FILE_SIZE_ERROR,message:l.translate("File size error."),file:t}),n(!1)):n(!0)}),l.Uploader=function(e){function a(){var e,t,i=0;if(this.state==l.STARTED){for(t=0;t<D.length;t++)e||D[t].status!=l.QUEUED?i++:(e=D[t],this.trigger("BeforeUpload",e)&&(e.status=l.UPLOADING,this.trigger("UploadFile",e)));i==D.length&&(this.state!==l.STOPPED&&(this.state=l.STOPPED,this.trigger("StateChanged")),this.trigger("UploadComplete",D))}}function u(e){e.percent=e.size>0?Math.ceil(100*(e.loaded/e.size)):100,d()}function d(){var e,t,n,r=0;for(I.reset(),e=0;e<D.length;e++)t=D[e],t.size!==i?(I.size+=t.origSize,n=t.loaded*t.origSize/t.size,(!t.completeTimestamp||t.completeTimestamp>S)&&(r+=n),I.loaded+=n):I.size=i,t.status==l.DONE?I.uploaded++:t.status==l.FAILED?I.failed++:I.queued++;I.size===i?I.percent=D.length>0?Math.ceil(100*(I.uploaded/D.length)):0:(I.bytesPerSec=Math.ceil(r/((+new Date-S||1)/1e3)),I.percent=I.size>0?Math.ceil(100*(I.loaded/I.size)):0)}function c(){var e=F[0]||P[0];return e?e.getRuntime().uid:!1}function f(){this.bind("FilesAdded FilesRemoved",function(e){e.trigger("QueueChanged"),e.refresh()}),this.bind("CancelUpload",b),this.bind("BeforeUpload",m),this.bind("UploadFile",_),this.bind("UploadProgress",E),this.bind("StateChanged",v),this.bind("QueueChanged",d),this.bind("Error",R),this.bind("FileUploaded",y),this.bind("Destroy",z)}function p(e,i){var n=this,r=0,s=[],a={runtime_order:e.runtimes,required_caps:e.required_features,preferred_caps:x,swf_url:e.flash_swf_url,xap_url:e.silverlight_xap_url};l.each(e.runtimes.split(/\s*,\s*/),function(t){e[t]&&(a[t]=e[t])}),e.browse_button&&l.each(e.browse_button,function(i){s.push(function(s){var u=new t.file.FileInput(l.extend({},a,{accept:e.filters.mime_types,name:e.file_data_name,multiple:e.multi_selection,container:e.container,browse_button:i}));u.onready=function(){var e=o.getInfo(this.ruid);l.extend(n.features,{chunks:e.can("slice_blob"),multipart:e.can("send_multipart"),multi_selection:e.can("select_multiple")}),r++,F.push(this),s()},u.onchange=function(){n.addFile(this.files)},u.bind("mouseenter mouseleave mousedown mouseup",function(t){U||(e.browse_button_hover&&("mouseenter"===t.type?l.addClass(i,e.browse_button_hover):"mouseleave"===t.type&&l.removeClass(i,e.browse_button_hover)),e.browse_button_active&&("mousedown"===t.type?l.addClass(i,e.browse_button_active):"mouseup"===t.type&&l.removeClass(i,e.browse_button_active)))}),u.bind("mousedown",function(){n.trigger("Browse")}),u.bind("error runtimeerror",function(){u=null,s()}),u.init()})}),e.drop_element&&l.each(e.drop_element,function(e){s.push(function(i){var s=new t.file.FileDrop(l.extend({},a,{drop_zone:e}));s.onready=function(){var e=o.getInfo(this.ruid);l.extend(n.features,{chunks:e.can("slice_blob"),multipart:e.can("send_multipart"),dragdrop:e.can("drag_and_drop")}),r++,P.push(this),i()},s.ondrop=function(){n.addFile(this.files)},s.bind("error runtimeerror",function(){s=null,i()}),s.init()})}),l.inSeries(s,function(){"function"==typeof i&&i(r)})}function g(e,n,r,s){var a=new t.image.Image;try{a.onload=function(){n.width>this.width&&n.height>this.height&&n.quality===i&&n.preserve_headers&&!n.crop?(this.destroy(),s(e)):a.downsize(n.width,n.height,n.crop,n.preserve_headers)},a.onresize=function(){var t=this.getAsBlob(e.type,n.quality);this.destroy(),s(t)},a.bind("error runtimeerror",function(){this.destroy(),s(e)}),a.load(e,r)}catch(o){s(e)}}function h(e,i,r){function s(e,i,n){var r=O[e];switch(e){case"max_file_size":"max_file_size"===e&&(O.max_file_size=O.filters.max_file_size=i);break;case"chunk_size":(i=l.parseSize(i))&&(O[e]=i,O.send_file_name=!0);break;case"multipart":O[e]=i,i||(O.send_file_name=!0);break;case"http_method":O[e]="PUT"===i.toUpperCase()?"PUT":"POST";break;case"unique_names":O[e]=i,i&&(O.send_file_name=!0);break;case"filters":"array"===l.typeOf(i)&&(i={mime_types:i}),n?l.extend(O.filters,i):O.filters=i,i.mime_types&&("string"===l.typeOf(i.mime_types)&&(i.mime_types=t.core.utils.Mime.mimes2extList(i.mime_types)),i.mime_types.regexp=function(e){var t=[];return l.each(e,function(e){l.each(e.extensions.split(/,/),function(e){/^\s*\*\s*$/.test(e)?t.push("\\.*"):t.push("\\."+e.replace(new RegExp("["+"/^$.*+?|()[]{}\\".replace(/./g,"\\$&")+"]","g"),"\\$&"))})}),new RegExp("("+t.join("|")+")$","i")}(i.mime_types),O.filters.mime_types=i.mime_types);break;case"resize":O.resize=i?l.extend({preserve_headers:!0,crop:!1},i):!1;break;case"prevent_duplicates":O.prevent_duplicates=O.filters.prevent_duplicates=!!i;break;case"container":case"browse_button":case"drop_element":i="container"===e?l.get(i):l.getAll(i);case"runtimes":case"multi_selection":case"flash_swf_url":case"silverlight_xap_url":O[e]=i,n||(u=!0);break;default:O[e]=i}n||a.trigger("OptionChanged",e,i,r)}var a=this,u=!1;"object"==typeof e?l.each(e,function(e,t){s(t,e,r)}):s(e,i,r),r?(O.required_features=n(l.extend({},O)),x=n(l.extend({},O,{required_features:!0}))):u&&(a.trigger("Destroy"),p.call(a,O,function(e){e?(a.runtime=o.getInfo(c()).type,a.trigger("Init",{runtime:a.runtime}),a.trigger("PostInit")):a.trigger("Error",{code:l.INIT_ERROR,message:l.translate("Init error.")})}))}function m(e,t){if(e.settings.unique_names){var i=t.name.match(/\.([^.]+)$/),n="part";i&&(n=i[1]),t.target_name=t.id+"."+n}}function _(e,i){function n(){c-->0?r(s,1e3):(i.loaded=p,e.trigger("Error",{code:l.HTTP_ERROR,message:l.translate("HTTP Error."),file:i,response:T.responseText,status:T.status,responseHeaders:T.getAllResponseHeaders()}))}function s(){var t,n,r={};i.status===l.UPLOADING&&e.state!==l.STOPPED&&(e.settings.send_file_name&&(r.name=i.target_name||i.name),d&&f.chunks&&o.size>d?(n=Math.min(d,o.size-p),t=o.slice(p,p+n)):(n=o.size,t=o),d&&f.chunks&&(e.settings.send_chunk_number?(r.chunk=Math.ceil(p/d),r.chunks=Math.ceil(o.size/d)):(r.offset=p,r.total=o.size)),e.trigger("BeforeChunkUpload",i,r,t,p)&&a(r,t,n))}function a(a,d,g){var m;T=new t.xhr.XMLHttpRequest,T.upload&&(T.upload.onprogress=function(t){i.loaded=Math.min(i.size,p+t.loaded),e.trigger("UploadProgress",i)}),T.onload=function(){return T.status<200||T.status>=400?(n(),void 0):(c=e.settings.max_retries,g<o.size?(d.destroy(),p+=g,i.loaded=Math.min(p,o.size),e.trigger("ChunkUploaded",i,{offset:i.loaded,total:o.size,response:T.responseText,status:T.status,responseHeaders:T.getAllResponseHeaders()}),"Android Browser"===l.ua.browser&&e.trigger("UploadProgress",i)):i.loaded=i.size,d=m=null,!p||p>=o.size?(i.size!=i.origSize&&(o.destroy(),o=null),e.trigger("UploadProgress",i),i.status=l.DONE,i.completeTimestamp=+new Date,e.trigger("FileUploaded",i,{response:T.responseText,status:T.status,responseHeaders:T.getAllResponseHeaders()})):r(s,1),void 0)},T.onerror=function(){n()},T.onloadend=function(){this.destroy()},e.settings.multipart&&f.multipart?(T.open(e.settings.http_method,u,!0),l.each(e.settings.headers,function(e,t){T.setRequestHeader(t,e)}),m=new t.xhr.FormData,l.each(l.extend(a,e.settings.multipart_params),function(e,t){m.append(t,e)}),m.append(e.settings.file_data_name,d),T.send(m,h)):(u=l.buildUrl(e.settings.url,l.extend(a,e.settings.multipart_params)),T.open(e.settings.http_method,u,!0),l.each(e.settings.headers,function(e,t){T.setRequestHeader(t,e)}),T.hasRequestHeader("Content-Type")||T.setRequestHeader("Content-Type","application/octet-stream"),T.send(d,h))}var o,u=e.settings.url,d=e.settings.chunk_size,c=e.settings.max_retries,f=e.features,p=0,h={runtime_order:e.settings.runtimes,required_caps:e.settings.required_features,preferred_caps:x,swf_url:e.settings.flash_swf_url,xap_url:e.settings.silverlight_xap_url};i.loaded&&(p=i.loaded=d?d*Math.floor(i.loaded/d):0),o=i.getSource(),l.isEmptyObj(e.settings.resize)||-1===l.inArray(o.type,["image/jpeg","image/png"])?s():g(o,e.settings.resize,h,function(e){o=e,i.size=e.size,s()})}function E(e,t){u(t)}function v(e){if(e.state==l.STARTED)S=+new Date;else if(e.state==l.STOPPED)for(var t=e.files.length-1;t>=0;t--)e.files[t].status==l.UPLOADING&&(e.files[t].status=l.QUEUED,d())}function b(){T&&T.abort()}function y(e){d(),r(function(){a.call(e)},1)}function R(e,t){t.code===l.INIT_ERROR?e.destroy():t.code===l.HTTP_ERROR&&(t.file.status=l.FAILED,t.file.completeTimestamp=+new Date,u(t.file),e.state==l.STARTED&&(e.trigger("CancelUpload"),r(function(){a.call(e)},1)))}function z(e){e.stop(),l.each(D,function(e){e.destroy()}),D=[],F.length&&(l.each(F,function(e){e.destroy()}),F=[]),P.length&&(l.each(P,function(e){e.destroy()}),P=[]),x={},U=!1,S=T=null,I.reset()}var O,S,I,T,w=l.guid(),D=[],x={},F=[],P=[],U=!1;O={chunk_size:0,file_data_name:"file",filters:{mime_types:[],max_file_size:0,prevent_duplicates:!1,prevent_empty:!0},flash_swf_url:"js/Moxie.swf",http_method:"POST",max_retries:0,multipart:!0,multi_selection:!0,resize:!1,runtimes:o.order,send_file_name:!0,send_chunk_number:!0,silverlight_xap_url:"js/Moxie.xap"},h.call(this,e,null,!0),I=new l.QueueProgress,l.extend(this,{id:w,uid:w,state:l.STOPPED,features:{},runtime:null,files:D,settings:O,total:I,init:function(){var e,t,i=this;return e=i.getOption("preinit"),"function"==typeof e?e(i):l.each(e,function(e,t){i.bind(t,e)}),f.call(i),l.each(["container","browse_button","drop_element"],function(e){return null===i.getOption(e)?(t={code:l.INIT_ERROR,message:l.sprintf(l.translate("%s specified, but cannot be found."),e)},!1):void 0}),t?i.trigger("Error",t):O.browse_button||O.drop_element?(p.call(i,O,function(e){var t=i.getOption("init");"function"==typeof t?t(i):l.each(t,function(e,t){i.bind(t,e)}),e?(i.runtime=o.getInfo(c()).type,i.trigger("Init",{runtime:i.runtime}),i.trigger("PostInit")):i.trigger("Error",{code:l.INIT_ERROR,message:l.translate("Init error.")})}),void 0):i.trigger("Error",{code:l.INIT_ERROR,message:l.translate("You must specify either browse_button or drop_element.")})},setOption:function(e,t){h.call(this,e,t,!this.runtime)},getOption:function(e){return e?O[e]:O},refresh:function(){F.length&&l.each(F,function(e){e.trigger("Refresh")}),this.trigger("Refresh")},start:function(){this.state!=l.STARTED&&(this.state=l.STARTED,this.trigger("StateChanged"),a.call(this))},stop:function(){this.state!=l.STOPPED&&(this.state=l.STOPPED,this.trigger("StateChanged"),this.trigger("CancelUpload"))},disableBrowse:function(){U=arguments[0]!==i?arguments[0]:!0,F.length&&l.each(F,function(e){e.disable(U)}),this.trigger("DisableBrowse",U)},getFile:function(e){var t;for(t=D.length-1;t>=0;t--)if(D[t].id===e)return D[t]},addFile:function(e,i){function n(e,t){var i=[];l.each(u.settings.filters,function(t,n){s[n]&&i.push(function(i){s[n].call(u,t,e,function(e){i(!e)})})}),l.inSeries(i,t)}function a(e){var s=l.typeOf(e);if(e instanceof t.file.File){if(!e.ruid&&!e.isDetached()){if(!o)return!1;e.ruid=o,e.connectRuntime(o)}a(new l.File(e))}else e instanceof t.file.Blob?(a(e.getSource()),e.destroy()):e instanceof l.File?(i&&(e.name=i),d.push(function(t){n(e,function(i){i||(D.push(e),f.push(e),u.trigger("FileFiltered",e)),r(t,1)})})):-1!==l.inArray(s,["file","blob"])?a(new t.file.File(null,e)):"node"===s&&"filelist"===l.typeOf(e.files)?l.each(e.files,a):"array"===s&&(i=null,l.each(e,a))}var o,u=this,d=[],f=[];o=c(),a(e),d.length&&l.inSeries(d,function(){f.length&&u.trigger("FilesAdded",f)})},removeFile:function(e){for(var t="string"==typeof e?e:e.id,i=D.length-1;i>=0;i--)if(D[i].id===t)return this.splice(i,1)[0]},splice:function(e,t){var n=D.splice(e===i?0:e,t===i?D.length:t),r=!1;return this.state==l.STARTED&&(l.each(n,function(e){return e.status===l.UPLOADING?(r=!0,!1):void 0}),r&&this.stop()),this.trigger("FilesRemoved",n),l.each(n,function(e){e.destroy()}),r&&this.start(),n},dispatchEvent:function(e){var t,i;if(e=e.toLowerCase(),t=this.hasEventListener(e)){t.sort(function(e,t){return t.priority-e.priority}),i=[].slice.call(arguments),i.shift(),i.unshift(this);for(var n=0;n<t.length;n++)if(t[n].fn.apply(t[n].scope,i)===!1)return!1}return!0},bind:function(e,t,i,n){l.Uploader.prototype.bind.call(this,e,t,n,i)},destroy:function(){this.trigger("Destroy"),O=I=null,this.unbindAll()}})},l.Uploader.prototype=t.core.EventTarget.instance,l.File=function(){function e(e){l.extend(this,{id:l.guid(),name:e.name||e.fileName,type:e.type||"",relativePath:e.relativePath||"",size:e.fileSize||e.size,origSize:e.fileSize||e.size,loaded:0,percent:0,status:l.QUEUED,lastModifiedDate:e.lastModifiedDate||(new Date).toLocaleString(),completeTimestamp:0,getNative:function(){var e=this.getSource().getSource();return-1!==l.inArray(l.typeOf(e),["blob","file"])?e:null},getSource:function(){return t[this.id]?t[this.id]:null},destroy:function(){var e=this.getSource();e&&(e.destroy(),delete t[this.id])}}),t[this.id]=e}var t={};return e}(),l.QueueProgress=function(){var e=this;e.size=0,e.loaded=0,e.uploaded=0,e.failed=0,e.queued=0,e.percent=0,e.bytesPerSec=0,e.reset=function(){e.size=e.loaded=e.uploaded=e.failed=e.queued=e.percent=e.bytesPerSec=0}},e.plupload=l}(this,e)});
\ No newline at end of file diff --git a/phpBB/bin/phpbbcli.php b/phpBB/bin/phpbbcli.php index 3061fee817..5ae18334d9 100755 --- a/phpBB/bin/phpbbcli.php +++ b/phpBB/bin/phpbbcli.php @@ -71,9 +71,12 @@ require($phpbb_root_path . 'includes/compatibility_globals.' . $phpEx); register_compatibility_globals(); +/** @var \phpbb\config\config $config */ +$config = $phpbb_container->get('config'); + /** @var \phpbb\language\language $language */ $language = $phpbb_container->get('language'); -$language->set_default_language($phpbb_container->get('config')['default_lang']); +$language->set_default_language($config['default_lang']); $language->add_lang(array('common', 'acp/common', 'cli')); /* @var $user \phpbb\user */ diff --git a/phpBB/composer.json b/phpBB/composer.json index 5bc8f5dc0d..33655b865f 100644 --- a/phpBB/composer.json +++ b/phpBB/composer.json @@ -4,7 +4,7 @@ "type": "project", "keywords": ["phpbb", "forum"], "homepage": "https://www.phpbb.com", - "license": "GPL-2.0", + "license": "GPL-2.0-only", "authors": [ { "name": "phpBB Limited", @@ -31,9 +31,9 @@ "guzzlehttp/guzzle": "~5.3", "lusitanian/oauth": "^0.8.1", "marc1706/fast-image-size": "^1.1", - "paragonie/random_compat": "^1.4", + "paragonie/random_compat": "^2.0", "patchwork/utf8": "^1.1", - "s9e/text-formatter": "~0.11.0", + "s9e/text-formatter": "^1.3", "symfony/config": "^2.8", "symfony/console": "^2.8", "symfony/debug": "^2.8", @@ -69,7 +69,7 @@ }, "config": { "platform": { - "php": "5.4" + "php": "5.4.7" } } } diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 9345d07dbf..d2a95fd8a3 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -1,11 +1,10 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "hash": "7c30306b2abcb79a206bf6497ef45a02", - "content-hash": "d559dd0af2317fb0fc15720a18834e33", + "content-hash": "cd42964227d699a6923798e33eab3dd5", "packages": [ { "name": "bantu/ini-get-wrapper", @@ -35,7 +34,7 @@ "MIT" ], "description": "Convenience wrapper around ini_get()", - "time": "2014-09-15 13:12:35" + "time": "2014-09-15T13:12:35+00:00" }, { "name": "google/recaptcha", @@ -80,25 +79,26 @@ "recaptcha", "spam" ], - "time": "2015-09-02 17:23:59" + "time": "2015-09-02T17:23:59+00:00" }, { "name": "guzzlehttp/guzzle", - "version": "5.3.1", + "version": "5.3.3", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "70f1fa53b71c4647bf2762c09068a95f77e12fb8" + "reference": "93bbdb30d59be6cd9839495306c65f2907370eb9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/70f1fa53b71c4647bf2762c09068a95f77e12fb8", - "reference": "70f1fa53b71c4647bf2762c09068a95f77e12fb8", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/93bbdb30d59be6cd9839495306c65f2907370eb9", + "reference": "93bbdb30d59be6cd9839495306c65f2907370eb9", "shasum": "" }, "require": { "guzzlehttp/ringphp": "^1.1", - "php": ">=5.4.0" + "php": ">=5.4.0", + "react/promise": "^2.2" }, "require-dev": { "ext-curl": "*", @@ -132,20 +132,20 @@ "rest", "web service" ], - "time": "2016-07-15 19:28:39" + "time": "2018-07-31T13:33:10+00:00" }, { "name": "guzzlehttp/ringphp", - "version": "1.1.0", + "version": "1.1.1", "source": { "type": "git", "url": "https://github.com/guzzle/RingPHP.git", - "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b" + "reference": "5e2a174052995663dd68e6b5ad838afd47dd615b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/RingPHP/zipball/dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", - "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", + "url": "https://api.github.com/repos/guzzle/RingPHP/zipball/5e2a174052995663dd68e6b5ad838afd47dd615b", + "reference": "5e2a174052995663dd68e6b5ad838afd47dd615b", "shasum": "" }, "require": { @@ -183,7 +183,7 @@ } ], "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.", - "time": "2015-05-20 03:37:09" + "time": "2018-07-31T13:22:33+00:00" }, { "name": "guzzlehttp/streams", @@ -233,7 +233,7 @@ "Guzzle", "stream" ], - "time": "2014-10-12 19:18:40" + "time": "2014-10-12T19:18:40+00:00" }, { "name": "ircmaxell/password-compat", @@ -275,20 +275,20 @@ "hashing", "password" ], - "time": "2014-11-20 16:49:30" + "time": "2014-11-20T16:49:30+00:00" }, { "name": "lusitanian/oauth", - "version": "v0.8.10", + "version": "v0.8.11", "source": { "type": "git", "url": "https://github.com/Lusitanian/PHPoAuthLib.git", - "reference": "09f4af38f17db6938253f4d1b171d537913ac1ed" + "reference": "fc11a53db4b66da555a6a11fce294f574a8374f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Lusitanian/PHPoAuthLib/zipball/09f4af38f17db6938253f4d1b171d537913ac1ed", - "reference": "09f4af38f17db6938253f4d1b171d537913ac1ed", + "url": "https://api.github.com/repos/Lusitanian/PHPoAuthLib/zipball/fc11a53db4b66da555a6a11fce294f574a8374f9", + "reference": "fc11a53db4b66da555a6a11fce294f574a8374f9", "shasum": "" }, "require": { @@ -342,23 +342,24 @@ "oauth", "security" ], - "time": "2016-07-12 22:15:00" + "time": "2016-07-12T22:15:00+00:00" }, { "name": "marc1706/fast-image-size", - "version": "v1.1.3", + "version": "v1.1.4", "source": { "type": "git", "url": "https://github.com/marc1706/fast-image-size.git", - "reference": "5f7e8377746524e2b8a49a631c1fc9afeb9d8bee" + "reference": "c4ded0223a4e49ae45a2183a69f6afac5baf7250" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/marc1706/fast-image-size/zipball/5f7e8377746524e2b8a49a631c1fc9afeb9d8bee", - "reference": "5f7e8377746524e2b8a49a631c1fc9afeb9d8bee", + "url": "https://api.github.com/repos/marc1706/fast-image-size/zipball/c4ded0223a4e49ae45a2183a69f6afac5baf7250", + "reference": "c4ded0223a4e49ae45a2183a69f6afac5baf7250", "shasum": "" }, "require": { + "ext-mbstring": "*", "php": ">=5.3.0" }, "require-dev": { @@ -393,7 +394,7 @@ "php", "size" ], - "time": "2017-03-26 12:48:28" + "time": "2017-10-23T18:52:01+00:00" }, { "name": "ocramius/proxy-manager", @@ -456,20 +457,20 @@ "proxy pattern", "service proxies" ], - "time": "2015-08-09 04:28:19" + "time": "2015-08-09T04:28:19+00:00" }, { "name": "paragonie/random_compat", - "version": "v1.4.2", + "version": "v2.0.18", "source": { "type": "git", "url": "https://github.com/paragonie/random_compat.git", - "reference": "965cdeb01fdcab7653253aa81d40441d261f1e66" + "reference": "0a58ef6e3146256cc3dc7cc393927bcc7d1b72db" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/965cdeb01fdcab7653253aa81d40441d261f1e66", - "reference": "965cdeb01fdcab7653253aa81d40441d261f1e66", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/0a58ef6e3146256cc3dc7cc393927bcc7d1b72db", + "reference": "0a58ef6e3146256cc3dc7cc393927bcc7d1b72db", "shasum": "" }, "require": { @@ -501,10 +502,11 @@ "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", "keywords": [ "csprng", + "polyfill", "pseudorandom", "random" ], - "time": "2017-03-13 16:22:52" + "time": "2019-01-03T20:59:08+00:00" }, { "name": "patchwork/utf8", @@ -563,20 +565,20 @@ "utf-8", "utf8" ], - "time": "2016-05-18 13:57:10" + "time": "2016-05-18T13:57:10+00:00" }, { "name": "psr/log", - "version": "1.0.2", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" + "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", + "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", "shasum": "" }, "require": { @@ -610,20 +612,20 @@ "psr", "psr-3" ], - "time": "2016-10-10 12:19:37" + "time": "2018-11-20T15:27:04+00:00" }, { "name": "react/promise", - "version": "v2.5.1", + "version": "v2.7.1", "source": { "type": "git", "url": "https://github.com/reactphp/promise.git", - "reference": "62785ae604c8d69725d693eb370e1d67e94c4053" + "reference": "31ffa96f8d2ed0341a57848cbb84d88b89dd664d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/promise/zipball/62785ae604c8d69725d693eb370e1d67e94c4053", - "reference": "62785ae604c8d69725d693eb370e1d67e94c4053", + "url": "https://api.github.com/repos/reactphp/promise/zipball/31ffa96f8d2ed0341a57848cbb84d88b89dd664d", + "reference": "31ffa96f8d2ed0341a57848cbb84d88b89dd664d", "shasum": "" }, "require": { @@ -656,32 +658,33 @@ "promise", "promises" ], - "time": "2017-03-25 12:08:31" + "time": "2019-01-07T21:25:54+00:00" }, { "name": "s9e/text-formatter", - "version": "0.11.0", + "version": "1.4.5", "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "664b3eaf52baaae4d93548f5e20246fa5942b2b9" + "reference": "6857c53658929b66dc0d92daece17f211c64ea61" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/664b3eaf52baaae4d93548f5e20246fa5942b2b9", - "reference": "664b3eaf52baaae4d93548f5e20246fa5942b2b9", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/6857c53658929b66dc0d92daece17f211c64ea61", + "reference": "6857c53658929b66dc0d92daece17f211c64ea61", "shasum": "" }, "require": { "ext-dom": "*", "ext-filter": "*", "lib-pcre": ">=7.2", - "php": ">=5.3.3" + "php": ">=5.4.7" }, "require-dev": { "matthiasmullie/minify": "*", - "php": ">=5.3.3", - "s9e/regexp-builder": ">=1.3.0" + "php-coveralls/php-coveralls": "*", + "phpunit/phpunit": "<6", + "s9e/regexp-builder": "1.*" }, "suggest": { "ext-curl": "Improves the performance of the MediaEmbed plugin and some JavaScript minifiers", @@ -721,25 +724,26 @@ "parser", "shortcodes" ], - "time": "2017-08-04 23:06:38" + "time": "2019-06-04T15:47:55+00:00" }, { "name": "symfony/config", - "version": "v2.8.21", + "version": "v2.8.50", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "0b8541d18507d10204a08384640ff6df3c739ebe" + "reference": "7dd5f5040dc04c118d057fb5886563963eb70011" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/0b8541d18507d10204a08384640ff6df3c739ebe", - "reference": "0b8541d18507d10204a08384640ff6df3c739ebe", + "url": "https://api.github.com/repos/symfony/config/zipball/7dd5f5040dc04c118d057fb5886563963eb70011", + "reference": "7dd5f5040dc04c118d057fb5886563963eb70011", "shasum": "" }, "require": { "php": ">=5.3.9", - "symfony/filesystem": "~2.3|~3.0.0" + "symfony/filesystem": "~2.3|~3.0.0", + "symfony/polyfill-ctype": "~1.8" }, "require-dev": { "symfony/yaml": "~2.7|~3.0.0" @@ -777,20 +781,20 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2017-04-12 14:07:15" + "time": "2018-11-26T09:38:12+00:00" }, { "name": "symfony/console", - "version": "v2.8.21", + "version": "v2.8.50", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "efa4d466b67c2fc9bf9419a981e683e1f99fa029" + "reference": "cbcf4b5e233af15cd2bbd50dee1ccc9b7927dc12" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/efa4d466b67c2fc9bf9419a981e683e1f99fa029", - "reference": "efa4d466b67c2fc9bf9419a981e683e1f99fa029", + "url": "https://api.github.com/repos/symfony/console/zipball/cbcf4b5e233af15cd2bbd50dee1ccc9b7927dc12", + "reference": "cbcf4b5e233af15cd2bbd50dee1ccc9b7927dc12", "shasum": "" }, "require": { @@ -804,7 +808,7 @@ "symfony/process": "~2.1|~3.0.0" }, "suggest": { - "psr/log": "For using the console logger", + "psr/log-implementation": "For using the console logger", "symfony/event-dispatcher": "", "symfony/process": "" }, @@ -838,20 +842,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2017-05-28 14:07:33" + "time": "2018-11-20T15:55:20+00:00" }, { "name": "symfony/debug", - "version": "v2.8.21", + "version": "v2.8.50", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "344f50ce827413b3640bfcb1e37386a67d06ea1f" + "reference": "74251c8d50dd3be7c4ce0c7b862497cdc641a5d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/344f50ce827413b3640bfcb1e37386a67d06ea1f", - "reference": "344f50ce827413b3640bfcb1e37386a67d06ea1f", + "url": "https://api.github.com/repos/symfony/debug/zipball/74251c8d50dd3be7c4ce0c7b862497cdc641a5d0", + "reference": "74251c8d50dd3be7c4ce0c7b862497cdc641a5d0", "shasum": "" }, "require": { @@ -895,20 +899,20 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2017-04-19 19:56:30" + "time": "2018-11-11T11:18:13+00:00" }, { "name": "symfony/dependency-injection", - "version": "v2.8.21", + "version": "v2.8.50", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "155b770e68150139779295864d6b6cb3172cd821" + "reference": "c306198fee8f872a8f5f031e6e4f6f83086992d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/155b770e68150139779295864d6b6cb3172cd821", - "reference": "155b770e68150139779295864d6b6cb3172cd821", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/c306198fee8f872a8f5f031e6e4f6f83086992d8", + "reference": "c306198fee8f872a8f5f031e6e4f6f83086992d8", "shasum": "" }, "require": { @@ -958,20 +962,20 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2017-05-25 22:57:22" + "time": "2019-04-16T11:33:46+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v2.8.21", + "version": "v2.8.50", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "7fc8e2b4118ff316550596357325dfd92a51f531" + "reference": "a77e974a5fecb4398833b0709210e3d5e334ffb0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/7fc8e2b4118ff316550596357325dfd92a51f531", - "reference": "7fc8e2b4118ff316550596357325dfd92a51f531", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/a77e974a5fecb4398833b0709210e3d5e334ffb0", + "reference": "a77e974a5fecb4398833b0709210e3d5e334ffb0", "shasum": "" }, "require": { @@ -1018,24 +1022,25 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2017-04-26 16:56:54" + "time": "2018-11-21T14:20:20+00:00" }, { "name": "symfony/filesystem", - "version": "v2.8.21", + "version": "v2.8.50", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "19c11158da8d110cc5289c063bf2ec4cc1ce9e7c" + "reference": "7ae46872dad09dffb7fe1e93a0937097339d0080" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/19c11158da8d110cc5289c063bf2ec4cc1ce9e7c", - "reference": "19c11158da8d110cc5289c063bf2ec4cc1ce9e7c", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/7ae46872dad09dffb7fe1e93a0937097339d0080", + "reference": "7ae46872dad09dffb7fe1e93a0937097339d0080", "shasum": "" }, "require": { - "php": ">=5.3.9" + "php": ">=5.3.9", + "symfony/polyfill-ctype": "~1.8" }, "type": "library", "extra": { @@ -1067,20 +1072,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2017-05-28 14:07:33" + "time": "2018-11-11T11:18:13+00:00" }, { "name": "symfony/finder", - "version": "v2.8.21", + "version": "v2.8.50", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "b058a6f0cb6ee9b6b727aae03d5a62474a308528" + "reference": "1444eac52273e345d9b95129bf914639305a9ba4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/b058a6f0cb6ee9b6b727aae03d5a62474a308528", - "reference": "b058a6f0cb6ee9b6b727aae03d5a62474a308528", + "url": "https://api.github.com/repos/symfony/finder/zipball/1444eac52273e345d9b95129bf914639305a9ba4", + "reference": "1444eac52273e345d9b95129bf914639305a9ba4", "shasum": "" }, "require": { @@ -1116,20 +1121,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2017-05-25 22:57:22" + "time": "2018-11-11T11:18:13+00:00" }, { "name": "symfony/http-foundation", - "version": "v2.8.21", + "version": "v2.8.50", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "03bf5ded5a4b54473e7551df5cfab854f7434ed4" + "reference": "746f8d3638bf46ee8b202e62f2b214c3d61fb06a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/03bf5ded5a4b54473e7551df5cfab854f7434ed4", - "reference": "03bf5ded5a4b54473e7551df5cfab854f7434ed4", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/746f8d3638bf46ee8b202e62f2b214c3d61fb06a", + "reference": "746f8d3638bf46ee8b202e62f2b214c3d61fb06a", "shasum": "" }, "require": { @@ -1171,20 +1176,20 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2017-05-19 11:49:58" + "time": "2019-04-16T10:00:53+00:00" }, { "name": "symfony/http-kernel", - "version": "v2.8.21", + "version": "v2.8.51", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "ae9dd4cfde4a3efa94475863fc330825715fe549" + "reference": "a01e2b4b267fda24dba9b06cd1c575ca87a51ad2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/ae9dd4cfde4a3efa94475863fc330825715fe549", - "reference": "ae9dd4cfde4a3efa94475863fc330825715fe549", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/a01e2b4b267fda24dba9b06cd1c575ca87a51ad2", + "reference": "a01e2b4b267fda24dba9b06cd1c575ca87a51ad2", "shasum": "" }, "require": { @@ -1192,10 +1197,12 @@ "psr/log": "~1.0", "symfony/debug": "^2.6.2", "symfony/event-dispatcher": "^2.6.7|~3.0.0", - "symfony/http-foundation": "~2.7.20|~2.8.13|~3.1.6" + "symfony/http-foundation": "~2.7.36|~2.8.29|~3.1.6", + "symfony/polyfill-ctype": "~1.8" }, "conflict": { - "symfony/config": "<2.7" + "symfony/config": "<2.7", + "twig/twig": "<1.34|<2.4,>=2" }, "require-dev": { "symfony/browser-kit": "~2.3|~3.0.0", @@ -1253,20 +1260,78 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", - "time": "2017-05-29 19:14:58" + "time": "2019-04-17T16:42:28+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.11.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "82ebae02209c21113908c229e9883c419720738a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a", + "reference": "82ebae02209c21113908c229e9883c419720738a", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.11-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + }, + { + "name": "Gert de Pagter", + "email": "backendtea@gmail.com" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2019-02-06T07:57:58+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.3.0", + "version": "v1.11.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4" + "reference": "fe5e94c604826c35a32fa832f35bd036b6799609" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e79d363049d1c2128f133a2667e4f4190904f7f4", - "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fe5e94c604826c35a32fa832f35bd036b6799609", + "reference": "fe5e94c604826c35a32fa832f35bd036b6799609", "shasum": "" }, "require": { @@ -1278,7 +1343,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3-dev" + "dev-master": "1.11-dev" } }, "autoload": { @@ -1312,20 +1377,20 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2019-02-06T07:57:58+00:00" }, { "name": "symfony/polyfill-php54", - "version": "v1.3.0", + "version": "v1.11.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php54.git", - "reference": "90e085822963fdcc9d1c5b73deb3d2e5783b16a0" + "reference": "2964b17ddc32dba7bcba009d5501c84d3fba1452" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php54/zipball/90e085822963fdcc9d1c5b73deb3d2e5783b16a0", - "reference": "90e085822963fdcc9d1c5b73deb3d2e5783b16a0", + "url": "https://api.github.com/repos/symfony/polyfill-php54/zipball/2964b17ddc32dba7bcba009d5501c84d3fba1452", + "reference": "2964b17ddc32dba7bcba009d5501c84d3fba1452", "shasum": "" }, "require": { @@ -1334,7 +1399,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3-dev" + "dev-master": "1.11-dev" } }, "autoload": { @@ -1370,20 +1435,20 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2019-02-06T07:57:58+00:00" }, { "name": "symfony/polyfill-php55", - "version": "v1.3.0", + "version": "v1.11.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php55.git", - "reference": "03e3f0350bca2220e3623a0e340eef194405fc67" + "reference": "96fa25cef405ea452919559a0025d5dc16e30e4c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php55/zipball/03e3f0350bca2220e3623a0e340eef194405fc67", - "reference": "03e3f0350bca2220e3623a0e340eef194405fc67", + "url": "https://api.github.com/repos/symfony/polyfill-php55/zipball/96fa25cef405ea452919559a0025d5dc16e30e4c", + "reference": "96fa25cef405ea452919559a0025d5dc16e30e4c", "shasum": "" }, "require": { @@ -1393,7 +1458,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3-dev" + "dev-master": "1.11-dev" } }, "autoload": { @@ -1426,20 +1491,20 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2019-02-06T07:57:58+00:00" }, { "name": "symfony/proxy-manager-bridge", - "version": "v2.8.21", + "version": "v2.8.50", "source": { "type": "git", "url": "https://github.com/symfony/proxy-manager-bridge.git", - "reference": "991c0fcd1d461ee9c7cde7d2c44d1ed7f4cc36ae" + "reference": "40802595fea26ada845ed58124d8000a13dd4c6f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/proxy-manager-bridge/zipball/991c0fcd1d461ee9c7cde7d2c44d1ed7f4cc36ae", - "reference": "991c0fcd1d461ee9c7cde7d2c44d1ed7f4cc36ae", + "url": "https://api.github.com/repos/symfony/proxy-manager-bridge/zipball/40802595fea26ada845ed58124d8000a13dd4c6f", + "reference": "40802595fea26ada845ed58124d8000a13dd4c6f", "shasum": "" }, "require": { @@ -1480,20 +1545,20 @@ ], "description": "Symfony ProxyManager Bridge", "homepage": "https://symfony.com", - "time": "2017-04-12 14:07:15" + "time": "2019-04-16T11:33:46+00:00" }, { "name": "symfony/routing", - "version": "v2.8.21", + "version": "v2.8.50", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "a8f328c7e701b7bb05a93fca62a5ab2b6b3e500e" + "reference": "8b0df6869d1997baafff6a1541826eac5a03d067" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/a8f328c7e701b7bb05a93fca62a5ab2b6b3e500e", - "reference": "a8f328c7e701b7bb05a93fca62a5ab2b6b3e500e", + "url": "https://api.github.com/repos/symfony/routing/zipball/8b0df6869d1997baafff6a1541826eac5a03d067", + "reference": "8b0df6869d1997baafff6a1541826eac5a03d067", "shasum": "" }, "require": { @@ -1504,7 +1569,6 @@ }, "require-dev": { "doctrine/annotations": "~1.0", - "doctrine/common": "~2.2", "psr/log": "~1.0", "symfony/config": "~2.7|~3.0.0", "symfony/expression-language": "~2.4|~3.0.0", @@ -1555,36 +1619,40 @@ "uri", "url" ], - "time": "2017-04-12 14:07:15" + "time": "2018-11-20T15:55:20+00:00" }, { "name": "symfony/twig-bridge", - "version": "v2.8.21", + "version": "v2.8.50", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "362aa855b5819355811b58f8b5f15679196a181e" + "reference": "ecc1e30d05fa99f25b504e2d6a8684555ae39f7c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/362aa855b5819355811b58f8b5f15679196a181e", - "reference": "362aa855b5819355811b58f8b5f15679196a181e", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/ecc1e30d05fa99f25b504e2d6a8684555ae39f7c", + "reference": "ecc1e30d05fa99f25b504e2d6a8684555ae39f7c", "shasum": "" }, "require": { "php": ">=5.3.9", - "twig/twig": "~1.28|~2.0" + "twig/twig": "~1.34|~2.4" + }, + "conflict": { + "symfony/form": "<2.8.23" }, "require-dev": { "symfony/asset": "~2.7|~3.0.0", "symfony/console": "~2.8|~3.0.0", "symfony/expression-language": "~2.4|~3.0.0", "symfony/finder": "~2.3|~3.0.0", - "symfony/form": "^2.8.19", + "symfony/form": "^2.8.23", + "symfony/http-foundation": "^2.8.29|~3.0.0", "symfony/http-kernel": "~2.8|~3.0.0", "symfony/polyfill-intl-icu": "~1.0", "symfony/routing": "~2.2|~3.0.0", - "symfony/security": "~2.6|~3.0.0", + "symfony/security": "^2.8.31|^3.3.13", "symfony/security-acl": "~2.6|~3.0.0", "symfony/stopwatch": "~2.2|~3.0.0", "symfony/templating": "~2.1|~3.0.0", @@ -1636,24 +1704,25 @@ ], "description": "Symfony Twig Bridge", "homepage": "https://symfony.com", - "time": "2017-04-12 14:07:15" + "time": "2018-11-11T11:18:13+00:00" }, { "name": "symfony/yaml", - "version": "v2.8.21", + "version": "v2.8.50", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "93ccdde79f4b079c7558da4656a3cb1c50c68e02" + "reference": "02c1859112aa779d9ab394ae4f3381911d84052b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/93ccdde79f4b079c7558da4656a3cb1c50c68e02", - "reference": "93ccdde79f4b079c7558da4656a3cb1c50c68e02", + "url": "https://api.github.com/repos/symfony/yaml/zipball/02c1859112aa779d9ab394ae4f3381911d84052b", + "reference": "02c1859112aa779d9ab394ae4f3381911d84052b", "shasum": "" }, "require": { - "php": ">=5.3.9" + "php": ">=5.3.9", + "symfony/polyfill-ctype": "~1.8" }, "type": "library", "extra": { @@ -1685,39 +1754,43 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2017-05-01 14:31:55" + "time": "2018-11-11T11:18:13+00:00" }, { "name": "twig/twig", - "version": "v1.33.2", + "version": "v1.42.2", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "dd6ca96227917e1e85b41c7c3cc6507b411e0927" + "reference": "21707d6ebd05476854805e4f91b836531941bcd4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/dd6ca96227917e1e85b41c7c3cc6507b411e0927", - "reference": "dd6ca96227917e1e85b41c7c3cc6507b411e0927", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/21707d6ebd05476854805e4f91b836531941bcd4", + "reference": "21707d6ebd05476854805e4f91b836531941bcd4", "shasum": "" }, "require": { - "php": ">=5.2.7" + "php": ">=5.4.0", + "symfony/polyfill-ctype": "^1.8" }, "require-dev": { "psr/container": "^1.0", - "symfony/debug": "~2.7", - "symfony/phpunit-bridge": "~3.3@dev" + "symfony/debug": "^2.7", + "symfony/phpunit-bridge": "^3.4.19|^4.1.8|^5.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.33-dev" + "dev-master": "1.42-dev" } }, "autoload": { "psr-0": { "Twig_": "lib/" + }, + "psr-4": { + "Twig\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1738,16 +1811,16 @@ }, { "name": "Twig Team", - "homepage": "http://twig.sensiolabs.org/contributors", + "homepage": "https://twig.symfony.com/contributors", "role": "Contributors" } ], "description": "Twig, the flexible, fast, and secure template language for PHP", - "homepage": "http://twig.sensiolabs.org", + "homepage": "https://twig.symfony.com", "keywords": [ "templating" ], - "time": "2017-04-20 17:39:48" + "time": "2019-06-18T15:35:16+00:00" }, { "name": "zendframework/zend-code", @@ -1800,7 +1873,7 @@ "code", "zf2" ], - "time": "2015-06-03 15:31:59" + "time": "2015-06-03T15:31:59+00:00" }, { "name": "zendframework/zend-eventmanager", @@ -1845,7 +1918,7 @@ "eventmanager", "zf2" ], - "time": "2015-06-03 15:32:01" + "time": "2015-06-03T15:32:01+00:00" }, { "name": "zendframework/zend-stdlib", @@ -1901,7 +1974,7 @@ "stdlib", "zf2" ], - "time": "2015-06-03 15:32:03" + "time": "2015-06-03T15:32:03+00:00" } ], "packages-dev": [ @@ -1957,7 +2030,7 @@ "constructor", "instantiate" ], - "time": "2015-06-14 21:17:01" + "time": "2015-06-14T21:17:01+00:00" }, { "name": "fabpot/goutte", @@ -2006,7 +2079,7 @@ "keywords": [ "scraper" ], - "time": "2015-05-05 21:14:57" + "time": "2015-05-05T21:14:57+00:00" }, { "name": "facebook/webdriver", @@ -2052,7 +2125,7 @@ "selenium", "webdriver" ], - "time": "2016-08-10 00:44:08" + "time": "2016-08-10T00:44:08+00:00" }, { "name": "laravel/homestead", @@ -2093,34 +2166,29 @@ } ], "description": "A virtual machine for web artisans.", - "time": "2016-09-17 04:42:33" + "time": "2016-09-17T04:42:33+00:00" }, { "name": "michelf/php-markdown", - "version": "1.7.0", + "version": "1.8.0", "source": { "type": "git", "url": "https://github.com/michelf/php-markdown.git", - "reference": "1f51cc520948f66cd2af8cbc45a5ee175e774220" + "reference": "01ab082b355bf188d907b9929cd99b2923053495" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/michelf/php-markdown/zipball/1f51cc520948f66cd2af8cbc45a5ee175e774220", - "reference": "1f51cc520948f66cd2af8cbc45a5ee175e774220", + "url": "https://api.github.com/repos/michelf/php-markdown/zipball/01ab082b355bf188d907b9929cd99b2923053495", + "reference": "01ab082b355bf188d907b9929cd99b2923053495", "shasum": "" }, "require": { "php": ">=5.3.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-lib": "1.4.x-dev" - } - }, "autoload": { - "psr-0": { - "Michelf": "" + "psr-4": { + "Michelf\\": "Michelf/" } }, "notification-url": "https://packagist.org/downloads/", @@ -2144,7 +2212,7 @@ "keywords": [ "markdown" ], - "time": "2016-10-29 18:58:20" + "time": "2018-01-15T00:49:33+00:00" }, { "name": "nikic/php-parser", @@ -2189,7 +2257,7 @@ "parser", "php" ], - "time": "2014-07-23 18:24:17" + "time": "2014-07-23T18:24:17+00:00" }, { "name": "phing/phing", @@ -2227,7 +2295,8 @@ "authors": [ { "name": "Michiel Rook", - "email": "mrook@php.net" + "email": "mrook@php.net", + "role": "Lead" }, { "name": "Phing Community", @@ -2241,7 +2310,7 @@ "task", "tool" ], - "time": "2012-11-29 21:23:47" + "time": "2012-11-29T21:23:47+00:00" }, { "name": "phpdocumentor/reflection-docblock", @@ -2290,42 +2359,42 @@ "email": "mike.vanriel@naenius.com" } ], - "time": "2016-01-25 08:17:30" + "time": "2016-01-25T08:17:30+00:00" }, { "name": "phpspec/prophecy", - "version": "v1.7.0", + "version": "1.8.1", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "93d39f1f7f9326d746203c7c056f300f7f126073" + "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/93d39f1f7f9326d746203c7c056f300f7f126073", - "reference": "93d39f1f7f9326d746203c7c056f300f7f126073", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/1927e75f4ed19131ec9bcc3b002e07fb1173ee76", + "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", - "sebastian/comparator": "^1.1|^2.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", + "sebastian/comparator": "^1.1|^2.0|^3.0", "sebastian/recursion-context": "^1.0|^2.0|^3.0" }, "require-dev": { "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8 || ^5.6.5" + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.6.x-dev" + "dev-master": "1.8.x-dev" } }, "autoload": { - "psr-0": { - "Prophecy\\": "src/" + "psr-4": { + "Prophecy\\": "src/Prophecy" } }, "notification-url": "https://packagist.org/downloads/", @@ -2353,7 +2422,7 @@ "spy", "stub" ], - "time": "2017-03-02 20:05:34" + "time": "2019-06-13T12:50:23+00:00" }, { "name": "phpunit/dbunit", @@ -2412,7 +2481,8 @@ "testing", "xunit" ], - "time": "2015-03-29 14:23:04" + "abandoned": true, + "time": "2015-03-29T14:23:04+00:00" }, { "name": "phpunit/php-code-coverage", @@ -2474,20 +2544,20 @@ "testing", "xunit" ], - "time": "2015-10-06 15:47:00" + "time": "2015-10-06T15:47:00+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "1.4.2", + "version": "1.4.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", "shasum": "" }, "require": { @@ -2521,7 +2591,7 @@ "filesystem", "iterator" ], - "time": "2016-10-03 07:40:28" + "time": "2017-11-27T13:52:08+00:00" }, { "name": "phpunit/php-text-template", @@ -2562,7 +2632,7 @@ "keywords": [ "template" ], - "time": "2015-06-21 13:50:34" + "time": "2015-06-21T13:50:34+00:00" }, { "name": "phpunit/php-timer", @@ -2611,20 +2681,20 @@ "keywords": [ "timer" ], - "time": "2017-02-26 11:10:40" + "time": "2017-02-26T11:10:40+00:00" }, { "name": "phpunit/php-token-stream", - "version": "1.4.11", + "version": "1.4.12", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7" + "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e03f8f67534427a787e21a385a67ec3ca6978ea7", - "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1ce90ba27c42e4e44e6d8458241466380b51fa16", + "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16", "shasum": "" }, "require": { @@ -2660,20 +2730,20 @@ "keywords": [ "tokenizer" ], - "time": "2017-02-27 10:12:30" + "time": "2017-12-04T08:55:13+00:00" }, { "name": "phpunit/phpunit", - "version": "4.8.35", + "version": "4.8.36", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "791b1a67c25af50e230f841ee7a9c6eba507dc87" + "reference": "46023de9a91eec7dfb06cc56cb4e260017298517" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/791b1a67c25af50e230f841ee7a9c6eba507dc87", - "reference": "791b1a67c25af50e230f841ee7a9c6eba507dc87", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/46023de9a91eec7dfb06cc56cb4e260017298517", + "reference": "46023de9a91eec7dfb06cc56cb4e260017298517", "shasum": "" }, "require": { @@ -2732,7 +2802,7 @@ "testing", "xunit" ], - "time": "2017-02-06 05:18:07" + "time": "2017-06-21T08:07:12+00:00" }, { "name": "phpunit/phpunit-mock-objects", @@ -2788,7 +2858,8 @@ "mock", "xunit" ], - "time": "2015-10-02 06:51:40" + "abandoned": true, + "time": "2015-10-02T06:51:40+00:00" }, { "name": "pimple/pimple", @@ -2834,7 +2905,7 @@ "container", "dependency injection" ], - "time": "2013-03-08 08:21:40" + "time": "2013-03-08T08:21:40+00:00" }, { "name": "sami/sami", @@ -2891,7 +2962,8 @@ "keywords": [ "phpdoc" ], - "time": "2015-06-05 03:36:34" + "abandoned": true, + "time": "2015-06-05T03:36:34+00:00" }, { "name": "sebastian/comparator", @@ -2955,7 +3027,7 @@ "compare", "equality" ], - "time": "2017-01-29 09:50:25" + "time": "2017-01-29T09:50:25+00:00" }, { "name": "sebastian/diff", @@ -3007,7 +3079,7 @@ "keywords": [ "diff" ], - "time": "2017-05-22 07:24:03" + "time": "2017-05-22T07:24:03+00:00" }, { "name": "sebastian/environment", @@ -3057,7 +3129,7 @@ "environment", "hhvm" ], - "time": "2016-08-18 05:49:44" + "time": "2016-08-18T05:49:44+00:00" }, { "name": "sebastian/exporter", @@ -3124,7 +3196,7 @@ "export", "exporter" ], - "time": "2016-06-17 09:04:28" + "time": "2016-06-17T09:04:28+00:00" }, { "name": "sebastian/global-state", @@ -3175,7 +3247,7 @@ "keywords": [ "global state" ], - "time": "2015-10-12 03:26:01" + "time": "2015-10-12T03:26:01+00:00" }, { "name": "sebastian/recursion-context", @@ -3228,7 +3300,7 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2016-10-03 07:41:43" + "time": "2016-10-03T07:41:43+00:00" }, { "name": "sebastian/version", @@ -3263,20 +3335,20 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-06-21 13:59:46" + "time": "2015-06-21T13:59:46+00:00" }, { "name": "squizlabs/php_codesniffer", - "version": "2.9.1", + "version": "2.9.2", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "dcbed1074f8244661eecddfc2a675430d8d33f62" + "reference": "2acf168de78487db620ab4bc524135a13cfe6745" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/dcbed1074f8244661eecddfc2a675430d8d33f62", - "reference": "dcbed1074f8244661eecddfc2a675430d8d33f62", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/2acf168de78487db620ab4bc524135a13cfe6745", + "reference": "2acf168de78487db620ab4bc524135a13cfe6745", "shasum": "" }, "require": { @@ -3341,20 +3413,20 @@ "phpcs", "standards" ], - "time": "2017-05-22 02:43:20" + "time": "2018-11-07T22:31:41+00:00" }, { "name": "symfony/browser-kit", - "version": "v2.8.21", + "version": "v2.8.50", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", - "reference": "4386755566fc8d29bddf89694663b0e96cb01e61" + "reference": "b507697225f32a76a9d333d0766fb46353e9d00d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/4386755566fc8d29bddf89694663b0e96cb01e61", - "reference": "4386755566fc8d29bddf89694663b0e96cb01e61", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/b507697225f32a76a9d333d0766fb46353e9d00d", + "reference": "b507697225f32a76a9d333d0766fb46353e9d00d", "shasum": "" }, "require": { @@ -3398,20 +3470,20 @@ ], "description": "Symfony BrowserKit Component", "homepage": "https://symfony.com", - "time": "2017-04-12 14:07:15" + "time": "2018-11-26T06:55:10+00:00" }, { "name": "symfony/css-selector", - "version": "v2.8.21", + "version": "v2.8.50", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "ba3204654efa779691fac9e948a96b4a7067e4ab" + "reference": "7b1692e418d7ccac24c373528453bc90e42797de" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/ba3204654efa779691fac9e948a96b4a7067e4ab", - "reference": "ba3204654efa779691fac9e948a96b4a7067e4ab", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/7b1692e418d7ccac24c373528453bc90e42797de", + "reference": "7b1692e418d7ccac24c373528453bc90e42797de", "shasum": "" }, "require": { @@ -3451,24 +3523,25 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", - "time": "2017-05-01 14:31:55" + "time": "2018-11-11T11:18:13+00:00" }, { "name": "symfony/dom-crawler", - "version": "v2.8.21", + "version": "v2.8.50", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "b19d01ec41c704497b0bee78bce8bf97619c0649" + "reference": "2cdc7d3909eea6f982a6298d2e9ab7db01b6403c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/b19d01ec41c704497b0bee78bce8bf97619c0649", - "reference": "b19d01ec41c704497b0bee78bce8bf97619c0649", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/2cdc7d3909eea6f982a6298d2e9ab7db01b6403c", + "reference": "2cdc7d3909eea6f982a6298d2e9ab7db01b6403c", "shasum": "" }, "require": { "php": ">=5.3.9", + "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { @@ -3507,20 +3580,20 @@ ], "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", - "time": "2017-05-25 22:57:22" + "time": "2018-11-24T22:30:19+00:00" }, { "name": "symfony/process", - "version": "v2.8.21", + "version": "v2.8.50", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "d54232f5682fda2f8bbebff7c81b864646867ab9" + "reference": "c3591a09c78639822b0b290d44edb69bf9f05dc8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/d54232f5682fda2f8bbebff7c81b864646867ab9", - "reference": "d54232f5682fda2f8bbebff7c81b864646867ab9", + "url": "https://api.github.com/repos/symfony/process/zipball/c3591a09c78639822b0b290d44edb69bf9f05dc8", + "reference": "c3591a09c78639822b0b290d44edb69bf9f05dc8", "shasum": "" }, "require": { @@ -3556,7 +3629,7 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2017-05-08 01:19:21" + "time": "2018-11-11T11:18:13+00:00" } ], "aliases": [], @@ -3569,6 +3642,6 @@ }, "platform-dev": [], "platform-overrides": { - "php": "5.4" + "php": "5.4.7" } } diff --git a/phpBB/config/default/container/services.yml b/phpBB/config/default/container/services.yml index 9bb1d673f4..3ead1e6181 100644 --- a/phpBB/config/default/container/services.yml +++ b/phpBB/config/default/container/services.yml @@ -122,7 +122,13 @@ services: group_helper: class: phpbb\group\helper arguments: + - '@auth' + - '@cache' + - '@config' - '@language' + - '@dispatcher' + - '@path_helper' + - '@user' log: class: phpbb\log\log diff --git a/phpBB/config/default/container/services_avatar.yml b/phpBB/config/default/container/services_avatar.yml index 6cc38516ae..d96aa6239a 100644 --- a/phpBB/config/default/container/services_avatar.yml +++ b/phpBB/config/default/container/services_avatar.yml @@ -3,6 +3,7 @@ services: class: phpbb\avatar\manager arguments: - '@config' + - '@dispatcher' - '@avatar.driver_collection' # ----- Avatar drivers ----- diff --git a/phpBB/config/default/container/services_console.yml b/phpBB/config/default/container/services_console.yml index 697e147d85..05e467ff8d 100644 --- a/phpBB/config/default/container/services_console.yml +++ b/phpBB/config/default/container/services_console.yml @@ -3,7 +3,6 @@ services: class: phpbb\console\exception_subscriber arguments: - '@language' - - '%debug.exceptions%' tags: - { name: kernel.event_subscriber } @@ -209,6 +208,7 @@ services: console.command.thumbnail.delete: class: phpbb\console\command\thumbnail\delete arguments: + - '@config' - '@user' - '@dbal.conn' - '%core.root_path%' @@ -218,6 +218,7 @@ services: console.command.thumbnail.generate: class: phpbb\console\command\thumbnail\generate arguments: + - '@config' - '@user' - '@dbal.conn' - '@cache' diff --git a/phpBB/config/default/container/services_content.yml b/phpBB/config/default/container/services_content.yml index 602fd25f4e..6717c20337 100644 --- a/phpBB/config/default/container/services_content.yml +++ b/phpBB/config/default/container/services_content.yml @@ -35,6 +35,7 @@ services: - '@config_text' - '@dbal.conn' - '@user' + - '@dispatcher' - '%core.root_path%' - '%core.php_ext%' diff --git a/phpBB/config/default/container/services_feed.yml b/phpBB/config/default/container/services_feed.yml index d3e7924f2f..e8bac4b5ce 100644 --- a/phpBB/config/default/container/services_feed.yml +++ b/phpBB/config/default/container/services_feed.yml @@ -18,9 +18,10 @@ services: class: phpbb\feed\helper arguments: - '@config' + - '@service_container' + - '@path_helper' + - '@text_formatter.renderer' - '@user' - - '%core.root_path%' - - '%core.php_ext%' feed.forum: class: phpbb\feed\forum @@ -78,6 +79,10 @@ services: - '@dispatcher' - '%core.php_ext%' + feed.quote_helper: + class: phpbb\feed\quote_helper + parent: text_formatter.s9e.quote_helper + feed.topic: class: phpbb\feed\topic shared: false diff --git a/phpBB/config/default/container/services_text_formatter.yml b/phpBB/config/default/container/services_text_formatter.yml index a9f2efdb16..07087cd4a9 100644 --- a/phpBB/config/default/container/services_text_formatter.yml +++ b/phpBB/config/default/container/services_text_formatter.yml @@ -26,6 +26,11 @@ services: text_formatter.utils: alias: text_formatter.s9e.utils + text_formatter.s9e.bbcode_merger: + class: phpbb\textformatter\s9e\bbcode_merger + arguments: + - '@text_formatter.s9e.factory' + text_formatter.s9e.factory: class: phpbb\textformatter\s9e\factory arguments: @@ -34,6 +39,7 @@ services: - '@dispatcher' - '@config' - '@text_formatter.s9e.link_helper' + - '@log' - '%text_formatter.cache.dir%' - '%text_formatter.cache.parser.key%' - '%text_formatter.cache.renderer.key%' diff --git a/phpBB/config/installer/container/services_install_obtain_data.yml b/phpBB/config/installer/container/services_install_obtain_data.yml index cd8d0c8072..010aba829d 100644 --- a/phpBB/config/installer/container/services_install_obtain_data.yml +++ b/phpBB/config/installer/container/services_install_obtain_data.yml @@ -33,13 +33,6 @@ services: tags: - { name: install_obtain_data, order: 40 } - installer.obtain_data.obtain_imagick_path: - class: phpbb\install\module\obtain_data\task\obtain_imagick_path - arguments: - - '@installer.helper.config' - tags: - - { name: install_obtain_data, order: 60 } - installer.obtain_data.obtain_server_data: class: phpbb\install\module\obtain_data\task\obtain_server_data arguments: diff --git a/phpBB/develop/add_permissions.php b/phpBB/develop/add_permissions.php index c575729d91..d7308a1acc 100644 --- a/phpBB/develop/add_permissions.php +++ b/phpBB/develop/add_permissions.php @@ -185,7 +185,7 @@ while ($row = $db->sql_fetchrow($result)) } $db->sql_freeresult($result); -if (sizeof($remove_auth_options)) +if (count($remove_auth_options)) { $db->sql_query('DELETE FROM ' . ACL_USERS_TABLE . ' WHERE auth_option_id IN (' . implode(', ', $remove_auth_options) . ')'); $db->sql_query('DELETE FROM ' . ACL_GROUPS_TABLE . ' WHERE auth_option_id IN (' . implode(', ', $remove_auth_options) . ')'); @@ -199,7 +199,7 @@ $prefixes = array('f_', 'a_', 'm_', 'u_'); foreach ($prefixes as $prefix) { $var = $prefix . 'permissions'; - if (sizeof(${$var})) + if (count(${$var})) { foreach (${$var} as $auth_option => $l_ary) { diff --git a/phpBB/develop/check_flash_bbcodes.php b/phpBB/develop/check_flash_bbcodes.php index 5dc112bfc0..282adad229 100644 --- a/phpBB/develop/check_flash_bbcodes.php +++ b/phpBB/develop/check_flash_bbcodes.php @@ -51,7 +51,7 @@ function check_table_flash_bbcodes($table_name, $id_field, $content_field, $uid_ $ids = get_table_flash_bbcode_pkids($table_name, $id_field, $content_field, $uid_field, $bitfield_field); - $size = sizeof($ids); + $size = count($ids); if ($size) { echo "Found $size potentially dangerous flash bbcodes.\n"; diff --git a/phpBB/develop/create_variable_overview.php b/phpBB/develop/create_variable_overview.php index ace2e4d953..da9a4fe683 100644 --- a/phpBB/develop/create_variable_overview.php +++ b/phpBB/develop/create_variable_overview.php @@ -489,12 +489,12 @@ foreach ($lang_references as $lang_var => $filenames) $html_data .= '<b>' . $lang_var . '</b><ul>'; - if (sizeof($filenames) != 1) + if (count($filenames) != 1) { fwrite($common_fp, (($entry['common']) ? ",\n" : '') . "\t'$var' => '" . $lang[$var] . "'"); $entry['common'] = true; } - else if (sizeof($filenames) == 1) + else if (count($filenames) == 1) { // Merge logical - hardcoded $fname = (preg_match('#^(' . implode('|', $merge) . ')#', $filenames[0], $match)) ? $match[0] . '.php' : str_replace($ext, 'php', $filenames[0]); diff --git a/phpBB/develop/regex_idn.php b/phpBB/develop/regex_idn.php index d871695c50..30373f8de3 100644 --- a/phpBB/develop/regex_idn.php +++ b/phpBB/develop/regex_idn.php @@ -120,7 +120,7 @@ do $pct_encoded = "%[\dA-F]{2}"; $unreserved = "$add_chars\pL0-9\-._~"; $sub_delims = ($inline) ? '!$&\'(*+,;=' : '!$&\'()*+,;='; - $scheme = ($inline) ? '[a-z][a-z\d+]*': '[a-z][a-z\d+\-.]*' ; // avoid automatic parsing of "word" in "last word.http://..." + $scheme = ($inline) ? '[a-z][a-z\d+]*(?<!javascript)': '[a-z][a-z\d+\-.]*(?<!javascript)' ; // avoid automatic parsing of "word" in "last word.http://..." $pchar = "(?:[^$remove_chars]*[$unreserved$sub_delims:@|]+|$pct_encoded)"; // rfc: no "|" $reg_name = "(?:[^$remove_chars]*[$unreserved$sub_delims:@|]+|$pct_encoded)+"; // rfc: * instead of + and no "|" and no "@" and no ":" (included instead of userinfo) diff --git a/phpBB/develop/search_fill.php b/phpBB/develop/search_fill.php index 07c4024b2f..4f684b5b27 100644 --- a/phpBB/develop/search_fill.php +++ b/phpBB/develop/search_fill.php @@ -89,7 +89,7 @@ for(;$postcounter <= $max_post_id; $postcounter += $batchsize) $rowset = $db->sql_fetchrowset($result); $db->sql_freeresult($result); - $post_rows = sizeof($rowset); + $post_rows = count($rowset); if( $post_rows ) { diff --git a/phpBB/docs/CHANGELOG.html b/phpBB/docs/CHANGELOG.html index 266a65a9c0..dc68e62f49 100644 --- a/phpBB/docs/CHANGELOG.html +++ b/phpBB/docs/CHANGELOG.html @@ -50,6 +50,18 @@ <ol> <li><a href="#changelog">Changelog</a> <ul> + <li><a href="#v327">Changes since 3.2.7</a></li> + <li><a href="#v326">Changes since 3.2.6</a></li> + <li><a href="#v326rc1">Changes since 3.2.6-RC1</a></li> + <li><a href="#v325">Changes since 3.2.5</a></li> + <li><a href="#v325rc1">Changes since 3.2.5-RC1</a></li> + <li><a href="#v324">Changes since 3.2.4</a></li> + <li><a href="#v324rc1">Changes since 3.2.4-RC1</a></li> + <li><a href="#v323">Changes since 3.2.3</a></li> + <li><a href="#v323rc2">Changes since 3.2.3-RC2</a></li> + <li><a href="#v323rc1">Changes since 3.2.3-RC1</a></li> + <li><a href="#v322">Changes since 3.2.2</a></li> + <li><a href="#v321">Changes since 3.2.1</a></li> <li><a href="#v320">Changes since 3.2.0</a></li> <li><a href="#v320rc1">Changes since 3.2.0-RC1</a></li> <li><a href="#v320b2">Changes since 3.2.0-b2</a></li> @@ -57,6 +69,7 @@ <li><a href="#v320a2">Changes since 3.2.0-a2</a></li> <li><a href="#v320a1">Changes since 3.2.0-a1</a></li> <li><a href="#v31x">Changes since 3.1.x</a></li> + <li><a href="#v3111">Changes since 3.1.11</a></li> <li><a href="#v3110">Changes since 3.1.10</a></li> <li><a href="#v319">Changes since 3.1.9</a></li> <li><a href="#v318">Changes since 3.1.8</a></li> @@ -126,6 +139,558 @@ <div class="inner"> <div class="content"> + <a name="v327"></a><h3>Changes since 3.2.7</h3> + <h4>Bug</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13175">PHPBB3-13175</a>] - External accounts can be linked to more than one local account</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14459">PHPBB3-14459</a>] - Check language input for group</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15211">PHPBB3-15211</a>] - Emoji characters in forum name causing SQL errors</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15885">PHPBB3-15885</a>] - Group rank not displaying on memberlist_body</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15897">PHPBB3-15897</a>] - Unicode Characters in Attachment Comment Causes mySQL Error </li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15932">PHPBB3-15932</a>] - Users can delete their attachments in the UCP, even if the post is locked</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15961">PHPBB3-15961</a>] - SMTP support for TLS is forcing use of deprecated TLS 1.0</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15974">PHPBB3-15974</a>] - The link "Back to previous page" can redirect to another page, not the previous one</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15976">PHPBB3-15976</a>] - Changing account settings without changing password resets user_passchg</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15982">PHPBB3-15982</a>] - Q&A captcha plug-in still throws PHP 7.2.x countable warning</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16003">PHPBB3-16003</a>] - Post count not updated when deleting only post in topic</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16021">PHPBB3-16021</a>] - Recognize number of Template Event instances in events.md file</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16040">PHPBB3-16040</a>] - Topic Icon with space in filename isn't displayed by viewforum_body.html</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16048">PHPBB3-16048</a>] - Unable to restore any backup from ACP</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16050">PHPBB3-16050</a>] - PHP warning in MCP banning tab on PHP 7.2+</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16053">PHPBB3-16053</a>] - BBCodes using {TEXT} in HTML tags no longer work</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16054">PHPBB3-16054</a>] - Style templates no longer able to login "from any page."</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16055">PHPBB3-16055</a>] - Unable to login using Oauth via Forums, topics or posts</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16061">PHPBB3-16061</a>] - Migrator never drops unique indexes</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16063">PHPBB3-16063</a>] - board_dst config value is not removed from config table after conversion</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16066">PHPBB3-16066</a>] - Banned or suspended user receives "The submitted form was invalid. Try submitting again."</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16071">PHPBB3-16071</a>] - Undefined index for custom attachments groups</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16073">PHPBB3-16073</a>] - Fix warning in ACP version check</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16074">PHPBB3-16074</a>] - Twemoji -fe0f sequence not rendering</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16075">PHPBB3-16075</a>] - PM filter “sent to my default usergroup” triggers array to string conversion warning</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16080">PHPBB3-16080</a>] - Warnings When a Style exists on database but not on FTP</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16093">PHPBB3-16093</a>] - Attach row template always gets displayed with JS disabled</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16096">PHPBB3-16096</a>] - MySQL full text search always uses MyISAM limits</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16124">PHPBB3-16124</a>] - Incorrect users search by last visit time in memberlist.php</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16126">PHPBB3-16126</a>] - AppVeyor builds fail due to chocolatey being unable to install PHP</li> + </ul> + <h4>Improvement</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15745">PHPBB3-15745</a>] - Hardcoded lang in credit line</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15886">PHPBB3-15886</a>] - Group helper functions</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15946">PHPBB3-15946</a>] - Add event - core.posting_modify_row_data</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15967">PHPBB3-15967</a>] - Unambiguous wording in user activation request email to Admin/Moderator</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15984">PHPBB3-15984</a>] - Use of 'Cache-Control: public' for serving files</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16000">PHPBB3-16000</a>] - Provide link to PHP Date Function in both ACP and UCP</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16013">PHPBB3-16013</a>] - Do not prevent username changes in ACP</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16019">PHPBB3-16019</a>] - Deny prosilver's uninstallation</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16024">PHPBB3-16024</a>] - Add core.topic_review_modify_sql_ary</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16025">PHPBB3-16025</a>] - Add 2 template events *_author_username_{append/prepend}</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16047">PHPBB3-16047</a>] - ACP Private Messages: Wording could be better</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16058">PHPBB3-16058</a>] - Remove sudo required from travis config</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16065">PHPBB3-16065</a>] - Undefined index: user_ip in oauth.php</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16068">PHPBB3-16068</a>] - Incorrect docblock parameter types</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16070">PHPBB3-16070</a>] - Remove support for WebSTAR and Xitami</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16078">PHPBB3-16078</a>] - Use chrome webdriver for UI tests</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16089">PHPBB3-16089</a>] - Add core.confirm_box_ajax_before</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16097">PHPBB3-16097</a>] - Add core.viewtopic_gen_sort_selects_before</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16101">PHPBB3-16101</a>] - Add Referrer-Policy header</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16102">PHPBB3-16102</a>] - Add core.posting_modify_post_subject</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16103">PHPBB3-16103</a>] - Add core.pm_modify_message_subject</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16106">PHPBB3-16106</a>] - Add core.mcp_main_before</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16107">PHPBB3-16107</a>] - Add mcp_move_destination_forum_before|after</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16108">PHPBB3-16108</a>] - Add topiclist_row_topic_by_author_before|after</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16109">PHPBB3-16109</a>] - Custom Profile Field visibility is incorrectly explained</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16111">PHPBB3-16111</a>] - Add core.message_history_modify_sql_ary</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16113">PHPBB3-16113</a>] - Add core.mcp_topic_modify_sql_ary</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16114">PHPBB3-16114</a>] - Add 2 mcp_topic_post_author_full_{append/prepend}</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16127">PHPBB3-16127</a>] - Add UI for Mass email $max_chunk_size</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16129">PHPBB3-16129</a>] - The attachment's ALT tag is supposed to describe the image, not the file.</li> + </ul> + <h4>Task</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16067">PHPBB3-16067</a>] - Define trusty build environment for travis builds</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16112">PHPBB3-16112</a>] - Update composer dependencies to latest</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16119">PHPBB3-16119</a>] - The text input for poll question has a too high maxlength attribute</li> + </ul> + + <a name="v326"></a><h3>Changes since 3.2.6</h3> + <h4>Bug</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16034">PHPBB3-16034</a>] - Links created with [url=] - are sometimes incorrectly shortened</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16036">PHPBB3-16036</a>] - Cannot login with 3.2.6</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16037">PHPBB3-16037</a>] - Private message ViewFolder Broken</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16039">PHPBB3-16039</a>] - Unable to change announcement to standard topic due to missing global</li> + </ul> + <h4>Improvement</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16042">PHPBB3-16042</a>] - Use S_LOGIN_REDIRECT to output login form token</li> + </ul> + + <a name="v326rc1"></a><h3>Changes since 3.2.6-RC1</h3> + <h4>Bug</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16027">PHPBB3-16027</a>] - Appveyor builds fail on PHP 7.0</li> + </ul> + <h4>Security Issue</h4> + <ul> + <li>[SECURITY-231] - Remote avatar functionality allows checking for files and ports on local network</li> + <li>[SECURITY-235] - Fulltext native search can be used to cause long execution times</li> + </ul> + <h4>Hardening</h4> + <ul> + <li>[SECURITY-228] - Require form token in login_box</li> + <li>[SECURITY-233] - SMTP auth data shouldn't be cached</li> + <li>[SECURITY-234] - Main website URL in Admin Control Panel should not support JS URLs</li> + </ul> + + <a name="v325"></a><h3>Changes since 3.2.5</h3> + <h4>Bug</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15509">PHPBB3-15509</a>] - Update database: info message is to scary</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15869">PHPBB3-15869</a>] - Cookies Problem with domains with special chars</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15876">PHPBB3-15876</a>] - Mysql 5.7 support Q&A plugin</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15883">PHPBB3-15883</a>] - No error for invalid usernames on bulk add to usergroup</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15904">PHPBB3-15904</a>] - PHP warning when accessing modules in ACP System tab</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15917">PHPBB3-15917</a>] - Unapproved posts count towards forum post count</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15918">PHPBB3-15918</a>] - Ban reason messages show backslash (\) before apostrophe -- ex. (don\'t).</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15919">PHPBB3-15919</a>] - Lint test throws PHP warnings due to node modules folder</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15931">PHPBB3-15931</a>] - Issues in PM report emails</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15954">PHPBB3-15954</a>] - Some calls to include() don't have a safeguard</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15957">PHPBB3-15957</a>] - User preferences show notification method "both" with disabled Jabber in ACP</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15959">PHPBB3-15959</a>] - Travis Network Test is Failing for news.cnet.com</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15965">PHPBB3-15965</a>] - Console command to handle thumbnails have files directory hardcoded</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15975">PHPBB3-15975</a>] - Delete or prune an user doesn't remove its entries in the user_notifications table</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15986">PHPBB3-15986</a>] - Add missing language key for posting.php</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15996">PHPBB3-15996</a>] - Invalid data provider function name in migrator_tool_permission_test</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16006">PHPBB3-16006</a>] - Duplicate form IDs in UCP oauth form</li> + </ul> + <h4>Improvement</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15884">PHPBB3-15884</a>] - Add memberlist_body_* events</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15889">PHPBB3-15889</a>] - Add core.memberlist_modify_memberrow_sql</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15890">PHPBB3-15890</a>] - Add core.memberlist_modify_viewprofile_sql</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15891">PHPBB3-15891</a>] - Add core.memberlist_modify_view_profile_template_vars</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15898">PHPBB3-15898</a>] - Add core.ucp_pm_compose_template</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15899">PHPBB3-15899</a>] - Add core.modify_attachment_sql_ary_on_* events</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15901">PHPBB3-15901</a>] - Add mcp_post_* template events</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15910">PHPBB3-15910</a>] - Pass object arguments by reference implicitly</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15914">PHPBB3-15914</a>] - Add core.modify_memberlist_viewprofile_group_sql and core.modify_memberlist_viewprofile_group_data</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15915">PHPBB3-15915</a>] - Add template events to posting_attach_body.html</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15924">PHPBB3-15924</a>] - Move from precise to trusty builds</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15926">PHPBB3-15926</a>] - Deny installs on PHP >= 7.3@dev - Increase min. req. to 5.4.7</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15928">PHPBB3-15928</a>] - Remove support for backup download</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15939">PHPBB3-15939</a>] - Pagination docblocks</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15941">PHPBB3-15941</a>] - Replace MAX SQL in functions_posting.php</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15942">PHPBB3-15942</a>] - Array to string conversion when permanently deleting a post</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15948">PHPBB3-15948</a>] - Add core.mcp_change_topic_type_after/before</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15949">PHPBB3-15949</a>] - [Template] - ucp_profile_signature_posting_editor_options_prepend</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15950">PHPBB3-15950</a>] - Add SQL transactions to mcp_main.php</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15960">PHPBB3-15960</a>] - Add SQL transactions to functions_admin.php</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15970">PHPBB3-15970</a>] - Add core.message_admin_form_submit_before</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15972">PHPBB3-15972</a>] - Add core.markread_after</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15992">PHPBB3-15992</a>] - Fix breadcrumb schema</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15995">PHPBB3-15995</a>] - Add core.memberlist_modify_sort_pagination_params</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15997">PHPBB3-15997</a>] - Increase webdriver timeout for UI tests</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16001">PHPBB3-16001</a>] - Append data to the OAuth's redirect URL</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16009">PHPBB3-16009</a>] - Display OAuth login's buttons in a row.</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16010">PHPBB3-16010</a>] - Automatically check order of events in events.md file</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16018">PHPBB3-16018</a>] - Update composer and dependencies for 3.2.6</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-16020">PHPBB3-16020</a>] - Fix placement of event viewforum_body_topic_author_username_append</li> + </ul> + <h4>New Feature</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15944">PHPBB3-15944</a>] - Add core.posting_modify_quote_attributes</li> + </ul> + <h4>Task</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15921">PHPBB3-15921</a>] - Update TextFormatter to 1.3.2</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15953">PHPBB3-15953</a>] - pm reported missing border color</li> + </ul> + + <a name="v325rc1"></a><h3>Changes since 3.2.5-RC1</h3> + <h4>Bug</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15888">PHPBB3-15888</a>] - Update link to user guide</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15893">PHPBB3-15893</a>] - Call to undefined $user in phpbb_format_quote() when BBCodes are disabled</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15911">PHPBB3-15911</a>] - SQL general error on DB update from 3.0 branch</li> + </ul> + <h4>Hardening</h4> + <ul> + <li>[SECURITY-229] - Update to latest version of jQuery 1.x and add ajax prefilter</li> + </ul> + + <a name="v324"></a><h3>Changes since 3.2.4</h3> + <h4>Bug</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15665">PHPBB3-15665</a>] - MSSQL implementation crashes when upload directory > 2GB</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15858">PHPBB3-15858</a>] - Unapproved User(s) appearing as Guest in Team Page.</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15867">PHPBB3-15867</a>] - Contact form without class</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15871">PHPBB3-15871</a>] - PHP 7.1+ warning in ACP extensions module</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15875">PHPBB3-15875</a>] - BBCode parsing error (PHP fatal error)</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15881">PHPBB3-15881</a>] - Login keys are not reset after password update in some cases</li> + </ul> + <h4>Improvement</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15542">PHPBB3-15542</a>] - Some JS files being called without assets version</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15859">PHPBB3-15859</a>] - Modify the topic ordering if needed</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15863">PHPBB3-15863</a>] - Modify the topic sort ordering from the beginning</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15870">PHPBB3-15870</a>] - Modify the forum ID to handle the correct display of viewtopic if needed</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15872">PHPBB3-15872</a>] - Add show_user_activity to display_user_activity_modify_actives</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15873">PHPBB3-15873</a>] - Event to add/modify MCP report details template data.</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15878">PHPBB3-15878</a>] - Add attachment to core.ucp_pm_view_message</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15879">PHPBB3-15879</a>] - Modify attachment's poster_id for get_submitted_attachment_data</li> + </ul> + + <a name="v324rc1"></a><h3>Changes since 3.2.4-RC1</h3> + <h4>Bug</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15860">PHPBB3-15860</a>] - Backups filenames arent saved in the expected format</li> + </ul> + <h4>Security Issue</h4> + <ul> + <li>[SECURITY-227] - Phar deserialization in ACP leads to Remote Code Execution</li> + </ul> + + <a name="v323"></a><h3>Changes since 3.2.3</h3> + <h4>Bug</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11453">PHPBB3-11453</a>] - phpbb_notification_method_email unnecessarily loads data of banned users.</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12430">PHPBB3-12430</a>] - hilit not removed from URL after search</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13043">PHPBB3-13043</a>] - Fixing HTML5 conformance</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13128">PHPBB3-13128</a>] - sql_query_info, max_matches and charset_type removed from sphinxsearch 2.2.2-beta</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14812">PHPBB3-14812</a>] - No shadow pruning with system cron enabled</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15329">PHPBB3-15329</a>] - View/Edit drafts contain underlying HTML coding</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15420">PHPBB3-15420</a>] - Quote Notification Sent for Edited Posts by Non Author</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15494">PHPBB3-15494</a>] - Users can only be removed once from newly registered users</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15507">PHPBB3-15507</a>] - PHP 7.2 Warning</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15544">PHPBB3-15544</a>] - Migrations don't delete modules in every case</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15552">PHPBB3-15552</a>] - Private Message (PM) "find a member" button "select marked" not working</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15557">PHPBB3-15557</a>] - Used composer version has bug with PHP 7.2</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15583">PHPBB3-15583</a>] - Updating session time in AJAX request ignores 60 seconds check</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15593">PHPBB3-15593</a>] - Disabling "print view" (permission or private messages settings) actually doesn't block the feature</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15600">PHPBB3-15600</a>] - Ban reasons are not escaped in mcp_ban.html template</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15604">PHPBB3-15604</a>] - Appveyor builds unable to download and unpack MSSQL drivers</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15606">PHPBB3-15606</a>] - Hide/Reveal 'Profile' Link According to Permission Setting</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15607">PHPBB3-15607</a>] - Board's cookies not deleted on disabled board</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15611">PHPBB3-15611</a>] - Prosilver mobile layout: Misaligned text in user profile</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15612">PHPBB3-15612</a>] - PHP warning with MSSQL on PHP 7.2</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15616">PHPBB3-15616</a>] - Jumpbox doesn't display in the login forum page (access to forum with password)</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15618">PHPBB3-15618</a>] - Team page link always appears when you are logout (anonymous), even if you don't have the permission (unlike memberlist link)</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15619">PHPBB3-15619</a>] - Legends of custom profile fields could be hidden in memberlist, when viewing an user group</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15620">PHPBB3-15620</a>] - Avatar gallery can be unusable on multilingual boards, unless people use the board default language</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15622">PHPBB3-15622</a>] - Quoting messages (while viewing one, not inside post editor) can return a wrong chain</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15637">PHPBB3-15637</a>] - Event list only has first line of PHP event description</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15651">PHPBB3-15651</a>] - Migration 'if' conditions only support booleans</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15659">PHPBB3-15659</a>] - retrieve_block_vars generates warnings in PHP 7.2</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15666">PHPBB3-15666</a>] - Language system is not fully supported in Twig</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15670">PHPBB3-15670</a>] - Group forum permission: Can see forum gives NO SQL ERROR</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15673">PHPBB3-15673</a>] - Duplicated links for (ACP,MCP,FAQ) in QuickLinks and main nav bar</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15680">PHPBB3-15680</a>] - INSTALL.html should point to 3.2 documentation instead of 3.1</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15693">PHPBB3-15693</a>] - gen_rand_string() don't return a string with the expected length</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15695">PHPBB3-15695</a>] - gen_rand_string can return less characters than expected</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15700">PHPBB3-15700</a>] - {T_THEME_LANG_NAME} template variable could be wrong when log off</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15705">PHPBB3-15705</a>] - phpbbcli language parse error in PHP <= 5.5.38</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15716">PHPBB3-15716</a>] - OAuth link information remains after deleting a user, causes fatal exception</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15717">PHPBB3-15717</a>] - Old email address missing from log when user changes email address</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15723">PHPBB3-15723</a>] - gen_rand_string() return wrong number or characters sometimes</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15733">PHPBB3-15733</a>] - Remove unused variables related to deprecated flood control</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15742">PHPBB3-15742</a>] - Remove get_magic_quotes_gpc from type_cast_helper</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15751">PHPBB3-15751</a>] - Warning when update with CLI</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15755">PHPBB3-15755</a>] - Broken events in /phpbb/attachment/delete.php</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15758">PHPBB3-15758</a>] - String INSECURE_REDIRECT is not shown translated</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15770">PHPBB3-15770</a>] - Sphinx assertion fails on unread posts when exceeding an offset of 999</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15788">PHPBB3-15788</a>] - Return button from privacy policy shows wrong text</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15817">PHPBB3-15817</a>] - Unable to install in Oracle 11R2 Express</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15824">PHPBB3-15824</a>] - UI test framework Broken for extensions</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15830">PHPBB3-15830</a>] - 'core.modify_notification_message' event is useless</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15849">PHPBB3-15849</a>] - PHP 7.2 compat for bitfield class</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15852">PHPBB3-15852</a>] - IPv6 address not working in Whois</li> + </ul> + <h4>Improvement</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10432">PHPBB3-10432</a>] - Don't require username when user forgets password</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11500">PHPBB3-11500</a>] - on Custom profile fields the field_ident field lacks name</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12739">PHPBB3-12739</a>] - Make the font color palette in ACP same as Prosilver</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14656">PHPBB3-14656</a>] - Add a list-unsubscribe header with the unsubscribe URL</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14990">PHPBB3-14990</a>] - Add core event to the Twig environment</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15554">PHPBB3-15554</a>] - Simple footer after load js</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15579">PHPBB3-15579</a>] - Add core.ucp_main_front_modify_sql and core.ucp_main_front_modify_template_vars</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15590">PHPBB3-15590</a>] - Add PHP events after adding, updating and deleting BBCodes</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15628">PHPBB3-15628</a>] - newtopic_notify.txt does not have directly link to the new topic</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15638">PHPBB3-15638</a>] - Add word-break for overflowing.</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15642">PHPBB3-15642</a>] - String to be used in HTML element contains ">"</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15656">PHPBB3-15656</a>] - Add "View post" link in the mod logs on the ACP</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15661">PHPBB3-15661</a>] - Add core.viewtopic_modify_poll_ajax_data</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15662">PHPBB3-15662</a>] - Add $this->template to core.modify_notification_message</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15668">PHPBB3-15668</a>] - Change JQuery .load(fn) event to .on('load',fn)</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15674">PHPBB3-15674</a>] - Edit language lines in file en\acp\profile.php</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15683">PHPBB3-15683</a>] - Better error message when commit message has CRLF</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15696">PHPBB3-15696</a>] - 'if' module tool should support calling other tools</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15706">PHPBB3-15706</a>] - [Template] - mcp_post_report_buttons_top_*</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15719">PHPBB3-15719</a>] - Add core event on viewtopic post_list query for query modification</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15726">PHPBB3-15726</a>] - Implement selective purge in APCu cache driver</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15735">PHPBB3-15735</a>] - [Template] - *_content_after (for posts)</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15737">PHPBB3-15737</a>] - [PHP] - Add $user_rows to core.delete_user_before</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15762">PHPBB3-15762</a>] - Topics per page Conformity</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15768">PHPBB3-15768</a>] - Add a license to a repository</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15771">PHPBB3-15771</a>] - Q&A configuration instructions not optilmal</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15799">PHPBB3-15799</a>] - Find correct poll for voting animation</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15803">PHPBB3-15803</a>] - Add core events on ucp_pm_compose for additional message list actions</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15819">PHPBB3-15819</a>] - Add core event to functions_posting to modify notifications</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15825">PHPBB3-15825</a>] - Add core.acp_manage_forums_move_content_sql_before</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15826">PHPBB3-15826</a>] - Add core.mcp_main_fork_sql_after</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15827">PHPBB3-15827</a>] - [Template] - Add *_username_{prepend/append} template events</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15831">PHPBB3-15831</a>] - ACP signature update should trigger event</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15832">PHPBB3-15832</a>] - ACP avatar update event</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15833">PHPBB3-15833</a>] - ACP and UCP avatar delete events</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15837">PHPBB3-15837</a>] - Add core.ucp_register_welcome_email_before</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15838">PHPBB3-15838</a>] - Add core.ucp_register_register_after</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15839">PHPBB3-15839</a>] - Add core.ucp_login_link_template_after</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15841">PHPBB3-15841</a>] - Allow postrow pm link to be modified by event</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15848">PHPBB3-15848</a>] - Up-version plupload to v2.3.6 to fix image rotation issues</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15850">PHPBB3-15850</a>] - Use standard SQL cache for notification types</li> + </ul> + <h4>New Feature</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15792">PHPBB3-15792</a>] - [Template] - confirm_delete_body_delete_reason_before</li> + </ul> + <h4>Task</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15596">PHPBB3-15596</a>] - Migrate from data-vocabulary.org to schema.org</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15621">PHPBB3-15621</a>] - Some graphical inconsistencies with colored users groups in posting, UCP and MCP</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15701">PHPBB3-15701</a>] - {SIGNATURE} variable is added in mcp_post.html but not defined in MCP</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15809">PHPBB3-15809</a>] - Allow events with twig syntax</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15857">PHPBB3-15857</a>] - Add rubencm to CREDITS.txt</li> + </ul> + + <a name="v323rc2"></a><h3>Changes since 3.2.3-RC2</h3> + <h4>Bug</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15504">PHPBB3-15504</a>] - phpBB Debug warning in 3.2.2</li> + </ul> + <h4>Improvement</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15740">PHPBB3-15740</a>] - Terms & Privavy hardcoded</li> + </ul> + + <a name="v323rc1"></a><h3>Changes since 3.2.3-RC1</h3> + <h4>Bug</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11847">PHPBB3-11847</a>] - auth_provider_oauth migration must depend on at least one migration that ensures the module tables exist as expected</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15548">PHPBB3-15548</a>] - Dead link in ACP_COOKIE_SETTINGS_EXPLAIN language entry</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15586">PHPBB3-15586</a>] - When creating a module without the modes array a missing 'module_langname' index is accessed</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15613">PHPBB3-15613</a>] - Notification dropdown said to be not RTL compliant</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15627">PHPBB3-15627</a>] - Improve wording of YES_ACCURATE_PM_BUTTON + EXPLAIN</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15678">PHPBB3-15678</a>] - PHP warning in filesystem.php</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15731">PHPBB3-15731</a>] - Fix acp_search language parameters when deleting index</li> + </ul> + <h4>Improvement</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15630">PHPBB3-15630</a>] - Change <b> to <strong> </li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15633">PHPBB3-15633</a>] - Remove extra space in GROUP_MAX_RECIPIENTS_EXPLAIN</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15657">PHPBB3-15657</a>] - Add core.mcp_queue_get_posts_for_posts_query_before and core.mcp_queue_get_posts_modify_post_row</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15676">PHPBB3-15676</a>] - Display privacy policy & terms of use more prominently</li> + </ul> + <h4>Task</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15677">PHPBB3-15677</a>] - Updated dependencies for 3.2.3-RC2</li> + </ul> + + <a name="v322"></a><h3>Changes since 3.2.2</h3> + <h4>Bug</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14936">PHPBB3-14936</a>] - Missing language variable INST_ERR_DB</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15491">PHPBB3-15491</a>] - Outdated linkes in installer support page</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15492">PHPBB3-15492</a>] - Permissions role combobox does not work in RTL</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15500">PHPBB3-15500</a>] - Docs outdated for new PHP 5.4.7 requirement</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15502">PHPBB3-15502</a>] - Errors in migrations in 3.2.2 release</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15506">PHPBB3-15506</a>] - Previewing new post empties attachment list of all but first attachment</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15512">PHPBB3-15512</a>] - Avoid reparsing non-existent polls</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15513">PHPBB3-15513</a>] - Signature edit in acp gives error</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15520">PHPBB3-15520</a>] - DbDriver->sql_build_query cant cope with sub-selects</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15522">PHPBB3-15522</a>] - Allow multiple color palettes per page</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15523">PHPBB3-15523</a>] - AdBlocker may cause JS error when using CookieConsent</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15525">PHPBB3-15525</a>] - composer.json License is Invalid/Deprecated</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15526">PHPBB3-15526</a>] - Cast bbcode ID to integer</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15527">PHPBB3-15527</a>] - Cannot interpret the BBCode definition</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15532">PHPBB3-15532</a>] - Update pull request template</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15533">PHPBB3-15533</a>] - Typo in viewtopic_topic_tools.html</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15558">PHPBB3-15558</a>] - phpbb\report\report_handler_post.php</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15559">PHPBB3-15559</a>] - phpbb\report\report_handler_pm.php:56</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15595">PHPBB3-15595</a>] - Migration Module Exists Tool Broken</li> + </ul> + <h4>Improvement</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12579">PHPBB3-12579</a>] - Add BUTTON_ language strings for post & PM buttons</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15495">PHPBB3-15495</a>] - Use transactions for queries in move_forum</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15499">PHPBB3-15499</a>] - Drop HHVM support</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15510">PHPBB3-15510</a>] - Link Orphan attachments in ACP>General to Orphaned attachments page </li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15514">PHPBB3-15514</a>] - Improve accessibility by adding vital info from explanation to a title</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15518">PHPBB3-15518</a>] - Do not attempt to accurately determine whether posters can read private messages in viewtopic</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15528">PHPBB3-15528</a>] - Display the version of the installed styles in acp</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15529">PHPBB3-15529</a>] - Color groups in ACP</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15531">PHPBB3-15531</a>] - Log malformed BBCodes</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15534">PHPBB3-15534</a>] - Outdated ACP extensions database link for phpBB 3.2</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15535">PHPBB3-15535</a>] - Add S_FIRST_POST to postrow on viewtopic</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15537">PHPBB3-15537</a>] - Add events core.search_(native|mysql|postgres|sphinx)_index_before</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15547">PHPBB3-15547</a>] - Add file object to event core.avatar_driver_upload_move_file_before</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15561">PHPBB3-15561</a>] - Add core events for adding columns to MySQL and Postgres search backends</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15568">PHPBB3-15568</a>] - Update depencies to latest versions</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15569">PHPBB3-15569</a>] - Adjust update instructions to suggest file replacement method</li> + </ul> + <h4>New Feature</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15398">PHPBB3-15398</a>] - Add event to oauth login after ID check</li> + </ul> + <h4>Security Issue</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15570">PHPBB3-15570</a>] - Extension version check is restricted to TLS 1.0</li> + </ul> + <h4>Task</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15466">PHPBB3-15466</a>] - Move Nils in CREDITS.txt</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15516">PHPBB3-15516</a>] - Add instructions on running UI tests</li> + </ul> + + <a name="v321"></a><h3>Changes since 3.2.1</h3> + <h4>Security Issue</h4> + <ul> + <li>[SECURITY-211] - URLs with javascript scheme should not be made clickable</li> + </ul> + <h4>Bug</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-7845">PHPBB3-7845</a>] - Error on posting local image when script path is empty</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13214">PHPBB3-13214</a>] - Contact us page textarea looks narrow in responsive mode</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14629">PHPBB3-14629</a>] - acp global quick reply will not enable quick reply correctly</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14857">PHPBB3-14857</a>] - ordinal suffix in dateformat is not handled in translations</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15041">PHPBB3-15041</a>] - Cannot delete Orphaned Attachments when large number of attachments</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15060">PHPBB3-15060</a>] - Online user list fails on notifications</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15089">PHPBB3-15089</a>] - Enable/Disable settings backwards for Cookie Secure</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15133">PHPBB3-15133</a>] - Fast image size library sometimes returns no size or invalid sizes</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15149">PHPBB3-15149</a>] - Unexpected Ctrl+Enter behavior on reply</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15171">PHPBB3-15171</a>] - Confusing bitfield values</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15172">PHPBB3-15172</a>] - $request->server('server_port') is returning wrong port</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15174">PHPBB3-15174</a>] - Unable to purge cache (ext & acp)</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15195">PHPBB3-15195</a>] - Code direction in print view is not defined as "ltr"</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15201">PHPBB3-15201</a>] - Removing style sets user_style to 0</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15224">PHPBB3-15224</a>] - Advanced search in "message text only" crashes with SQL error when using Mysql fulltext search index</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15245">PHPBB3-15245</a>] - Relative URLs in atom feeds broken when accessing via app.php</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15262">PHPBB3-15262</a>] - WebFontConfig google families script issue in 3.2.1</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15266">PHPBB3-15266</a>] - Content visibility events do not allow what they describe</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15273">PHPBB3-15273</a>] - 'COOKIE_PATH_EXPLAIN' does not make sense</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15285">PHPBB3-15285</a>] - Travis tests are failing due to trusty changes</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15292">PHPBB3-15292</a>] - Retina imageset is blurry when displayed in Chrome browser</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15297">PHPBB3-15297</a>] - Current date in board index is broken into lines in RTL</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15298">PHPBB3-15298</a>] - Errors being suppressed in cli</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15303">PHPBB3-15303</a>] - Typo in memcached driver</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15306">PHPBB3-15306</a>] - Error and missing information in core.acp_users_profile_validate event</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15309">PHPBB3-15309</a>] - Improved fix for pagination layout in tables</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15314">PHPBB3-15314</a>] - Wrong class constructor definition for convertor component</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15319">PHPBB3-15319</a>] - Database update v310\style_update_p2 fails to drop sequences</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15320">PHPBB3-15320</a>] - Redis cache does not save keys with expiration date 0 (no expiration)</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15322">PHPBB3-15322</a>] - Wrong return Return-Path in emails</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15331">PHPBB3-15331</a>] - Gravatars cannot be overridden</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15332">PHPBB3-15332</a>] - Dark background is always removed after confirm popup</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15333">PHPBB3-15333</a>] - Callback isn't called when confirm dialog is canceled</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15339">PHPBB3-15339</a>] - Missing acp_send_statistics -> Upgrading to 3.2.0 fails for phpBB 3.0.5</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15346">PHPBB3-15346</a>] - The installer tries to enable all extensions even if they are not enableable</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15347">PHPBB3-15347</a>] - Password updater in cron generates invalid postgres SQL</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15349">PHPBB3-15349</a>] - Cli doesn't check if an extension is enableable before enable it</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15350">PHPBB3-15350</a>] - Links to Plural rules are outdated</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15351">PHPBB3-15351</a>] - Confirm box function does not work with symlink on server config</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15353">PHPBB3-15353</a>] - Invalid HTML in ACP board settings</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15355">PHPBB3-15355</a>] - Empty version field in versioncheck when using the latest version</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15356">PHPBB3-15356</a>] - Avatar remote upload doesn't work</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15361">PHPBB3-15361</a>] - Topic / Forum Icons Look Withered (on Safari)</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15362">PHPBB3-15362</a>] - Excessive value for {NOTIFICATION_TYPES_COLS}</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15365">PHPBB3-15365</a>] - Fix invalidating OPcache</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15367">PHPBB3-15367</a>] - Sphinx search backend doesn't escape special characters</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15368">PHPBB3-15368</a>] - Schema upgrade fails in 3.2.1 when using SQL Server</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15379">PHPBB3-15379</a>] - Reparser cron will always run</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15381">PHPBB3-15381</a>] - L_CONTACT_US_ENABLE_EXPLAIN should specify that "Enable board-wide emails" is also needed for it to work</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15390">PHPBB3-15390</a>] - Admin permissions role tooltip popup has vertical bar running through it.</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15396">PHPBB3-15396</a>] - revert_schema() steps not executed in correct order</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15401">PHPBB3-15401</a>] - Use separate constant for memcached driver config</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15419">PHPBB3-15419</a>] - Sphinx does not search UTF keywords in delta index</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15423">PHPBB3-15423</a>] - Wrong title for topic's "Unappproved posts" icon</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15432">PHPBB3-15432</a>] - Don't remove dark background if fadedark is false</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15433">PHPBB3-15433</a>] - phpbbcli can enable non-existent extension</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15445">PHPBB3-15445</a>] - Git Contribution Guidelines in README.md is outdated</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15464">PHPBB3-15464</a>] - Can't reparse [IMG] - in uppercase</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15475">PHPBB3-15475</a>] - Restore Travis PR commit message validation</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15478">PHPBB3-15478</a>] - core.js $loadingIndicator JavaScript errors</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15489">PHPBB3-15489</a>] - Wrong footer text on forum of type "category"</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15496">PHPBB3-15496</a>] - SQL Error in PostgreSQL Fulltext search when results displayed as topics</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15497">PHPBB3-15497</a>] - Declaration of admin_activate_user::create_insert_array not compatible with base</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15498">PHPBB3-15498</a>] - confirm_box() adds duplicate strings to URLs in extensions</li> + </ul> + <h4>Improvement</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-7488">PHPBB3-7488</a>] - View Only - Categories: No Message</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-9819">PHPBB3-9819</a>] - Move functions definitions out of mcp.php and includes/mcp/mcp_*.php</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12291">PHPBB3-12291</a>] - Allow extensions to use custom topic icons</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12939">PHPBB3-12939</a>] - Drop support for IE <11 on January 2016</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14677">PHPBB3-14677</a>] - Extension update check is not very colorblind / colourblind friendly.</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14820">PHPBB3-14820</a>] - Style Version Missing</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14919">PHPBB3-14919</a>] - Inconsistent use of globals vs class elements in acp_extensions</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14927">PHPBB3-14927</a>] - event core.user_add_modify_data</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14944">PHPBB3-14944</a>] - Add possibility to search for template loop indexes by key</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14950">PHPBB3-14950</a>] - Add possibility to delete a template block with alter_block_array</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14979">PHPBB3-14979</a>] - Remove underline from unread icon</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14994">PHPBB3-14994</a>] - Refactor template->assign_block_var to be consistent with alter_block_array</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14995">PHPBB3-14995</a>] - Add ACP template events acp_ext_list_*_name_after</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15111">PHPBB3-15111</a>] - Fix the typo in ucp_pm_view_messsage</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15134">PHPBB3-15134</a>] - Avatar upload driver should use filesystem service</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15247">PHPBB3-15247</a>] - Add driver for APCu v5.x cache</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15267">PHPBB3-15267</a>] - Hide birthday block if the user cannot view profile</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15291">PHPBB3-15291</a>] - Allow short array notation in event declarations</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15293">PHPBB3-15293</a>] - Prevent skipping file changes in automatic updater</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15307">PHPBB3-15307</a>] - Allow extensions to add custom modes to acp_users module</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15328">PHPBB3-15328</a>] - Disable email/jabber checkbox if notification method isn't supported</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15340">PHPBB3-15340</a>] - Update to plupload 2.3.1, stable for one year</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15352">PHPBB3-15352</a>] - Add text to clarify forum descriptions won't display on categories</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15374">PHPBB3-15374</a>] - Add core event to modify page title in viewforum.php</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15384">PHPBB3-15384</a>] - Add linebreaks to SMTP configuration option explanations</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15385">PHPBB3-15385</a>] - nginx sample config: www redirection, security regex</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15387">PHPBB3-15387</a>] - prosilver: vertical bars on forum rows on index page not full height</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15389">PHPBB3-15389</a>] - Simplify migration between event names</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15391">PHPBB3-15391</a>] - Remove not needed image rendering from topic/forum images</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15394">PHPBB3-15394</a>] - Add $user_cache and $post_edit_list to core.viewtopic_modify_post_row</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15408">PHPBB3-15408</a>] - Reject duplicate BBCodes in ACP</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15409">PHPBB3-15409</a>] - Add u_action to core.acp_users_overview_run_quicktool</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15442">PHPBB3-15442</a>] - Allow unsafe HTML in bbcode.html</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15444">PHPBB3-15444</a>] - Merge duplicate BBCodes via a migration</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15446">PHPBB3-15446</a>] - Add event core.acp_profile_action</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15447">PHPBB3-15447</a>] - Add event core.acp_profile_modify_profile_row</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15451">PHPBB3-15451</a>] - [EVENT] - mcp_topic_postrow_attachments_before/after</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15452">PHPBB3-15452</a>] - [EVENT] - mcp_topic_postrow_post_before</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15453">PHPBB3-15453</a>] - Add event in acp_language after delete language</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15454">PHPBB3-15454</a>] - event - mcp_queue_approve_details_template</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15470">PHPBB3-15470</a>] - attachment boxes need there own font-size</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15471">PHPBB3-15471</a>] - Add core events to ACP when pruning a forum</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15476">PHPBB3-15476</a>] - Add core event before search rows are edited</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15485">PHPBB3-15485</a>] - Add template event to forumlist_body > forum images</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15486">PHPBB3-15486</a>] - Add core event to the function user_add() to modify notifications data</li> + </ul> + <h4>New Feature</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13344">PHPBB3-13344</a>] - Add new events for logging</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15122">PHPBB3-15122</a>] - Support using memcached instead of memcache</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15372">PHPBB3-15372</a>] - Add a "Can view topics" permission</li> + </ul> + <h4>Sub-task</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13150">PHPBB3-13150</a>] - [Event] - core.phpbb_log_get_topic_auth_sql_after</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15468">PHPBB3-15468</a>] - Add a service to merge duplicate BBCodes</li> + </ul> + <h4>Task</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15179">PHPBB3-15179</a>] - Update 3.2.x dependencies and fix Twig > 1.25 compatibility</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15304">PHPBB3-15304</a>] - Update s9e/text-formatter dependency</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15455">PHPBB3-15455</a>] - Margin discrepancy due to <!-- INCLUDE jumpbox.html --></li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15457">PHPBB3-15457</a>] - Update s9e/text-formatter dependency</li> + </ul> + <a name="v320"></a><h3>Changes since 3.2.0</h3> <h4>Bug</h4> <ul> @@ -718,6 +1283,53 @@ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14265">PHPBB3-14265</a>] - Make all tables available in the container</li> </ul> + <a name="v3111"></a><h3>Changes since 3.1.11</h3> + + <h4>Security Issue</h4> + <ul> + <li>[SECURITY-211] - URLs with javascript scheme should not be made clickable</li> + </ul> + <h4>Bug</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-9533">PHPBB3-9533</a>] - phpbb_own_realpath() doesn't always replicate realpath() behaviour</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12835">PHPBB3-12835</a>] - Jump-box dropdown menu doesn't expand with according to line length in IE8</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13360">PHPBB3-13360</a>] - rename_too_long_indexes migration never deleted the old unique index</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13464">PHPBB3-13464</a>] - problem with drop down options and Arabic letters in chrome</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13574">PHPBB3-13574</a>] - Last post not showing in "Active topics" when Prosilver goes responsive</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15174">PHPBB3-15174</a>] - Unable to purge cache (ext & acp)</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15285">PHPBB3-15285</a>] - Travis tests are failing due to trusty changes</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15303">PHPBB3-15303</a>] - Typo in memcached driver</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15347">PHPBB3-15347</a>] - Password updater in cron generates invalid postgres SQL</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15367">PHPBB3-15367</a>] - Sphinx search backend doesn't escape special characters</li> + </ul> + <h4>Improvement</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10122">PHPBB3-10122</a>] - [list=] - should support "none", along with CSS2 types</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11063">PHPBB3-11063</a>] - Change version check to SSL</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14820">PHPBB3-14820</a>] - Style Version Missing</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14919">PHPBB3-14919</a>] - Inconsistent use of globals vs class elements in acp_extensions</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14927">PHPBB3-14927</a>] - event core.user_add_modify_data</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14944">PHPBB3-14944</a>] - Add possibility to search for template loop indexes by key</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14995">PHPBB3-14995</a>] - Add ACP template events acp_ext_list_*_name_after</li> + </ul> + <h4>New Feature</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13344">PHPBB3-13344</a>] - Add new events for logging</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-15122">PHPBB3-15122</a>] - Support using memcached instead of memcache</li> + </ul> + <h4>Sub-task</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11182">PHPBB3-11182</a>] - Ensure that template files use L_COLON instead of colons.</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11676">PHPBB3-11676</a>] - generate_text_for_storage on includes/acp/acp_users.php</li> + </ul> + <h4>Task</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10758">PHPBB3-10758</a>] - Improve Functional Test Code Coverage</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10791">PHPBB3-10791</a>] - Add a section for extensions to readme.html</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10792">PHPBB3-10792</a>] - Add a section for 3.0 to 3.1 upgrades to install.html</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13874">PHPBB3-13874</a>] - Add master to sami API docs</li> + </ul> + <a name="v3110"></a><h3>Changes since 3.1.10</h3> <h4>Bug</h4> diff --git a/phpBB/docs/CREDITS.txt b/phpBB/docs/CREDITS.txt index 2df7543ce1..90e9a31127 100644 --- a/phpBB/docs/CREDITS.txt +++ b/phpBB/docs/CREDITS.txt @@ -20,15 +20,16 @@ phpBB Project Manager: Marshalrusty (Yuriy Rusko) -phpBB Product Manager: naderman (Nils Adermann) - phpBB Lead Developer: Marc (Marc Alexander) phpBB Developers: bantu (Andreas Fischer) CHItA (Máté Bartus) + Derky (Derk Ruitenbeek) Elsensee (Oliver Schramm) + Hanakin (Michael Miday) + MichaelC (Michael Cullum) Nicofuma (Tristan Darricau) - prototech (Cesar Gallegos) + rubencm (Rubén Calvo) For a list of phpBB Team members, please see: http://www.phpbb.com/about/team/ @@ -41,7 +42,10 @@ https://github.com/phpbb/phpbb/graphs/contributors phpBB Project Manager: theFinn (James Atkinson) [Founder - 04/2007] SHS` (Jonathan Stanley) -phpBB Lead Developer: Acyd Burn (Meik Sievertsen) [09/2005 - 01/2010] +phpBB Product Manager: naderman (Nils Adermann) [02/2016 - 02/2017] + +phpBB Lead Developer: naderman (Nils Adermann) [01/2010 - 02/2016] + Acyd Burn (Meik Sievertsen) [09/2005 - 01/2010] psoTFX (Paul S. Owen) [2001 - 09/2005] phpBB Developers: A_Jelly_Doughnut (Josh Woody) [01/2010 - 11/2010] @@ -61,6 +65,7 @@ phpBB Developers: A_Jelly_Doughnut (Josh Woody) [01/2010 - 11/2010] kellanved (Henry Sudhof) [04/2007 - 03/2011] nickvergessen (Joas Schilling)[04/2010 - 12/2015] Oleg (Oleg Pudeyev) [01/2011 - 05/2013] + prototech (Cesar Gallegos) [01/2014 - 12/2016] rxu (Ruslan Uzdenov) [04/2010 - 12/2012] TerraFrost (Jim Wigginton) [04/2009 - 01/2011] ToonArmy (Chris Smith) [06/2008 - 11/2011] @@ -99,3 +104,6 @@ Text_Diff-0.2.1 http://pear.php.net/package/Text_Diff MIT licenced: Symfony2 (c) 2004-2011 Fabien Potencier, https://symfony.com/ Cookie Consent (c) 2015 Silktide Ltd, https://cookieconsent.insites.com + +Emoji by: +Twemoji (c) 2018 Twitter, Inc, https://twemoji.twitter.com/ diff --git a/phpBB/docs/INSTALL.html b/phpBB/docs/INSTALL.html index 956a384263..4f7f07d3dc 100644 --- a/phpBB/docs/INSTALL.html +++ b/phpBB/docs/INSTALL.html @@ -44,7 +44,7 @@ <p> A basic overview of running phpBB can be found in the accompanying <a href="README.html">README</a> file. Please ensure you read that document in addition to this! For more detailed information on using, installing, - updating and converting phpBB you should read <a href="https://www.phpbb.com/support/docs/en/3.1/ug/">the documentation</a> + updating and converting phpBB you should read <a href="https://www.phpbb.com/support/docs/en/3.2/ug/">the documentation</a> available online. </p> </div> @@ -147,7 +147,7 @@ <li>Oracle</li> </ul> </li> - <li><strong>PHP 5.4.0+</strong> with support for the database you intend to use.</li> + <li><strong>PHP 5.4.7+</strong> but less than <strong>PHP 7.3</strong> with support for the database you intend to use.</li> <li>The following PHP modules are required: <ul> <li>json</li> @@ -159,7 +159,6 @@ <li>zlib Compression support</li> <li>Remote FTP support</li> <li>XML support</li> - <li>ImageMagick support</li> <li>GD Support</li> </ul> </li> @@ -269,11 +268,11 @@ <a name="update_full"></a><h3>4.i. Full package</h3> - <p>The full package is normally meant for new installations only, but if you want to replace all source files, this package comes in handy.</p> + <p>Updating using the full package is the recommended update method for boards without modifications to core phpBB files.</p> - <p>First, you should make a copy of your existing <code>config.php</code> file; keep it in a safe place! Next, delete all the existing phpBB files, you may want to leave your <code>files/</code>, <code>images/</code> and <code>ext/</code> directories in place, otherwise you will lose your file attachments, uploaded images and get error due to missing extension files. You can leave alternative styles in place too. With this complete, you can upload the new phpBB files (see <a href="#install">New installation</a> for details if necessary). Once complete, copy back your saved <code>config.php</code>, replacing the new one. Another method is to just <strong>replace</strong> the existing files with the files from the full package - though make sure you do <strong>not</strong> overwrite your config.php file.</p> + <p>First, you should make a copy of your existing <code>config.php</code> file; keep it in a safe place! Next, delete all the existing phpBB files, you should leave your <code>files/</code>, <code>images/</code> and <code>ext/</code> directories in place, otherwise you will lose your file attachments, uploaded images and get errors due to missing extension files. You can leave alternative styles in place too. With this complete, you can upload the new phpBB files (see <a href="#install">New installation</a> for details if necessary). Once complete, copy back your saved <code>config.php</code>, replacing the new one. Another method is to just <strong>replace</strong> the existing files with the files from the full package - though make sure you do <strong>not</strong> overwrite your config.php file.</p> - <p>You should now got to <code>/install/app.php/update</code> which will display a warning: <strong>No valid update directory was found, please make sure you uploaded the relevant files</strong>. Beneath that warning you will see a radion button <em>Update database only</em>, just click <strong>Submit</strong>. Depending on your previous version this will make a number of database changes. You may receive <em>FAILURES</em> during this procedure. They should not be a cause for concern unless you see an actual <em>ERROR</em>, in which case the script will stop (in this case you should seek help via our forums or bug tracker). If you have shell access to your server, you may wish to update via the command line interface. From your board's root, execute the following command: <code>php bin/phpbbcli.php --safe-mode db:migrate</code>.</p> + <p>You should now got to <code>/install/app.php/update</code> which will display a warning: <strong>No valid update directory was found, please make sure you uploaded the relevant files</strong>. Beneath that warning you will see a radio button <em>Update database only</em>, just click <strong>Submit</strong>. Depending on your previous version this will make a number of database changes. You may receive <em>FAILURES</em> during this procedure. They should not be a cause for concern unless you see an actual <em>ERROR</em>, in which case the script will stop (in this case you should seek help via our forums or bug tracker). If you have shell access to your server, you may wish to update via the command line interface. From your board's root, execute the following command: <code>php bin/phpbbcli.php --safe-mode db:migrate</code>.</p> <p>Once <code>/install/app.php/update</code> has completed, it displays the success message: <strong>The database update was successful</strong>. You may proceed to the Administration Control Panel and then remove the install directory as advised.</p> @@ -301,7 +300,7 @@ <a name="update_auto"></a><h3>4.iv. Automatic update package</h3> - <p>This update method is the recommended method for updating. This package detects changed files automatically and merges in changes if needed.</p> + <p>This update method is only recommended for installations with modifications to core phpBB files. This package detects changed files automatically and merges in changes if needed.</p> <p>The automatic update package will update the board from a given version to the latest version. A number of automatic update files are available, and you should choose the one that corresponds to the version of the board that you are currently running. For example, if your current version is <strong>3.2.0</strong>, you need the <code>phpBB-3.2.0_to_3.2.1.zip/tar.bz2</code> file.</p> diff --git a/phpBB/docs/README.html b/phpBB/docs/README.html index 7fd80b3c2d..8fb9036ad8 100644 --- a/phpBB/docs/README.html +++ b/phpBB/docs/README.html @@ -323,11 +323,11 @@ <div class="content"> - <p>phpBB 3.2.x takes advantage of new features added in PHP 5.4. We recommend that you upgrade to the latest stable release of PHP to run phpBB. The minimum version required is PHP 5.4.0 and the maximum supported version is the latest stable version of PHP.</p> + <p>phpBB 3.2.x takes advantage of new features added in PHP 5.4. We recommend that you upgrade to the latest stable release of PHP to run phpBB. The minimum version required is PHP 5.4.7 and the maximum supported version is the latest stable version of PHP.</p> <p>Please remember that running any application on a development (unstable, e.g. a beta release) version of PHP can lead to strange/unexpected results which may appear to be bugs in the application. Therefore, we recommend you upgrade to the newest stable version of PHP before running phpBB. If you are running a development version of PHP please check any bugs you find on a system running a stable release before submitting.</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, MariaDB 5.x, PostgreSQL 8.x, Oracle 8 and SQLite 3. Versions of PHP used range from 5.4.x above 5.6.x to 7.0.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, MariaDB 5.x, PostgreSQL 8.x, Oracle 8 and SQLite 3. Versions of PHP used range from 5.4.7 above 5.6.x to 7.1.x and 7.2.x without problem.</p> <a name="phpsec"></a><h3>7.i. Notice on PHP security issues</h3> diff --git a/phpBB/docs/coding-guidelines.html b/phpBB/docs/coding-guidelines.html index d90f4d4d32..569ffe680c 100644 --- a/phpBB/docs/coding-guidelines.html +++ b/phpBB/docs/coding-guidelines.html @@ -627,7 +627,7 @@ $min = ($i < $j) ? $i : $j;</pre> <pre>if (isset($forum) && $forum == 5)</pre> </div> - <p>The <code>empty()</code> function is useful if you want to check if a variable is not set or being empty (an empty string, 0 as an integer or string, NULL, false, an empty array or a variable declared, but without a value in a class). Therefore empty should be used in favor of <code>isset($array) && sizeof($array) > 0</code> - this can be written in a shorter way as <code>!empty($array)</code>.</p> + <p>The <code>empty()</code> function is useful if you want to check if a variable is not set or being empty (an empty string, 0 as an integer or string, NULL, false, an empty array or a variable declared, but without a value in a class). Therefore empty should be used in favor of <code>isset($array) && count($array) > 0</code> - this can be written in a shorter way as <code>!empty($array)</code>.</p> <h4>Switch statements:</h4> <p>Switch/case code blocks can get a bit long sometimes. To have some level of notice and being in-line with the opening/closing brace requirement (where they are on the same line for better readability), this also applies to switch/case code blocks and the breaks. An example:</p> @@ -994,9 +994,9 @@ $sql = $db->sql_build_query('SELECT', $sql_array);</pre> <h4>Operations in loop definition: </h4> <p>Always try to optimize your loops if operations are going on at the comparing part, since this part is executed every time the loop is parsed through. For assignments a descriptive name should be chosen. Example:</p> - <p class="bad">// On every iteration the sizeof function is called</p> + <p class="bad">// On every iteration the count function is called</p> <div class="codebox"><pre> -for ($i = 0; $i < sizeof($post_data); $i++) +for ($i = 0; $i < count($post_data); $i++) { do_something(); }</pre> @@ -1004,7 +1004,7 @@ for ($i = 0; $i < sizeof($post_data); $i++) <p class="good">// You are able to assign the (not changing) result within the loop itself</p> <div class="codebox"><pre> -for ($i = 0, $size = sizeof($post_data); $i < $size; $i++) +for ($i = 0, $size = count($post_data); $i < $size; $i++) { do_something(); }</pre> diff --git a/phpBB/docs/events.md b/phpBB/docs/events.md index 6af3f55d21..467b03e8f3 100644 --- a/phpBB/docs/events.md +++ b/phpBB/docs/events.md @@ -28,29 +28,29 @@ acp_bbcodes_edit_fieldsets_after * Since: 3.1.0-a3 * Purpose: Add settings to BBCode add/edit form -acp_email_group_options_append +acp_email_find_username_append === * Location: adm/style/acp_email.html * Since: 3.1.7-RC1 -* Purpose: Add content at the end of the group options select box +* Purpose: Add content at the end of the find username link -acp_email_group_options_prepend +acp_email_find_username_prepend === * Location: adm/style/acp_email.html * Since: 3.1.7-RC1 -* Purpose: Add content at the start of the group options select box +* Purpose: Add content at the start of the find username link -acp_email_find_username_append +acp_email_group_options_append === * Location: adm/style/acp_email.html * Since: 3.1.7-RC1 -* Purpose: Add content at the end of the fimd username link +* Purpose: Add content at the end of the group options select box -acp_email_find_username_prepend +acp_email_group_options_prepend === * Location: adm/style/acp_email.html * Since: 3.1.7-RC1 -* Purpose: Add content at the start of the fimd username link +* Purpose: Add content at the start of the group options select box acp_email_options_after === @@ -160,17 +160,17 @@ acp_forums_rules_settings_prepend * Since: 3.1.2-RC1 * Purpose: Add settings to forums before rules settings section -acp_group_options_before +acp_group_options_after === * Location: adm/style/acp_groups.html * Since: 3.1.0-b4 -* Purpose: Add addtional options to group settings (before GROUP_FOUNDER_MANAGE) +* Purpose: Add additional options to group settings (after GROUP_RECEIVE_PM) -acp_group_options_after +acp_group_options_before === * Location: adm/style/acp_groups.html * Since: 3.1.0-b4 -* Purpose: Add addtional options to group settings (after GROUP_RECEIVE_PM) +* Purpose: Add additional options to group settings (before GROUP_FOUNDER_MANAGE) acp_groups_find_username_append === @@ -281,29 +281,29 @@ acp_overall_header_stylesheets_after * Purpose: Add assets after stylesheets within the `<head>` tags in the ACP. Note that INCLUDECSS will not work with this event. -acp_permission_forum_copy_src_forum_append +acp_permission_forum_copy_dest_forum_append === * Location: adm/style/permission_forum_copy.html * Since: 3.1.7-RC1 -* Purpose: Add content after the sourse forum select form +* Purpose: Add content after the destination forum select form -acp_permission_forum_copy_src_forum_prepend +acp_permission_forum_copy_dest_forum_prepend === * Location: adm/style/permission_forum_copy.html * Since: 3.1.7-RC1 -* Purpose: Add content before the sourse forum select form +* Purpose: Add content before the destination forum select form -acp_permission_forum_copy_dest_forum_append +acp_permission_forum_copy_src_forum_append === * Location: adm/style/permission_forum_copy.html * Since: 3.1.7-RC1 -* Purpose: Add content after the destiny forum select form +* Purpose: Add content after the source forum select form -acp_permission_forum_copy_dest_forum_prepend +acp_permission_forum_copy_src_forum_prepend === * Location: adm/style/permission_forum_copy.html * Since: 3.1.7-RC1 -* Purpose: Add content before the destiny forum select form +* Purpose: Add content before the source forum select form acp_permissions_add_group_options_append === @@ -433,6 +433,13 @@ acp_prune_forums_prepend * Since: 3.1.7-RC1 * Purpose: Add content before the forum select form label +acp_prune_forums_settings_append +=== +* Locations: + + adm/style/acp_prune_forums.html +* Since: 3.2.2-RC1 +* Purpose: Add content after the prune settings + acp_prune_users_find_username_append === * Locations: @@ -491,41 +498,6 @@ acp_ranks_list_header_before * Purpose: Add content after the last header-column (but before the action column) in the ranks list in the ACP -acp_styles_list_before -=== -* Locations: - + adm/style/acp_styles.html -* Since: 3.1.7-RC1 -* Purpose: Add content before list of styles - -acp_users_mode_add -=== -* Locations: - + adm/style/acp_users.html -* Since: 3.2.2-RC1 -* Purpose: Add extra modes to the ACP user page - -acp_users_profile_before -=== -* Locations: - + adm/style/acp_users_profile.html -* Since: 3.1.4-RC1 -* Purpose: Add content before the profile details when editing a user in the ACP - -acp_users_profile_after -=== -* Locations: - + adm/style/acp_users_profile.html -* Since: 3.1.4-RC1 -* Purpose: Add content after the profile details but before the custom profile fields when editing a user in the ACP - -acp_users_profile_custom_after -=== -* Locations: - + adm/style/acp_users_profile.html -* Since: 3.1.4-RC1 -* Purpose: Add content after the the custom profile fields when editing a user in the ACP - acp_simple_footer_after === * Location: adm/style/simple_footer.html @@ -551,6 +523,20 @@ acp_simple_header_stylesheets_after * Purpose: Add assets after stylesheets within the `<head>` tags in the simple header of the ACP. Note that INCLUDECSS will not work with this event. +acp_styles_list_before +=== +* Locations: + + adm/style/acp_styles.html +* Since: 3.1.7-RC1 +* Purpose: Add content before list of styles + +acp_users_mode_add +=== +* Locations: + + adm/style/acp_users.html +* Since: 3.2.2-RC1 +* Purpose: Add extra modes to the ACP user page + acp_users_overview_options_append === * Location: adm/style/acp_users_overview.html @@ -563,12 +549,6 @@ acp_users_prefs_append * Since: 3.1.0-b3 * Purpose: Add user options fieldset to the bottom of ACP users prefs settings -acp_users_prefs_prepend -=== -* Location: adm/style/acp_users_prefs.html -* Since: 3.1.0-b3 -* Purpose: Add user options fieldset to the top of ACP users prefs settings - acp_users_prefs_personal_append === * Location: adm/style/acp_users_prefs.html @@ -593,6 +573,12 @@ acp_users_prefs_post_prepend * Since: 3.1.0-b3 * Purpose: Add user options fieldset to the top of ACP users post prefs settings +acp_users_prefs_prepend +=== +* Location: adm/style/acp_users_prefs.html +* Since: 3.1.0-b3 +* Purpose: Add user options fieldset to the top of ACP users prefs settings + acp_users_prefs_view_append === * Location: adm/style/acp_users_prefs.html @@ -605,6 +591,27 @@ acp_users_prefs_view_prepend * Since: 3.1.0-b3 * Purpose: Add user options fieldset to the top of ACP users view prefs settings +acp_users_profile_after +=== +* Locations: + + adm/style/acp_users_profile.html +* Since: 3.1.4-RC1 +* Purpose: Add content after the profile details but before the custom profile fields when editing a user in the ACP + +acp_users_profile_before +=== +* Locations: + + adm/style/acp_users_profile.html +* Since: 3.1.4-RC1 +* Purpose: Add content before the profile details when editing a user in the ACP + +acp_users_profile_custom_after +=== +* Locations: + + adm/style/acp_users_profile.html +* Since: 3.1.4-RC1 +* Purpose: Add content after the the custom profile fields when editing a user in the ACP + acp_users_select_group_after === * Location: adm/style/acp_users.html @@ -645,6 +652,13 @@ attachment_file_prepend * Since: 3.1.6-RC1 * Purpose: Add custom attachment types displaying to the top of attachment block. +confirm_delete_body_delete_reason_before +=== +* Locations: + + styles/prosilver/template/confirm_delete_body.html +* Since: 3.2.4-RC1 +* Purpose: Add custom text to the confirmation of a post that is deleted. + forumlist_body_category_header_after === * Locations: @@ -673,6 +687,34 @@ forumlist_body_category_header_row_prepend * Since: 3.1.5-RC1 * Purpose: Add content before the header row of the category on the forum list. +forumlist_body_forum_image_after +=== +* Locations: + + styles/prosilver/template/forumlist_body.html +* Since: 3.2.2-RC1 +* Purpose: Add content after the forum image on the forum list. + +forumlist_body_forum_image_append +=== +* Locations: + + styles/prosilver/template/forumlist_body.html +* Since: 3.2.2-RC1 +* Purpose: Add content at the start of the forum image on the forum list. + +forumlist_body_forum_image_before +=== +* Locations: + + styles/prosilver/template/forumlist_body.html +* Since: 3.2.2-RC1 +* Purpose: Add content before the forum image on the forum list. + +forumlist_body_forum_image_prepend +=== +* Locations: + + styles/prosilver/template/forumlist_body.html +* Since: 3.2.2-RC1 +* Purpose: Add content at the end of the forum image on the forum list. + forumlist_body_forum_row_after === * Locations: @@ -708,6 +750,27 @@ forumlist_body_last_post_title_prepend * Since: 3.1.0-a1 * Purpose: Add content before the post title of the latest post in a forum on the forum list. +forumlist_body_last_poster_username_append +=== +* Locations: + + styles/prosilver/template/forumlist_body.html +* Since: 3.2.4-RC1 +* Purpose: Append information to last poster username of member + +forumlist_body_last_poster_username_prepend +=== +* Locations: + + styles/prosilver/template/forumlist_body.html +* Since: 3.2.4-RC1 +* Purpose: Prepend information to last poster username of member + +forumlist_body_last_row_after +=== +* Locations: + + styles/prosilver/template/forumlist_body.html +* Since: 3.1.0-b2 +* Purpose: Add content after the very last row of the forum list. + forumlist_body_subforum_link_append === * Locations: @@ -736,13 +799,6 @@ forumlist_body_subforums_before * Since: 3.1.0-a4 * Purpose: Add content before the list of subforums (if any) for each forum on the forum list. -forumlist_body_last_row_after -=== -* Locations: - + styles/prosilver/template/forumlist_body.html -* Since: 3.1.0-b2 -* Purpose: Add content after the very last row of the forum list. - index_body_birthday_block_before === * Locations: @@ -876,19 +932,19 @@ mcp_forum_actions_before * Since: 3.1.11-RC1 * Purpose: Add some information before actions fieldset -mcp_forum_topic_title_before +mcp_forum_topic_title_after === * Locations: + styles/prosilver/template/mcp_forum.html * Since: 3.1.6-RC1 -* Purpose: Add some information before the topic title +* Purpose: Add some information after the topic title -mcp_forum_topic_title_after +mcp_forum_topic_title_before === * Locations: + styles/prosilver/template/mcp_forum.html * Since: 3.1.6-RC1 -* Purpose: Add some information after the topic title +* Purpose: Add some information before the topic title mcp_front_latest_logs_after === @@ -932,6 +988,20 @@ mcp_move_before * Since: 3.1.10-RC1 * Purpose: Add content before move topic/post form +mcp_move_destination_forum_after +=== +* Locations: + + styles/prosilver/template/mcp_move.html +* Since: 3.2.8-RC1 +* Purpose: Add content after the destination select element in the move topic/post form + +mcp_move_destination_forum_before +=== +* Locations: + + styles/prosilver/template/mcp_move.html +* Since: 3.2.8-RC1 +* Purpose: Add content before the destination select element in the move topic/post form + mcp_post_additional_options === * Locations: @@ -939,6 +1009,34 @@ mcp_post_additional_options * Since: 3.1.5-RC1 * Purpose: Add content within the list of post moderation actions +mcp_post_report_buttons_top_after +=== +* Locations: + + styles/prosilver/template/mcp_post.html +* Since: 3.2.4-RC1 +* Purpose: Add content after report buttons + +mcp_post_report_buttons_top_before +=== +* Locations: + + styles/prosilver/template/mcp_post.html +* Since: 3.2.4-RC1 +* Purpose: Add content before report buttons + +mcp_post_text_after +=== +* Locations: + + styles/prosilver/template/mcp_post.html +* Since: 3.2.6-RC1 +* Purpose: Add content after the post text + +mcp_post_text_before +=== +* Locations: + + styles/prosilver/template/mcp_post.html +* Since: 3.2.6-RC1 +* Purpose: Add content before the post text + mcp_topic_options_after === * Locations: @@ -953,6 +1051,41 @@ mcp_topic_options_before * Since: 3.1.6-RC1 * Purpose: Add some options (field, checkbox, ...) before the subject field when split a subject +mcp_topic_post_author_full_append +=== +* Locations: + + styles/prosilver/template/mcp_topic.html +* Since: 3.2.8-RC1 +* Purpose: Append information to message author username for post details in topic moderation + +mcp_topic_post_author_full_prepend +=== +* Locations: + + styles/prosilver/template/mcp_topic.html +* Since: 3.2.8-RC1 +* Purpose: Prepend information to message author username for post details in topic moderation + +mcp_topic_postrow_attachments_after +=== +* Locations: + + styles/prosilver/template/mcp_topic.html +* Since: 3.2.2-RC1 +* Purpose: Show additional content after attachments in mcp topic review + +mcp_topic_postrow_attachments_before +=== +* Locations: + + styles/prosilver/template/mcp_topic.html +* Since: 3.2.2-RC1 +* Purpose: Show additional content before attachments in mcp topic review + +mcp_topic_postrow_post_before +=== +* Locations: + + styles/prosilver/template/mcp_topic.html +* Since: 3.2.2-RC1 +* Purpose: Show additional content after postrow begins in mcp topic review + mcp_topic_postrow_post_details_after === * Locations: @@ -1023,6 +1156,83 @@ mcp_warn_user_add_warning_field_before * Since: 3.1.0-RC4 * Purpose: Add content during warning a user - before add warning field. +memberlist_body_group_desc_after +=== +* Locations: + + styles/prosilver/template/memberlist_body.html +* Since: 3.2.6-RC1 +* Purpose: Add data after the group description and type in the group profile page. + +memberlist_body_group_name_after +=== +* Locations: + + styles/prosilver/template/memberlist_body.html +* Since: 3.2.6-RC1 +* Purpose: Add data after the group name in the group profile page. + +memberlist_body_group_name_before +=== +* Locations: + + styles/prosilver/template/memberlist_body.html +* Since: 3.2.6-RC1 +* Purpose: Add data before the group name in the group profile page. + +memberlist_body_group_rank_after +=== +* Locations: + + styles/prosilver/template/memberlist_body.html +* Since: 3.2.6-RC1 +* Purpose: Add data after the group rank in the group profile page. + +memberlist_body_group_rank_before +=== +* Locations: + + styles/prosilver/template/memberlist_body.html +* Since: 3.2.6-RC1 +* Purpose: Add data before the group rank in the group profile page. + +memberlist_body_leaders_set_after +=== +* Locations: + + styles/prosilver/template/memberlist_body.html +* Since: 3.2.6-RC1 +* Purpose: Add data after the last row in the memberlist mode leaders. + +memberlist_body_memberlist_after +=== +* Locations: + + styles/prosilver/template/memberlist_body.html +* Since: 3.2.6-RC1 +* Purpose: Add data after the last row in the memberlist. + +memberlist_body_memberrow_after +=== +* Locations: + + styles/prosilver/template/memberlist_body.html +* Since: 3.2.6-RC1 +* Purpose: Add data after the last memberrow in the memberlist. + +memberlist_body_page_footer_before +=== +* Locations: + + styles/prosilver/template/memberlist_body.html +* Since: 3.2.6-RC1 +* Purpose: Add data before the page footer. + +memberlist_body_page_header_after +=== +* Locations: + + styles/prosilver/template/memberlist_body.html +* Since: 3.2.6-RC1 +* Purpose: Add data after the page header. + +memberlist_body_page_title_before +=== +* Locations: + + styles/prosilver/template/memberlist_body.html +* Since: 3.2.6-RC1 +* Purpose: Add data before the page title. + memberlist_body_rank_append === * Locations: @@ -1039,6 +1249,13 @@ memberlist_body_rank_prepend * Purpose: Add information before rank in memberlist. Works in all display modes (leader, group and normal memberlist). +memberlist_body_show_group_after +=== +* Locations: + + styles/prosilver/template/memberlist_body.html +* Since: 3.2.6-RC1 +* Purpose: Add data after the last row in the memberlist mode group. + memberlist_body_username_append === * Locations: @@ -1195,6 +1412,20 @@ memberlist_view_user_statistics_before * Since: 3.1.0-a1 * Purpose: Add entries before the user statistics part of any user profile +memberlist_view_username_append +=== +* Locations: + + styles/prosilver/template/memberlist_view.html +* Since: 3.2.4-RC1 +* Purpose: Append information to username of member + +memberlist_view_username_prepend +=== +* Locations: + + styles/prosilver/template/memberlist_view.html +* Since: 3.2.4-RC1 +* Purpose: Prepend information to username of member + memberlist_view_zebra_after === * Locations: @@ -1490,19 +1721,61 @@ overall_header_stylesheets_after * Purpose: Add asset calls after stylesheets within the `</head>` tag. Note that INCLUDECSS will not work with this event. +posting_attach_body_attach_row_after +=== +* Locations: + + styles/prosilver/template/posting_attach_body.html +* Since: 3.2.6-RC1 +* Purpose: Add content after attachment row in the file list + +posting_attach_body_attach_row_append +=== +* Locations: + + styles/prosilver/template/posting_attach_body.html +* Since: 3.2.6-RC1 +* Purpose: Add content appending the attachment row in the file list + +posting_attach_body_attach_row_before +=== +* Locations: + + styles/prosilver/template/posting_attach_body.html +* Since: 3.2.6-RC1 +* Purpose: Add content before attachment row in the file list + posting_attach_body_attach_row_controls_append === * Locations: + styles/prosilver/template/posting_attach_body.html * Since: 3.2.2-RC1 -* Purpose: Add content after attachment control elements +* Purpose: Add content after attachment control elements posting_attach_body_attach_row_controls_prepend === * Locations: + styles/prosilver/template/posting_attach_body.html * Since: 3.2.2-RC1 -* Purpose: Add content before attachment control elements +* Purpose: Add content before attachment control elements + +posting_attach_body_attach_row_prepend +=== +* Locations: + + styles/prosilver/template/posting_attach_body.html +* Since: 3.2.6-RC1 +* Purpose: Add content prepending attachment row in the file list + +posting_attach_body_file_list_after +=== +* Locations: + + styles/prosilver/template/posting_attach_body.html +* Since: 3.2.6-RC1 +* Purpose: Add content after attachments list + +posting_attach_body_file_list_before +=== +* Locations: + + styles/prosilver/template/posting_attach_body.html +* Since: 3.2.6-RC1 +* Purpose: Add content before attachments list posting_editor_add_panel_tab === @@ -1651,6 +1924,13 @@ posting_poll_body_options_after * Since: 3.1.4-RC1 * Purpose: Add content after the poll options on creating a poll +posting_preview_content_after +=== +* Locations: + + styles/prosilver/template/posting_preview.html +* Since: 3.2.4-RC1 +* Purpose: Add content after the message content preview + posting_preview_poll_after === * Locations: @@ -1658,6 +1938,41 @@ posting_preview_poll_after * Since: 3.1.7-RC1 * Purpose: Add content after the poll preview block +posting_review_row_post_author_username_append +=== +* Locations: + + styles/prosilver/template/posting_review.html +* Since: 3.2.8-RC1 +* Purpose: Append information to post author username of member + +posting_review_row_post_author_username_prepend +=== +* Locations: + + styles/prosilver/template/posting_review.html +* Since: 3.2.8-RC1 +* Purpose: Prepend information to post author username of member + +posting_topic_review_row_content_after +=== +* Locations: + + styles/prosilver/template/posting_topic_review.html +* Since: 3.2.4-RC1 +* Purpose: Add content after the message content in topic review + +posting_topic_review_row_post_author_username_append +=== +* Locations: + + styles/prosilver/template/posting_topic_review.html +* Since: 3.2.8-RC1 +* Purpose: Append information to post author username of member + +posting_topic_review_row_post_author_username_prepend +=== +* Locations: + + styles/prosilver/template/posting_topic_review.html +* Since: 3.2.8-RC1 +* Purpose: Prepend information to post author username of member + posting_topic_review_row_post_details_after === * Locations: @@ -1686,33 +2001,33 @@ posting_topic_title_before * Since: 3.1.6-RC1 * Purpose: Allows to add some information on the left of the topic title in the posting form -quickreply_editor_panel_after +quickreply_editor_message_after === * Locations: + styles/prosilver/template/quickreply_editor.html -* Since: 3.1.0-b2 -* Purpose: Add content after the quick reply panel (but inside the form) +* Since: 3.1.0-a4 +* Purpose: Add content after the quick reply textbox -quickreply_editor_panel_before +quickreply_editor_message_before === * Locations: + styles/prosilver/template/quickreply_editor.html -* Since: 3.1.0-b2 -* Purpose: Add content before the quick reply panel (but inside the form) +* Since: 3.1.0-a4 +* Purpose: Add content before the quick reply textbox -quickreply_editor_message_after +quickreply_editor_panel_after === * Locations: + styles/prosilver/template/quickreply_editor.html -* Since: 3.1.0-a4 -* Purpose: Add content after the quick reply textbox +* Since: 3.1.0-b2 +* Purpose: Add content after the quick reply panel (but inside the form) -quickreply_editor_message_before +quickreply_editor_panel_before === * Locations: + styles/prosilver/template/quickreply_editor.html -* Since: 3.1.0-a4 -* Purpose: Add content before the quick reply textbox +* Since: 3.1.0-b2 +* Purpose: Add content before the quick reply panel (but inside the form) quickreply_editor_subject_before === @@ -1819,6 +2134,13 @@ search_body_search_query_prepend * Since: 3.1.7-RC1 * Purpose: Put content at the top of the search query fields set +search_results_content_after +=== +* Locations: + + styles/prosilver/template/search_results.html +* Since: 3.2.4-RC1 +* Purpose: Add content after the message content in search results + search_results_header_after === * Locations: @@ -1833,6 +2155,20 @@ search_results_header_before * Since: 3.1.4-RC1 * Purpose: Add content before the header of the search results. +search_results_last_post_author_username_append +=== +* Locations: + + styles/prosilver/template/search_results.html (2) +* Since: 3.2.4-RC1 +* Purpose: Append information to last post author username of member + +search_results_last_post_author_username_prepend +=== +* Locations: + + styles/prosilver/template/search_results.html (2) +* Since: 3.2.4-RC1 +* Purpose: Prepend information to last post author username of member + search_results_post_after === * Locations: @@ -1840,6 +2176,20 @@ search_results_post_after * Since: 3.1.0-b3 * Purpose: Add data after search result posts +search_results_post_author_username_append +=== +* Locations: + + styles/prosilver/template/search_results.html +* Since: 3.2.4-RC1 +* Purpose: Append information to post author username of member + +search_results_post_author_username_prepend +=== +* Locations: + + styles/prosilver/template/search_results.html +* Since: 3.2.4-RC1 +* Purpose: Prepend information to post author username of member + search_results_post_before === * Locations: @@ -1875,6 +2225,20 @@ search_results_topic_after * Since: 3.1.0-b4 * Purpose: Add data after search result topics +search_results_topic_author_username_append +=== +* Locations: + + styles/prosilver/template/search_results.html +* Since: 3.2.4-RC1 +* Purpose: Append information to topic author username of member + +search_results_topic_author_username_prepend +=== +* Locations: + + styles/prosilver/template/search_results.html +* Since: 3.2.4-RC1 +* Purpose: Prepend information to topic author username of member + search_results_topic_before === * Locations: @@ -1894,6 +2258,13 @@ simple_footer_after * Locations: + styles/prosilver/template/simple_footer.html * Since: 3.1.0-a1 +* Purpose: Add content prior to the scripts of the simple footer + +simple_footer_body_after +=== +* Locations: + + styles/prosilver/template/simple_footer.html +* Since: 3.2.4-RC1 * Purpose: Add content directly prior to the `</body>` tag of the simple footer simple_header_body_before @@ -1918,7 +2289,7 @@ simple_header_stylesheets_after * Purpose: Add asset calls after stylesheets within the `</head>` tag. Note that INCLUDECSS will not work with this event. -topiclist_row_prepend +topiclist_row_append === * Locations: + styles/prosilver/template/search_results.html @@ -1928,7 +2299,7 @@ topiclist_row_prepend * Changed: 3.1.6-RC1 Added event to mcp_forum.html * Purpose: Add content into topic rows (inside the elements containing topic titles) -topiclist_row_append +topiclist_row_prepend === * Locations: + styles/prosilver/template/search_results.html @@ -1938,6 +2309,24 @@ topiclist_row_append * Changed: 3.1.6-RC1 Added event to mcp_forum.html * Purpose: Add content into topic rows (inside the elements containing topic titles) +topiclist_row_topic_by_author_after +=== +* Locations: + + styles/prosilver/template/search_results.html + + styles/prosilver/template/viewforum_body.html + + styles/prosilver/template/mcp_forum.html +* Since: 3.2.8-RC1 +* Purpose: Add content into topic rows (after the "by topic author" row) + +topiclist_row_topic_by_author_before +=== +* Locations: + + styles/prosilver/template/search_results.html + + styles/prosilver/template/viewforum_body.html + + styles/prosilver/template/mcp_forum.html +* Since: 3.2.8-RC1 +* Purpose: Add content into topic rows (before the "by topic author" row) + topiclist_row_topic_title_after === * Locations: @@ -1961,6 +2350,20 @@ ucp_agreement_terms_before * Since: 3.1.0-b3 * Purpose: Add content before the terms of agreement text at user registration +ucp_friend_list_after +=== +* Locations: + + styles/prosilver/template/ucp_zebra_friends.html +* Since: 3.1.0-a4 +* Purpose: Add optional elements after list of friends in UCP + +ucp_friend_list_before +=== +* Locations: + + styles/prosilver/template/ucp_zebra_friends.html +* Since: 3.1.0-a4 +* Purpose: Add optional elements before list of friends in UCP + ucp_main_front_user_activity_after === * Locations: @@ -2035,6 +2438,20 @@ ucp_pm_history_review_before * Since: 3.1.6-RC1 * Purpose: Add content before the private messages history review. +ucp_pm_history_row_message_author_username_append +=== +* Locations: + + styles/prosilver/template/ucp_pm_history.html +* Since: 3.2.8-RC1 +* Purpose: Append information to message author username of member + +ucp_pm_history_row_message_author_username_prepend +=== +* Locations: + + styles/prosilver/template/ucp_pm_history.html +* Since: 3.2.8-RC1 +* Purpose: Prepend information to message author username of member + ucp_pm_viewmessage_avatar_after === * Locations: @@ -2143,6 +2560,13 @@ ucp_pm_viewmessage_rank_before * Purpose: Add data before the rank on the user profile when viewing a private message +ucp_prefs_personal_append +=== +* Locations: + + styles/prosilver/template/ucp_prefs_personal.html +* Since: 3.1.0-a1 +* Purpose: Add user options to the bottom of the Edit Global Settings block + ucp_prefs_personal_prepend === * Locations: @@ -2150,12 +2574,12 @@ ucp_prefs_personal_prepend * Since: 3.1.0-a1 * Purpose: Add user options to the top of the Edit Global Settings block -ucp_prefs_personal_append +ucp_prefs_post_append === * Locations: - + styles/prosilver/template/ucp_prefs_personal.html + + styles/prosilver/template/ucp_prefs_post.html * Since: 3.1.0-a1 -* Purpose: Add user options to the bottom of the Edit Global Settings block +* Purpose: Add user options to the bottom of the Edit Posting Defaults block ucp_prefs_post_prepend === @@ -2164,12 +2588,13 @@ ucp_prefs_post_prepend * Since: 3.1.0-a1 * Purpose: Add user options to the top of the Edit Posting Defaults block -ucp_prefs_post_append +ucp_prefs_view_radio_buttons_append === * Locations: - + styles/prosilver/template/ucp_prefs_post.html + + styles/prosilver/template/ucp_prefs_view.html * Since: 3.1.0-a1 -* Purpose: Add user options to the bottom of the Edit Posting Defaults block +* Purpose: Add options to the bottom of the radio buttons block of the Edit +Display Options screen ucp_prefs_view_radio_buttons_prepend === @@ -2179,12 +2604,12 @@ ucp_prefs_view_radio_buttons_prepend * Purpose: Add options to the top of the radio buttons block of the Edit Display Options screen -ucp_prefs_view_radio_buttons_append +ucp_prefs_view_select_menu_append === * Locations: + styles/prosilver/template/ucp_prefs_view.html * Since: 3.1.0-a1 -* Purpose: Add options to the bottom of the radio buttons block of the Edit +* Purpose: Add options to the bottom of the drop-down lists block of the Edit Display Options screen ucp_prefs_view_select_menu_prepend @@ -2195,13 +2620,12 @@ ucp_prefs_view_select_menu_prepend * Purpose: Add options to the top of the drop-down lists block of the Edit Display Options screen -ucp_prefs_view_select_menu_append +ucp_profile_profile_info_after === * Locations: - + styles/prosilver/template/ucp_prefs_view.html -* Since: 3.1.0-a1 -* Purpose: Add options to the bottom of the drop-down lists block of the Edit -Display Options screen + + styles/prosilver/template/ucp_profile_profile_info.html +* Since: 3.1.4-RC1 +* Purpose: Add options in profile page fieldset - after custom profile fields. ucp_profile_profile_info_before === @@ -2210,12 +2634,12 @@ ucp_profile_profile_info_before * Since: 3.1.4-RC1 * Purpose: Add options in profile page fieldset - before jabber field. -ucp_profile_profile_info_after +ucp_profile_register_details_after === * Locations: - + styles/prosilver/template/ucp_profile_profile_info.html + + styles/prosilver/template/ucp_profile_reg_details.html * Since: 3.1.4-RC1 -* Purpose: Add options in profile page fieldset - after custom profile fields. +* Purpose: Add options in profile page fieldset - after confirm password field. ucp_profile_register_details_before === @@ -2224,12 +2648,12 @@ ucp_profile_register_details_before * Since: 3.1.4-RC1 * Purpose: Add options in profile page fieldset - before first field. -ucp_profile_register_details_after +ucp_profile_signature_posting_editor_options_prepend === * Locations: - + styles/prosilver/template/ucp_profile_reg_details.html -* Since: 3.1.4-RC1 -* Purpose: Add options in profile page fieldset - after confirm password field. + + styles/prosilver/template/ucp_profile_signature.html +* Since: 3.2.6-RC1 +* Purpose: Add options signature posting editor - before first option. ucp_register_buttons_before === @@ -2238,33 +2662,33 @@ ucp_register_buttons_before * Since: 3.1.11-RC1 * Purpose: Add content before buttons in registration form. -ucp_register_credentials_before +ucp_register_credentials_after === * Locations: + styles/prosilver/template/ucp_register.html * Since: 3.1.0-b5 -* Purpose: Add options in registration page fieldset - before first field. +* Purpose: Add options in registration page fieldset - after password field. -ucp_register_profile_fields_after +ucp_register_credentials_before === * Locations: + styles/prosilver/template/ucp_register.html * Since: 3.1.0-b5 -* Purpose: Add options in registration page fieldset - after last field. +* Purpose: Add options in registration page fieldset - before first field. -ucp_register_credentials_after +ucp_register_options_before === * Locations: + styles/prosilver/template/ucp_register.html * Since: 3.1.0-b5 -* Purpose: Add options in registration page fieldset - after password field. +* Purpose: Add options in registration page fieldset - before language selector. -ucp_register_options_before +ucp_register_profile_fields_after === * Locations: + styles/prosilver/template/ucp_register.html * Since: 3.1.0-b5 -* Purpose: Add options in registration page fieldset - before language selector. +* Purpose: Add options in registration page fieldset - after last field. ucp_register_profile_fields_before === @@ -2273,19 +2697,33 @@ ucp_register_profile_fields_before * Since: 3.1.0-b5 * Purpose: Add options in registration page fieldset - before profile fields. -ucp_friend_list_before +viewforum_body_last_post_author_username_append === * Locations: - + styles/prosilver/template/ucp_zebra_friends.html -* Since: 3.1.0-a4 -* Purpose: Add optional elements before list of friends in UCP + + styles/prosilver/template/viewforum_body.html (2) +* Since: 3.2.4-RC1 +* Purpose: Append information to last post author username of member -ucp_friend_list_after +viewforum_body_last_post_author_username_prepend === * Locations: - + styles/prosilver/template/ucp_zebra_friends.html -* Since: 3.1.0-a4 -* Purpose: Add optional elements after list of friends in UCP + + styles/prosilver/template/viewforum_body.html (2) +* Since: 3.2.4-RC1 +* Purpose: Prepend information to last post author username of member + +viewforum_body_topic_author_username_append +=== +* Locations: + + styles/prosilver/template/viewforum_body.html +* Since: 3.2.4-RC1 +* Purpose: Append information to topic author username of member + +viewforum_body_topic_author_username_prepend +=== +* Locations: + + styles/prosilver/template/viewforum_body.html +* Since: 3.2.4-RC1 +* Purpose: Prepend information to topic author username of member viewforum_body_topic_row_after === @@ -2322,13 +2760,6 @@ viewforum_body_topicrow_row_before * Since: 3.1.10-RC1 * Purpose: Add content before list of topics. -viewforum_buttons_bottom_before -=== -* Locations: - + styles/prosilver/template/viewforum_body.html -* Since: 3.1.0-RC5 -* Purpose: Add buttons before New Topic button on the bottom of the topic's list - viewforum_buttons_bottom_after === * Locations: @@ -2336,12 +2767,12 @@ viewforum_buttons_bottom_after * Since: 3.1.0-RC5 * Purpose: Add buttons after New Topic button on the bottom of the topic's list -viewforum_buttons_top_before +viewforum_buttons_bottom_before === * Locations: + styles/prosilver/template/viewforum_body.html * Since: 3.1.0-RC5 -* Purpose: Add buttons before New Topic button on the top of the topic's list +* Purpose: Add buttons before New Topic button on the bottom of the topic's list viewforum_buttons_top_after === @@ -2350,47 +2781,12 @@ viewforum_buttons_top_after * Since: 3.1.0-RC5 * Purpose: Add buttons after New Topic button on the top of the topic's list -viewtopic_buttons_bottom_before -=== -* Locations: - + styles/prosilver/template/viewtopic_body.html -* Since: 3.1.0-RC5 -* Purpose: Add buttons before Post Reply button on the bottom of the posts's list - -viewtopic_buttons_bottom_after -=== -* Locations: - + styles/prosilver/template/viewtopic_body.html -* Since: 3.1.0-RC5 -* Purpose: Add buttons after Post Reply button on the bottom of the posts's list - -viewtopic_buttons_top_before -=== -* Locations: - + styles/prosilver/template/viewtopic_body.html -* Since: 3.1.0-RC5 -* Purpose: Add buttons before Post Reply button on the top of the posts's list - -viewtopic_buttons_top_after +viewforum_buttons_top_before === * Locations: - + styles/prosilver/template/viewtopic_body.html + + styles/prosilver/template/viewforum_body.html * Since: 3.1.0-RC5 -* Purpose: Add buttons after Post Reply button on the top of the posts's list - -viewtopic_dropdown_bottom_custom -=== -* Locations: - + styles/prosilver/template/viewtopic_body.html -* Since: 3.1.6-RC1 -* Purpose: Create a custom dropdown menu - -viewtopic_dropdown_top_custom -=== -* Locations: - + styles/prosilver/template/viewtopic_body.html -* Since: 3.1.6-RC1 -* Purpose: Create a custom dropdown menu +* Purpose: Add buttons before New Topic button on the top of the topic's list viewforum_forum_name_append === @@ -2420,19 +2816,19 @@ viewforum_forum_title_before * Since: 3.1.5-RC1 * Purpose: Add content directly before the forum title on the View forum screen -viewtopic_print_head_append +viewonline_body_username_append === * Locations: - + styles/prosilver/template/viewtopic_print.html -* Since: 3.1.0-a1 -* Purpose: Add asset calls directly before the `</head>` tag of the Print Topic screen + + styles/prosilver/template/viewonline_body.html +* Since: 3.2.4-RC1 +* Purpose: Append information to username of member -viewtopic_body_pagination_top_after +viewonline_body_username_prepend === * Locations: - + styles/prosilver/template/viewtopic_body.html -* Since: 3.1.4-RC1 -* Purpose: Add content after the pagination at top + + styles/prosilver/template/viewonline_body.html +* Since: 3.2.4-RC1 +* Purpose: Prepend information to username of member viewtopic_body_avatar_after === @@ -2472,6 +2868,13 @@ viewtopic_body_footer_before * Purpose: Add content to the bottom of the View topic screen below the posts and quick reply, directly before the jumpbox in Prosilver. +viewtopic_body_pagination_top_after +=== +* Locations: + + styles/prosilver/template/viewtopic_body.html +* Since: 3.1.4-RC1 +* Purpose: Add content after the pagination at top + viewtopic_body_poll_after === * Locations: @@ -2574,28 +2977,35 @@ viewtopic_body_postrow_back2top_after * Locations: + styles/prosilver/template/viewtopic_body.html * Since: 3.1.8-RC1 -* Purpose: Add content to the post's bottom after the back to top link +* Purpose: Add content to the post's bottom after the back to top link viewtopic_body_postrow_back2top_append === * Locations: + styles/prosilver/template/viewtopic_body.html * Since: 3.1.8-RC1 -* Purpose: Add content to the post's bottom directly after the back to top link +* Purpose: Add content to the post's bottom directly after the back to top link viewtopic_body_postrow_back2top_before === * Locations: + styles/prosilver/template/viewtopic_body.html * Since: 3.1.8-RC1 -* Purpose: Add content to the post's bottom before the back to top link +* Purpose: Add content to the post's bottom before the back to top link viewtopic_body_postrow_back2top_prepend === * Locations: + styles/prosilver/template/viewtopic_body.html * Since: 3.1.8-RC1 -* Purpose: Add content to the post's bottom directly before the back to top link +* Purpose: Add content to the post's bottom directly before the back to top link + +viewtopic_body_postrow_content_after +=== +* Locations: + + styles/prosilver/template/viewtopic_body.html +* Since: 3.2.4-RC1 +* Purpose: Add content after the message content in topics views viewtopic_body_postrow_custom_fields_after === @@ -2685,19 +3095,61 @@ viewtopic_body_topic_actions_before * Since: 3.1.0-a4 * Purpose: Add data before the topic actions buttons (after the posts sorting options) -viewtopic_topic_title_after +viewtopic_buttons_bottom_after === * Locations: + styles/prosilver/template/viewtopic_body.html -* Since: 3.1.7-RC1 -* Purpose: Add content directly after the topic title link on the View topic screen (outside of the h2 HTML tag) +* Since: 3.1.0-RC5 +* Purpose: Add buttons after Post Reply button on the bottom of the posts's list -viewtopic_topic_title_before +viewtopic_buttons_bottom_before === * Locations: + styles/prosilver/template/viewtopic_body.html -* Since: 3.2.2-RC1 -* Purpose: Add content directly before the topic title link on the View topic screen (outside of the h2 HTML tag) +* Since: 3.1.0-RC5 +* Purpose: Add buttons before Post Reply button on the bottom of the posts's list + +viewtopic_buttons_top_after +=== +* Locations: + + styles/prosilver/template/viewtopic_body.html +* Since: 3.1.0-RC5 +* Purpose: Add buttons after Post Reply button on the top of the posts's list + +viewtopic_buttons_top_before +=== +* Locations: + + styles/prosilver/template/viewtopic_body.html +* Since: 3.1.0-RC5 +* Purpose: Add buttons before Post Reply button on the top of the posts's list + +viewtopic_dropdown_bottom_custom +=== +* Locations: + + styles/prosilver/template/viewtopic_body.html +* Since: 3.1.6-RC1 +* Purpose: Create a custom dropdown menu + +viewtopic_dropdown_top_custom +=== +* Locations: + + styles/prosilver/template/viewtopic_body.html +* Since: 3.1.6-RC1 +* Purpose: Create a custom dropdown menu + +viewtopic_print_head_append +=== +* Locations: + + styles/prosilver/template/viewtopic_print.html +* Since: 3.1.0-a1 +* Purpose: Add asset calls directly before the `</head>` tag of the Print Topic screen + +viewtopic_topic_title_after +=== +* Locations: + + styles/prosilver/template/viewtopic_body.html +* Since: 3.1.7-RC1 +* Purpose: Add content directly after the topic title link on the View topic screen (outside of the h2 HTML tag) viewtopic_topic_title_append === @@ -2706,6 +3158,13 @@ viewtopic_topic_title_append * Since: 3.1.0-b3 * Purpose: Add content directly after the topic title link on the View topic screen +viewtopic_topic_title_before +=== +* Locations: + + styles/prosilver/template/viewtopic_body.html +* Since: 3.2.2-RC1 +* Purpose: Add content directly before the topic title link on the View topic screen (outside of the h2 HTML tag) + viewtopic_topic_title_prepend === * Locations: diff --git a/phpBB/docs/nginx.sample.conf b/phpBB/docs/nginx.sample.conf index ce929b6e54..55c01a1fc9 100644 --- a/phpBB/docs/nginx.sample.conf +++ b/phpBB/docs/nginx.sample.conf @@ -18,11 +18,11 @@ http { gzip_vary on; gzip_http_version 1.1; gzip_min_length 700; - + # Compression levels over 6 do not give an appreciable improvement # in compression ratio, but take more resources. gzip_comp_level 6; - + # IE 6 and lower do not support gzip with Vary correctly. gzip_disable "msie6"; # Before nginx 0.7.63: @@ -49,9 +49,7 @@ http { server_name myforums.com; # A trick from http://wiki.nginx.org/Pitfalls#Taxing_Rewrites: - rewrite ^ http://www.myforums.com$request_uri permanent; - # Equivalent to: - #rewrite ^(.*)$ http://www.myforums.com$1 permanent; + return 301 http://www.myforums.com$request_uri; } # The actual board domain. @@ -72,7 +70,7 @@ http { } # Deny access to internal phpbb files. - location ~ /(config\.php|common\.php|cache|files|images/avatars/upload|includes|phpbb|store|vendor) { + location ~ /(config\.php|common\.php|cache|files|images/avatars/upload|includes|(?<!ext/)phpbb|store|vendor) { deny all; # deny was ignored before 0.8.40 for connections over IPv6. # Use internal directive to prohibit access on older versions. diff --git a/phpBB/docs/sphinx.sample.conf b/phpBB/docs/sphinx.sample.conf index 0a210ecd1a..85cba190d7 100644 --- a/phpBB/docs/sphinx.sample.conf +++ b/phpBB/docs/sphinx.sample.conf @@ -29,7 +29,6 @@ source source_phpbb_{SPHINX_ID}_main 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 - sql_query_info = SELECT * FROM phpbb_posts WHERE post_id = $id sql_attr_uint = forum_id sql_attr_uint = topic_id sql_attr_uint = poster_id @@ -72,7 +71,6 @@ index index_phpbb_{SPHINX_ID}_main morphology = none stopwords = min_word_len = 2 - charset_type = utf-8 charset_table = U+FF10..U+FF19->0..9, 0..9, U+FF41..U+FF5A->a..z, U+FF21..U+FF3A->a..z, A..Z->a..z, a..z, U+0149, U+017F, U+0138, U+00DF, U+00FF, U+00C0..U+00D6->U+00E0..U+00F6, U+00E0..U+00F6, U+00D8..U+00DE->U+00F8..U+00FE, U+00F8..U+00FE, U+0100->U+0101, U+0101, U+0102->U+0103, U+0103, U+0104->U+0105, U+0105, U+0106->U+0107, U+0107, U+0108->U+0109, U+0109, U+010A->U+010B, U+010B, U+010C->U+010D, U+010D, U+010E->U+010F, U+010F, U+0110->U+0111, U+0111, U+0112->U+0113, U+0113, U+0114->U+0115, U+0115, U+0116->U+0117, U+0117, U+0118->U+0119, U+0119, U+011A->U+011B, U+011B, U+011C->U+011D, U+011D, U+011E->U+011F, U+011F, U+0130->U+0131, U+0131, U+0132->U+0133, U+0133, U+0134->U+0135, U+0135, U+0136->U+0137, U+0137, U+0139->U+013A, U+013A, U+013B->U+013C, U+013C, U+013D->U+013E, U+013E, U+013F->U+0140, U+0140, U+0141->U+0142, U+0142, U+0143->U+0144, U+0144, U+0145->U+0146, U+0146, U+0147->U+0148, U+0148, U+014A->U+014B, U+014B, U+014C->U+014D, U+014D, U+014E->U+014F, U+014F, U+0150->U+0151, U+0151, U+0152->U+0153, U+0153, U+0154->U+0155, U+0155, U+0156->U+0157, U+0157, U+0158->U+0159, U+0159, U+015A->U+015B, U+015B, U+015C->U+015D, U+015D, U+015E->U+015F, U+015F, U+0160->U+0161, U+0161, U+0162->U+0163, U+0163, U+0164->U+0165, U+0165, U+0166->U+0167, U+0167, U+0168->U+0169, U+0169, U+016A->U+016B, U+016B, U+016C->U+016D, U+016D, U+016E->U+016F, U+016F, U+0170->U+0171, U+0171, U+0172->U+0173, U+0173, U+0174->U+0175, U+0175, U+0176->U+0177, U+0177, U+0178->U+00FF, U+00FF, U+0179->U+017A, U+017A, U+017B->U+017C, U+017C, U+017D->U+017E, U+017E, U+0410..U+042F->U+0430..U+044F, U+0430..U+044F, U+4E00..U+9FFF min_prefix_len = 0 min_infix_len = 0 @@ -88,13 +86,11 @@ indexer } searchd { - compat_sphinxql_magics = 0 listen = localhost:9312 log = {DATA_PATH}/log/searchd.log query_log = {DATA_PATH}/log/sphinx-query.log read_timeout = 5 max_children = 30 pid_file = {DATA_PATH}/searchd.pid - max_matches = 20000 binlog_path = {DATA_PATH} } diff --git a/phpBB/download/file.php b/phpBB/download/file.php index a9cd4a3b3c..9ee489cef4 100644 --- a/phpBB/download/file.php +++ b/phpBB/download/file.php @@ -159,6 +159,8 @@ $user->session_begin(false); $auth->acl($user->data); $user->setup('viewtopic'); +$phpbb_content_visibility = $phpbb_container->get('content.visibility'); + if (!$config['allow_attachments'] && !$config['allow_pm_attach']) { send_status_line(404, 'Not Found'); @@ -225,7 +227,7 @@ else $post_row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - if (!$post_row || ($post_row['post_visibility'] != ITEM_APPROVED && !$auth->acl_get('m_approve', $post_row['forum_id']))) + if (!$post_row || !$phpbb_content_visibility->is_visible('post', $post_row['forum_id'], $post_row)) { // Attachment of a soft deleted post and the user is not allowed to see the post send_status_line(404, 'Not Found'); diff --git a/phpBB/includes/acp/acp_attachments.php b/phpBB/includes/acp/acp_attachments.php index 3cfe5de293..94e3660de8 100644 --- a/phpBB/includes/acp/acp_attachments.php +++ b/phpBB/includes/acp/acp_attachments.php @@ -27,6 +27,9 @@ class acp_attachments /** @var \phpbb\config\config */ protected $config; + /** @var \phpbb\language\language */ + protected $language; + /** @var ContainerBuilder */ protected $phpbb_container; @@ -54,6 +57,7 @@ class acp_attachments $this->id = $id; $this->db = $db; $this->config = $config; + $this->language = $phpbb_container->get('language'); $this->template = $template; $this->user = $user; $this->phpbb_container = $phpbb_container; @@ -128,7 +132,7 @@ class acp_attachments $s_assigned_groups = array(); while ($row = $db->sql_fetchrow($result)) { - $row['group_name'] = (isset($user->lang['EXT_GROUP_' . $row['group_name']])) ? $user->lang['EXT_GROUP_' . $row['group_name']] : $row['group_name']; + $row['group_name'] = $this->language->is_set('EXT_GROUP_' . utf8_strtoupper($row['group_name'])) ? $this->language->lang('EXT_GROUP_' . utf8_strtoupper($row['group_name'])) : $row['group_name']; $s_assigned_groups[$row['cat_id']][] = $row['group_name']; } $db->sql_freeresult($result); @@ -164,7 +168,6 @@ class acp_attachments 'img_create_thumbnail' => array('lang' => 'CREATE_THUMBNAIL', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'img_max_thumb_width' => array('lang' => 'MAX_THUMB_WIDTH', 'validate' => 'int:0:999999999999999', 'type' => 'number:0:999999999999999', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), 'img_min_thumb_filesize' => array('lang' => 'MIN_THUMB_FILESIZE', 'validate' => 'int:0:999999999999999', 'type' => 'number:0:999999999999999', 'explain' => true, 'append' => ' ' . $user->lang['BYTES']), - 'img_imagick' => array('lang' => 'IMAGICK_PATH', 'validate' => 'absolute_path', 'type' => 'text:20:200', 'explain' => true, 'append' => ' <span>[ <a href="' . $this->u_action . '&action=imgmagick">' . $user->lang['SEARCH_IMAGICK'] . '</a> ]</span>'), 'img_max' => array('lang' => 'MAX_IMAGE_SIZE', 'validate' => 'int:0:9999', 'type' => 'dimension:0:9999', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), 'img_link' => array('lang' => 'IMAGE_LINK_SIZE', 'validate' => 'int:0:9999', 'type' => 'dimension:0:9999', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), ) @@ -190,7 +193,7 @@ class acp_attachments validate_config_vars($display_vars['vars'], $cfg_array, $error); // Do not write values if there is an error - if (sizeof($error)) + if (count($error)) { $submit = false; } @@ -226,7 +229,7 @@ class acp_attachments // Check Settings $this->test_upload($error, $this->new_config['upload_path'], false); - if (!sizeof($error)) + if (!count($error)) { trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action)); } @@ -234,38 +237,6 @@ class acp_attachments $template->assign_var('S_ATTACHMENT_SETTINGS', true); - if ($action == 'imgmagick') - { - $this->new_config['img_imagick'] = $this->search_imagemagick(); - } - - // We strip eventually manual added convert program, we only want the patch - if ($this->new_config['img_imagick']) - { - // Change path separator - $this->new_config['img_imagick'] = str_replace('\\', '/', $this->new_config['img_imagick']); - $this->new_config['img_imagick'] = str_replace(array('convert', '.exe'), array('', ''), $this->new_config['img_imagick']); - - // Check for trailing slash - if (substr($this->new_config['img_imagick'], -1) !== '/') - { - $this->new_config['img_imagick'] .= '/'; - } - } - - $supported_types = get_supported_image_types(); - - // Check Thumbnail Support - if (!$this->new_config['img_imagick'] && (!isset($supported_types['format']) || !sizeof($supported_types['format']))) - { - $this->new_config['img_create_thumbnail'] = 0; - } - - $template->assign_vars(array( - 'U_SEARCH_IMAGICK' => $this->u_action . '&action=imgmagick', - 'S_THUMBNAIL_SUPPORT' => (!$this->new_config['img_imagick'] && (!isset($supported_types['format']) || !sizeof($supported_types['format']))) ? false : true) - ); - // Secure Download Options - Same procedure as with banning $allow_deny = ($this->new_config['secure_allow_deny']) ? 'ALLOWED' : 'DISALLOWED'; @@ -290,7 +261,7 @@ class acp_attachments $template->assign_vars(array( 'S_SECURE_DOWNLOADS' => $this->new_config['secure_downloads'], 'S_DEFINED_IPS' => ($defined_ips != '') ? true : false, - 'S_WARNING' => (sizeof($error)) ? true : false, + 'S_WARNING' => (count($error)) ? true : false, 'WARNING_MSG' => implode('<br />', $error), 'DEFINED_IPS' => $defined_ips, @@ -363,7 +334,7 @@ class acp_attachments // Generate correct Change List $extensions = array(); - for ($i = 0, $size = sizeof($extension_change_list); $i < $size; $i++) + for ($i = 0, $size = count($extension_change_list); $i < $size; $i++) { $extensions[$extension_change_list[$i]]['group_id'] = $group_select_list[$i]; } @@ -390,7 +361,7 @@ class acp_attachments // Delete Extension? $extension_id_list = $request->variable('extension_id_list', array(0)); - if (sizeof($extension_id_list)) + if (count($extension_id_list)) { $sql = 'SELECT extension FROM ' . EXTENSIONS_TABLE . ' @@ -420,7 +391,7 @@ class acp_attachments if ($add_extension && $add) { - if (!sizeof($error)) + if (!count($error)) { $sql = 'SELECT extension_id FROM ' . EXTENSIONS_TABLE . " @@ -433,7 +404,7 @@ class acp_attachments } $db->sql_freeresult($result); - if (!sizeof($error)) + if (!count($error)) { $sql_ary = array( 'group_id' => $add_extension_group, @@ -447,7 +418,7 @@ class acp_attachments } } - if (!sizeof($error)) + if (!count($error)) { $notify[] = $user->lang['EXTENSIONS_UPDATED']; } @@ -558,7 +529,7 @@ class acp_attachments $db->sql_freeresult($result); } - if (!sizeof($error)) + if (!count($error)) { // Ok, build the update/insert array $upload_icon = $request->variable('upload_icon', 'no_image'); @@ -575,7 +546,7 @@ class acp_attachments $max_filesize = 0; } - if (!sizeof($allowed_forums)) + if (!count($allowed_forums)) { $forum_select = false; } @@ -606,13 +577,13 @@ class acp_attachments $group_id = $db->sql_nextid(); } - $group_name = (isset($user->lang['EXT_GROUP_' . $group_name])) ? $user->lang['EXT_GROUP_' . $group_name] : $group_name; + $group_name = $this->language->is_set('EXT_GROUP_' . utf8_strtoupper($group_name)) ? $this->language->lang('EXT_GROUP_' . utf8_strtoupper($group_name)) : $group_name; $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACH_EXTGROUP_' . strtoupper($action), false, array($group_name)); } $extension_list = $request->variable('extensions', array(0)); - if ($action == 'edit' && sizeof($extension_list)) + if ($action == 'edit' && count($extension_list)) { $sql = 'UPDATE ' . EXTENSIONS_TABLE . " SET group_id = 0 @@ -620,7 +591,7 @@ class acp_attachments $db->sql_query($sql); } - if (sizeof($extension_list)) + if (count($extension_list)) { $sql = 'UPDATE ' . EXTENSIONS_TABLE . " SET group_id = $group_id @@ -630,7 +601,7 @@ class acp_attachments $cache->destroy('_extensions'); - if (!sizeof($error)) + if (!count($error)) { $notify[] = $user->lang['SUCCESS_EXTENSION_GROUP_' . strtoupper($action)]; } @@ -806,7 +777,7 @@ class acp_attachments 'S_FILENAME_LIST' => $filename_list, 'S_EDIT_GROUP' => true, 'S_NO_IMAGE' => $no_image_select, - 'S_FORUM_IDS' => (sizeof($forum_ids)) ? true : false, + 'S_FORUM_IDS' => (count($forum_ids)) ? true : false, 'U_EXTENSIONS' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=extensions"), 'U_BACK' => $this->u_action, @@ -908,7 +879,7 @@ class acp_attachments 'U_EDIT' => $this->u_action . "&action=edit&g={$row['group_id']}", 'U_DELETE' => $this->u_action . "&action=delete&g={$row['group_id']}", - 'GROUP_NAME' => (isset($user->lang['EXT_GROUP_' . $row['group_name']])) ? $user->lang['EXT_GROUP_' . $row['group_name']] : $row['group_name'], + 'GROUP_NAME' => $this->language->is_set('EXT_GROUP_' . utf8_strtoupper($row['group_name'])) ? $this->language->lang('EXT_GROUP_' . utf8_strtoupper($row['group_name'])) : $row['group_name'], 'CATEGORY' => $cat_lang[$row['cat_id']], ) ); @@ -922,13 +893,16 @@ class acp_attachments case 'orphan': + /* @var $pagination \phpbb\pagination */ + $pagination = $this->phpbb_container->get('pagination'); + if ($submit) { $delete_files = (isset($_POST['delete'])) ? array_keys($request->variable('delete', array('' => 0))) : array(); $add_files = (isset($_POST['add'])) ? array_keys($request->variable('add', array('' => 0))) : array(); $post_ids = $request->variable('post_id', array('' => 0)); - if (sizeof($delete_files)) + if (count($delete_files)) { $sql = 'SELECT * FROM ' . ATTACHMENTS_TABLE . ' @@ -951,7 +925,7 @@ class acp_attachments $db->sql_freeresult($result); } - if (sizeof($delete_files)) + if (count($delete_files)) { $sql = 'DELETE FROM ' . ATTACHMENTS_TABLE . ' WHERE ' . $db->sql_in_set('attach_id', array_keys($delete_files)); @@ -971,7 +945,7 @@ class acp_attachments } unset($add_files); - if (sizeof($upload_list)) + if (count($upload_list)) { $template->assign_var('S_UPLOADING_FILES', true); @@ -1064,13 +1038,29 @@ class acp_attachments 'S_ORPHAN' => true) ); + $attachments_per_page = (int) $config['topics_per_page']; + + // Get total number or orphans older than 3 hours + $sql = 'SELECT COUNT(attach_id) as num_files, SUM(filesize) as total_size + FROM ' . ATTACHMENTS_TABLE . ' + WHERE is_orphan = 1 + AND filetime < ' . (time() - 3*60*60); + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $num_files = (int) $row['num_files']; + $total_size = (int) $row['total_size']; + $this->db->sql_freeresult($result); + + $start = $request->variable('start', 0); + $start = $pagination->validate_start($start, $attachments_per_page, $num_files); + // Just get the files with is_orphan set and older than 3 hours $sql = 'SELECT * FROM ' . ATTACHMENTS_TABLE . ' WHERE is_orphan = 1 AND filetime < ' . (time() - 3*60*60) . ' ORDER BY filetime DESC'; - $result = $db->sql_query($sql); + $result = $db->sql_query_limit($sql, $attachments_per_page, $start); while ($row = $db->sql_fetchrow($result)) { @@ -1086,6 +1076,20 @@ class acp_attachments } $db->sql_freeresult($result); + $pagination->generate_template_pagination( + $this->u_action, + 'pagination', + 'start', + $num_files, + $attachments_per_page, + $start + ); + + $template->assign_vars(array( + 'TOTAL_FILES' => $num_files, + 'TOTAL_SIZE' => get_formatted_filesize($total_size), + )); + break; case 'manage': @@ -1094,7 +1098,7 @@ class acp_attachments { $delete_files = (isset($_POST['delete'])) ? array_keys($request->variable('delete', array('' => 0))) : array(); - if (sizeof($delete_files)) + if (count($delete_files)) { // Select those attachments we want to delete... $sql = 'SELECT real_filename @@ -1110,7 +1114,7 @@ class acp_attachments if ($num_deleted = $this->attachment_manager->delete('attach', $delete_files)) { - if (sizeof($delete_files) != $num_deleted) + if (count($delete_files) != $num_deleted) { $error[] = $user->lang['FILES_GONE']; } @@ -1231,28 +1235,24 @@ class acp_attachments // Grab extensions $extensions = $cache->obtain_attach_extensions(true); - for ($i = 0, $end = sizeof($attachments_list); $i < $end; ++$i) + for ($i = 0, $end = count($attachments_list); $i < $end; ++$i) { $row = $attachments_list[$i]; $row['extension'] = strtolower(trim((string) $row['extension'])); $comment = ($row['attach_comment'] && !$row['in_message']) ? str_replace(array("\n", "\r"), array('<br />', "\n"), $row['attach_comment']) : ''; - $display_cat = $extensions[$row['extension']]['display_cat']; + $display_cat = isset($extensions[$row['extension']]['display_cat']) ? $extensions[$row['extension']]['display_cat'] : ATTACHMENT_CATEGORY_NONE; $l_downloaded_viewed = ($display_cat == ATTACHMENT_CATEGORY_NONE) ? 'DOWNLOAD_COUNTS' : 'VIEWED_COUNTS'; $template->assign_block_vars('attachments', array( 'ATTACHMENT_POSTER' => get_username_string('full', (int) $row['poster_id'], (string) $row['username'], (string) $row['user_colour'], (string) $row['username']), 'FILESIZE' => get_formatted_filesize((int) $row['filesize']), 'FILETIME' => $user->format_date((int) $row['filetime']), - 'REAL_FILENAME' => (!$row['in_message']) ? utf8_basename((string) $row['real_filename']) : '', - 'PHYSICAL_FILENAME' => utf8_basename((string) $row['physical_filename']), - 'EXT_GROUP_NAME' => (!empty($extensions[$row['extension']]['group_name'])) ? $user->lang['EXT_GROUP_' . $extensions[$row['extension']]['group_name']] : '', + 'REAL_FILENAME' => utf8_basename((string) $row['real_filename']), + 'EXT_GROUP_NAME' => $this->language->is_set('EXT_GROUP_' . utf8_strtoupper($extensions[$row['extension']]['group_name'])) ? $this->language->lang('EXT_GROUP_' . utf8_strtoupper($extensions[$row['extension']]['group_name'])) : $extensions[$row['extension']]['group_name'], 'COMMENT' => $comment, 'TOPIC_TITLE' => (!$row['in_message']) ? (string) $row['topic_title'] : '', 'ATTACH_ID' => (int) $row['attach_id'], - 'POST_ID' => (int) $row['post_msg_id'], - 'TOPIC_ID' => (int) $row['topic_id'], - 'POST_IDS' => (!empty($post_ids[$row['attach_id']])) ? (int) $post_ids[$row['attach_id']] : '', 'L_DOWNLOAD_COUNT' => $user->lang($l_downloaded_viewed, (int) $row['download_count']), @@ -1266,7 +1266,7 @@ class acp_attachments break; } - if (sizeof($error)) + if (count($error)) { $template->assign_vars(array( 'S_WARNING' => true, @@ -1274,7 +1274,7 @@ class acp_attachments ); } - if (sizeof($notify)) + if (count($notify)) { $template->assign_vars(array( 'S_NOTIFY' => true, @@ -1434,7 +1434,7 @@ class acp_attachments $group_name = array(); while ($row = $db->sql_fetchrow($result)) { - $row['group_name'] = (isset($user->lang['EXT_GROUP_' . $row['group_name']])) ? $user->lang['EXT_GROUP_' . $row['group_name']] : $row['group_name']; + $row['group_name'] = $this->language->is_set('EXT_GROUP_' . utf8_strtoupper($row['group_name'])) ? $this->language->lang('EXT_GROUP_' . utf8_strtoupper($row['group_name'])) : $row['group_name']; $group_name[] = $row; } $db->sql_freeresult($result); @@ -1443,7 +1443,7 @@ class acp_attachments $row['group_name'] = $user->lang['NOT_ASSIGNED']; $group_name[] = $row; - for ($i = 0, $groups_size = sizeof($group_name); $i < $groups_size; $i++) + for ($i = 0, $groups_size = count($group_name); $i < $groups_size; $i++) { if ($default_group === false) { @@ -1463,47 +1463,6 @@ class acp_attachments } /** - * Search Imagick - */ - function search_imagemagick() - { - $imagick = ''; - - $exe = ((defined('PHP_OS')) && (preg_match('#^win#i', PHP_OS))) ? '.exe' : ''; - - $magic_home = getenv('MAGICK_HOME'); - - if (empty($magic_home)) - { - $locations = array('C:/WINDOWS/', 'C:/WINNT/', 'C:/WINDOWS/SYSTEM/', 'C:/WINNT/SYSTEM/', 'C:/WINDOWS/SYSTEM32/', 'C:/WINNT/SYSTEM32/', '/usr/bin/', '/usr/sbin/', '/usr/local/bin/', '/usr/local/sbin/', '/opt/', '/usr/imagemagick/', '/usr/bin/imagemagick/'); - $path_locations = str_replace('\\', '/', (explode(($exe) ? ';' : ':', getenv('PATH')))); - - $locations = array_merge($path_locations, $locations); - - foreach ($locations as $location) - { - // The path might not end properly, fudge it - if (substr($location, -1) !== '/') - { - $location .= '/'; - } - - if (@file_exists($location) && @is_readable($location . 'mogrify' . $exe) && @filesize($location . 'mogrify' . $exe) > 3000) - { - $imagick = str_replace('\\', '/', $location); - continue; - } - } - } - else - { - $imagick = str_replace('\\', '/', $magic_home); - } - - return $imagick; - } - - /** * Test Settings */ function test_upload(&$error, $upload_dir, $create_directory = false) @@ -1676,7 +1635,7 @@ class acp_attachments } $db->sql_freeresult($result); - if (sizeof($iplist)) + if (count($iplist)) { foreach ($iplist as $ip_entry) { @@ -1686,7 +1645,7 @@ class acp_attachments } } - if (sizeof($hostlist)) + if (count($hostlist)) { foreach ($hostlist as $host_entry) { @@ -1709,7 +1668,7 @@ class acp_attachments { $unip_sql = $request->variable('unip', array(0)); - if (sizeof($unip_sql)) + if (count($unip_sql)) { $l_unip_list = ''; diff --git a/phpBB/includes/acp/acp_bbcodes.php b/phpBB/includes/acp/acp_bbcodes.php index f958ae93c7..1f7374a07f 100644 --- a/phpBB/includes/acp/acp_bbcodes.php +++ b/phpBB/includes/acp/acp_bbcodes.php @@ -253,7 +253,7 @@ class acp_bbcodes if ($row) { - $bbcode_id = $row['max_bbcode_id'] + 1; + $bbcode_id = (int) $row['max_bbcode_id'] + 1; // Make sure it is greater than the core bbcode ids... if ($bbcode_id <= NUM_CORE_BBCODES) @@ -295,6 +295,22 @@ class acp_bbcodes $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log_action, false, array($data['bbcode_tag'])); + /** + * Event after a BBCode has been added or updated + * + * @event core.acp_bbcodes_modify_create_after + * @var string action Type of the action: modify|create + * @var int bbcode_id The id of the added or updated bbcode + * @var array sql_ary Array with bbcode data (read only) + * @since 3.2.4-RC1 + */ + $vars = array( + 'action', + 'bbcode_id', + 'sql_ary', + ); + extract($phpbb_dispatcher->trigger_event('core.acp_bbcodes_modify_create_after', compact($vars))); + trigger_error($user->lang[$lang] . adm_back_link($this->u_action)); } else @@ -325,10 +341,28 @@ class acp_bbcodes { if (confirm_box(true)) { + $bbcode_tag = $row['bbcode_tag']; + $db->sql_query('DELETE FROM ' . BBCODES_TABLE . " WHERE bbcode_id = $bbcode_id"); $cache->destroy('sql', BBCODES_TABLE); $phpbb_container->get('text_formatter.cache')->invalidate(); - $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_BBCODE_DELETE', false, array($row['bbcode_tag'])); + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_BBCODE_DELETE', false, array($bbcode_tag)); + + /** + * Event after a BBCode has been deleted + * + * @event core.acp_bbcodes_delete_after + * @var string action Type of the action: delete + * @var int bbcode_id The id of the deleted bbcode + * @var string bbcode_tag The tag of the deleted bbcode + * @since 3.2.4-RC1 + */ + $vars = array( + 'action', + 'bbcode_id', + 'bbcode_tag', + ); + extract($phpbb_dispatcher->trigger_event('core.acp_bbcodes_delete_after', compact($vars))); if ($request->is_ajax()) { @@ -494,7 +528,7 @@ class acp_bbcodes // Pad backreference numbers from tokens if (preg_match_all('/(?<!\\\\)\$([0-9]+)/', $replace, $repad)) { - $repad = $pad + sizeof(array_unique($repad[0])); + $repad = $pad + count(array_unique($repad[0])); $replace = preg_replace_callback('/(?<!\\\\)\$([0-9]+)/', function ($match) use ($pad) { return '${' . ($match[1] + $pad) . '}'; }, $replace); @@ -553,10 +587,10 @@ class acp_bbcodes } // Lowercase tags - $bbcode_tag = preg_replace('/.*?\[([a-z0-9_-]+=?).*/i', '$1', $bbcode_match); - $bbcode_search = preg_replace('/.*?\[([a-z0-9_-]+)=?.*/i', '$1', $bbcode_match); + $bbcode_tag = preg_replace('/.*?\[([a-z0-9_-]+).*/i', '$1', $bbcode_match); + $bbcode_search = preg_replace('/.*?\[([a-z0-9_-]+).*/i', '$1', $bbcode_match); - if (!preg_match('/^[a-zA-Z0-9_-]+=?$/', $bbcode_tag)) + if (!preg_match('/^[a-zA-Z0-9_-]+$/', $bbcode_tag)) { global $user; trigger_error($user->lang['BBCODE_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index 77e6133fe6..0730b4e285 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -30,10 +30,13 @@ class acp_board function main($id, $mode) { - global $user, $template, $request; + global $user, $template, $request, $language; global $config, $phpbb_root_path, $phpEx; global $cache, $phpbb_container, $phpbb_dispatcher, $phpbb_log; + /** @var \phpbb\language\language $language Language object */ + $language = $phpbb_container->get('language'); + $user->add_lang('acp/board'); $submit = (isset($_POST['submit']) || isset($_POST['allow_quick_reply_enable'])) ? true : false; @@ -56,7 +59,7 @@ class acp_board 'legend1' => 'ACP_BOARD_SETTINGS', 'sitename' => array('lang' => 'SITE_NAME', 'validate' => 'string', 'type' => 'text:40:255', 'explain' => false), 'site_desc' => array('lang' => 'SITE_DESC', 'validate' => 'string', 'type' => 'text:40:255', 'explain' => false), - 'site_home_url' => array('lang' => 'SITE_HOME_URL', 'validate' => 'string', 'type' => 'url:40:255', 'explain' => true), + 'site_home_url' => array('lang' => 'SITE_HOME_URL', 'validate' => 'url', 'type' => 'url:40:255', 'explain' => true), 'site_home_text' => array('lang' => 'SITE_HOME_TEXT', 'validate' => 'string', 'type' => 'text:40:255', 'explain' => true), 'board_index_text' => array('lang' => 'BOARD_INDEX_TEXT', 'validate' => 'string', 'type' => 'text:40:255', 'explain' => true), 'board_disable' => array('lang' => 'DISABLE_BOARD', 'validate' => 'bool', 'type' => 'custom', 'method' => 'board_disable', 'explain' => true), @@ -122,6 +125,7 @@ class acp_board $avatar_vars = array(); foreach ($avatar_drivers as $current_driver) { + /** @var \phpbb\avatar\driver\driver_interface $driver */ $driver = $phpbb_avatar_manager->get_driver($current_driver, false); /* @@ -356,6 +360,7 @@ class acp_board 'load_user_activity_limit' => array('lang' => 'LOAD_USER_ACTIVITY_LIMIT', 'validate' => 'int:0:99999999', 'type' => 'number:0:99999999', 'explain' => true), 'load_tplcompile' => array('lang' => 'RECOMPILE_STYLES', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'allow_cdn' => array('lang' => 'ALLOW_CDN', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'enable_accurate_pm_button' => array('lang' => 'YES_ACCURATE_PM_BUTTON', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'allow_live_searches' => array('lang' => 'ALLOW_LIVE_SEARCHES', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'legend3' => 'CUSTOM_PROFILE_FIELDS', @@ -444,11 +449,12 @@ class acp_board 'legend1' => 'GENERAL_SETTINGS', 'email_enable' => array('lang' => 'ENABLE_EMAIL', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true), 'board_email_form' => array('lang' => 'BOARD_EMAIL_FORM', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true), - 'email_function_name' => array('lang' => 'EMAIL_FUNCTION_NAME', 'validate' => 'string', 'type' => 'text:20:50', 'explain' => true), 'email_package_size' => array('lang' => 'EMAIL_PACKAGE_SIZE', 'validate' => 'int:0', 'type' => 'number:0:99999', 'explain' => true), + 'email_max_chunk_size' => array('lang' => 'EMAIL_MAX_CHUNK_SIZE', 'validate' => 'int:1:99999', 'type' => 'number:1:99999', 'explain' => true), 'board_contact' => array('lang' => 'CONTACT_EMAIL', 'validate' => 'email', 'type' => 'email:25:100', 'explain' => true), 'board_contact_name' => array('lang' => 'CONTACT_EMAIL_NAME', 'validate' => 'string', 'type' => 'text:25:50', 'explain' => true), 'board_email' => array('lang' => 'ADMIN_EMAIL', 'validate' => 'email', 'type' => 'email:25:100', 'explain' => true), + 'email_force_sender' => array('lang' => 'EMAIL_FORCE_SENDER', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'board_email_sig' => array('lang' => 'EMAIL_SIG', 'validate' => 'string', 'type' => 'textarea:5:30', 'explain' => true), 'board_hide_emails' => array('lang' => 'BOARD_HIDE_EMAILS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'send_test_email' => array('lang' => 'SEND_TEST_EMAIL', 'validate' => 'bool', 'type' => 'custom', 'method' => 'send_test_email', 'explain' => true), @@ -503,7 +509,7 @@ class acp_board $error[] = $user->lang['FORM_INVALID']; } // Do not write values if there is an error - if (sizeof($error)) + if (count($error)) { $submit = false; } @@ -532,13 +538,6 @@ class acp_board $this->new_config[$config_name] = $config_value = $cfg_array[$config_name]; - if ($config_name == 'email_function_name') - { - $this->new_config['email_function_name'] = trim(str_replace(array('(', ')'), array('', ''), $this->new_config['email_function_name'])); - $this->new_config['email_function_name'] = (empty($this->new_config['email_function_name']) || !function_exists($this->new_config['email_function_name'])) ? 'mail' : $this->new_config['email_function_name']; - $config_value = $this->new_config['email_function_name']; - } - if ($submit) { if (strpos($data['type'], 'password') === 0 && $config_value === '********') @@ -690,7 +689,7 @@ class acp_board 'L_TITLE' => $user->lang[$display_vars['title']], 'L_TITLE_EXPLAIN' => $user->lang[$display_vars['title'] . '_EXPLAIN'], - 'S_ERROR' => (sizeof($error)) ? true : false, + 'S_ERROR' => (count($error)) ? true : false, 'ERROR_MSG' => implode('<br />', $error), 'U_ACTION' => $this->u_action) @@ -736,7 +735,7 @@ class acp_board $template->assign_block_vars('options', array( 'KEY' => $config_key, 'TITLE' => (isset($user->lang[$vars['lang']])) ? $user->lang[$vars['lang']] : $vars['lang'], - 'S_EXPLAIN' => $vars['explain'], + 'S_EXPLAIN' => $vars['explain'] && !empty($l_explain), 'TITLE_EXPLAIN' => $l_explain, 'CONTENT' => $content, ) @@ -1110,7 +1109,7 @@ class acp_board $db->sql_query($sql); // Already emptied for all... - if (sizeof($values)) + if (count($values)) { // Set for selected forums $sql = 'UPDATE ' . FORUMS_TABLE . ' diff --git a/phpBB/includes/acp/acp_bots.php b/phpBB/includes/acp/acp_bots.php index e89b16663c..8bd357bc91 100644 --- a/phpBB/includes/acp/acp_bots.php +++ b/phpBB/includes/acp/acp_bots.php @@ -55,7 +55,7 @@ class acp_bots switch ($action) { case 'activate': - if ($bot_id || sizeof($mark)) + if ($bot_id || count($mark)) { $sql_id = ($bot_id) ? " = $bot_id" : ' IN (' . implode(', ', $mark) . ')'; @@ -69,7 +69,7 @@ class acp_bots break; case 'deactivate': - if ($bot_id || sizeof($mark)) + if ($bot_id || count($mark)) { $sql_id = ($bot_id) ? " = $bot_id" : ' IN (' . implode(', ', $mark) . ')'; @@ -83,7 +83,7 @@ class acp_bots break; case 'delete': - if ($bot_id || sizeof($mark)) + if ($bot_id || count($mark)) { if (confirm_box(true)) { @@ -109,7 +109,7 @@ class acp_bots WHERE bot_id $sql_id"; $db->sql_query($sql); - if (sizeof($user_id_ary)) + if (count($user_id_ary)) { $_tables = array(USERS_TABLE, USER_GROUP_TABLE); foreach ($_tables as $table) @@ -207,7 +207,7 @@ class acp_bots $error[] = $user->lang['BOT_NAME_TAKEN']; } - if (!sizeof($error)) + if (!count($error)) { // New bot? Create a new user and group entry if ($action == 'add') @@ -338,7 +338,7 @@ class acp_bots 'L_TITLE' => $user->lang['BOT_' . $l_title], 'U_ACTION' => $this->u_action . "&id=$bot_id&action=$action", 'U_BACK' => $this->u_action, - 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', + 'ERROR_MSG' => (count($error)) ? implode('<br />', $error) : '', 'BOT_NAME' => $bot_row['bot_name'], 'BOT_IP' => $bot_row['bot_ip'], @@ -348,7 +348,7 @@ class acp_bots 'S_ACTIVE_OPTIONS' => $s_active_options, 'S_STYLE_OPTIONS' => $style_select, 'S_LANG_OPTIONS' => $lang_select, - 'S_ERROR' => (sizeof($error)) ? true : false, + 'S_ERROR' => (count($error)) ? true : false, ) ); diff --git a/phpBB/includes/acp/acp_database.php b/phpBB/includes/acp/acp_database.php index 00c7ef40c0..677fce7217 100644 --- a/phpBB/includes/acp/acp_database.php +++ b/phpBB/includes/acp/acp_database.php @@ -23,6 +23,7 @@ class acp_database { var $db_tools; var $u_action; + public $page_title; function main($id, $mode) { @@ -57,9 +58,8 @@ class acp_database $type = $request->variable('type', ''); $table = array_intersect($this->db_tools->sql_list_tables(), $request->variable('table', array(''))); $format = $request->variable('method', ''); - $where = $request->variable('where', ''); - if (!sizeof($table)) + if (!count($table)) { trigger_error($user->lang['TABLE_SELECT_ERROR'] . adm_back_link($this->u_action), E_USER_WARNING); } @@ -69,17 +69,9 @@ class acp_database trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); } - $store = $download = $structure = $schema_data = false; - - if ($where == 'store_and_download' || $where == 'store') - { - $store = true; - } - - if ($where == 'store_and_download' || $where == 'download') - { - $download = true; - } + $store = true; + $structure = false; + $schema_data = false; if ($type == 'full' || $type == 'structure') { @@ -98,8 +90,9 @@ class acp_database $filename = 'backup_' . $time . '_' . unique_id(); + /** @var phpbb\db\extractor\extractor_interface $extractor Database extractor */ $extractor = $phpbb_container->get('dbal.extractor'); - $extractor->init_extractor($format, $filename, $time, $download, $store); + $extractor->init_extractor($format, $filename, $time, false, $store); $extractor->write_start($table_prefix); @@ -145,11 +138,6 @@ class acp_database $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DB_BACKUP'); - if ($download == true) - { - exit; - } - trigger_error($user->lang['BACKUP_SUCCESS'] . adm_back_link($this->u_action)); break; @@ -201,16 +189,10 @@ class acp_database case 'submit': $delete = $request->variable('delete', ''); $file = $request->variable('file', ''); - $download = $request->variable('download', ''); - if (!preg_match('#^backup_\d{10,}_[a-z\d]{16}\.(sql(?:\.(?:gz|bz2))?)$#', $file, $matches)) - { - trigger_error($user->lang['BACKUP_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); - } - - $file_name = $phpbb_root_path . 'store/' . $matches[0]; + $backup_info = $this->get_backup_file($phpbb_root_path . 'store/', $file); - if (!file_exists($file_name) || !is_readable($file_name)) + if (empty($backup_info) || !is_readable($backup_info['file_name'])) { trigger_error($user->lang['BACKUP_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); } @@ -219,7 +201,7 @@ class acp_database { if (confirm_box(true)) { - unlink($file_name); + unlink($backup_info['file_name']); $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DB_DELETE'); trigger_error($user->lang['BACKUP_DELETE'] . adm_back_link($this->u_action)); } @@ -228,50 +210,12 @@ class acp_database confirm_box(false, $user->lang['DELETE_SELECTED_BACKUP'], build_hidden_fields(array('delete' => $delete, 'file' => $file))); } } - else if ($download || confirm_box(true)) + else if (confirm_box(true)) { - if ($download) - { - $name = $matches[0]; - - switch ($matches[1]) - { - case 'sql': - $mimetype = 'text/x-sql'; - break; - case 'sql.bz2': - $mimetype = 'application/x-bzip2'; - break; - case 'sql.gz': - $mimetype = 'application/x-gzip'; - break; - } - - header('Cache-Control: private, no-cache'); - header("Content-Type: $mimetype; name=\"$name\""); - header("Content-disposition: attachment; filename=$name"); - - @set_time_limit(0); - - $fp = @fopen($file_name, 'rb'); - - if ($fp !== false) - { - while (!feof($fp)) - { - echo fread($fp, 8192); - } - fclose($fp); - } - - flush(); - exit; - } - - switch ($matches[1]) + switch ($backup_info['extension']) { case 'sql': - $fp = fopen($file_name, 'rb'); + $fp = fopen($backup_info['file_name'], 'rb'); $read = 'fread'; $seek = 'fseek'; $eof = 'feof'; @@ -280,7 +224,7 @@ class acp_database break; case 'sql.bz2': - $fp = bzopen($file_name, 'r'); + $fp = bzopen($backup_info['file_name'], 'r'); $read = 'bzread'; $seek = ''; $eof = 'feof'; @@ -289,13 +233,17 @@ class acp_database break; case 'sql.gz': - $fp = gzopen($file_name, 'rb'); + $fp = gzopen($backup_info['file_name'], 'rb'); $read = 'gzread'; $seek = 'gzseek'; $eof = 'gzeof'; $close = 'gzclose'; $fgetd = 'fgetd'; break; + + default: + trigger_error($user->lang['BACKUP_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + return; } switch ($db->get_sql_layer()) @@ -375,43 +323,13 @@ class acp_database trigger_error($user->lang['RESTORE_SUCCESS'] . adm_back_link($this->u_action)); break; } - else if (!$download) + else { confirm_box(false, $user->lang['RESTORE_SELECTED_BACKUP'], build_hidden_fields(array('file' => $file))); } default: - $methods = array('sql'); - $available_methods = array('sql.gz' => 'zlib', 'sql.bz2' => 'bz2'); - - foreach ($available_methods as $type => $module) - { - if (!@extension_loaded($module)) - { - continue; - } - $methods[] = $type; - } - - $dir = $phpbb_root_path . 'store/'; - $dh = @opendir($dir); - - $backup_files = array(); - - if ($dh) - { - while (($file = readdir($dh)) !== false) - { - if (preg_match('#^backup_(\d{10,})_[a-z\d]{16}\.(sql(?:\.(?:gz|bz2))?)$#', $file, $matches)) - { - if (in_array($matches[2], $methods)) - { - $backup_files[(int) $matches[1]] = $file; - } - } - } - closedir($dh); - } + $backup_files = $this->get_file_list($phpbb_root_path . 'store/'); if (!empty($backup_files)) { @@ -420,8 +338,8 @@ class acp_database foreach ($backup_files as $name => $file) { $template->assign_block_vars('files', array( - 'FILE' => $file, - 'NAME' => $user->format_date($name, 'd-m-Y H:i:s', true), + 'FILE' => sha1($file), + 'NAME' => $user->format_date($name, 'd-m-Y H:i', true), 'SUPPORTED' => true, )); } @@ -435,6 +353,92 @@ class acp_database break; } } + + /** + * Get backup file from file hash + * + * @param string $directory Relative path to directory + * @param string $file_hash Hash of selected file + * + * @return array Backup file data or empty array if unable to find file + */ + protected function get_backup_file($directory, $file_hash) + { + $backup_data = []; + + $file_list = $this->get_file_list($directory); + $supported_extensions = $this->get_supported_extensions(); + + foreach ($file_list as $file) + { + preg_match('#^backup_(\d{10,})_(?:[a-z\d]{16}|[a-z\d]{32})\.(sql(?:\.(?:gz|bz2))?)$#i', $file, $matches); + if (sha1($file) === $file_hash && in_array($matches[2], $supported_extensions)) + { + $backup_data = [ + 'file_name' => $directory . $file, + 'extension' => $matches[2], + ]; + break; + } + } + + return $backup_data; + } + + /** + * Get backup file list for directory + * + * @param string $directory Relative path to backup directory + * + * @return array List of backup files in specified directory + */ + protected function get_file_list($directory) + { + $supported_extensions = $this->get_supported_extensions(); + + $dh = @opendir($directory); + + $backup_files = []; + + if ($dh) + { + while (($file = readdir($dh)) !== false) + { + if (preg_match('#^backup_(\d{10,})_(?:[a-z\d]{16}|[a-z\d]{32})\.(sql(?:\.(?:gz|bz2))?)$#i', $file, $matches)) + { + if (in_array($matches[2], $supported_extensions)) + { + $backup_files[(int) $matches[1]] = $file; + } + } + } + closedir($dh); + } + + return $backup_files; + } + + /** + * Get supported extensions for backup + * + * @return array List of supported extensions + */ + protected function get_supported_extensions() + { + $extensions = ['sql']; + $available_methods = ['sql.gz' => 'zlib', 'sql.bz2' => 'bz2']; + + foreach ($available_methods as $type => $module) + { + if (!@extension_loaded($module)) + { + continue; + } + $extensions[] = $type; + } + + return $extensions; + } } // get how much space we allow for a chunk of data, very similar to phpMyAdmin's way of doing things ;-) (hey, we only do this for MySQL anyway :P) @@ -495,7 +499,7 @@ function sanitize_data_mssql($text) { $val[] = "'" . $value . "'"; } - if (sizeof($matches[0])) + if (count($matches[0])) { $val[] = 'char(' . ord(array_shift($matches[0])) . ')'; } @@ -519,7 +523,7 @@ function sanitize_data_oracle($text) { $val[] = "'" . $value . "'"; } - if (sizeof($matches[0])) + if (count($matches[0])) { $val[] = 'chr(' . ord(array_shift($matches[0])) . ')'; } @@ -541,7 +545,7 @@ function sanitize_data_generic($text) { $val[] = "'" . $value . "'"; } - if (sizeof($matches[0])) + if (count($matches[0])) { $val[] = "'" . array_shift($matches[0]) . "'"; } @@ -583,7 +587,7 @@ function fgetd_seekless(&$fp, $delim, $read, $seek, $eof, $buffer = 8192) static $array = array(); static $record = ''; - if (!sizeof($array)) + if (!count($array)) { while (!$eof($fp)) { @@ -605,7 +609,7 @@ function fgetd_seekless(&$fp, $delim, $read, $seek, $eof, $buffer = 8192) } } - if (sizeof($array)) + if (count($array)) { return array_shift($array); } diff --git a/phpBB/includes/acp/acp_email.php b/phpBB/includes/acp/acp_email.php index 57eefad02d..5a1fbac9f6 100644 --- a/phpBB/includes/acp/acp_email.php +++ b/phpBB/includes/acp/acp_email.php @@ -68,7 +68,7 @@ class acp_email $error[] = $user->lang['NO_EMAIL_MESSAGE']; } - if (!sizeof($error)) + if (!count($error)) { if (!empty($usernames)) { @@ -168,7 +168,7 @@ class acp_email { $i = 0; - if (sizeof($email_list)) + if (count($email_list)) { $j++; } @@ -235,16 +235,16 @@ class acp_email ); extract($phpbb_dispatcher->trigger_event('core.acp_email_send_before', compact($vars))); - for ($i = 0, $size = sizeof($email_list); $i < $size; $i++) + for ($i = 0, $size = count($email_list); $i < $size; $i++) { $used_lang = $email_list[$i][0]['lang']; $used_method = $email_list[$i][0]['method']; - for ($j = 0, $list_size = sizeof($email_list[$i]); $j < $list_size; $j++) + for ($j = 0, $list_size = count($email_list[$i]); $j < $list_size; $j++) { $email_row = $email_list[$i][$j]; - $messenger->{((sizeof($email_list[$i]) == 1) ? 'to' : 'bcc')}($email_row['email'], $email_row['name']); + $messenger->{((count($email_list[$i]) == 1) ? 'to' : 'bcc')}($email_row['email'], $email_row['name']); $messenger->im($email_row['jabber'], $email_row['name']); } @@ -322,8 +322,8 @@ class acp_email $s_priority_options .= '<option value="' . MAIL_HIGH_PRIORITY . '">' . $user->lang['MAIL_HIGH_PRIORITY'] . '</option>'; $template_data = array( - 'S_WARNING' => (sizeof($error)) ? true : false, - 'WARNING_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', + 'S_WARNING' => (count($error)) ? true : false, + 'WARNING_MSG' => (count($error)) ? implode('<br />', $error) : '', 'U_ACTION' => $this->u_action, 'S_GROUP_OPTIONS' => $select_list, 'USERNAMES' => implode("\n", $usernames), diff --git a/phpBB/includes/acp/acp_extensions.php b/phpBB/includes/acp/acp_extensions.php index 6f65dc9fa0..a1cb2108e7 100644 --- a/phpBB/includes/acp/acp_extensions.php +++ b/phpBB/includes/acp/acp_extensions.php @@ -35,11 +35,13 @@ class acp_extensions private $request; private $phpbb_dispatcher; private $ext_manager; + private $phpbb_container; + private $php_ini; function main() { // Start the page - global $config, $user, $template, $request, $phpbb_extension_manager, $phpbb_root_path, $phpbb_log, $phpbb_dispatcher; + global $config, $user, $template, $request, $phpbb_extension_manager, $phpbb_root_path, $phpbb_log, $phpbb_dispatcher, $phpbb_container; $this->config = $config; $this->template = $template; @@ -48,6 +50,8 @@ class acp_extensions $this->log = $phpbb_log; $this->phpbb_dispatcher = $phpbb_dispatcher; $this->ext_manager = $phpbb_extension_manager; + $this->phpbb_container = $phpbb_container; + $this->php_ini = $this->phpbb_container->get('php_ini'); $this->user->add_lang(array('install', 'acp/extensions', 'migrator')); @@ -57,7 +61,7 @@ class acp_extensions $ext_name = $this->request->variable('ext_name', ''); // What is a safe limit of execution time? Half the max execution time should be safe. - $safe_time_limit = (ini_get('max_execution_time') / 2); + $safe_time_limit = ($this->php_ini->getNumeric('max_execution_time') / 2); $start_time = time(); // Cancel action diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php index 66bb630241..cb0593b14a 100644 --- a/phpBB/includes/acp/acp_forums.php +++ b/phpBB/includes/acp/acp_forums.php @@ -90,7 +90,7 @@ class acp_forums $errors = $this->delete_forum($forum_id, $action_posts, $action_subforums, $posts_to_id, $subforums_to_id); - if (sizeof($errors)) + if (count($errors)) { break; } @@ -198,7 +198,7 @@ class acp_forums $errors = $this->update_forum_data($forum_data); - if (!sizeof($errors)) + if (!count($errors)) { $forum_perm_from = $request->variable('forum_perm_from', 0); $cache->destroy('sql', FORUMS_TABLE); @@ -622,7 +622,7 @@ class acp_forums $template_data = array( 'S_EDIT_FORUM' => true, - 'S_ERROR' => (sizeof($errors)) ? true : false, + 'S_ERROR' => (count($errors)) ? true : false, 'S_PARENT_ID' => $this->parent_id, 'S_FORUM_PARENT_ID' => $forum_data['parent_id'], 'S_ADD_ACTION' => ($action == 'add') ? true : false, @@ -632,7 +632,7 @@ class acp_forums 'L_COPY_PERMISSIONS_EXPLAIN' => $user->lang['COPY_PERMISSIONS_' . strtoupper($action) . '_EXPLAIN'], 'L_TITLE' => $user->lang[$this->page_title], - 'ERROR_MSG' => (sizeof($errors)) ? implode('<br />', $errors) : '', + 'ERROR_MSG' => (count($errors)) ? implode('<br />', $errors) : '', 'FORUM_NAME' => $forum_data['forum_name'], 'FORUM_DATA_LINK' => $forum_data['forum_link'], @@ -772,8 +772,8 @@ class acp_forums 'S_FORUM_LINK' => ($forum_data['forum_type'] == FORUM_LINK) ? true : false, 'S_HAS_SUBFORUMS' => ($forum_data['right_id'] - $forum_data['left_id'] > 1) ? true : false, 'S_FORUMS_LIST' => $forums_list, - 'S_ERROR' => (sizeof($errors)) ? true : false, - 'ERROR_MSG' => (sizeof($errors)) ? implode('<br />', $errors) : '') + 'S_ERROR' => (count($errors)) ? true : false, + 'ERROR_MSG' => (count($errors)) ? implode('<br />', $errors) : '') ); return; @@ -924,7 +924,7 @@ class acp_forums unset($rowset); $template->assign_vars(array( - 'ERROR_MSG' => (sizeof($errors)) ? implode('<br />', $errors) : '', + 'ERROR_MSG' => (count($errors)) ? implode('<br />', $errors) : '', 'NAVIGATION' => $navigation, 'FORUM_BOX' => $forum_box, 'U_SEL_ACTION' => $this->u_action, @@ -986,6 +986,13 @@ class acp_forums $errors[] = $user->lang['FORUM_NAME_EMPTY']; } + // No Emojis + if (preg_match_all('/[\x{10000}-\x{10FFFF}]/u', $forum_data_ary['forum_name'], $matches)) + { + $character_list = implode('<br>', $matches[0]); + $errors[] = $user->lang('FORUM_NAME_EMOJI', $character_list); + } + if (utf8_strlen($forum_data_ary['forum_desc']) > 4000) { $errors[] = $user->lang['FORUM_DESC_TOO_LONG']; @@ -1012,7 +1019,7 @@ class acp_forums } $range_test_ary = array( - array('lang' => 'FORUM_TOPICS_PAGE', 'value' => $forum_data_ary['forum_topics_per_page'], 'column_type' => 'TINT:0'), + array('lang' => 'FORUM_TOPICS_PAGE', 'value' => $forum_data_ary['forum_topics_per_page'], 'column_type' => 'USINT:0'), ); if (!empty($forum_data_ary['forum_image']) && !file_exists($phpbb_root_path . $forum_data_ary['forum_image'])) @@ -1053,7 +1060,7 @@ class acp_forums // What are we going to do tonight Brain? The same thing we do everynight, // try to take over the world ... or decide whether to continue update // and if so, whether it's a new forum/cat/link or an existing one - if (sizeof($errors)) + if (count($errors)) { return $errors; } @@ -1217,12 +1224,12 @@ class acp_forums $errors = array_merge($errors, $this->delete_forum_content($_row['forum_id'])); } - if (sizeof($errors)) + if (count($errors)) { return $errors; } - if (sizeof($forum_ids)) + if (count($forum_ids)) { $sql = 'DELETE FROM ' . FORUMS_TABLE . ' WHERE ' . $db->sql_in_set('forum_id', $forum_ids); @@ -1252,7 +1259,7 @@ class acp_forums $allowed_forums = array_diff($allowed_forums, $forum_ids); $sql = 'UPDATE ' . EXTENSION_GROUPS_TABLE . " - SET allowed_forums = '" . ((sizeof($allowed_forums)) ? serialize($allowed_forums) : '') . "' + SET allowed_forums = '" . ((count($allowed_forums)) ? serialize($allowed_forums) : '') . "' WHERE group_id = {$_row['group_id']}"; $db->sql_query($sql); } @@ -1321,7 +1328,7 @@ class acp_forums $forum_data_sql['forum_last_poster_colour'] = ''; } - if (sizeof($errors)) + if (count($errors)) { return $errors; } @@ -1338,7 +1345,7 @@ class acp_forums } } - if (sizeof($errors)) + if (count($errors)) { return $errors; } @@ -1431,12 +1438,14 @@ class acp_forums return $errors; } + $db->sql_transaction('begin'); + $moved_forums = get_forum_branch($from_id, 'children', 'descending'); $from_data = $moved_forums[0]; - $diff = sizeof($moved_forums) * 2; + $diff = count($moved_forums) * 2; $moved_ids = array(); - for ($i = 0, $size = sizeof($moved_forums); $i < $size; ++$i) + for ($i = 0, $size = count($moved_forums); $i < $size; ++$i) { $moved_ids[] = $moved_forums[$i]['forum_id']; } @@ -1502,6 +1511,8 @@ class acp_forums WHERE " . $db->sql_in_set('forum_id', $moved_ids); $db->sql_query($sql); + $db->sql_transaction('commit'); + return $errors; } @@ -1537,6 +1548,16 @@ class acp_forums $table_ary = array(LOG_TABLE, POSTS_TABLE, TOPICS_TABLE, DRAFTS_TABLE, TOPICS_TRACK_TABLE); + /** + * Perform additional actions before move forum content + * + * @event core.acp_manage_forums_move_content_sql_before + * @var array table_ary Array of tables from which forum_id will be updated + * @since 3.2.4-RC1 + */ + $vars = array('table_ary'); + extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_move_content_sql_before', compact($vars))); + foreach ($table_ary as $table) { $sql = "UPDATE $table @@ -1612,7 +1633,7 @@ class acp_forums } } - if (sizeof($errors)) + if (count($errors)) { return $errors; } @@ -1628,12 +1649,12 @@ class acp_forums $errors = array_merge($errors, $this->delete_forum_content($row['forum_id'])); } - if (sizeof($errors)) + if (count($errors)) { return $errors; } - $diff = sizeof($forum_ids) * 2; + $diff = count($forum_ids) * 2; $sql = 'DELETE FROM ' . FORUMS_TABLE . ' WHERE ' . $db->sql_in_set('forum_id', $forum_ids); @@ -1706,7 +1727,7 @@ class acp_forums } } - if (sizeof($errors)) + if (count($errors)) { return $errors; } @@ -1754,7 +1775,7 @@ class acp_forums $allowed_forums = array_diff($allowed_forums, $forum_ids); $sql = 'UPDATE ' . EXTENSION_GROUPS_TABLE . " - SET allowed_forums = '" . ((sizeof($allowed_forums)) ? serialize($allowed_forums) : '') . "' + SET allowed_forums = '" . ((count($allowed_forums)) ? serialize($allowed_forums) : '') . "' WHERE group_id = {$row['group_id']}"; $db->sql_query($sql); } @@ -1927,9 +1948,9 @@ class acp_forums } $db->sql_freeresult($result); - if (sizeof($ids)) + if (count($ids)) { - $start += sizeof($ids); + $start += count($ids); foreach ($tables as $table) { @@ -1937,7 +1958,7 @@ class acp_forums } } } - while (sizeof($ids) == $batch_size); + while (count($ids) == $batch_size); } unset($ids); @@ -1978,7 +1999,7 @@ class acp_forums } // Adjust users post counts - if (sizeof($post_counts)) + if (count($post_counts)) { foreach ($post_counts as $poster_id => $substract) { @@ -2062,7 +2083,7 @@ class acp_forums } $db->sql_freeresult($result); - if (!sizeof($target)) + if (!count($target)) { // The forum is already on top or bottom return false; diff --git a/phpBB/includes/acp/acp_groups.php b/phpBB/includes/acp/acp_groups.php index 305296d013..7b1dc706db 100644 --- a/phpBB/includes/acp/acp_groups.php +++ b/phpBB/includes/acp/acp_groups.php @@ -29,6 +29,9 @@ class acp_groups global $phpbb_root_path, $phpbb_admin_path, $phpEx; global $request, $phpbb_container, $phpbb_dispatcher; + /** @var \phpbb\language\language $language Language object */ + $language = $phpbb_container->get('language'); + $user->add_lang('acp/groups'); $this->tpl_name = 'acp_groups'; $this->page_title = 'ACP_GROUPS_MANAGE'; @@ -187,7 +190,7 @@ class acp_groups group_user_attributes('default', $group_id, $mark_ary, false, $group_name, $group_row); - $start = (sizeof($mark_ary) < 200) ? 0 : $start + 200; + $start = (count($mark_ary) < 200) ? 0 : $start + 200; } else { @@ -293,7 +296,19 @@ class acp_groups // Add user/s to group if ($error = group_user_add($group_id, false, $name_ary, $group_name, $default, $leader, 0, $group_row)) { - trigger_error($user->lang[$error] . adm_back_link($this->u_action . '&action=list&g=' . $group_id), E_USER_WARNING); + $display_message = $language->lang($error); + + if ($error == 'GROUP_USERS_INVALID') + { + // Find which users don't exist + $actual_name_ary = $name_ary; + $actual_user_id_ary = []; + user_get_id_name($actual_user_id_ary, $actual_name_ary, false, true); + + $display_message = $language->lang('GROUP_USERS_INVALID', implode($language->lang('COMMA_SEPARATOR'), array_udiff($name_ary, $actual_name_ary, 'strcasecmp'))); + } + + trigger_error($display_message . adm_back_link($this->u_action . '&action=list&g=' . $group_id), E_USER_WARNING); } $message = ($leader) ? 'GROUP_MODS_ADDED' : 'GROUP_USERS_ADDED'; @@ -486,7 +501,7 @@ class acp_groups $error = array_merge($error, $validation_error); } - if (!sizeof($error)) + if (!count($error)) { // Only set the rank, colour, etc. if it's changed or if we're adding a new // group. This prevents existing group members being updated if no changes @@ -614,7 +629,7 @@ class acp_groups } } - if (sizeof($error)) + if (count($error)) { $error = array_map(array(&$user, 'lang'), $error); $group_rank = $submit_ary['rank']; @@ -732,12 +747,12 @@ class acp_groups 'S_ADD_GROUP' => ($action == 'add') ? true : false, 'S_GROUP_PERM' => ($action == 'add' && $auth->acl_get('a_authgroups') && $auth->acl_gets('a_aauth', 'a_fauth', 'a_mauth', 'a_uauth')) ? true : false, 'S_INCLUDE_SWATCH' => true, - 'S_ERROR' => (sizeof($error)) ? true : false, + 'S_ERROR' => (count($error)) ? true : false, 'S_SPECIAL_GROUP' => ($group_type == GROUP_SPECIAL) ? true : false, 'S_USER_FOUNDER' => ($user->data['user_type'] == USER_FOUNDER) ? true : false, 'S_AVATARS_ENABLED' => ($config['allow_avatar'] && $avatars_enabled), - 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', + 'ERROR_MSG' => (count($error)) ? implode('<br />', $error) : '', 'GROUP_NAME' => $group_helper->get_name($group_name), 'GROUP_INTERNAL_NAME' => $group_name, 'GROUP_DESC' => $group_desc_data['text'], @@ -926,7 +941,7 @@ class acp_groups ); // Get us all the groups - $sql = 'SELECT g.group_id, g.group_name, g.group_type + $sql = 'SELECT g.group_id, g.group_name, g.group_type, g.group_colour FROM ' . GROUPS_TABLE . ' g ORDER BY g.group_type ASC, g.group_name'; $result = $db->sql_query($sql); @@ -985,6 +1000,7 @@ class acp_groups 'S_GROUP_SPECIAL' => ($row['group_type'] == GROUP_SPECIAL) ? true : false, 'GROUP_NAME' => $group_name, + 'GROUP_COLOR' => $row['group_colour'], 'TOTAL_MEMBERS' => $row['total_members'], 'PENDING_MEMBERS' => $row['pending_members'] )); diff --git a/phpBB/includes/acp/acp_help_phpbb.php b/phpBB/includes/acp/acp_help_phpbb.php index 7991a0dad6..a36b36eddc 100644 --- a/phpBB/includes/acp/acp_help_phpbb.php +++ b/phpBB/includes/acp/acp_help_phpbb.php @@ -48,7 +48,7 @@ class acp_help_phpbb $error[] = $user->lang['FORM_INVALID']; } // Do not write values if there is an error - if (sizeof($error)) + if (count($error)) { $submit = false; } diff --git a/phpBB/includes/acp/acp_icons.php b/phpBB/includes/acp/acp_icons.php index 6cd5386857..2c3948f644 100644 --- a/phpBB/includes/acp/acp_icons.php +++ b/phpBB/includes/acp/acp_icons.php @@ -166,7 +166,7 @@ class acp_icons } $db->sql_freeresult($result); - if (sizeof($smilies)) + if (count($smilies)) { foreach ($smilies as $row) { @@ -301,7 +301,7 @@ class acp_icons } // Ok, another row for adding an addition code for a pre-existing image... - if ($action == 'add' && $mode == 'smilies' && sizeof($smilies)) + if ($action == 'add' && $mode == 'smilies' && count($smilies)) { $template->assign_vars(array( 'S_ADD_CODE' => true, @@ -378,7 +378,7 @@ class acp_icons { $smiley_count = $this->item_count($table); - $addable_smileys_count = sizeof($images); + $addable_smileys_count = count($images); foreach ($images as $image) { if (!isset($image_add[$image])) @@ -546,8 +546,8 @@ class acp_icons { if (preg_match_all("#'(.*?)', ?#", $pak_entry, $data)) { - if ((sizeof($data[1]) != 4 && $mode == 'icons') || - ((sizeof($data[1]) != 6 || (empty($data[1][4]) || empty($data[1][5]))) && $mode == 'smilies' )) + if ((count($data[1]) != 4 && $mode == 'icons') || + ((count($data[1]) != 6 || (empty($data[1][4]) || empty($data[1][5]))) && $mode == 'smilies' )) { trigger_error($user->lang['WRONG_PAK_TYPE'] . adm_back_link($this->u_action), E_USER_WARNING); } @@ -605,7 +605,7 @@ class acp_icons if ($mode == 'smilies') { $smiley_count = $this->item_count($table); - if ($smiley_count + sizeof($pak_ary) > SMILEY_LIMIT) + if ($smiley_count + count($pak_ary) > SMILEY_LIMIT) { trigger_error($user->lang('TOO_MANY_SMILIES', SMILEY_LIMIT) . adm_back_link($this->u_action), E_USER_WARNING); } @@ -616,8 +616,8 @@ class acp_icons $data = array(); if (preg_match_all("#'(.*?)', ?#", $pak_entry, $data)) { - if ((sizeof($data[1]) != 4 && $mode == 'icons') || - (sizeof($data[1]) != 6 && $mode == 'smilies')) + if ((count($data[1]) != 4 && $mode == 'icons') || + (count($data[1]) != 6 && $mode == 'smilies')) { trigger_error($user->lang['WRONG_PAK_TYPE'] . adm_back_link($this->u_action), E_USER_WARNING); } diff --git a/phpBB/includes/acp/acp_inactive.php b/phpBB/includes/acp/acp_inactive.php index ec256e93ef..4ee4cd4816 100644 --- a/phpBB/includes/acp/acp_inactive.php +++ b/phpBB/includes/acp/acp_inactive.php @@ -24,9 +24,9 @@ class acp_inactive var $u_action; var $p_master; - function acp_inactive(&$p_master) + function __construct($p_master) { - $this->p_master = &$p_master; + $this->p_master = $p_master; } function main($id, $mode) @@ -70,7 +70,7 @@ class acp_inactive $s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = ''; gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param); - if ($submit && sizeof($mark)) + if ($submit && count($mark)) { if ($action !== 'delete' && !check_form_key($form_key)) { diff --git a/phpBB/includes/acp/acp_language.php b/phpBB/includes/acp/acp_language.php index 4baff921b6..8881f624e3 100644 --- a/phpBB/includes/acp/acp_language.php +++ b/phpBB/includes/acp/acp_language.php @@ -32,7 +32,7 @@ class acp_language function main($id, $mode) { global $config, $db, $user, $template, $phpbb_log, $phpbb_container; - global $phpbb_root_path, $phpEx, $request; + global $phpbb_root_path, $phpEx, $request, $phpbb_dispatcher; if (!function_exists('validate_language_iso_name')) { @@ -229,7 +229,20 @@ class acp_language $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_LANGUAGE_PACK_DELETED', false, array($row['lang_english_name'])); - trigger_error(sprintf($user->lang['LANGUAGE_PACK_DELETED'], $row['lang_english_name']) . adm_back_link($this->u_action)); + $delete_message = sprintf($user->lang['LANGUAGE_PACK_DELETED'], $row['lang_english_name']); + $lang_iso = $row['lang_iso']; + /** + * Run code after language deleted + * + * @event core.acp_language_after_delete + * @var string lang_iso Language ISO code + * @var string delete_message Delete message appear to user + * @since 3.2.2-RC1 + */ + $vars = array('lang_iso', 'delete_message'); + extract($phpbb_dispatcher->trigger_event('core.acp_language_after_delete', compact($vars))); + + trigger_error($delete_message . adm_back_link($this->u_action)); } else { @@ -402,7 +415,7 @@ class acp_language unset($installed); - if (sizeof($new_ary)) + if (count($new_ary)) { foreach ($new_ary as $iso => $lang_ary) { diff --git a/phpBB/includes/acp/acp_logs.php b/phpBB/includes/acp/acp_logs.php index c33ca8c4fc..f9bb35791c 100644 --- a/phpBB/includes/acp/acp_logs.php +++ b/phpBB/includes/acp/acp_logs.php @@ -57,7 +57,7 @@ class acp_logs { $conditions = array(); - if ($deletemark && sizeof($marked)) + if ($deletemark && count($marked)) { $conditions['log_id'] = array('IN' => $marked); } @@ -151,7 +151,7 @@ class acp_logs { $data = array(); - $checks = array('viewtopic', 'viewlogs', 'viewforum'); + $checks = array('viewpost', 'viewtopic', 'viewlogs', 'viewforum'); foreach ($checks as $check) { if (isset($row[$check]) && $row[$check]) @@ -167,7 +167,7 @@ class acp_logs 'IP' => $row['ip'], 'DATE' => $user->format_date($row['time']), 'ACTION' => $row['action'], - 'DATA' => (sizeof($data)) ? implode(' | ', $data) : '', + 'DATA' => (count($data)) ? implode(' | ', $data) : '', 'ID' => $row['id'], ) ); diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php index 9b1a248923..8f169d15a7 100644 --- a/phpBB/includes/acp/acp_main.php +++ b/phpBB/includes/acp/acp_main.php @@ -337,7 +337,7 @@ class acp_main } unset($posted); - if (sizeof($sql_ary)) + if (count($sql_ary)) { $db->sql_multi_insert(TOPICS_POSTED_TABLE, $sql_ary); } @@ -585,6 +585,7 @@ class acp_main 'U_INACTIVE_USERS' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=inactive&mode=list'), 'U_VERSIONCHECK' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=update&mode=version_check'), 'U_VERSIONCHECK_FORCE' => append_sid("{$phpbb_admin_path}index.$phpEx", 'versioncheck_force=1'), + 'U_ATTACH_ORPHAN' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=acp_attachments&mode=orphan'), 'S_VERSIONCHECK' => ($auth->acl_get('a_board')) ? true : false, 'S_ACTION_OPTIONS' => ($auth->acl_get('a_board')) ? true : false, diff --git a/phpBB/includes/acp/acp_modules.php b/phpBB/includes/acp/acp_modules.php index 4d90b2da8b..fb0c09055e 100644 --- a/phpBB/includes/acp/acp_modules.php +++ b/phpBB/includes/acp/acp_modules.php @@ -249,7 +249,7 @@ class acp_modules trigger_error($msg . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); } - if (!sizeof($errors)) + if (!count($errors)) { $module_manager->remove_cache_file($this->module_class); @@ -364,7 +364,7 @@ class acp_modules trigger_error($msg . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); } - if (!sizeof($errors)) + if (!count($errors)) { $module_manager->remove_cache_file($this->module_class); @@ -430,7 +430,7 @@ class acp_modules array_change_key_case($module_data, CASE_UPPER)) ); - if (sizeof($errors)) + if (count($errors)) { $template->assign_vars(array( 'S_ERROR' => true, @@ -444,7 +444,7 @@ class acp_modules } // Default management page - if (sizeof($errors)) + if (count($errors)) { if ($request->is_ajax()) { diff --git a/phpBB/includes/acp/acp_permission_roles.php b/phpBB/includes/acp/acp_permission_roles.php index 0bfe67830f..80cad9915d 100644 --- a/phpBB/includes/acp/acp_permission_roles.php +++ b/phpBB/includes/acp/acp_permission_roles.php @@ -348,7 +348,7 @@ class acp_permission_roles { $hold_ary = $this->auth_admin->get_role_mask($role_id); - if (sizeof($hold_ary)) + if (count($hold_ary)) { $role_name = (!empty($user->lang[$role_row['role_name']])) ? $user->lang[$role_row['role_name']] : $role_row['role_name']; @@ -496,7 +496,7 @@ class acp_permission_roles $content_array = $content_array[0]; - $template->assign_var('S_NUM_PERM_COLS', sizeof($categories)); + $template->assign_var('S_NUM_PERM_COLS', count($categories)); // Assign to template foreach ($content_array as $cat => $cat_array) diff --git a/phpBB/includes/acp/acp_permissions.php b/phpBB/includes/acp/acp_permissions.php index 12c43bf94c..e683b1972e 100644 --- a/phpBB/includes/acp/acp_permissions.php +++ b/phpBB/includes/acp/acp_permissions.php @@ -131,11 +131,11 @@ class acp_permissions } unset($usernames); - if (sizeof($username) && !sizeof($user_id)) + if (count($username) && !count($user_id)) { user_get_id_name($user_id, $username); - if (!sizeof($user_id)) + if (!count($user_id)) { trigger_error($user->lang['SELECTED_USER_NOT_EXIST'] . adm_back_link($this->u_action), E_USER_WARNING); } @@ -260,17 +260,17 @@ class acp_permissions { $items = $this->retrieve_defined_user_groups($permission_scope, $forum_id, $permission_type); - if ($all_users && sizeof($items['user_ids'])) + if ($all_users && count($items['user_ids'])) { $user_id = $items['user_ids']; } - else if ($all_groups && sizeof($items['group_ids'])) + else if ($all_groups && count($items['group_ids'])) { $group_id = $items['group_ids']; } } - if (sizeof($user_id) || sizeof($group_id)) + if (count($user_id) || count($group_id)) { $this->remove_permissions($mode, $permission_type, $auth_admin, $user_id, $group_id, $forum_id); } @@ -349,7 +349,7 @@ class acp_permissions { case 'forum_dropdown': - if (sizeof($forum_id)) + if (count($forum_id)) { $this->check_existence('forum', $forum_id); continue 2; @@ -364,7 +364,7 @@ class acp_permissions case 'forums': - if (sizeof($forum_id)) + if (count($forum_id)) { $this->check_existence('forum', $forum_id); continue 2; @@ -394,7 +394,7 @@ class acp_permissions case 'user': - if (sizeof($user_id)) + if (count($user_id)) { $this->check_existence('user', $user_id); continue 2; @@ -409,7 +409,7 @@ class acp_permissions case 'group': - if (sizeof($group_id)) + if (count($group_id)) { $this->check_existence('group', $group_id); continue 2; @@ -428,14 +428,14 @@ class acp_permissions $all_users = (isset($_POST['all_users'])) ? true : false; $all_groups = (isset($_POST['all_groups'])) ? true : false; - if ((sizeof($user_id) && !$all_users) || (sizeof($group_id) && !$all_groups)) + if ((count($user_id) && !$all_users) || (count($group_id) && !$all_groups)) { - if (sizeof($user_id)) + if (count($user_id)) { $this->check_existence('user', $user_id); } - if (sizeof($group_id)) + if (count($group_id)) { $this->check_existence('group', $group_id); } @@ -446,13 +446,13 @@ class acp_permissions // Now we check the users... because the "all"-selection is different here (all defined users/groups) $items = $this->retrieve_defined_user_groups($permission_scope, $forum_id, $permission_type); - if ($all_users && sizeof($items['user_ids'])) + if ($all_users && count($items['user_ids'])) { $user_id = $items['user_ids']; continue 2; } - if ($all_groups && sizeof($items['group_ids'])) + if ($all_groups && count($items['group_ids'])) { $group_id = $items['group_ids']; continue 2; @@ -487,14 +487,14 @@ class acp_permissions 'ANONYMOUS_USER_ID' => ANONYMOUS, 'S_SELECT_VICTIM' => true, - 'S_ALLOW_ALL_SELECT' => (sizeof($forum_id) > 5) ? false : true, + 'S_ALLOW_ALL_SELECT' => (count($forum_id) > 5) ? false : true, 'S_CAN_SELECT_USER' => ($auth->acl_get('a_authusers')) ? true : false, 'S_CAN_SELECT_GROUP' => ($auth->acl_get('a_authgroups')) ? true : false, 'S_HIDDEN_FIELDS' => $s_hidden_fields) ); // Let the forum names being displayed - if (sizeof($forum_id)) + if (count($forum_id)) { $sql = 'SELECT forum_name FROM ' . FORUMS_TABLE . ' @@ -510,7 +510,7 @@ class acp_permissions $db->sql_freeresult($result); $template->assign_vars(array( - 'S_FORUM_NAMES' => (sizeof($forum_names)) ? true : false, + 'S_FORUM_NAMES' => (count($forum_names)) ? true : false, 'FORUM_NAMES' => implode($user->lang['COMMA_SEPARATOR'], $forum_names)) ); } @@ -527,13 +527,13 @@ class acp_permissions )); // Do not allow forum_ids being set and no other setting defined (will bog down the server too much) - if (sizeof($forum_id) && !sizeof($user_id) && !sizeof($group_id)) + if (count($forum_id) && !count($user_id) && !count($group_id)) { trigger_error($user->lang['ONLY_FORUM_DEFINED'] . adm_back_link($this->u_action), E_USER_WARNING); } $template->assign_vars(array( - 'S_PERMISSION_DROPDOWN' => (sizeof($this->permission_dropdown) > 1) ? $this->build_permission_dropdown($this->permission_dropdown, $permission_type, $permission_scope) : false, + 'S_PERMISSION_DROPDOWN' => (count($this->permission_dropdown) > 1) ? $this->build_permission_dropdown($this->permission_dropdown, $permission_type, $permission_scope) : false, 'L_PERMISSION_TYPE' => $this->permissions->get_type_lang($permission_type), 'U_ACTION' => $this->u_action, @@ -546,8 +546,8 @@ class acp_permissions 'S_SETTING_PERMISSIONS' => true) ); - $hold_ary = $auth_admin->get_mask('set', (sizeof($user_id)) ? $user_id : false, (sizeof($group_id)) ? $group_id : false, (sizeof($forum_id)) ? $forum_id : false, $permission_type, $permission_scope, ACL_NO); - $auth_admin->display_mask('set', $permission_type, $hold_ary, ((sizeof($user_id)) ? 'user' : 'group'), (($permission_scope == 'local') ? true : false)); + $hold_ary = $auth_admin->get_mask('set', (count($user_id)) ? $user_id : false, (count($group_id)) ? $group_id : false, (count($forum_id)) ? $forum_id : false, $permission_type, $permission_scope, ACL_NO); + $auth_admin->display_mask('set', $permission_type, $hold_ary, ((count($user_id)) ? 'user' : 'group'), (($permission_scope == 'local') ? true : false)); } else { @@ -555,8 +555,8 @@ class acp_permissions 'S_VIEWING_PERMISSIONS' => true) ); - $hold_ary = $auth_admin->get_mask('view', (sizeof($user_id)) ? $user_id : false, (sizeof($group_id)) ? $group_id : false, (sizeof($forum_id)) ? $forum_id : false, $permission_type, $permission_scope, ACL_NEVER); - $auth_admin->display_mask('view', $permission_type, $hold_ary, ((sizeof($user_id)) ? 'user' : 'group'), (($permission_scope == 'local') ? true : false)); + $hold_ary = $auth_admin->get_mask('view', (count($user_id)) ? $user_id : false, (count($group_id)) ? $group_id : false, (count($forum_id)) ? $forum_id : false, $permission_type, $permission_scope, ACL_NEVER); + $auth_admin->display_mask('view', $permission_type, $hold_ary, ((count($user_id)) ? 'user' : 'group'), (($permission_scope == 'local') ? true : false)); } } @@ -652,7 +652,7 @@ class acp_permissions break; } - if (sizeof($ids)) + if (count($ids)) { $sql = "SELECT $sql_id FROM $table @@ -667,7 +667,7 @@ class acp_permissions $db->sql_freeresult($result); } - if (!sizeof($ids)) + if (!count($ids)) { trigger_error($user->lang['SELECTED_' . strtoupper($mode) . '_NOT_EXIST'] . adm_back_link($this->u_action), E_USER_WARNING); } @@ -676,7 +676,7 @@ class acp_permissions /** * Apply permissions */ - function set_permissions($mode, $permission_type, &$auth_admin, &$user_id, &$group_id) + function set_permissions($mode, $permission_type, $auth_admin, &$user_id, &$group_id) { global $db, $cache, $user, $auth; global $request; @@ -684,7 +684,7 @@ class acp_permissions $psubmit = $request->variable('psubmit', array(0 => array(0 => 0))); // User or group to be set? - $ug_type = (sizeof($user_id)) ? 'user' : 'group'; + $ug_type = (count($user_id)) ? 'user' : 'group'; // Check the permission setting again if (!$auth->acl_get('a_' . str_replace('_', '', $permission_type) . 'auth') || !$auth->acl_get('a_auth' . $ug_type . 's')) @@ -715,7 +715,7 @@ class acp_permissions $ug_id = array($ug_id); $forum_id = array($forum_id); - if (sizeof($inherit)) + if (count($inherit)) { foreach ($inherit as $_ug_id => $forum_id_ary) { @@ -765,13 +765,13 @@ class acp_permissions /** * Apply all permissions */ - function set_all_permissions($mode, $permission_type, &$auth_admin, &$user_id, &$group_id) + function set_all_permissions($mode, $permission_type, $auth_admin, &$user_id, &$group_id) { global $db, $cache, $user, $auth; global $request; // User or group to be set? - $ug_type = (sizeof($user_id)) ? 'user' : 'group'; + $ug_type = (count($user_id)) ? 'user' : 'group'; // Check the permission setting again if (!$auth->acl_get('a_' . str_replace('_', '', $permission_type) . 'auth') || !$auth->acl_get('a_auth' . $ug_type . 's')) @@ -870,7 +870,7 @@ class acp_permissions } } - if (sizeof(array_diff_assoc($auth_settings, $test_auth_settings))) + if (count(array_diff_assoc($auth_settings, $test_auth_settings))) { return false; } @@ -881,12 +881,12 @@ class acp_permissions /** * Remove permissions */ - function remove_permissions($mode, $permission_type, &$auth_admin, &$user_id, &$group_id, &$forum_id) + function remove_permissions($mode, $permission_type, $auth_admin, &$user_id, &$group_id, &$forum_id) { global $user, $db, $cache, $auth; // User or group to be set? - $ug_type = (sizeof($user_id)) ? 'user' : 'group'; + $ug_type = (count($user_id)) ? 'user' : 'group'; // Check the permission setting again if (!$auth->acl_get('a_' . str_replace('_', '', $permission_type) . 'auth') || !$auth->acl_get('a_auth' . $ug_type . 's')) @@ -895,7 +895,7 @@ class acp_permissions trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); } - $auth_admin->acl_delete($ug_type, (($ug_type == 'user') ? $user_id : $group_id), (sizeof($forum_id) ? $forum_id : false), $permission_type); + $auth_admin->acl_delete($ug_type, (($ug_type == 'user') ? $user_id : $group_id), (count($forum_id) ? $forum_id : false), $permission_type); // Do we need to recache the moderator lists? if ($permission_type == 'm_') @@ -903,7 +903,7 @@ class acp_permissions 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))); + $this->log_action($mode, 'del', $permission_type, $ug_type, (($ug_type == 'user') ? $user_id : $group_id), (count($forum_id) ? $forum_id : array(0 => 0))); if ($mode == 'setting_forum_local' || $mode == 'setting_mod_local') { @@ -1053,7 +1053,7 @@ class acp_permissions $total = ACL_NO; $add_key = (($forum_id) ? '_LOCAL' : ''); - if (sizeof($groups)) + if (count($groups)) { // Get group auth settings $hold_ary = $auth->acl_group_raw_data(array_keys($groups), $permission, $forum_id); @@ -1099,7 +1099,7 @@ class acp_permissions // Get user specific permission... globally or for this forum $hold_ary = $auth->acl_user_raw_data($user_id, $permission, $forum_id); - $auth_setting = (!sizeof($hold_ary)) ? ACL_NO : $hold_ary[$user_id][$forum_id][$permission]; + $auth_setting = (!count($hold_ary)) ? ACL_NO : $hold_ary[$user_id][$forum_id][$permission]; switch ($auth_setting) { @@ -1258,7 +1258,7 @@ class acp_permissions /** @var \phpbb\group\helper $group_helper */ $group_helper = $phpbb_container->get('group_helper'); - $sql_forum_id = ($permission_scope == 'global') ? 'AND a.forum_id = 0' : ((sizeof($forum_id)) ? 'AND ' . $db->sql_in_set('a.forum_id', $forum_id) : 'AND a.forum_id <> 0'); + $sql_forum_id = ($permission_scope == 'global') ? 'AND a.forum_id = 0' : ((count($forum_id)) ? 'AND ' . $db->sql_in_set('a.forum_id', $forum_id) : 'AND a.forum_id <> 0'); // Permission options are only able to be a permission set... therefore we will pre-fetch the possible options and also the possible roles $option_ids = $role_ids = array(); @@ -1274,7 +1274,7 @@ class acp_permissions } $db->sql_freeresult($result); - if (sizeof($option_ids)) + if (count($option_ids)) { $sql = 'SELECT DISTINCT role_id FROM ' . ACL_ROLES_DATA_TABLE . ' @@ -1288,15 +1288,15 @@ class acp_permissions $db->sql_freeresult($result); } - if (sizeof($option_ids) && sizeof($role_ids)) + if (count($option_ids) && count($role_ids)) { $sql_where = 'AND (' . $db->sql_in_set('a.auth_option_id', $option_ids) . ' OR ' . $db->sql_in_set('a.auth_role_id', $role_ids) . ')'; } - else if (sizeof($role_ids)) + else if (count($role_ids)) { $sql_where = 'AND ' . $db->sql_in_set('a.auth_role_id', $role_ids); } - else if (sizeof($option_ids)) + else if (count($option_ids)) { $sql_where = 'AND ' . $db->sql_in_set('a.auth_option_id', $option_ids); } diff --git a/phpBB/includes/acp/acp_profile.php b/phpBB/includes/acp/acp_profile.php index 18dde382ca..49da7d84a4 100644 --- a/phpBB/includes/acp/acp_profile.php +++ b/phpBB/includes/acp/acp_profile.php @@ -446,7 +446,7 @@ class acp_profile { $exploded_options = (is_array($options)) ? $options : explode("\n", $options); - if (sizeof($exploded_options) == sizeof($lang_options) || $action == 'create') + if (count($exploded_options) == count($lang_options) || $action == 'create') { // The number of options in the field is equal to the number of options already in the database // Or we are creating a new dropdown list. @@ -567,7 +567,7 @@ class acp_profile } } - if (sizeof($error)) + if (count($error)) { $submit = false; } @@ -600,9 +600,9 @@ class acp_profile $s_hidden_fields .= build_hidden_fields($_new_key_ary); } - if (!sizeof($error)) + if (!count($error)) { - if (($step == 3 && (sizeof($this->lang_defs['iso']) == 1 || $save)) || ($action == 'edit' && $save)) + if (($step == 3 && (count($this->lang_defs['iso']) == 1 || $save)) || ($action == 'edit' && $save)) { if (!check_form_key($form_key)) { @@ -616,7 +616,7 @@ class acp_profile $template->assign_vars(array( 'S_EDIT' => true, 'S_EDIT_MODE' => ($action == 'edit') ? true : false, - 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', + 'ERROR_MSG' => (count($error)) ? implode('<br />', $error) : '', 'L_TITLE' => $user->lang['STEP_' . $step . '_TITLE_' . strtoupper($action)], 'L_EXPLAIN' => $user->lang['STEP_' . $step . '_EXPLAIN_' . strtoupper($action)], @@ -664,7 +664,7 @@ class acp_profile $template->assign_vars(array( 'S_STEP_TWO' => true, - 'L_NEXT_STEP' => (sizeof($this->lang_defs['iso']) == 1) ? $user->lang['SAVE'] : $user->lang['PROFILE_LANG_OPTIONS']) + 'L_NEXT_STEP' => (count($this->lang_defs['iso']) == 1) ? $user->lang['SAVE'] : $user->lang['PROFILE_LANG_OPTIONS']) ); // Build options based on profile type @@ -738,6 +738,32 @@ class acp_profile break; } + $tpl_name = $this->tpl_name; + $page_title = $this->page_title; + $u_action = $this->u_action; + + /** + * Event to handle actions on the ACP profile fields page + * + * @event core.acp_profile_action + * @var string action Action that is being performed + * @var string tpl_name Template file to load + * @var string page_title Page title + * @var string u_action The URL we are at, read only + * @since 3.2.2-RC1 + */ + $vars = array( + 'action', + 'tpl_name', + 'page_title', + 'u_action', + ); + extract($phpbb_dispatcher->trigger_event('core.acp_profile_action', compact($vars))); + + $this->tpl_name = $tpl_name; + $this->page_title = $page_title; + unset($u_action); + $sql = 'SELECT * FROM ' . PROFILE_FIELDS_TABLE . ' ORDER BY field_order'; @@ -750,7 +776,7 @@ class acp_profile $active_value = (!$row['field_active']) ? 'activate' : 'deactivate'; $id = $row['field_id']; - $s_need_edit = (sizeof($this->lang_defs['diff'][$row['field_id']])) ? true : false; + $s_need_edit = (count($this->lang_defs['diff'][$row['field_id']])) ? true : false; if ($s_need_edit) { @@ -762,7 +788,8 @@ class acp_profile continue; } $profile_field = $this->type_collection[$row['field_type']]; - $template->assign_block_vars('fields', array( + + $field_block = array( 'FIELD_IDENT' => $row['field_ident'], 'FIELD_TYPE' => $profile_field->get_name(), @@ -774,8 +801,26 @@ class acp_profile 'U_MOVE_UP' => $this->u_action . "&action=move_up&field_id=$id" . '&hash=' . generate_link_hash('acp_profile'), 'U_MOVE_DOWN' => $this->u_action . "&action=move_down&field_id=$id" . '&hash=' . generate_link_hash('acp_profile'), - 'S_NEED_EDIT' => $s_need_edit) + 'S_NEED_EDIT' => $s_need_edit, ); + + /** + * Event to modify profile field data before it is assigned to the template + * + * @event core.acp_profile_modify_profile_row + * @var array row Array with data for the current profile field + * @var array field_block Template data that is being assigned to the 'fields' block + * @var object profile_field A profile field instance, implements \phpbb\profilefields\type\type_base + * @since 3.2.2-RC1 + */ + $vars = array( + 'row', + 'field_block', + 'profile_field', + ); + extract($phpbb_dispatcher->trigger_event('core.acp_profile_modify_profile_row', compact($vars))); + + $template->assign_block_vars('fields', $field_block); } $db->sql_freeresult($result); @@ -800,7 +845,7 @@ class acp_profile /** * Build all Language specific options */ - function build_language_options(&$cp, $field_type, $action = 'create') + function build_language_options($cp, $field_type, $action = 'create') { global $user, $config, $db, $request; @@ -897,7 +942,7 @@ class acp_profile /** * Save Profile Field */ - function save_profile_field(&$cp, $field_type, $action = 'create') + function save_profile_field($cp, $field_type, $action = 'create') { global $db, $config, $user, $phpbb_container, $phpbb_log, $request, $phpbb_dispatcher; @@ -1011,7 +1056,7 @@ class acp_profile $this->update_insert(PROFILE_LANG_TABLE, $sql_ary, array('field_id' => $field_id, 'lang_id' => $default_lang_id)); } - if (is_array($cp->vars['l_lang_name']) && sizeof($cp->vars['l_lang_name'])) + if (is_array($cp->vars['l_lang_name']) && count($cp->vars['l_lang_name'])) { foreach ($cp->vars['l_lang_name'] as $lang_id => $data) { @@ -1087,7 +1132,7 @@ class acp_profile } } - if (is_array($cp->vars['l_lang_options']) && sizeof($cp->vars['l_lang_options'])) + if (is_array($cp->vars['l_lang_options']) && count($cp->vars['l_lang_options'])) { $empty_lang = array(); @@ -1098,7 +1143,7 @@ class acp_profile $lang_ary = explode("\n", $lang_ary); } - if (sizeof($lang_ary) != sizeof($cp->vars['lang_options'])) + if (count($lang_ary) != count($cp->vars['lang_options'])) { $empty_lang[$lang_id] = true; } @@ -1150,7 +1195,7 @@ class acp_profile } } - if (sizeof($profile_lang_fields)) + if (count($profile_lang_fields)) { foreach ($profile_lang_fields as $sql) { @@ -1213,7 +1258,7 @@ class acp_profile $where_sql[] = $key . ' = ' . ((is_string($value)) ? "'" . $db->sql_escape($value) . "'" : (int) $value); } - if (!sizeof($where_sql)) + if (!count($where_sql)) { return; } @@ -1229,14 +1274,14 @@ class acp_profile { $sql_ary = array_merge($where_fields, $sql_ary); - if (sizeof($sql_ary)) + if (count($sql_ary)) { $db->sql_query("INSERT INTO $table " . $db->sql_build_array('INSERT', $sql_ary)); } } else { - if (sizeof($sql_ary)) + if (count($sql_ary)) { $sql = "UPDATE $table SET " . $db->sql_build_array('UPDATE', $sql_ary) . ' WHERE ' . implode(' AND ', $where_sql); diff --git a/phpBB/includes/acp/acp_prune.php b/phpBB/includes/acp/acp_prune.php index d37050869a..3eee4f7922 100644 --- a/phpBB/includes/acp/acp_prune.php +++ b/phpBB/includes/acp/acp_prune.php @@ -55,7 +55,7 @@ class acp_prune */ function prune_forums($id, $mode) { - global $db, $user, $auth, $template, $phpbb_log, $request; + global $db, $user, $auth, $template, $phpbb_log, $request, $phpbb_dispatcher; $all_forums = $request->variable('all_forums', 0); $forum_id = $request->variable('f', array(0)); @@ -97,7 +97,7 @@ class acp_prune 'S_PRUNED' => true) ); - $sql_forum = (sizeof($forum_id)) ? ' AND ' . $db->sql_in_set('forum_id', $forum_id) : ''; + $sql_forum = (count($forum_id)) ? ' AND ' . $db->sql_in_set('forum_id', $forum_id) : ''; // Get a list of forum's or the data for the forum that we are pruning. $sql = 'SELECT forum_id, forum_name @@ -165,7 +165,7 @@ class acp_prune } else { - confirm_box(false, $user->lang['PRUNE_FORUM_CONFIRM'], build_hidden_fields(array( + $hidden_fields = array( 'i' => $id, 'mode' => $mode, 'submit' => 1, @@ -177,13 +177,25 @@ class acp_prune 'prune_old_polls' => $request->variable('prune_old_polls', 0), 'prune_announce' => $request->variable('prune_announce', 0), 'prune_sticky' => $request->variable('prune_sticky', 0), - ))); + ); + + /** + * Use this event to pass data from the prune form to the confirmation screen + * + * @event core.prune_forums_settings_confirm + * @var array hidden_fields Hidden fields that are passed through the confirm screen + * @since 3.2.2-RC1 + */ + $vars = array('hidden_fields'); + extract($phpbb_dispatcher->trigger_event('core.prune_forums_settings_confirm', compact($vars))); + + confirm_box(false, $user->lang['PRUNE_FORUM_CONFIRM'], build_hidden_fields($hidden_fields)); } } // If they haven't selected a forum for pruning yet then // display a select box to use for pruning. - if (!sizeof($forum_id)) + if (!count($forum_id)) { $template->assign_vars(array( 'U_ACTION' => $this->u_action, @@ -215,15 +227,27 @@ class acp_prune $db->sql_freeresult($result); - $l_selected_forums = (sizeof($forum_id) == 1) ? 'SELECTED_FORUM' : 'SELECTED_FORUMS'; + $l_selected_forums = (count($forum_id) == 1) ? 'SELECTED_FORUM' : 'SELECTED_FORUMS'; - $template->assign_vars(array( + $template_data = array( 'L_SELECTED_FORUMS' => $user->lang[$l_selected_forums], 'U_ACTION' => $this->u_action, 'U_BACK' => $this->u_action, 'FORUM_LIST' => $forum_list, - 'S_HIDDEN_FIELDS' => $s_hidden_fields) + 'S_HIDDEN_FIELDS' => $s_hidden_fields, ); + + /** + * Event to add/modify prune forums settings template data + * + * @event core.prune_forums_settings_template_data + * @var array template_data Array with form template data + * @since 3.2.2-RC1 + */ + $vars = array('template_data'); + extract($phpbb_dispatcher->trigger_event('core.prune_forums_settings_template_data', compact($vars))); + + $template->assign_vars($template_data); } } @@ -252,7 +276,7 @@ class acp_prune $user_ids = $usernames = array(); $this->get_prune_users($user_ids, $usernames); - if (sizeof($user_ids)) + if (count($user_ids)) { if ($action == 'deactivate') { @@ -291,7 +315,7 @@ class acp_prune $user_ids = $usernames = array(); $this->get_prune_users($user_ids, $usernames); - if (!sizeof($user_ids)) + if (!count($user_ids)) { trigger_error($user->lang['USER_PRUNE_FAILURE'] . adm_back_link($this->u_action), E_USER_WARNING); } @@ -434,7 +458,7 @@ class acp_prune } // implicit else when both arrays are empty do nothing - if ((sizeof($active) && sizeof($active) != 3) || (sizeof($joined_before) && sizeof($joined_before) != 3) || (sizeof($joined_after) && sizeof($joined_after) != 3)) + if ((count($active) && count($active) != 3) || (count($joined_before) && count($joined_before) != 3) || (count($joined_after) && count($joined_after) != 3)) { trigger_error($user->lang['WRONG_ACTIVE_JOINED_DATE'] . adm_back_link($this->u_action), E_USER_WARNING); } @@ -448,15 +472,15 @@ class acp_prune $where_sql .= ($count !== false) ? " AND user_posts " . $key_match[$count_select] . ' ' . (int) $count . ' ' : ''; // First handle pruning of users who never logged in, last active date is 0000-00-00 - if (sizeof($active) && (int) $active[0] == 0 && (int) $active[1] == 0 && (int) $active[2] == 0) + if (count($active) && (int) $active[0] == 0 && (int) $active[1] == 0 && (int) $active[2] == 0) { $where_sql .= ' AND user_lastvisit = 0'; } - else if (sizeof($active) && $active_select != 'lt') + else if (count($active) && $active_select != 'lt') { $where_sql .= ' AND user_lastvisit ' . $key_match[$active_select] . ' ' . gmmktime(0, 0, 0, (int) $active[1], (int) $active[2], (int) $active[0]); } - else if (sizeof($active)) + else if (count($active)) { $where_sql .= ' AND (user_lastvisit > 0 AND user_lastvisit < ' . gmmktime(0, 0, 0, (int) $active[1], (int) $active[2], (int) $active[0]) . ')'; } diff --git a/phpBB/includes/acp/acp_reasons.php b/phpBB/includes/acp/acp_reasons.php index 51c398681d..dfb2ccbfd3 100644 --- a/phpBB/includes/acp/acp_reasons.php +++ b/phpBB/includes/acp/acp_reasons.php @@ -103,7 +103,7 @@ class acp_reasons } } - if (!sizeof($error)) + if (!count($error)) { // New reason? if ($action == 'add') @@ -171,7 +171,7 @@ class acp_reasons 'L_TITLE' => $user->lang['REASON_' . $l_title], 'U_ACTION' => $this->u_action . "&id=$reason_id&action=$action", 'U_BACK' => $this->u_action, - 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', + 'ERROR_MSG' => (count($error)) ? implode('<br />', $error) : '', 'REASON_TITLE' => $reason_row['reason_title'], 'REASON_DESCRIPTION' => $reason_row['reason_description'], @@ -182,7 +182,7 @@ class acp_reasons 'S_AVAILABLE_TITLES' => implode($user->lang['COMMA_SEPARATOR'], array_map('htmlspecialchars', array_keys($user->lang['report_reasons']['TITLE']))), 'S_EDIT_REASON' => true, 'S_TRANSLATED' => $translated, - 'S_ERROR' => (sizeof($error)) ? true : false, + 'S_ERROR' => (count($error)) ? true : false, ) ); diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php index a792ee6b79..538a28a926 100644 --- a/phpBB/includes/acp/acp_search.php +++ b/phpBB/includes/acp/acp_search.php @@ -332,9 +332,9 @@ class acp_search $forum_ids[] = $row['forum_id']; } $db->sql_freeresult($result); - $row_count += sizeof($ids); + $row_count += count($ids); - if (sizeof($ids)) + if (count($ids)) { $this->search->index_remove($ids, $posters, $forum_ids); } @@ -349,7 +349,7 @@ class acp_search $totaltime = microtime(true) - $starttime; $rows_per_second = $row_count / $totaltime; meta_refresh(1, append_sid($this->u_action . '&action=delete&skip_rows=' . $post_counter . '&hash=' . generate_link_hash('acp_search'))); - trigger_error($user->lang('SEARCH_INDEX_DELETE_REDIRECT', (int) $row_count, $post_counter, $rows_per_second)); + trigger_error($user->lang('SEARCH_INDEX_DELETE_REDIRECT', (int) $row_count, $post_counter) . $user->lang('SEARCH_INDEX_DELETE_REDIRECT_RATE', $rows_per_second)); } } @@ -474,8 +474,8 @@ class acp_search $statistics = array(); foreach ($data as $statistic => $value) { - $n = sizeof($statistics); - if ($n && sizeof($statistics[$n - 1]) < 3) + $n = count($statistics); + if ($n && count($statistics[$n - 1]) < 3) { $statistics[$n - 1] += array('statistic_2' => $statistic, 'value_2' => $value); } @@ -492,7 +492,7 @@ class acp_search 'S_ACTIVE' => ($type == $config['search_type']) ? true : false, 'S_HIDDEN_FIELDS' => build_hidden_fields(array('search_type' => $type)), 'S_INDEXED' => (bool) $search->index_created(), - 'S_STATS' => (bool) sizeof($statistics)) + 'S_STATS' => (bool) count($statistics)) ); foreach ($statistics as $statistic) diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php index b954f90451..87c8d88f52 100644 --- a/phpBB/includes/acp/acp_styles.php +++ b/phpBB/includes/acp/acp_styles.php @@ -259,6 +259,19 @@ class acp_styles // Get list of styles to uninstall $ids = $this->request_vars('id', 0, true); + // Don't remove prosilver, you can still deactivate it. + $sql = 'SELECT style_id + FROM ' . STYLES_TABLE . " + WHERE style_name = '" . $this->db->sql_escape('prosilver') . "'"; + $result = $this->db->sql_query($sql); + $prosilver_id = (int) $this->db->sql_fetchfield('style_id'); + $this->db->sql_freeresult($result); + + if ($prosilver_id && in_array($prosilver_id, $ids)) + { + trigger_error($this->user->lang('UNINSTALL_PROSILVER') . adm_back_link($this->u_action), E_USER_WARNING); + } + // Check if confirmation box was submitted if (confirm_box(true)) { @@ -398,7 +411,7 @@ class acp_styles // Reset default style for users who use selected styles $sql = 'UPDATE ' . USERS_TABLE . ' - SET user_style = 0 + SET user_style = ' . (int) $this->default_style . ' WHERE user_style IN (' . implode(', ', $ids) . ')'; $this->db->sql_query($sql); @@ -952,6 +965,7 @@ class acp_styles // Style data 'STYLE_ID' => $style['style_id'], 'STYLE_NAME' => htmlspecialchars($style['style_name']), + 'STYLE_PHPBB_VERSION' => $this->read_style_cfg($style['style_path'])['phpbb_version'], 'STYLE_PATH' => htmlspecialchars($style['style_path']), 'STYLE_COPYRIGHT' => strip_tags($style['style_copyright']), 'STYLE_ACTIVE' => $style['style_active'], @@ -997,11 +1011,14 @@ class acp_styles 'L_ACTION' => $this->user->lang['EXPORT'] ); */ - // Uninstall - $actions[] = array( - 'U_ACTION' => $this->u_action . '&action=uninstall&hash=' . generate_link_hash('uninstall') . '&id=' . $style['style_id'], - 'L_ACTION' => $this->user->lang['STYLE_UNINSTALL'] - ); + if ($style['style_name'] !== 'prosilver') + { + // Uninstall + $actions[] = array( + 'U_ACTION' => $this->u_action . '&action=uninstall&hash=' . generate_link_hash('uninstall') . '&id=' . $style['style_id'], + 'L_ACTION' => $this->user->lang['STYLE_UNINSTALL'] + ); + } // Preview $actions[] = array( @@ -1122,7 +1139,14 @@ class acp_styles */ protected function read_style_cfg($dir) { + // This should never happen, we give them a red warning because of its relevance. + if (!file_exists($this->styles_path . $dir . '/style.cfg')) + { + trigger_error($this->user->lang('NO_STYLE_CFG', $dir), E_USER_WARNING); + } + static $required = array('name', 'phpbb_version', 'copyright'); + $cfg = parse_cfg_file($this->styles_path . $dir . '/style.cfg'); // Check if it is a valid file @@ -1249,7 +1273,7 @@ class acp_styles // Change default style for users $sql = 'UPDATE ' . USERS_TABLE . ' - SET user_style = 0 + SET user_style = ' . (int) $this->default_style . ' WHERE user_style = ' . $id; $this->db->sql_query($sql); @@ -1355,18 +1379,18 @@ class acp_styles } // Hardcoded template bitfield to add for new templates + $default_bitfield = '1111111111111'; + $bitfield = new bitfield(); - $bitfield->set(0); - $bitfield->set(1); - $bitfield->set(2); - $bitfield->set(3); - $bitfield->set(4); - $bitfield->set(8); - $bitfield->set(9); - $bitfield->set(11); - $bitfield->set(12); - $value = $bitfield->get_base64(); - return $value; + for ($i = 0; $i < strlen($default_bitfield); $i++) + { + if ($default_bitfield[$i] == '1') + { + $bitfield->set($i); + } + } + + return $bitfield->get_base64(); } } diff --git a/phpBB/includes/acp/acp_update.php b/phpBB/includes/acp/acp_update.php index 9124a59ef2..fa3afa6ce3 100644 --- a/phpBB/includes/acp/acp_update.php +++ b/phpBB/includes/acp/acp_update.php @@ -59,17 +59,19 @@ class acp_update $update_link = $phpbb_root_path . 'install/app.' . $phpEx; - $template->assign_vars(array( - 'S_UP_TO_DATE' => empty($updates_available), - 'U_ACTION' => $this->u_action, - 'U_VERSIONCHECK_FORCE' => append_sid($this->u_action . '&versioncheck_force=1'), + $template_ary = [ + 'S_UP_TO_DATE' => empty($updates_available), + 'U_ACTION' => $this->u_action, + 'U_VERSIONCHECK_FORCE' => append_sid($this->u_action . '&versioncheck_force=1'), - 'CURRENT_VERSION' => $config['version'], + 'CURRENT_VERSION' => $config['version'], - 'UPDATE_INSTRUCTIONS' => sprintf($user->lang['UPDATE_INSTRUCTIONS'], $update_link), + 'UPDATE_INSTRUCTIONS' => $user->lang('UPDATE_INSTRUCTIONS', $update_link), 'S_VERSION_UPGRADEABLE' => !empty($upgrades_available), 'UPGRADE_INSTRUCTIONS' => !empty($upgrades_available) ? $user->lang('UPGRADE_INSTRUCTIONS', $upgrades_available['current'], $upgrades_available['announcement']) : false, - )); + ]; + + $template->assign_vars($template_ary); // Incomplete update? if (phpbb_version_compare($config['version'], PHPBB_VERSION, '<')) diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index 090cb32ebb..fd4b5e8c24 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -24,9 +24,9 @@ class acp_users var $u_action; var $p_master; - function acp_users(&$p_master) + function __construct($p_master) { - $this->p_master = &$p_master; + $this->p_master = $p_master; } function main($id, $mode) @@ -690,7 +690,7 @@ class acp_users } $db->sql_freeresult($result); - if (sizeof($topic_id_ary)) + if (count($topic_id_ary)) { $sql = 'SELECT topic_id, forum_id, topic_title, topic_posts_approved, topic_posts_unapproved, topic_posts_softdeleted, topic_attachment FROM ' . TOPICS_TABLE . ' @@ -718,12 +718,12 @@ class acp_users } // Entire topic comprises posts by this user, move these topics - if (sizeof($move_topic_ary)) + if (count($move_topic_ary)) { move_topics($move_topic_ary, $new_forum_id, false); } - if (sizeof($move_post_ary)) + if (count($move_post_ary)) { // Create new topic // Update post_ids, report_ids, attachment_ids @@ -769,13 +769,13 @@ class acp_users $forum_id_ary = array_unique($forum_id_ary); $topic_id_ary = array_unique(array_merge(array_keys($topic_id_ary), $new_topic_id_ary)); - if (sizeof($topic_id_ary)) + if (count($topic_id_ary)) { sync('topic_reported', 'topic_id', $topic_id_ary); sync('topic', 'topic_id', $topic_id_ary); } - if (sizeof($forum_id_ary)) + if (count($forum_id_ary)) { sync('forum', 'forum_id', $forum_id_ary, false, true); } @@ -855,7 +855,7 @@ class acp_users $check_ary += array( 'username' => array( array('string', false, $config['min_name_chars'], $config['max_name_chars']), - array('username', $user_row['username']) + array('username', $user_row['username'], true) ), ); } @@ -892,7 +892,7 @@ class acp_users $update_password = $data['new_password'] && !$passwords_manager->check($data['new_password'], $user_row['user_password']); $update_email = ($data['email'] != $user_row['user_email']) ? $data['email'] : false; - if (!sizeof($error)) + if (!count($error)) { $sql_ary = array(); @@ -994,7 +994,7 @@ class acp_users )); } - if (sizeof($sql_ary)) + if (count($sql_ary)) { $sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' @@ -1347,7 +1347,7 @@ class acp_users { $s_hidden_fields['delall'] = 1; } - if (isset($_POST['delall']) || (isset($_POST['delmarked']) && sizeof($marked))) + if (isset($_POST['delall']) || (isset($_POST['delmarked']) && count($marked))) { confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields($s_hidden_fields)); } @@ -1383,9 +1383,9 @@ class acp_users { // Check if there are more occurrences of % than arguments, if there are we fill out the arguments array // It doesn't matter if we add more arguments than placeholders - if ((substr_count($row['action'], '%') - sizeof($log_data_ary)) > 0) + if ((substr_count($row['action'], '%') - count($log_data_ary)) > 0) { - $log_data_ary = array_merge($log_data_ary, array_fill(0, substr_count($row['action'], '%') - sizeof($log_data_ary), '')); + $log_data_ary = array_merge($log_data_ary, array_fill(0, substr_count($row['action'], '%') - count($log_data_ary), '')); } $row['action'] = vsprintf($row['action'], $log_data_ary); $row['action'] = bbcode_nl2br(censor_text($row['action'])); @@ -1478,7 +1478,7 @@ class acp_users // validate custom profile fields $cp->submit_cp_field('profile', $user_row['iso_lang_id'], $cp_data, $cp_error); - if (sizeof($cp_error)) + if (count($cp_error)) { $error = array_merge($error, $cp_error); } @@ -1501,7 +1501,7 @@ class acp_users $vars = array('data', 'user_id', 'user_row', 'error'); extract($phpbb_dispatcher->trigger_event('core.acp_users_profile_validate', compact($vars))); - if (!sizeof($error)) + if (!count($error)) { $sql_ary = array( 'user_jabber' => $data['jabber'], @@ -1645,7 +1645,7 @@ class acp_users $error[] = 'FORM_INVALID'; } - if (!sizeof($error)) + if (!count($error)) { $this->optionset($user_row, 'viewimg', $data['view_images']); $this->optionset($user_row, 'viewflash', $data['view_flash']); @@ -1696,7 +1696,7 @@ class acp_users $vars = array('data', 'user_row', 'sql_ary', 'error'); extract($phpbb_dispatcher->trigger_event('core.acp_users_prefs_modify_sql', compact($vars))); - if (!sizeof($error)) + if (!count($error)) { $sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " @@ -1883,6 +1883,17 @@ class acp_users 'user_avatar_height' => $result['avatar_height'], ); + /** + * Modify users preferences data before assigning it to the template + * + * @event core.acp_users_avatar_sql + * @var array user_row Array with user data + * @var array result Array with user avatar data to be updated in the DB + * @since 3.2.4-RC1 + */ + $vars = array('user_row', 'result'); + extract($phpbb_dispatcher->trigger_event('core.acp_users_avatar_sql', compact($vars))); + $sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $result) . ' WHERE user_id = ' . (int) $user_id; @@ -2060,7 +2071,7 @@ class acp_users 'sig' ); - if (sizeof($warn_msg)) + if (count($warn_msg)) { $error += $warn_msg; } @@ -2072,7 +2083,7 @@ class acp_users } else { - if (!sizeof($error)) + if (!count($error)) { $this->optionset($user_row, 'sig_bbcode', $enable_bbcode); $this->optionset($user_row, 'sig_smilies', $enable_smilies); @@ -2085,6 +2096,17 @@ class acp_users 'user_sig_bbcode_bitfield' => $bbcode_bitfield, ); + /** + * Modify user signature before it is stored in the DB + * + * @event core.acp_users_modify_signature_sql_ary + * @var array user_row Array with user data + * @var array sql_ary Array with user signature data to be updated in the DB + * @since 3.2.4-RC1 + */ + $vars = array('user_row', 'sql_ary'); + extract($phpbb_dispatcher->trigger_event('core.acp_users_modify_signature_sql_ary', compact($vars))); + $sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' WHERE user_id = ' . $user_id; @@ -2099,7 +2121,7 @@ class acp_users if ($request->is_set_post('preview')) { - $decoded_message = generate_text_for_edit($signature, $bbcode_uid, $bbcode_bitfield); + $decoded_message = generate_text_for_edit($signature, $bbcode_uid, $bbcode_flags); } /** @var \phpbb\controller\helper $controller_helper */ @@ -2147,7 +2169,7 @@ class acp_users $sort_key = $request->variable('sk', 'a'); $sort_dir = $request->variable('sd', 'd'); - if ($deletemark && sizeof($marked)) + if ($deletemark && count($marked)) { $sql = 'SELECT attach_id FROM ' . ATTACHMENTS_TABLE . ' @@ -2164,7 +2186,7 @@ class acp_users $db->sql_freeresult($result); } - if ($deletemark && sizeof($marked)) + if ($deletemark && count($marked)) { if (confirm_box(true)) { @@ -2185,7 +2207,7 @@ class acp_users $attachment_manager->delete('attach', $marked); unset($attachment_manager); - $message = (sizeof($log_attachments) == 1) ? $user->lang['ATTACHMENT_DELETED'] : $user->lang['ATTACHMENTS_DELETED']; + $message = (count($log_attachments) == 1) ? $user->lang['ATTACHMENT_DELETED'] : $user->lang['ATTACHMENTS_DELETED']; $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ATTACHMENTS_DELETED', false, array(implode($user->lang['COMMA_SEPARATOR'], $log_attachments))); trigger_error($message . adm_back_link($this->u_action . '&u=' . $user_id)); @@ -2455,7 +2477,7 @@ class acp_users // Select box for other groups $sql = 'SELECT group_id, group_name, group_type, group_founder_manage FROM ' . GROUPS_TABLE . ' - ' . ((sizeof($id_ary)) ? 'WHERE ' . $db->sql_in_set('group_id', $id_ary, true) : '') . ' + ' . ((count($id_ary)) ? 'WHERE ' . $db->sql_in_set('group_id', $id_ary, true) : '') . ' ORDER BY group_type DESC, group_name ASC'; $result = $db->sql_query($sql); @@ -2497,7 +2519,7 @@ class acp_users 'U_DELETE' => $this->u_action . "&action=delete&u=$user_id&g=" . $data['group_id'], 'U_APPROVE' => ($group_type == 'pending') ? $this->u_action . "&action=approve&u=$user_id&g=" . $data['group_id'] : '', - 'GROUP_NAME' => ($group_type == 'special') ? $user->lang['G_' . $data['group_name']] : $data['group_name'], + 'GROUP_NAME' => $group_helper->get_name($data['group_name']), 'L_DEMOTE_PROMOTE' => ($data['group_leader']) ? $user->lang['GROUP_DEMOTE'] : $user->lang['GROUP_PROMOTE'], 'S_IS_MEMBER' => ($group_type != 'pending') ? true : false, @@ -2604,8 +2626,8 @@ class acp_users // Assign general variables $template->assign_vars(array( - 'S_ERROR' => (sizeof($error)) ? true : false, - 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '') + 'S_ERROR' => (count($error)) ? true : false, + 'ERROR_MSG' => (count($error)) ? implode('<br />', $error) : '') ); } diff --git a/phpBB/includes/acp/auth.php b/phpBB/includes/acp/auth.php index b36b900396..b414a3121a 100644 --- a/phpBB/includes/acp/auth.php +++ b/phpBB/includes/acp/auth.php @@ -27,7 +27,7 @@ class auth_admin extends \phpbb\auth\auth /** * Init auth settings */ - function auth_admin() + function __construct() { global $db, $cache; @@ -107,7 +107,7 @@ class auth_admin extends \phpbb\auth\auth $compare_options = array_diff(preg_replace('/^((?!' . $auth_option . ').+)|(' . $auth_option . ')$/', '', array_keys($this->acl_options[$scope])), array('')); // If forum_ids is false and the scope is local we actually want to have all forums within the array - if ($scope == 'local' && !sizeof($forum_ids)) + if ($scope == 'local' && !count($forum_ids)) { $sql = 'SELECT forum_id FROM ' . FORUMS_TABLE; @@ -177,9 +177,9 @@ class auth_admin extends \phpbb\auth\auth // Now, we need to fill the gaps with $acl_fill. ;) // Now switch back to keys - if (sizeof($compare_options)) + if (count($compare_options)) { - $compare_options = array_combine($compare_options, array_fill(1, sizeof($compare_options), $acl_fill)); + $compare_options = array_combine($compare_options, array_fill(1, count($compare_options), $acl_fill)); } // Defining the user-function here to save some memory @@ -189,7 +189,7 @@ class auth_admin extends \phpbb\auth\auth }; // Actually fill the gaps - if (sizeof($hold_ary)) + if (count($hold_ary)) { foreach ($hold_ary as $ug_id => $row) { @@ -356,7 +356,7 @@ class auth_admin extends \phpbb\auth\auth // Build js roles array (role data assignments) $s_role_js_array = ''; - if (sizeof($roles)) + if (count($roles)) { $s_role_js_array = array(); @@ -422,7 +422,7 @@ class auth_admin extends \phpbb\auth\auth // If we only have one forum id to display or being in local mode and more than one user/group to display, // we switch the complete interface to group by user/usergroup instead of grouping by forum // To achieve this, we need to switch the array a bit - if (sizeof($forum_ids) == 1 || ($local && sizeof($ug_names_ary) > 1)) + if (count($forum_ids) == 1 || ($local && count($ug_names_ary) > 1)) { $hold_ary_temp = $hold_ary; $hold_ary = array(); @@ -453,9 +453,9 @@ class auth_admin extends \phpbb\auth\auth 'S_LOCAL' => ($local) ? true : false, 'S_GLOBAL' => (!$local) ? true : false, - 'S_NUM_CATS' => sizeof($categories), + 'S_NUM_CATS' => count($categories), 'S_VIEW' => ($mode == 'view') ? true : false, - 'S_NUM_OBJECTS' => sizeof($content_array), + 'S_NUM_OBJECTS' => count($content_array), 'S_USER_MODE' => ($user_mode == 'user') ? true : false, 'S_GROUP_MODE' => ($user_mode == 'group') ? true : false) ); @@ -546,15 +546,15 @@ class auth_admin extends \phpbb\auth\auth 'NAME' => $ug_name, 'CATEGORIES' => implode('</th><th>', $categories), - 'USER_GROUPS_DEFAULT' => ($user_mode == 'user' && isset($user_groups_default[$ug_id]) && sizeof($user_groups_default[$ug_id])) ? implode($user->lang['COMMA_SEPARATOR'], $user_groups_default[$ug_id]) : '', - 'USER_GROUPS_CUSTOM' => ($user_mode == 'user' && isset($user_groups_custom[$ug_id]) && sizeof($user_groups_custom[$ug_id])) ? implode($user->lang['COMMA_SEPARATOR'], $user_groups_custom[$ug_id]) : '', + 'USER_GROUPS_DEFAULT' => ($user_mode == 'user' && isset($user_groups_default[$ug_id]) && count($user_groups_default[$ug_id])) ? implode($user->lang['COMMA_SEPARATOR'], $user_groups_default[$ug_id]) : '', + 'USER_GROUPS_CUSTOM' => ($user_mode == 'user' && isset($user_groups_custom[$ug_id]) && count($user_groups_custom[$ug_id])) ? implode($user->lang['COMMA_SEPARATOR'], $user_groups_custom[$ug_id]) : '', 'L_ACL_TYPE' => $l_acl_type, 'S_LOCAL' => ($local) ? true : false, 'S_GLOBAL' => (!$local) ? true : false, - 'S_NUM_CATS' => sizeof($categories), + 'S_NUM_CATS' => count($categories), 'S_VIEW' => ($mode == 'view') ? true : false, - 'S_NUM_OBJECTS' => sizeof($content_array), + 'S_NUM_OBJECTS' => count($content_array), 'S_USER_MODE' => ($user_mode == 'user') ? true : false, 'S_GROUP_MODE' => ($user_mode == 'group') ? true : false) ); @@ -637,7 +637,7 @@ class auth_admin extends \phpbb\auth\auth global $db, $template, $user, $phpbb_root_path, $phpEx; global $phpbb_container; - if (!sizeof($hold_ary)) + if (!count($hold_ary)) { return; } @@ -669,7 +669,7 @@ class auth_admin extends \phpbb\auth\auth 'FORUM_ID' => $forum_id) ); - if (isset($auth_ary['users']) && sizeof($auth_ary['users'])) + if (isset($auth_ary['users']) && count($auth_ary['users'])) { $sql = 'SELECT user_id, username FROM ' . USERS_TABLE . ' @@ -688,7 +688,7 @@ class auth_admin extends \phpbb\auth\auth $db->sql_freeresult($result); } - if (isset($auth_ary['groups']) && sizeof($auth_ary['groups'])) + if (isset($auth_ary['groups']) && count($auth_ary['groups'])) { $sql = 'SELECT group_id, group_name, group_type FROM ' . GROUPS_TABLE . ' @@ -819,7 +819,7 @@ class auth_admin extends \phpbb\auth\auth // Because we just changed the options and also purged the options cache, we instantly update/regenerate it for later calls to succeed. $this->acl_options = array(); - $this->auth_admin(); + $this->__construct(); return true; } @@ -890,7 +890,7 @@ class auth_admin extends \phpbb\auth\auth } $db->sql_freeresult($result); - if (sizeof($role_ids)) + if (count($role_ids)) { $sql = "DELETE FROM $table WHERE $forum_sql @@ -1000,7 +1000,7 @@ class auth_admin extends \phpbb\auth\auth } // If no data is there, we set the any-flag to ACL_NEVER... - if (!sizeof($sql_ary)) + if (!count($sql_ary)) { $sql_ary[] = array( 'role_id' => (int) $role_id, @@ -1083,7 +1083,7 @@ class auth_admin extends \phpbb\auth\auth $db->sql_freeresult($result); // Get role data for resetting data - if (sizeof($cur_role_auth)) + if (count($cur_role_auth)) { $sql = 'SELECT ao.auth_option, rd.role_id, rd.auth_setting FROM ' . ACL_OPTIONS_TABLE . ' ao, ' . ACL_ROLES_DATA_TABLE . ' rd diff --git a/phpBB/includes/bbcode.php b/phpBB/includes/bbcode.php index 6572c0ad2c..c31b63a403 100644 --- a/phpBB/includes/bbcode.php +++ b/phpBB/includes/bbcode.php @@ -35,9 +35,18 @@ class bbcode /** * Constructor + */ + function __construct($bitfield = '') + { + $this->bbcode_set_bitfield($bitfield); + } + + /** * Init bbcode cache entries if bitfield is specified + * + * @param string $bbcode_bitfield The bbcode bitfield */ - function bbcode($bitfield = '') + function bbcode_set_bitfield($bitfield = '') { if ($bitfield) { @@ -94,13 +103,13 @@ class bbcode ${$type}['replace'][] = $replace; } - if (sizeof($str['search'])) + if (count($str['search'])) { $message = str_replace($str['search'], $str['replace'], $message); $str = array('search' => array(), 'replace' => array()); } - if (sizeof($preg['search'])) + if (count($preg['search'])) { // we need to turn the entities back into their original form to allow the // search patterns to work properly @@ -191,7 +200,7 @@ class bbcode } } - if (sizeof($sql)) + if (count($sql)) { global $db; diff --git a/phpBB/includes/compatibility_globals.php b/phpBB/includes/compatibility_globals.php index 0f403896a7..ad394e3782 100644 --- a/phpBB/includes/compatibility_globals.php +++ b/phpBB/includes/compatibility_globals.php @@ -29,7 +29,7 @@ function register_compatibility_globals() { global $phpbb_container; - global $cache, $phpbb_dispatcher, $request, $user, $auth, $db, $config, $phpbb_log; + global $cache, $phpbb_dispatcher, $request, $user, $auth, $db, $config, $language, $phpbb_log; global $symfony_request, $phpbb_filesystem, $phpbb_path_helper, $phpbb_extension_manager, $template; // set up caching @@ -48,6 +48,9 @@ function register_compatibility_globals() /* @var $user \phpbb\user */ $user = $phpbb_container->get('user'); + /* @var \phpbb\language\language $language */ + $language = $phpbb_container->get('language'); + /* @var $auth \phpbb\auth\auth */ $auth = $phpbb_container->get('auth'); diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php index 07f9f27555..a2e7d92f7d 100644 --- a/phpBB/includes/constants.php +++ b/phpBB/includes/constants.php @@ -28,7 +28,7 @@ if (!defined('IN_PHPBB')) */ // phpBB Version -@define('PHPBB_VERSION', '3.2.2-dev'); +@define('PHPBB_VERSION', '3.2.9-dev'); // QA-related // define('PHPBB_QA', 1); diff --git a/phpBB/includes/diff/diff.php b/phpBB/includes/diff/diff.php index d307880c4b..d8ae9d77ac 100644 --- a/phpBB/includes/diff/diff.php +++ b/phpBB/includes/diff/diff.php @@ -50,7 +50,7 @@ class diff * @param array &$to_content An array of strings. * @param bool $preserve_cr If true, \r is replaced by a new line in the diff output */ - function diff(&$from_content, &$to_content, $preserve_cr = true) + function __construct(&$from_content, &$to_content, $preserve_cr = true) { $diff_engine = new diff_engine(); $this->_edits = $diff_engine->diff($from_content, $to_content, $preserve_cr); @@ -75,7 +75,7 @@ class diff { $count = 0; - for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) + for ($i = 0, $size = count($this->_edits); $i < $size; $i++) { $edit = $this->_edits[$i]; @@ -98,7 +98,7 @@ class diff { $count = 0; - for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) + for ($i = 0, $size = count($this->_edits); $i < $size; $i++) { $edit = $this->_edits[$i]; @@ -136,7 +136,7 @@ class diff $rev->_edits = array(); - for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) + for ($i = 0, $size = count($this->_edits); $i < $size; $i++) { $edit = $this->_edits[$i]; $rev->_edits[] = $edit->reverse(); @@ -152,7 +152,7 @@ class diff */ function is_empty() { - for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) + for ($i = 0, $size = count($this->_edits); $i < $size; $i++) { $edit = $this->_edits[$i]; @@ -168,8 +168,8 @@ class diff $final = $edit->final; // We can simplify one case where the array is usually supposed to be empty... - if (sizeof($orig) == 1 && trim($orig[0]) === '') $orig = array(); - if (sizeof($final) == 1 && trim($final[0]) === '') $final = array(); + if (count($orig) == 1 && trim($orig[0]) === '') $orig = array(); + if (count($final) == 1 && trim($final[0]) === '') $final = array(); if (!$orig && !$final) { @@ -196,13 +196,13 @@ class diff { $lcs = 0; - for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) + for ($i = 0, $size = count($this->_edits); $i < $size; $i++) { $edit = $this->_edits[$i]; if (is_a($edit, 'diff_op_copy')) { - $lcs += sizeof($edit->orig); + $lcs += count($edit->orig); } } return $lcs; @@ -219,13 +219,13 @@ class diff { $lines = array(); - for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) + for ($i = 0, $size = count($this->_edits); $i < $size; $i++) { $edit = $this->_edits[$i]; if ($edit->orig) { - array_splice($lines, sizeof($lines), 0, $edit->orig); + array_splice($lines, count($lines), 0, $edit->orig); } } return $lines; @@ -242,13 +242,13 @@ class diff { $lines = array(); - for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) + for ($i = 0, $size = count($this->_edits); $i < $size; $i++) { $edit = $this->_edits[$i]; if ($edit->final) { - array_splice($lines, sizeof($lines), 0, $edit->final); + array_splice($lines, count($lines), 0, $edit->final); } } return $lines; @@ -296,7 +296,7 @@ class diff $prevtype = null; - for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) + for ($i = 0, $size = count($this->_edits); $i < $size; $i++) { $edit = $this->_edits[$i]; @@ -330,30 +330,30 @@ class mapped_diff extends diff * compared when computing the diff. * @param array $mapped_to_lines This array should have the same number of elements as $to_lines. */ - function mapped_diff(&$from_lines, &$to_lines, &$mapped_from_lines, &$mapped_to_lines) + function __construct(&$from_lines, &$to_lines, &$mapped_from_lines, &$mapped_to_lines) { - if (sizeof($from_lines) != sizeof($mapped_from_lines) || sizeof($to_lines) != sizeof($mapped_to_lines)) + if (count($from_lines) != count($mapped_from_lines) || count($to_lines) != count($mapped_to_lines)) { return false; } - parent::diff($mapped_from_lines, $mapped_to_lines); + parent::__construct($mapped_from_lines, $mapped_to_lines); $xi = $yi = 0; - for ($i = 0; $i < sizeof($this->_edits); $i++) + for ($i = 0; $i < count($this->_edits); $i++) { $orig = &$this->_edits[$i]->orig; if (is_array($orig)) { - $orig = array_slice($from_lines, $xi, sizeof($orig)); - $xi += sizeof($orig); + $orig = array_slice($from_lines, $xi, count($orig)); + $xi += count($orig); } $final = &$this->_edits[$i]->final; if (is_array($final)) { - $final = array_slice($to_lines, $yi, sizeof($final)); - $yi += sizeof($final); + $final = array_slice($to_lines, $yi, count($final)); + $yi += count($final); } } } @@ -377,12 +377,12 @@ class diff_op function norig() { - return ($this->orig) ? sizeof($this->orig) : 0; + return ($this->orig) ? count($this->orig) : 0; } function nfinal() { - return ($this->final) ? sizeof($this->final) : 0; + return ($this->final) ? count($this->final) : 0; } } @@ -394,7 +394,7 @@ class diff_op */ class diff_op_copy extends diff_op { - function diff_op_copy($orig, $final = false) + function __construct($orig, $final = false) { if (!is_array($final)) { @@ -419,7 +419,7 @@ class diff_op_copy extends diff_op */ class diff_op_delete extends diff_op { - function diff_op_delete($lines) + function __construct($lines) { $this->orig = $lines; $this->final = false; @@ -440,7 +440,7 @@ class diff_op_delete extends diff_op */ class diff_op_add extends diff_op { - function diff_op_add($lines) + function __construct($lines) { $this->final = $lines; $this->orig = false; @@ -461,7 +461,7 @@ class diff_op_add extends diff_op */ class diff_op_change extends diff_op { - function diff_op_change($orig, $final) + function __construct($orig, $final) { $this->orig = $orig; $this->final = $final; @@ -498,7 +498,7 @@ class diff3 extends diff * @param bool $preserve_cr If true, \r\n and bare \r are replaced by a new line * in the diff output */ - function diff3(&$orig, &$final1, &$final2, $preserve_cr = true) + function __construct(&$orig, &$final1, &$final2, $preserve_cr = true) { $diff_engine = new diff_engine(); @@ -517,7 +517,7 @@ class diff3 extends diff { $conflicts = 0; - for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) + for ($i = 0, $size = count($this->_edits); $i < $size; $i++) { $edit = $this->_edits[$i]; @@ -550,7 +550,7 @@ class diff3 extends diff $lines = array(); - for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) + for ($i = 0, $size = count($this->_edits); $i < $size; $i++) { $edit = $this->_edits[$i]; @@ -590,7 +590,7 @@ class diff3 extends diff { $lines = array(); - for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) + for ($i = 0, $size = count($this->_edits); $i < $size; $i++) { $edit = $this->_edits[$i]; @@ -614,7 +614,7 @@ class diff3 extends diff { $lines = array(); - for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) + for ($i = 0, $size = count($this->_edits); $i < $size; $i++) { $edit = $this->_edits[$i]; @@ -638,7 +638,7 @@ class diff3 extends diff { $conflicts = array(); - for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) + for ($i = 0, $size = count($this->_edits); $i < $size; $i++) { $edit = $this->_edits[$i]; @@ -754,7 +754,7 @@ class diff3 extends diff */ class diff3_op { - function diff3_op($orig = false, $final1 = false, $final2 = false) + function __construct($orig = false, $final1 = false, $final2 = false) { $this->orig = $orig ? $orig : array(); $this->final1 = $final1 ? $final1 : array(); @@ -803,9 +803,9 @@ class diff3_op function solve_prepare() { // We can simplify one case where the array is usually supposed to be empty... - if (sizeof($this->orig) == 1 && trim($this->orig[0]) === '') $this->orig = array(); - if (sizeof($this->final1) == 1 && trim($this->final1[0]) === '') $this->final1 = array(); - if (sizeof($this->final2) == 1 && trim($this->final2[0]) === '') $this->final2 = array(); + if (count($this->orig) == 1 && trim($this->orig[0]) === '') $this->orig = array(); + if (count($this->final1) == 1 && trim($this->final1[0]) === '') $this->final1 = array(); + if (count($this->final2) == 1 && trim($this->final2[0]) === '') $this->final2 = array(); // Now we only can have the case where the only difference between arrays are newlines, so compare all cases @@ -848,10 +848,10 @@ class diff3_op $_final1 = &$this->$final1; // Ok, we basically search for $orig in $final1 - $compare_seq = sizeof($_orig); + $compare_seq = count($_orig); // Go through the conflict code - for ($i = 0, $j = 0, $size = sizeof($_final1); $i < $size; $i++, $j = $i) + for ($i = 0, $j = 0, $size = count($_final1); $i < $size; $i++, $j = $i) { $line = $_final1[$i]; $skip = 0; @@ -895,7 +895,7 @@ class diff3_op // CASE ONE: orig changed into final2, but modified/unknown code in final1. // IF orig is found "as is" in final1 we replace the code directly in final1 and populate this as final2/merge - if (sizeof($this->orig) && sizeof($this->final2)) + if (count($this->orig) && count($this->final2)) { $result = $this->_compare_conflict_seq('orig', 'final1', 'final2'); @@ -915,7 +915,7 @@ class diff3_op } // Try to solve $Id$ issues. ;) - if (sizeof($this->orig) == 1 && sizeof($this->final1) == 1 && sizeof($this->final2) == 1) + if (count($this->orig) == 1 && count($this->final1) == 1 && count($this->final2) == 1) { $match = '#^' . preg_quote('* @version $Id: ', '#') . '[a-z\._\- ]+[0-9]+ [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9\:Z]+ [a-z0-9_\- ]+\$$#'; @@ -939,9 +939,9 @@ class diff3_op } // The same is true for a line at the end. ;) - if (sizeof($this->orig) && sizeof($this->final2) && sizeof($this->orig) === sizeof($this->final2) && trim($this->orig[sizeof($this->orig)-1]) === '' && trim($this->final2[sizeof($this->final2)-1]) === '') + if (count($this->orig) && count($this->final2) && count($this->orig) === count($this->final2) && trim($this->orig[count($this->orig)-1]) === '' && trim($this->final2[count($this->final2)-1]) === '') { - unset($this->orig[sizeof($this->orig)-1], $this->final2[sizeof($this->final2)-1]); + unset($this->orig[count($this->orig)-1], $this->final2[count($this->final2)-1]); $this->orig = array_values($this->orig); $this->final2 = array_values($this->final2); @@ -972,7 +972,7 @@ class diff3_op } // CASE TWO: Added lines from orig to final2 but final1 had added lines too. Just merge them. - if (!sizeof($this->orig) && $this->final1 !== $this->final2 && sizeof($this->final1) && sizeof($this->final2)) + if (!count($this->orig) && $this->final1 !== $this->final2 && count($this->final1) && count($this->final2)) { $result = $this->_compare_conflict_seq('final2', 'final1'); @@ -1001,7 +1001,7 @@ class diff3_op } // CASE THREE: Removed lines (orig has the to-remove line(s), but final1 has additional lines which does not need to be removed). Just remove orig from final1 and then use final1 as final2/merge - if (!sizeof($this->final2) && sizeof($this->orig) && sizeof($this->final1) && $this->orig !== $this->final1) + if (!count($this->final2) && count($this->orig) && count($this->final1) && $this->orig !== $this->final1) { $result = $this->_compare_conflict_seq('orig', 'final1'); @@ -1011,11 +1011,11 @@ class diff3_op } // First of all, try to find the code in orig in final1. ;) - $compare_seq = sizeof($this->orig); + $compare_seq = count($this->orig); $begin = $end = -1; $j = 0; - for ($i = 0, $size = sizeof($this->final1); $i < $size; $i++) + for ($i = 0, $size = count($this->final1); $i < $size; $i++) { $line = $this->final1[$i]; @@ -1066,7 +1066,7 @@ class diff3_op */ class diff3_op_copy extends diff3_op { - function diff3_op_copy($lines = false) + function __construct($lines = false) { $this->orig = $lines ? $lines : array(); $this->final1 = &$this->orig; @@ -1092,7 +1092,7 @@ class diff3_op_copy extends diff3_op */ class diff3_block_builder { - function diff3_block_builder() + function __construct() { $this->_init(); } @@ -1147,6 +1147,6 @@ class diff3_block_builder function _append(&$array, $lines) { - array_splice($array, sizeof($array), 0, $lines); + array_splice($array, count($array), 0, $lines); } } diff --git a/phpBB/includes/diff/engine.php b/phpBB/includes/diff/engine.php index bc21b3b9ba..757fdadde9 100644 --- a/phpBB/includes/diff/engine.php +++ b/phpBB/includes/diff/engine.php @@ -84,8 +84,8 @@ class diff_engine $to_lines = explode("\n", preg_replace('#[\n\r]+#', "\n", $to_lines)); } - $n_from = sizeof($from_lines); - $n_to = sizeof($to_lines); + $n_from = count($from_lines); + $n_to = count($to_lines); $this->xchanged = $this->ychanged = $this->xv = $this->yv = $this->xind = $this->yind = array(); unset($this->seq, $this->in_seq, $this->lcs); @@ -145,7 +145,7 @@ class diff_engine } // Find the LCS. - $this->_compareseq(0, sizeof($this->xv), 0, sizeof($this->yv)); + $this->_compareseq(0, count($this->xv), 0, count($this->yv)); // Merge edits when possible. if ($this->skip_whitespace_changes) @@ -444,8 +444,8 @@ class diff_engine $i = 0; $j = 0; - $len = sizeof($lines); - $other_len = sizeof($other_changed); + $len = count($lines); + $other_len = count($other_changed); while (1) { diff --git a/phpBB/includes/diff/renderer.php b/phpBB/includes/diff/renderer.php index 6b7f07cf9c..8a8b0c295e 100644 --- a/phpBB/includes/diff/renderer.php +++ b/phpBB/includes/diff/renderer.php @@ -56,7 +56,7 @@ class diff_renderer /** * Constructor. */ - function diff_renderer($params = array()) + function __construct($params = array()) { foreach ($params as $param => $value) { @@ -128,8 +128,8 @@ class diff_renderer if (is_array($block)) { // How many lines to keep as context from the copy block. - $keep = ($i == sizeof($diffs) - 1) ? $ntrail : $nlead + $ntrail; - if (sizeof($edit->orig) <= $keep) + $keep = ($i == count($diffs) - 1) ? $ntrail : $nlead + $ntrail; + if (count($edit->orig) <= $keep) { // We have less lines in the block than we want for context => keep the whole block. $block[] = $edit; @@ -156,9 +156,9 @@ class diff_renderer if (!is_array($block)) { // Extract context lines from the preceding copy block. - $context = array_slice($context, sizeof($context) - $nlead); - $x0 = $xi - sizeof($context); - $y0 = $yi - sizeof($context); + $context = array_slice($context, count($context) - $nlead); + $x0 = $xi - count($context); + $y0 = $yi - count($context); $block = array(); if ($context) @@ -169,8 +169,8 @@ class diff_renderer $block[] = $edit; } - $xi += ($edit->orig) ? sizeof($edit->orig) : 0; - $yi += ($edit->final) ? sizeof($edit->final) : 0; + $xi += ($edit->orig) ? count($edit->orig) : 0; + $yi += ($edit->final) ? count($edit->final) : 0; } if (is_array($block)) @@ -433,7 +433,7 @@ class diff_renderer_inline extends diff_renderer { array_walk($lines, array(&$this, '_encode')); $lines[0] = $this->_ins_prefix . $lines[0]; - $lines[sizeof($lines) - 1] .= $this->_ins_suffix; + $lines[count($lines) - 1] .= $this->_ins_suffix; return $this->_lines($lines, ' ', false); } @@ -441,7 +441,7 @@ class diff_renderer_inline extends diff_renderer { array_walk($lines, array(&$this, '_encode')); $lines[0] = $this->_del_prefix . $lines[0]; - $lines[sizeof($lines) - 1] .= $this->_del_suffix; + $lines[count($lines) - 1] .= $this->_del_suffix; return $this->_lines($lines, ' ', false); } @@ -617,7 +617,7 @@ class diff_renderer_side_by_side extends diff_renderer $this->render($diff); // Is the diff empty? - if (!sizeof($this->lines)) + if (!count($this->lines)) { $output .= '<tr><th colspan="2">' . $user->lang['NO_VISIBLE_CHANGES'] . '</th></tr>'; } @@ -672,8 +672,8 @@ class diff_renderer_side_by_side extends diff_renderer case 'change': // Pop the old/new stacks one by one, until both are empty. - $oldsize = sizeof($change['old']); - $newsize = sizeof($change['new']); + $oldsize = count($change['old']); + $newsize = count($change['new']); $left = $right = ''; for ($row = 0, $row_max = max($oldsize, $newsize); $row < $row_max; ++$row) diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 2cd62d7bac..c9f589c174 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -66,29 +66,48 @@ function set_var(&$result, $var, $type, $multibyte = false) /** * Generates an alphanumeric random string of given length * +* @param int $num_chars Length of random string, defaults to 8. +* This number should be less or equal than 64. +* * @return string */ function gen_rand_string($num_chars = 8) { - // [a, z] + [0, 9] = 36 - return substr(strtoupper(base_convert(unique_id(), 16, 36)), 0, $num_chars); + $range = array_merge(range('A', 'Z'), range(0, 9)); + $size = count($range); + + $output = ''; + for ($i = 0; $i < $num_chars; $i++) + { + $rand = random_int(0, $size-1); + $output .= $range[$rand]; + } + + return $output; } /** * Generates a user-friendly alphanumeric random string of given length * We remove 0 and O so users cannot confuse those in passwords etc. * +* @param int $num_chars Length of random string, defaults to 8. +* This number should be less or equal than 64. +* * @return string */ function gen_rand_string_friendly($num_chars = 8) { - $rand_str = unique_id(); + $range = array_merge(range('A', 'N'), range('P', 'Z'), range(1, 9)); + $size = count($range); - // Remove Z and Y from the base_convert(), replace 0 with Z and O with Y - // [a, z] + [0, 9] - {z, y} = [a, z] + [0, 9] - {0, o} = 34 - $rand_str = str_replace(array('0', 'O'), array('Z', 'Y'), strtoupper(base_convert($rand_str, 16, 34))); + $output = ''; + for ($i = 0; $i < $num_chars; $i++) + { + $rand = random_int(0, $size-1); + $output .= $range[$rand]; + } - return substr($rand_str, 0, $num_chars); + return $output; } /** @@ -96,7 +115,7 @@ function gen_rand_string_friendly($num_chars = 8) */ function unique_id() { - return bin2hex(random_bytes(8)); + return strtolower(gen_rand_string(16)); } /** @@ -602,7 +621,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ if ($mode == 'all') { - if ($forum_id === false || !sizeof($forum_id)) + if (empty($forum_id)) { // Mark all forums read (index page) /* @var $phpbb_notifications \phpbb\notification\manager */ @@ -661,8 +680,6 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ } } } - - return; } else if ($mode == 'topics') { @@ -727,7 +744,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ } $db->sql_freeresult($result); - if (sizeof($sql_update)) + if (count($sql_update)) { $sql = 'UPDATE ' . FORUMS_TRACK_TABLE . " SET mark_time = $post_time @@ -789,8 +806,6 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ unset($tracking); } - - return; } else if ($mode == 'topic') { @@ -863,7 +878,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ // We get the ten most minimum stored time offsets and its associated topic ids $time_keys = array(); - for ($i = 0; $i < 10 && sizeof($tracking['t']); $i++) + for ($i = 0; $i < 10 && count($tracking['t']); $i++) { $min_value = min($tracking['t']); $m_tkey = array_search($min_value, $tracking['t']); @@ -904,8 +919,6 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ $user->set_cookie('track', tracking_serialize($tracking), $post_time + 31536000); $request->overwrite($config['cookie_name'] . '_track', tracking_serialize($tracking), \phpbb\request\request_interface::COOKIE); } - - return; } else if ($mode == 'post') { @@ -930,9 +943,28 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ $db->sql_return_on_error(false); } - - return; } + + /** + * This event is used for performing actions directly after forums, + * topics or posts have been marked as read. + * + * @event core.markread_after + * @var string mode Variable containing marking mode value + * @var mixed forum_id Variable containing forum id, or false + * @var mixed topic_id Variable containing topic id, or false + * @var int post_time Variable containing post time + * @var int user_id Variable containing the user id + * @since 3.2.6-RC1 + */ + $vars = array( + 'mode', + 'forum_id', + 'topic_id', + 'post_time', + 'user_id', + ); + extract($phpbb_dispatcher->trigger_event('core.markread_after', compact($vars))); } /** @@ -959,7 +991,7 @@ function get_topic_tracking($forum_id, $topic_ids, &$rowset, $forum_mark_time, $ $topic_ids = array_diff($topic_ids, array_keys($last_read)); - if (sizeof($topic_ids)) + if (count($topic_ids)) { $mark_time = array(); @@ -1011,7 +1043,7 @@ function get_complete_topic_tracking($forum_id, $topic_ids, $global_announce_lis $topic_ids = array_diff($topic_ids, array_keys($last_read)); - if (sizeof($topic_ids)) + if (count($topic_ids)) { $sql = 'SELECT forum_id, mark_time FROM ' . FORUMS_TRACK_TABLE . " @@ -1038,7 +1070,7 @@ function get_complete_topic_tracking($forum_id, $topic_ids, $global_announce_lis { global $tracking_topics; - if (!isset($tracking_topics) || !sizeof($tracking_topics)) + if (!isset($tracking_topics) || !count($tracking_topics)) { $tracking_topics = $request->variable($config['cookie_name'] . '_track', '', true, \phpbb\request\request_interface::COOKIE); $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array(); @@ -1065,7 +1097,7 @@ function get_complete_topic_tracking($forum_id, $topic_ids, $global_announce_lis $topic_ids = array_diff($topic_ids, array_keys($last_read)); - if (sizeof($topic_ids)) + if (count($topic_ids)) { $mark_time = array(); @@ -1407,7 +1439,7 @@ function tracking_unserialize($string, $max_depth = 3) switch ($string[$i]) { case '(': - if (sizeof($stack) >= $max_depth) + if (count($stack) >= $max_depth) { die('Invalid data supplied'); } @@ -1461,7 +1493,7 @@ function tracking_unserialize($string, $max_depth = 3) } } - if (sizeof($stack) != 0 || ($mode != 0 && $mode != 3)) + if (count($stack) != 0 || ($mode != 0 && $mode != 3)) { die('Invalid data supplied'); } @@ -1725,14 +1757,14 @@ function redirect($url, $return = false, $disable_cd_check = false) if ($url_parts === false) { // Malformed url - trigger_error('INSECURE_REDIRECT', E_USER_ERROR); + trigger_error('INSECURE_REDIRECT', E_USER_WARNING); } else if (!empty($url_parts['scheme']) && !empty($url_parts['host'])) { // Attention: only able to redirect within the same domain if $disable_cd_check is false (yourdomain.com -> www.yourdomain.com will not work) if (!$disable_cd_check && $url_parts['host'] !== $user->host) { - trigger_error('INSECURE_REDIRECT', E_USER_ERROR); + trigger_error('INSECURE_REDIRECT', E_USER_WARNING); } } else if ($url[0] == '/') @@ -1772,13 +1804,13 @@ function redirect($url, $return = false, $disable_cd_check = false) if (!$disable_cd_check && strpos($url, generate_board_url(true) . '/') !== 0) { - trigger_error('INSECURE_REDIRECT', E_USER_ERROR); + trigger_error('INSECURE_REDIRECT', E_USER_WARNING); } // Make sure no linebreaks are there... to prevent http response splitting for PHP < 4.4.2 if (strpos(urldecode($url), "\n") !== false || strpos(urldecode($url), "\r") !== false || strpos($url, ';') !== false) { - trigger_error('INSECURE_REDIRECT', E_USER_ERROR); + trigger_error('INSECURE_REDIRECT', E_USER_WARNING); } // Now, also check the protocol and for a valid url the last time... @@ -1787,7 +1819,7 @@ function redirect($url, $return = false, $disable_cd_check = false) if ($url_parts === false || empty($url_parts['scheme']) || !in_array($url_parts['scheme'], $allowed_protocols)) { - trigger_error('INSECURE_REDIRECT', E_USER_ERROR); + trigger_error('INSECURE_REDIRECT', E_USER_WARNING); } /** @@ -1811,27 +1843,6 @@ function redirect($url, $return = false, $disable_cd_check = false) garbage_collection(); } - // Redirect via an HTML form for PITA webservers - if (@preg_match('#WebSTAR|Xitami#', getenv('SERVER_SOFTWARE'))) - { - header('Refresh: 0; URL=' . $url); - - echo '<!DOCTYPE html>'; - echo '<html dir="' . $user->lang['DIRECTION'] . '" lang="' . $user->lang['USER_LANG'] . '">'; - echo '<head>'; - echo '<meta charset="utf-8">'; - echo '<meta http-equiv="X-UA-Compatible" content="IE=edge">'; - echo '<meta http-equiv="refresh" content="0; url=' . str_replace('&', '&', $url) . '" />'; - echo '<title>' . $user->lang['REDIRECT'] . '</title>'; - echo '</head>'; - echo '<body>'; - echo '<div style="text-align: center;">' . sprintf($user->lang['URL_REDIRECT'], '<a href="' . str_replace('&', '&', $url) . '">', '</a>') . '</div>'; - echo '</body>'; - echo '</html>'; - - exit; - } - // Behave as per HTTP/1.1 spec for others header('Location: ' . $url); exit; @@ -2111,25 +2122,29 @@ function check_form_key($form_name, $timespan = false) /** * Build Confirm box * @param boolean $check True for checking if confirmed (without any additional parameters) and false for displaying the confirm box -* @param string $title Title/Message used for confirm box. +* @param string|array $title Title/Message used for confirm box. * message text is _CONFIRM appended to title. * If title cannot be found in user->lang a default one is displayed * If title_CONFIRM cannot be found in user->lang the text given is used. +* If title is an array, the first array value is used as explained per above, +* all other array values are sent as parameters to the language function. * @param string $hidden Hidden variables * @param string $html_body Template used for confirm box * @param string $u_action Custom form action +* +* @return bool True if confirmation was successful, false if not */ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_body.html', $u_action = '') { global $user, $template, $db, $request; - global $config, $phpbb_path_helper; + global $config, $language, $phpbb_path_helper, $phpbb_dispatcher; if (isset($_POST['cancel'])) { return false; } - $confirm = ($user->lang['YES'] === $request->variable('confirm', '', true, \phpbb\request\request_interface::POST)); + $confirm = ($language->lang('YES') === $request->variable('confirm', '', true, \phpbb\request\request_interface::POST)); if ($check && $confirm) { @@ -2163,13 +2178,27 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo // generate activation key $confirm_key = gen_rand_string(10); + // generate language strings + if (is_array($title)) + { + $key = array_shift($title); + $count = array_shift($title); + $confirm_title = $language->is_set($key) ? $language->lang($key, $count, $title) : $language->lang('CONFIRM'); + $confirm_text = $language->is_set($key . '_CONFIRM') ? $language->lang($key . '_CONFIRM', $count, $title) : $key; + } + else + { + $confirm_title = $language->is_set($title) ? $language->lang($title) : $language->lang('CONFIRM'); + $confirm_text = $language->is_set($title . '_CONFIRM') ? $language->lang($title . '_CONFIRM') : $title; + } + if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin']) { - adm_page_header((!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title]); + adm_page_header($confirm_title); } else { - page_header((!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title]); + page_header($confirm_title); } $template->set_filenames(array( @@ -2185,14 +2214,14 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo // re-add sid / transform & to & for user->page (user->page is always using &) $use_page = ($u_action) ? $u_action : str_replace('&', '&', $user->page['page']); - $u_action = reapply_sid($phpbb_path_helper->get_valid_page($use_page, $config['enable_mod_rewrite']), $phpbb_path_helper->is_router_used()); + $u_action = reapply_sid($phpbb_path_helper->get_valid_page($use_page, $config['enable_mod_rewrite'])); $u_action .= ((strpos($u_action, '?') === false) ? '?' : '&') . 'confirm_key=' . $confirm_key; $template->assign_vars(array( - 'MESSAGE_TITLE' => (!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang($title, 1), - 'MESSAGE_TEXT' => (!isset($user->lang[$title . '_CONFIRM'])) ? $title : $user->lang[$title . '_CONFIRM'], + 'MESSAGE_TITLE' => $confirm_title, + 'MESSAGE_TEXT' => $confirm_text, - 'YES_VALUE' => $user->lang['YES'], + 'YES_VALUE' => $language->lang('YES'), 'S_CONFIRM_ACTION' => $u_action, 'S_HIDDEN_FIELDS' => $hidden . $s_hidden_fields, 'S_AJAX_REQUEST' => $request->is_ajax(), @@ -2205,16 +2234,36 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo if ($request->is_ajax()) { $u_action .= '&confirm_uid=' . $user->data['user_id'] . '&sess=' . $user->session_id . '&sid=' . $user->session_id; - $json_response = new \phpbb\json_response; - $json_response->send(array( + $data = array( 'MESSAGE_BODY' => $template->assign_display('body'), - 'MESSAGE_TITLE' => (!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title], - 'MESSAGE_TEXT' => (!isset($user->lang[$title . '_CONFIRM'])) ? $title : $user->lang[$title . '_CONFIRM'], + 'MESSAGE_TITLE' => $confirm_title, + 'MESSAGE_TEXT' => $confirm_text, - 'YES_VALUE' => $user->lang['YES'], + 'YES_VALUE' => $language->lang('YES'), 'S_CONFIRM_ACTION' => str_replace('&', '&', $u_action), //inefficient, rewrite whole function 'S_HIDDEN_FIELDS' => $hidden . $s_hidden_fields - )); + ); + + /** + * This event allows an extension to modify the ajax output of confirm box. + * + * @event core.confirm_box_ajax_before + * @var string u_action Action of the form + * @var array data Data to be sent + * @var string hidden Hidden fields generated by caller + * @var string s_hidden_fields Hidden fields generated by this function + * @since 3.2.8-RC1 + */ + $vars = array( + 'u_action', + 'data', + 'hidden', + 's_hidden_fields', + ); + extract($phpbb_dispatcher->trigger_event('core.confirm_box_ajax_before', compact($vars))); + + $json_response = new \phpbb\json_response; + $json_response->send($data); } if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin']) @@ -2225,6 +2274,8 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo { page_footer(); } + + exit; // unreachable, page_footer() above will call exit() } /** @@ -2236,6 +2287,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa global $request, $phpbb_container, $phpbb_dispatcher, $phpbb_log; $err = ''; + $form_name = 'login'; // Make sure user->setup() has been called if (!$user->is_setup()) @@ -2311,8 +2363,19 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa trigger_error('NO_AUTH_ADMIN_USER_DIFFER'); } - // If authentication is successful we redirect user to previous page - $result = $auth->login($username, $password, $autologin, $viewonline, $admin); + // Check form key + if ($password && !defined('IN_CHECK_BAN') && !check_form_key($form_name)) + { + $result = array( + 'status' => false, + 'error_msg' => 'FORM_INVALID', + ); + } + else + { + // If authentication is successful we redirect user to previous page + $result = $auth->login($username, $password, $autologin, $viewonline, $admin); + } // If admin authentication and login, we will log if it was a success or not... // We also break the operation on the first non-success login - it could be argued that the user already knows @@ -2344,10 +2407,12 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa * @event core.login_box_redirect * @var string redirect Redirect string * @var bool admin Is admin? + * @var array result Result from auth provider * @since 3.1.0-RC5 * @changed 3.1.9-RC1 Removed undefined return variable + * @changed 3.2.4-RC1 Added result */ - $vars = array('redirect', 'admin'); + $vars = array('redirect', 'admin', 'result'); extract($phpbb_dispatcher->trigger_event('core.login_box_redirect', compact($vars))); // append/replace SID (may change during the session for AOL users) @@ -2463,7 +2528,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa $s_hidden_fields = build_hidden_fields($s_hidden_fields); - $template->assign_vars(array( + $login_box_template_data = array( 'LOGIN_ERROR' => $err, 'LOGIN_EXPLAIN' => $l_explain, @@ -2471,6 +2536,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa 'U_RESEND_ACTIVATION' => ($config['require_activation'] == USER_ACTIVATION_SELF && $config['email_enable']) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=resend_act') : '', 'U_TERMS_USE' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=terms'), 'U_PRIVACY' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=privacy'), + 'UA_PRIVACY' => addslashes(append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=privacy')), 'S_DISPLAY_FULL_LOGIN' => ($s_display) ? true : false, 'S_HIDDEN_FIELDS' => $s_hidden_fields, @@ -2480,7 +2546,29 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa 'USERNAME_CREDENTIAL' => 'username', 'PASSWORD_CREDENTIAL' => ($admin) ? 'password_' . $credential : 'password', - )); + ); + + /** + * Event to add/modify login box template data + * + * @event core.login_box_modify_template_data + * @var int admin Flag whether user is admin + * @var string username User name + * @var int autologin Flag whether autologin is enabled + * @var string redirect Redirect URL + * @var array login_box_template_data Array with the login box template data + * @since 3.2.3-RC2 + */ + $vars = array( + 'admin', + 'username', + 'autologin', + 'redirect', + 'login_box_template_data', + ); + extract($phpbb_dispatcher->trigger_event('core.login_box_modify_template_data', compact($vars))); + + $template->assign_vars($login_box_template_data); page_header($user->lang['LOGIN']); @@ -2497,7 +2585,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa */ function login_forum_box($forum_data) { - global $db, $phpbb_container, $request, $template, $user, $phpbb_dispatcher; + global $db, $phpbb_container, $request, $template, $user, $phpbb_dispatcher, $phpbb_root_path, $phpEx; $password = $request->variable('password', '', true); @@ -2582,6 +2670,8 @@ function login_forum_box($forum_data) 'body' => 'login_forum.html') ); + make_jumpbox(append_sid("{$phpbb_root_path}viewforum.$phpEx"), $forum_data['forum_id']); + page_footer(); } @@ -2676,9 +2766,9 @@ function parse_cfg_file($filename, $lines = false) { $value = ''; } - else if (($value[0] == "'" && $value[sizeof($value) - 1] == "'") || ($value[0] == '"' && $value[sizeof($value) - 1] == '"')) + else if (($value[0] == "'" && $value[strlen($value) - 1] == "'") || ($value[0] == '"' && $value[strlen($value) - 1] == '"')) { - $value = htmlspecialchars(substr($value, 1, sizeof($value)-2)); + $value = htmlspecialchars(substr($value, 1, strlen($value)-2)); } else { @@ -2780,12 +2870,17 @@ function get_preg_expression($mode) case 'url': // generated with regex_idn.php file in the develop folder - return "[a-z][a-z\d+\-.]*:/{2}(?:(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'()*+,;=:@|]+|%[\dA-F]{2})+|[0-9.]+|\[[a-z0-9.]+:[a-z0-9.]+:[a-z0-9.:]+\])(?::\d*)?(?:/(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'()*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'()*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'()*+,;=:@/?|]+|%[\dA-F]{2})*)?"; + return "[a-z][a-z\d+\-.]*(?<!javascript):/{2}(?:(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'()*+,;=:@|]+|%[\dA-F]{2})+|[0-9.]+|\[[a-z0-9.]+:[a-z0-9.]+:[a-z0-9.:]+\])(?::\d*)?(?:/(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'()*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'()*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'()*+,;=:@/?|]+|%[\dA-F]{2})*)?"; + break; + + case 'url_http': + // generated with regex_idn.php file in the develop folder + return "http[s]?:/{2}(?:(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'()*+,;=:@|]+|%[\dA-F]{2})+|[0-9.]+|\[[a-z0-9.]+:[a-z0-9.]+:[a-z0-9.:]+\])(?::\d*)?(?:/(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'()*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'()*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'()*+,;=:@/?|]+|%[\dA-F]{2})*)?"; break; case 'url_inline': // generated with regex_idn.php file in the develop folder - return "[a-z][a-z\d+]*:/{2}(?:(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})+|[0-9.]+|\[[a-z0-9.]+:[a-z0-9.]+:[a-z0-9.:]+\])(?::\d*)?(?:/(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?"; + return "[a-z][a-z\d+]*(?<!javascript):/{2}(?:(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})+|[0-9.]+|\[[a-z0-9.]+:[a-z0-9.]+:[a-z0-9.:]+\])(?::\d*)?(?:/(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?"; break; case 'www_url': @@ -3007,7 +3102,7 @@ function phpbb_inet_pton($address) if (preg_match(get_preg_expression('ipv6'), $address)) { $parts = explode(':', $address); - $missing_parts = 8 - sizeof($parts) + 1; + $missing_parts = 8 - count($parts) + 1; if (substr($address, 0, 2) === '::') { @@ -3024,7 +3119,7 @@ function phpbb_inet_pton($address) if (preg_match(get_preg_expression('ipv4'), $last_part)) { - $parts[sizeof($parts) - 1] = ''; + $parts[count($parts) - 1] = ''; $last_part = phpbb_inet_pton($last_part); $embedded_ipv4 = true; --$missing_parts; @@ -3036,7 +3131,7 @@ function phpbb_inet_pton($address) { $ret .= str_pad($part, 4, '0', STR_PAD_LEFT); } - else if ($i && $i < sizeof($parts) - 1) + else if ($i && $i < count($parts) - 1) { $ret .= str_repeat('0000', $missing_parts); } @@ -3632,7 +3727,7 @@ function obtain_users_online_string($online_users, $item_id = 0, $item = 'forum' // Need caps version of $item for language-strings $item_caps = strtoupper($item); - if (sizeof($online_users['online_users'])) + if (count($online_users['online_users'])) { $sql_ary = array( 'SELECT' => 'u.username, u.username_clean, u.user_id, u.user_type, u.user_allow_viewonline, u.user_colour', @@ -4030,9 +4125,9 @@ function phpbb_get_user_avatar($user_row, $alt = 'USER_AVATAR', $ignore_config = * * @return string Avatar html */ -function phpbb_get_group_avatar($user_row, $alt = 'GROUP_AVATAR', $ignore_config = false, $lazy = false) +function phpbb_get_group_avatar($group_row, $alt = 'GROUP_AVATAR', $ignore_config = false, $lazy = false) { - $row = \phpbb\avatar\manager::clean_row($user_row, 'group'); + $row = \phpbb\avatar\manager::clean_row($group_row, 'group'); return phpbb_get_avatar($row, $alt, $ignore_config, $lazy); } @@ -4337,6 +4432,23 @@ function page_header($page_title = '', $display_online_list = false, $item_id = $controller_helper = $phpbb_container->get('controller.helper'); $notification_mark_hash = generate_link_hash('mark_all_notifications_read'); + $s_login_redirect = build_hidden_fields(array('redirect' => $phpbb_path_helper->remove_web_root_path(build_url()))); + + // Add form token for login box, in case page is presenting a login form. + add_form_key('login', '_LOGIN'); + + /** + * Workaround for missing template variable in pre phpBB 3.2.6 styles. + * @deprecated 3.2.7 (To be removed: 3.3.0-a1) + */ + $form_token_login = $template->retrieve_var('S_FORM_TOKEN_LOGIN'); + if (!empty($form_token_login)) + { + $s_login_redirect .= $form_token_login; + // Remove S_FORM_TOKEN_LOGIN as it's already appended to S_LOGIN_REDIRECT + $template->assign_var('S_FORM_TOKEN_LOGIN', ''); + } + // The following assigns all _common_ variables that may be used at any point in a template. $template->assign_vars(array( 'SITENAME' => $config['sitename'], @@ -4396,9 +4508,10 @@ function page_header($page_title = '', $display_online_list = false, $item_id = 'U_SEARCH_ACTIVE_TOPICS'=> append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=active_topics'), 'U_DELETE_COOKIES' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=delete_cookies'), 'U_CONTACT_US' => ($config['contact_admin_form_enable'] && $config['email_enable']) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contactadmin') : '', - 'U_TEAM' => ($user->data['user_id'] != ANONYMOUS && !$auth->acl_get('u_viewprofile')) ? '' : append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=team'), + 'U_TEAM' => (!$auth->acl_get('u_viewprofile')) ? '' : append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=team'), 'U_TERMS_USE' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=terms'), 'U_PRIVACY' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=privacy'), + 'UA_PRIVACY' => addslashes(append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=privacy')), 'U_RESTORE_PERMISSIONS' => ($user->data['user_perm_from'] && $auth->acl_get('a_switchperm')) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=restore_perm') : '', 'U_FEED' => $controller_helper->route('phpbb_feed_index'), @@ -4425,7 +4538,7 @@ function page_header($page_title = '', $display_online_list = false, $item_id = 'S_TOPIC_ID' => $topic_id, 'S_LOGIN_ACTION' => ((!defined('ADMIN_START')) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login') : append_sid("{$phpbb_admin_path}index.$phpEx", false, true, $user->session_id)), - 'S_LOGIN_REDIRECT' => build_hidden_fields(array('redirect' => $phpbb_path_helper->remove_web_root_path(build_url()))), + 'S_LOGIN_REDIRECT' => $s_login_redirect, 'S_ENABLE_FEEDS' => ($config['feed_enable']) ? true : false, 'S_ENABLE_FEEDS_OVERALL' => ($config['feed_overall']) ? true : false, @@ -4458,7 +4571,7 @@ function page_header($page_title = '', $display_online_list = false, $item_id = 'S_COOKIE_NOTICE' => !empty($config['cookie_notice']), 'T_THEME_NAME' => rawurlencode($user->style['style_path']), - 'T_THEME_LANG_NAME' => $user->data['user_lang'], + 'T_THEME_LANG_NAME' => $user->lang_name, 'T_TEMPLATE_NAME' => $user->style['style_path'], 'T_SUPER_TEMPLATE_NAME' => rawurlencode((isset($user->style['style_parent_tree']) && $user->style['style_parent_tree']) ? $user->style['style_parent_tree'] : $user->style['style_path']), 'T_IMAGES' => 'images', @@ -4476,12 +4589,13 @@ function page_header($page_title = '', $display_online_list = false, $item_id = if ($send_headers) { - // An array of http headers that phpbb will set. The following event may override these. + // An array of http headers that phpBB will set. The following event may override these. $http_headers += array( // application/xhtml+xml not used because of IE 'Content-type' => 'text/html; charset=UTF-8', 'Cache-Control' => 'private, no-cache="set-cookie"', 'Expires' => gmdate('D, d M Y H:i:s', time()) . ' GMT', + 'Referrer-Policy' => 'strict-origin-when-cross-origin', ); if (!empty($user->data['is_bot'])) { diff --git a/phpBB/includes/functions_acp.php b/phpBB/includes/functions_acp.php index 8bf42aa36e..a2014a7d5b 100644 --- a/phpBB/includes/functions_acp.php +++ b/phpBB/includes/functions_acp.php @@ -112,12 +112,13 @@ function adm_page_header($page_title) 'CONTAINER_EXCEPTION' => $phpbb_container->hasParameter('container_exception') ? $phpbb_container->getParameter('container_exception') : false, )); - // An array of http headers that phpbb will set. The following event may override these. + // An array of http headers that phpBB will set. The following event may override these. $http_headers = array( // application/xhtml+xml not used because of IE 'Content-type' => 'text/html; charset=UTF-8', 'Cache-Control' => 'private, no-cache="set-cookie"', 'Expires' => gmdate('D, d M Y H:i:s', time()) . ' GMT', + 'Referrer-Policy' => 'strict-origin-when-cross-origin', ); /** @@ -419,7 +420,7 @@ function build_cfg_template($tpl_type, $key, &$new_ary, $config_key, $vars) */ function validate_config_vars($config_vars, &$cfg_array, &$error) { - global $phpbb_root_path, $user, $phpbb_dispatcher, $phpbb_filesystem; + global $phpbb_root_path, $user, $phpbb_dispatcher, $phpbb_filesystem, $language; $type = 0; $min = 1; @@ -442,6 +443,16 @@ function validate_config_vars($config_vars, &$cfg_array, &$error) // Validate a bit. ;) (0 = type, 1 = min, 2= max) switch ($validator[$type]) { + case 'url': + $cfg_array[$config_name] = trim($cfg_array[$config_name]); + + if (!empty($cfg_array[$config_name]) && !preg_match('#^' . get_preg_expression('url') . '$#iu', $cfg_array[$config_name])) + { + $error[] = $language->lang('URL_INVALID', $language->lang($config_definition['lang'])); + } + + // no break here + case 'string': $length = utf8_strlen($cfg_array[$config_name]); @@ -564,9 +575,6 @@ function validate_config_vars($config_vars, &$cfg_array, &$error) $cfg_array[$config_name] = trim($destination); - // Absolute file path - case 'absolute_path': - case 'absolute_path_writable': // Path being relative (still prefixed by phpbb_root_path), but with the ability to escape the root dir... case 'path': case 'wpath': @@ -585,7 +593,7 @@ function validate_config_vars($config_vars, &$cfg_array, &$error) break; } - $path = in_array($config_definition['validate'], array('wpath', 'path', 'rpath', 'rwpath')) ? $phpbb_root_path . $cfg_array[$config_name] : $cfg_array[$config_name]; + $path = $phpbb_root_path . $cfg_array[$config_name]; if (!file_exists($path)) { @@ -598,7 +606,7 @@ function validate_config_vars($config_vars, &$cfg_array, &$error) } // Check if the path is writable - if ($config_definition['validate'] == 'wpath' || $config_definition['validate'] == 'rwpath' || $config_definition['validate'] === 'absolute_path_writable') + if ($config_definition['validate'] == 'wpath' || $config_definition['validate'] == 'rwpath') { if (file_exists($path) && !$phpbb_filesystem->is_writable($path)) { diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index 1ad41156f9..c19d48b0be 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -167,7 +167,7 @@ function size_select_options($size_compare) $s_size_options = ''; - for ($i = 0, $size = sizeof($size_types_text); $i < $size; $i++) + for ($i = 0, $size = count($size_types_text); $i < $size; $i++) { $selected = ($size_compare == $size_types[$i]) ? ' selected="selected"' : ''; $s_size_options .= '<option value="' . $size_types[$i] . '"' . $selected . '>' . $size_types_text[$i] . '</option>'; @@ -192,7 +192,7 @@ function group_select_options($group_id, $exclude_ids = false, $manage_founder = /** @var \phpbb\group\helper $group_helper */ $group_helper = $phpbb_container->get('group_helper'); - $exclude_sql = ($exclude_ids !== false && sizeof($exclude_ids)) ? 'WHERE ' . $db->sql_in_set('group_id', array_map('intval', $exclude_ids), true) : ''; + $exclude_sql = ($exclude_ids !== false && count($exclude_ids)) ? 'WHERE ' . $db->sql_in_set('group_id', array_map('intval', $exclude_ids), true) : ''; $sql_and = (!$config['coppa_enable']) ? (($exclude_sql) ? ' AND ' : ' WHERE ') . "group_name <> 'REGISTERED_COPPA'" : ''; $sql_founder = ($manage_founder !== false) ? (($exclude_sql || $sql_and) ? ' AND ' : ' WHERE ') . 'group_founder_manage = ' . (int) $manage_founder : ''; @@ -747,7 +747,7 @@ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_s { $where_ids = (is_array($where_ids)) ? array_unique($where_ids) : array($where_ids); - if (!sizeof($where_ids)) + if (!count($where_ids)) { return array('topics' => 0, 'posts' => 0); } @@ -777,9 +777,9 @@ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_s } $db->sql_freeresult($result); - $return['topics'] = sizeof($topic_ids); + $return['topics'] = count($topic_ids); - if (!sizeof($topic_ids)) + if (!count($topic_ids)) { return $return; } @@ -837,7 +837,7 @@ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_s } $db->sql_freeresult($result); - if (sizeof($moved_topic_ids)) + if (count($moved_topic_ids)) { $sql = 'DELETE FROM ' . TOPICS_TABLE . ' WHERE ' . $db->sql_in_set('topic_id', $moved_topic_ids); @@ -923,7 +923,7 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = $where_ids = array($where_ids); } - if (!sizeof($where_ids)) + if (!count($where_ids)) { return false; } @@ -931,7 +931,7 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = $where_ids = array_map('intval', $where_ids); /* Possible code for splitting post deletion - if (sizeof($where_ids) >= 1001) + if (count($where_ids) >= 1001) { // Split into chunks of 1000 $chunks = array_chunk($where_ids, 1000); @@ -974,7 +974,7 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = } $db->sql_freeresult($result); - if (!sizeof($post_ids)) + if (!count($post_ids)) { return false; } @@ -1018,7 +1018,7 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = unset($table_ary); // Adjust users post counts - if (sizeof($post_counts) && $post_count_sync) + if (count($post_counts) && $post_count_sync) { foreach ($post_counts as $poster_id => $substract) { @@ -1037,7 +1037,7 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = } // Remove topics now having no posts? - if (sizeof($topic_ids)) + if (count($topic_ids)) { $sql = 'SELECT topic_id FROM ' . POSTS_TABLE . ' @@ -1147,7 +1147,7 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = } // We actually remove topics now to not be inconsistent (the delete_topics function calls this function too) - if (sizeof($remove_topics) && $call_delete_topics) + if (count($remove_topics) && $call_delete_topics) { delete_topics('topic_id', $remove_topics, $auto_sync, $post_count_sync, false); } @@ -1157,7 +1157,7 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = $phpbb_notifications->delete_notifications($delete_notifications_types, $post_ids); - return sizeof($post_ids); + return count($post_ids); } /** @@ -1232,7 +1232,7 @@ function delete_topic_shadows($forum_id, $sql_more = '', $auto_sync = true) $db->sql_query($sql); } } - while (sizeof($topic_ids) == $batch_size); + while (count($topic_ids) == $batch_size); if ($auto_sync) { @@ -1363,7 +1363,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, // Do not sync the "global forum" $where_ids = array_diff($where_ids, array(0)); - if (!sizeof($where_ids)) + if (!count($where_ids)) { // Empty array with IDs. This means that we don't have any work to do. Just return. return; @@ -1377,7 +1377,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, } else { - if (!sizeof($where_ids)) + if (!count($where_ids)) { return; } @@ -1416,7 +1416,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, } $db->sql_freeresult($result); - if (!sizeof($topic_id_ary)) + if (!count($topic_id_ary)) { return; } @@ -1533,7 +1533,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, $post_ids[] = $post_id; } - if (sizeof($post_ids)) + if (count($post_ids)) { $sql = 'UPDATE ' . POSTS_TABLE . ' SET post_reported = 1 - post_reported @@ -1579,7 +1579,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, } $db->sql_freeresult($result); - if (sizeof($topic_ids)) + if (count($topic_ids)) { $sql = 'UPDATE ' . TOPICS_TABLE . ' SET topic_reported = 1 - topic_reported @@ -1638,7 +1638,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, $post_ids[] = $post_id; } - if (sizeof($post_ids)) + if (count($post_ids)) { $sql = 'UPDATE ' . POSTS_TABLE . ' SET post_attachment = 1 - post_attachment @@ -1684,7 +1684,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, } $db->sql_freeresult($result); - if (sizeof($topic_ids)) + if (count($topic_ids)) { $sql = 'UPDATE ' . TOPICS_TABLE . ' SET topic_attachment = 1 - topic_attachment @@ -1736,7 +1736,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, } $db->sql_freeresult($result); - if (!sizeof($forum_ids)) + if (!count($forum_ids)) { break; } @@ -1775,7 +1775,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, // 3: Get post count for each forum (optional) if ($sync_extra) { - if (sizeof($forum_ids) == 1) + if (count($forum_ids) == 1) { $sql = 'SELECT SUM(t.topic_posts_approved) AS forum_posts_approved, SUM(t.topic_posts_unapproved) AS forum_posts_unapproved, SUM(t.topic_posts_softdeleted) AS forum_posts_softdeleted FROM ' . TOPICS_TABLE . ' t @@ -1795,7 +1795,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, while ($row = $db->sql_fetchrow($result)) { - $forum_id = (sizeof($forum_ids) == 1) ? (int) $forum_ids[0] : (int) $row['forum_id']; + $forum_id = (count($forum_ids) == 1) ? (int) $forum_ids[0] : (int) $row['forum_id']; $forum_data[$forum_id]['posts_approved'] = (int) $row['forum_posts_approved']; $forum_data[$forum_id]['posts_unapproved'] = (int) $row['forum_posts_unapproved']; @@ -1805,7 +1805,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, } // 4: Get last_post_id for each forum - if (sizeof($forum_ids) == 1) + if (count($forum_ids) == 1) { $sql = 'SELECT MAX(t.topic_last_post_id) as last_post_id FROM ' . TOPICS_TABLE . ' t @@ -1825,7 +1825,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, while ($row = $db->sql_fetchrow($result)) { - $forum_id = (sizeof($forum_ids) == 1) ? (int) $forum_ids[0] : (int) $row['forum_id']; + $forum_id = (count($forum_ids) == 1) ? (int) $forum_ids[0] : (int) $row['forum_id']; $forum_data[$forum_id]['last_post_id'] = (int) $row['last_post_id']; @@ -1834,7 +1834,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, $db->sql_freeresult($result); // 5: Retrieve last_post infos - if (sizeof($post_ids)) + if (count($post_ids)) { $sql = 'SELECT p.post_id, p.poster_id, p.post_subject, p.post_time, p.post_username, u.username, u.user_colour FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u @@ -1902,7 +1902,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, } } - if (sizeof($sql_ary)) + if (count($sql_ary)) { $sql = 'UPDATE ' . FORUMS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' @@ -2025,20 +2025,20 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, } // Now we delete empty topics and orphan posts - if (sizeof($delete_posts)) + if (count($delete_posts)) { delete_posts('topic_id', array_keys($delete_posts), false); unset($delete_posts); } - if (!sizeof($topic_data)) + if (!count($topic_data)) { // If we get there, topic ids were invalid or topics did not contain any posts delete_topics($where_type, $where_ids, true); return; } - if (sizeof($delete_topics)) + if (count($delete_topics)) { $delete_topic_ids = array(); foreach ($delete_topics as $topic_id => $void) @@ -2081,7 +2081,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, $db->sql_freeresult($result); // Make sure shadow topics do link to existing topics - if (sizeof($moved_topics)) + if (count($moved_topics)) { $delete_topics = array(); @@ -2098,7 +2098,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, } $db->sql_freeresult($result); - if (sizeof($delete_topics)) + if (count($delete_topics)) { delete_topics('topic_id', $delete_topics, false); } @@ -2121,7 +2121,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, $db->sql_freeresult($result); $sync_shadow_topics = array(); - if (sizeof($post_ids)) + if (count($post_ids)) { $sql = 'SELECT p.post_id, p.topic_id, p.post_visibility, p.poster_id, p.post_subject, p.post_username, p.post_time, u.username, u.user_colour FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u @@ -2174,7 +2174,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, $shadow_topic_data = array(); // Update the information we collected - if (sizeof($sync_shadow_topics)) + if (count($sync_shadow_topics)) { foreach ($sync_shadow_topics as $sync_topic_id => $sql_ary) { @@ -2239,7 +2239,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, } } - if (sizeof($sql_ary)) + if (count($sql_ary)) { $sql = 'UPDATE ' . TOPICS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' @@ -2256,7 +2256,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, // if some topics have been resync'ed then resync parent forums // except when we're only syncing a range, we don't want to sync forums during // batch processing. - if ($resync_parents && sizeof($resync_forums) && $where_type != 'range') + if ($resync_parents && count($resync_forums) && $where_type != 'range') { sync('forum', 'forum_id', array_values($resync_forums), true, true); } @@ -2278,7 +2278,7 @@ function prune($forum_id, $prune_mode, $prune_date, $prune_flags = 0, $auto_sync $forum_id = array($forum_id); } - if (!sizeof($forum_id)) + if (!count($forum_id)) { return; } @@ -2369,6 +2369,16 @@ function prune($forum_id, $prune_mode, $prune_date, $prune_flags = 0, $auto_sync $topic_list = array_unique($topic_list); } + /** + * Perform additional actions before topic deletion via pruning + * + * @event core.prune_delete_before + * @var int[] topic_list The IDs of the topics to be deleted + * @since 3.2.2-RC1 + */ + $vars = array('topic_list'); + extract($phpbb_dispatcher->trigger_event('core.prune_delete_before', compact($vars))); + return delete_topics('topic_id', $topic_list, $auto_sync, false); } @@ -2441,7 +2451,7 @@ function phpbb_cache_moderators($db, $cache, $auth) $hold_ary = $auth->acl_user_raw_data(false, 'm_%', false); // Add users? - if (sizeof($hold_ary)) + if (!empty($hold_ary)) { // At least one moderative option warrants a display $ug_id_ary = array_keys($hold_ary); @@ -2486,7 +2496,7 @@ function phpbb_cache_moderators($db, $cache, $auth) } $db->sql_freeresult($result); - if (sizeof($hold_ary)) + if (count($hold_ary)) { // Get usernames... $sql = 'SELECT user_id, username @@ -2526,7 +2536,7 @@ function phpbb_cache_moderators($db, $cache, $auth) // Now to the groups... $hold_ary = $auth->acl_group_raw_data(false, 'm_%', false); - if (sizeof($hold_ary)) + if (!empty($hold_ary)) { $ug_id_ary = array_keys($hold_ary); @@ -2630,7 +2640,7 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id function phpbb_update_foes($db, $auth, $group_id = false, $user_id = false) { // update foes for some user - if (is_array($user_id) && sizeof($user_id)) + if (is_array($user_id) && count($user_id)) { $sql = 'DELETE FROM ' . ZEBRA_TABLE . ' WHERE ' . $db->sql_in_set('zebra_id', $user_id) . ' @@ -2640,7 +2650,7 @@ function phpbb_update_foes($db, $auth, $group_id = false, $user_id = false) } // update foes for some group - if (is_array($group_id) && sizeof($group_id)) + if (is_array($group_id) && count($group_id)) { // Grab group settings... $sql_ary = array( @@ -2674,7 +2684,7 @@ function phpbb_update_foes($db, $auth, $group_id = false, $user_id = false) } $db->sql_freeresult($result); - if (!sizeof($groups)) + if (!count($groups)) { return; } @@ -2704,7 +2714,7 @@ function phpbb_update_foes($db, $auth, $group_id = false, $user_id = false) } $db->sql_freeresult($result); - if (sizeof($users)) + if (count($users)) { $sql = 'DELETE FROM ' . ZEBRA_TABLE . ' WHERE ' . $db->sql_in_set('zebra_id', $users) . ' @@ -2727,7 +2737,7 @@ function phpbb_update_foes($db, $auth, $group_id = false, $user_id = false) } } - if (sizeof($perms)) + if (count($perms)) { $sql = 'DELETE FROM ' . ZEBRA_TABLE . ' WHERE ' . $db->sql_in_set('zebra_id', array_unique($perms)) . ' @@ -2990,7 +3000,7 @@ function tidy_warnings() } $db->sql_freeresult($result); - if (sizeof($warning_list)) + if (count($warning_list)) { $db->sql_transaction('begin'); @@ -3032,6 +3042,8 @@ function tidy_database() } $db->sql_freeresult($result); + $db->sql_transaction('begin'); + // Delete those rows from the acl tables not having listed the forums above $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . ' WHERE ' . $db->sql_in_set('forum_id', $forum_ids, true); @@ -3041,6 +3053,8 @@ function tidy_database() WHERE ' . $db->sql_in_set('forum_id', $forum_ids, true); $db->sql_query($sql); + $db->sql_transaction('commit'); + $config->set('database_last_gc', time(), false); } diff --git a/phpBB/includes/functions_compatibility.php b/phpBB/includes/functions_compatibility.php index 4fe7e71117..e95fa40a58 100644 --- a/phpBB/includes/functions_compatibility.php +++ b/phpBB/includes/functions_compatibility.php @@ -391,7 +391,7 @@ function request_var($var_name, $default, $multibyte = false, $cookie = false, $ * * @deprecated 3.1.0 (To be removed: 3.3.0) */ -function get_tables(&$db) +function get_tables($db) { $db_tools_factory = new \phpbb\db\tools\factory(); $db_tools = $db_tools_factory->get($db); diff --git a/phpBB/includes/functions_compress.php b/phpBB/includes/functions_compress.php index 910708f502..e86da77b38 100644 --- a/phpBB/includes/functions_compress.php +++ b/phpBB/includes/functions_compress.php @@ -210,7 +210,7 @@ class compress_zip extends compress /** * Constructor */ - function compress_zip($mode, $file) + function __construct($mode, $file) { global $phpbb_filesystem; @@ -409,7 +409,7 @@ class compress_zip extends compress function close() { // Write out central file directory and footer ... if it exists - if (sizeof($this->ctrl_dir)) + if (count($this->ctrl_dir)) { fwrite($this->fp, $this->file()); } @@ -511,8 +511,8 @@ class compress_zip extends compress $ctrldir = implode('', $this->ctrl_dir); return $ctrldir . $this->eof_cdh . - pack('v', sizeof($this->ctrl_dir)) . // total # of entries "on this disk" - pack('v', sizeof($this->ctrl_dir)) . // total # of entries overall + pack('v', count($this->ctrl_dir)) . // total # of entries "on this disk" + pack('v', count($this->ctrl_dir)) . // total # of entries overall pack('V', strlen($ctrldir)) . // size of central dir pack('V', $this->datasec_len) . // offset to start of central dir "\x00\x00"; // .zip file comment length @@ -569,7 +569,7 @@ class compress_tar extends compress /** * Constructor */ - function compress_tar($mode, $file, $type = '') + function __construct($mode, $file, $type = '') { global $phpbb_filesystem; diff --git a/phpBB/includes/functions_content.php b/phpBB/includes/functions_content.php index 06223027d8..2542be5e02 100644 --- a/phpBB/includes/functions_content.php +++ b/phpBB/includes/functions_content.php @@ -336,7 +336,7 @@ function get_context($text, $words, $length = 400) $text = str_replace($entities, $characters, $text); $word_indizes = array(); - if (sizeof($words)) + if (count($words)) { $match = ''; // find the starting indizes of all words @@ -361,12 +361,12 @@ function get_context($text, $words, $length = 400) } unset($match); - if (sizeof($word_indizes)) + if (count($word_indizes)) { $word_indizes = array_unique($word_indizes); sort($word_indizes); - $wordnum = sizeof($word_indizes); + $wordnum = count($word_indizes); // number of characters on the right and left side of each word $sequence_length = (int) ($length / (2 * $wordnum)) - 2; $final_text = ''; @@ -434,7 +434,7 @@ function get_context($text, $words, $length = 400) } } - if (!sizeof($words) || !sizeof($word_indizes)) + if (!count($words) || !count($word_indizes)) { return str_replace($characters, $entities, ((utf8_strlen($text) >= $length + 3) ? utf8_substr($text, 0, $length) . '...' : $text)); } @@ -627,7 +627,7 @@ function generate_text_for_display($text, $uid, $bitfield, $flags, $censor_text } else { - $bbcode->bbcode($bitfield); + $bbcode->bbcode_set_bitfield($bitfield); } $bbcode->bbcode_second_pass($text, $uid); @@ -1021,7 +1021,7 @@ function censor_text($text) } } - if (sizeof($censors)) + if (count($censors)) { return preg_replace($censors['match'], $censors['replace'], $text); } @@ -1079,7 +1079,7 @@ function smiley_text($text, $force_option = false) */ function parse_attachments($forum_id, &$message, &$attachments, &$update_count_ary, $preview = false) { - if (!sizeof($attachments)) + if (!count($attachments)) { return; } @@ -1114,7 +1114,7 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count_a } // Grab attachments (security precaution) - if (sizeof($attach_ids)) + if (count($attach_ids)) { global $db; @@ -1151,7 +1151,7 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count_a foreach ($attachments as $attachment) { - if (!sizeof($attachment)) + if (!count($attachment)) { continue; } @@ -1443,7 +1443,7 @@ function truncate_string($string, $max_length = 60, $max_store_length = 255, $al $chars = array_map('utf8_htmlspecialchars', $_chars); // Now check the length ;) - if (sizeof($chars) > $max_length) + if (count($chars) > $max_length) { // Cut off the last elements from the array $string = implode('', array_slice($chars, 0, $max_length - utf8_strlen($append))); @@ -1482,6 +1482,8 @@ function truncate_string($string, $max_length = 60, $max_store_length = 255, $al * Get username details for placing into templates. * This function caches all modes on first call, except for no_profile and anonymous user - determined by $user_id. * +* @html Username spans and links +* * @param string $mode Can be profile (for getting an url to the profile), username (for obtaining the username), colour (for obtaining the user colour), full (for obtaining a html string representing a coloured link to the users profile) or no_profile (the same as full but forcing no profile link) * @param int $user_id The users id * @param string $username The users name @@ -1501,6 +1503,7 @@ function get_username_string($mode, $user_id, $username, $username_colour = '', { global $phpbb_root_path, $phpEx; + /** @html Username spans and links for usage in the template */ $_profile_cache['base_url'] = append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u={USER_ID}'); $_profile_cache['tpl_noprofile'] = '<span class="username">{USERNAME}</span>'; $_profile_cache['tpl_noprofile_colour'] = '<span style="color: {USERNAME_COLOUR};" class="username-coloured">{USERNAME}</span>'; @@ -1651,7 +1654,7 @@ function phpbb_generate_string_list($items, $user) return ''; } - $count = sizeof($items); + $count = count($items); $last_item = array_pop($items); $lang_key = 'STRING_LIST_MULTI'; @@ -1672,7 +1675,7 @@ class bitfield { var $data; - function bitfield($bitfield = '') + function __construct($bitfield = '') { $this->data = base64_decode($bitfield); } @@ -1758,3 +1761,48 @@ class bitfield $this->data = $this->data | $bitfield->get_blob(); } } + +/** + * Formats the quote according to the given BBCode status setting + * + * @param phpbb\language\language $language Language class + * @param parse_message $message_parser Message parser class + * @param phpbb\textformatter\utils_interface $text_formatter_utils Text formatter utilities + * @param bool $bbcode_status The status of the BBCode setting + * @param array $quote_attributes The attributes of the quoted post + * @param string $message_link Link of the original quoted post + */ +function phpbb_format_quote($language, $message_parser, $text_formatter_utils, $bbcode_status, $quote_attributes, $message_link = '') +{ + if ($bbcode_status) + { + $quote_text = $text_formatter_utils->generate_quote( + censor_text($message_parser->message), + $quote_attributes + ); + + $message_parser->message = $quote_text . "\n\n"; + } + else + { + $offset = 0; + $quote_string = "> "; + $message = censor_text(trim($message_parser->message)); + // see if we are nesting. It's easily tricked but should work for one level of nesting + if (strpos($message, ">") !== false) + { + $offset = 10; + } + $message = utf8_wordwrap($message, 75 + $offset, "\n"); + + $message = $quote_string . $message; + $message = str_replace("\n", "\n" . $quote_string, $message); + + $message_parser->message = $quote_attributes['author'] . " " . $language->lang('WROTE') . ":\n" . $message . "\n"; + } + + if ($message_link) + { + $message_parser->message = $message_link . $message_parser->message; + } +} diff --git a/phpBB/includes/functions_convert.php b/phpBB/includes/functions_convert.php index 176e3dd6de..2cfbe9541d 100644 --- a/phpBB/includes/functions_convert.php +++ b/phpBB/includes/functions_convert.php @@ -192,7 +192,7 @@ function get_group_id($group_name) $db->sql_freeresult($result); } - if (!sizeof($group_mapping)) + if (!count($group_mapping)) { add_default_groups(); return get_group_id($group_name); @@ -249,7 +249,7 @@ function validate_website($url) { return ''; } - else if (!preg_match('#^[a-z0-9]+://#i', $url) && strlen($url) > 0) + else if (!preg_match('#^http[s]?://#i', $url) && strlen($url) > 0) { return 'http://' . $url; } @@ -307,7 +307,7 @@ function decode_ip($int_ip) $hexipbang = explode('.', chunk_split($int_ip, 2, '.')); // Any mod changing the way ips are stored? Then we are not able to convert and enter the ip "as is" to not "destroy" anything... - if (sizeof($hexipbang) < 4) + if (count($hexipbang) < 4) { return $int_ip; } @@ -479,7 +479,7 @@ function import_avatar_gallery($gallery_name = '', $subdirs_as_galleries = false $dir->close(); } - for ($i = 0, $end = sizeof($dirlist); $i < $end; ++$i) + for ($i = 0, $end = count($dirlist); $i < $end; ++$i) { $dir = $dirlist[$i]; @@ -1261,7 +1261,7 @@ function get_config() } } - if (!sizeof($convert_config)) + if (!count($convert_config)) { $convert->p_master->error($user->lang['CONV_ERROR_CONFIG_EMPTY'], __LINE__, __FILE__); } @@ -1406,9 +1406,9 @@ function get_path($src_path, $src_url, $test_file) $url_parts = explode('/', $m[2]); if (substr($src_url, -1) != '/') { - if (preg_match('/.*\.([a-z0-9]{3,4})$/i', $url_parts[sizeof($url_parts) - 1])) + if (preg_match('/.*\.([a-z0-9]{3,4})$/i', $url_parts[count($url_parts) - 1])) { - $url_parts[sizeof($url_parts) - 1] = ''; + $url_parts[count($url_parts) - 1] = ''; } else { @@ -1425,9 +1425,9 @@ function get_path($src_path, $src_url, $test_file) $path_array = array(); $phpbb_parts = explode('/', $script_path); - for ($i = 0, $end = sizeof($url_parts); $i < $end; ++$i) + for ($i = 0, $end = count($url_parts); $i < $end; ++$i) { - if ($i < sizeof($phpbb_parts[$i]) && $url_parts[$i] == $phpbb_parts[$i]) + if ($i < count($phpbb_parts[$i]) && $url_parts[$i] == $phpbb_parts[$i]) { $path_array[] = $url_parts[$i]; unset($url_parts[$i]); @@ -1435,7 +1435,7 @@ function get_path($src_path, $src_url, $test_file) else { $path = ''; - for ($j = $i, $end2 = sizeof($phpbb_parts); $j < $end2; ++$j) + for ($j = $i, $end2 = count($phpbb_parts); $j < $end2; ++$j) { $path .= '../'; } @@ -1458,7 +1458,7 @@ function get_path($src_path, $src_url, $test_file) function compare_table($tables, $tablename, &$prefixes) { - for ($i = 0, $table_size = sizeof($tables); $i < $table_size; ++$i) + for ($i = 0, $table_size = count($tables); $i < $table_size; ++$i) { if (preg_match('/(.*)' . $tables[$i] . '$/', $tablename, $m)) { @@ -1754,7 +1754,7 @@ function add_default_groups() ); } - if (sizeof($sql_ary)) + if (count($sql_ary)) { $db->sql_multi_insert(GROUPS_TABLE, $sql_ary); } @@ -1786,7 +1786,7 @@ function add_groups_to_teampage() } $db->sql_freeresult($result); - if (sizeof($teampage_ary)) + if (count($teampage_ary)) { $db->sql_multi_insert(TEAMPAGE_TABLE, $teampage_ary); } @@ -2101,7 +2101,7 @@ function update_topics_posted() } unset($posted); - if (sizeof($sql_ary)) + if (count($sql_ary)) { $db->sql_multi_insert(TOPICS_POSTED_TABLE, $sql_ary); } @@ -2136,7 +2136,7 @@ function fix_empty_primary_groups() } $db->sql_freeresult($result); - if (sizeof($user_ids)) + if (count($user_ids)) { $db->sql_query('UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('administrators') . ' WHERE group_id = 0 AND ' . $db->sql_in_set('user_id', $user_ids)); @@ -2152,7 +2152,7 @@ function fix_empty_primary_groups() } $db->sql_freeresult($result); - if (sizeof($user_ids)) + if (count($user_ids)) { $db->sql_query('UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('global_moderators') . ' WHERE group_id = 0 AND ' . $db->sql_in_set('user_id', $user_ids)); @@ -2264,7 +2264,7 @@ function convert_bbcode($message, $convert_size = true, $extended_bbcodes = fals "\n\n" ); - for ($i = 0, $end = sizeof($str_from); $i < $end; ++$i) + for ($i = 0, $end = count($str_from); $i < $end; ++$i) { $origx[] = '#\\' . str_replace(']', '\\]', $str_from[$i]) . '#is'; $replx[] = $str_to[$i]; @@ -2273,7 +2273,7 @@ function convert_bbcode($message, $convert_size = true, $extended_bbcodes = fals if (preg_match_all('#\[email=([^\]]+)\](.*?)\[/email\]#i', $message, $m)) { - for ($i = 0, $end = sizeof($m[1]); $i < $end; ++$i) + for ($i = 0, $end = count($m[1]); $i < $end; ++$i) { if ($m[1][$i] == $m[2][$i]) { @@ -2292,7 +2292,7 @@ function convert_bbcode($message, $convert_size = true, $extended_bbcodes = fals $message = preg_replace('#\[size=([0-9]+)\](.*?)\[/size\]#i', '[size=\1]\2[/size]', $message); $message = preg_replace('#\[size=[0-9]{2,}\](.*?)\[/size\]#i', '[size=29]\1[/size]', $message); - for ($i = sizeof($size); $i;) + for ($i = count($size); $i;) { $i--; $message = str_replace('[size=' . $i . ']', '[size=' . $size[$i] . ']', $message); @@ -2335,9 +2335,9 @@ function copy_file($src, $trg, $overwrite = false, $die_on_failure = true, $sour $path = $phpbb_root_path; $parts = explode('/', $trg); - unset($parts[sizeof($parts) - 1]); + unset($parts[count($parts) - 1]); - for ($i = 0, $end = sizeof($parts); $i < $end; ++$i) + for ($i = 0, $end = count($parts); $i < $end; ++$i) { $path .= $parts[$i] . '/'; @@ -2437,7 +2437,7 @@ function copy_dir($src, $trg, $copy_subdirs = true, $overwrite = false, $die_on_ if ($copy_subdirs) { - for ($i = 0, $end = sizeof($dirlist); $i < $end; ++$i) + for ($i = 0, $end = count($dirlist); $i < $end; ++$i) { $dir = $dirlist[$i]; @@ -2458,21 +2458,21 @@ function copy_dir($src, $trg, $copy_subdirs = true, $overwrite = false, $die_on_ $bad_dirs[] = $trg_path . $dir; } - if (!sizeof($bad_dirs)) + if (!count($bad_dirs)) { copy_dir($src . $dir, $trg . $dir, true, $overwrite, $die_on_failure, $source_relative_path); } } } - if (sizeof($bad_dirs)) + if (count($bad_dirs)) { - $str = (sizeof($bad_dirs) == 1) ? $user->lang['MAKE_FOLDER_WRITABLE'] : $user->lang['MAKE_FOLDERS_WRITABLE']; + $str = (count($bad_dirs) == 1) ? $user->lang['MAKE_FOLDER_WRITABLE'] : $user->lang['MAKE_FOLDERS_WRITABLE']; sort($bad_dirs); $convert->p_master->error(sprintf($str, implode('<br />', $bad_dirs)), __LINE__, __FILE__); } - for ($i = 0, $end = sizeof($filelist); $i < $end; ++$i) + for ($i = 0, $end = count($filelist); $i < $end; ++$i) { copy_file($src . $filelist[$i], $trg . $filelist[$i], $overwrite, $die_on_failure, $source_relative_path); } diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php index e5d6d683fe..d0a0c97c4e 100644 --- a/phpBB/includes/functions_display.php +++ b/phpBB/includes/functions_display.php @@ -506,7 +506,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod } } - $l_subforums = (sizeof($subforums[$forum_id]) == 1) ? $user->lang['SUBFORUM'] : $user->lang['SUBFORUMS']; + $l_subforums = (count($subforums[$forum_id]) == 1) ? $user->lang['SUBFORUM'] : $user->lang['SUBFORUMS']; $folder_image = ($forum_unread) ? 'forum_unread_subforum' : 'forum_read_subforum'; } else @@ -537,7 +537,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod // Create last post link information, if appropriate if ($row['forum_last_post_id']) { - if ($row['forum_password_last_post'] === '' && $auth->acl_get('f_read', $row['forum_id_last_post'])) + if ($row['forum_password_last_post'] === '' && $auth->acl_gets('f_read', 'f_list_topics', $row['forum_id_last_post'])) { $last_post_subject = censor_text($row['forum_last_post_subject']); $last_post_subject_truncated = truncate_string($last_post_subject, 30, 255, false, $user->lang['ELLIPSIS']); @@ -559,7 +559,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod $l_moderator = $moderators_list = ''; if ($display_moderators && !empty($forum_moderators[$forum_id])) { - $l_moderator = (sizeof($forum_moderators[$forum_id]) == 1) ? $user->lang['MODERATOR'] : $user->lang['MODERATORS']; + $l_moderator = (count($forum_moderators[$forum_id]) == 1) ? $user->lang['MODERATOR'] : $user->lang['MODERATORS']; $moderators_list = implode($user->lang['COMMA_SEPARATOR'], $forum_moderators[$forum_id]); } @@ -606,7 +606,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod 'S_AUTH_READ' => $auth->acl_get('f_read', $row['forum_id']), 'S_LOCKED_FORUM' => ($row['forum_status'] == ITEM_LOCKED) ? true : false, 'S_LIST_SUBFORUMS' => ($row['display_subforum_list']) ? true : false, - 'S_SUBFORUMS' => (sizeof($subforums_list)) ? true : false, + 'S_SUBFORUMS' => (count($subforums_list)) ? true : false, 'S_DISPLAY_SUBJECT' => ($last_post_subject !== '' && $config['display_last_subject']) ? true : false, 'S_FEED_ENABLED' => ($config['feed_forum'] && !phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $row['forum_options']) && $row['forum_type'] == FORUM_POST) ? true : false, @@ -1243,6 +1243,7 @@ function display_user_activity(&$userdata_ary) } $userdata = $userdata_ary; + $show_user_activity = true; /** * Alter list of forums and topics to display as active * @@ -1250,9 +1251,11 @@ function display_user_activity(&$userdata_ary) * @var array userdata User's data * @var array active_f_row List of active forums * @var array active_t_row List of active posts + * @var bool show_user_activity Show user forum and topic activity * @since 3.1.0-RC3 + * @changed 3.2.5-RC1 Added show_user_activity into event */ - $vars = array('userdata', 'active_f_row', 'active_t_row'); + $vars = array('userdata', 'active_f_row', 'active_t_row', 'show_user_activity'); extract($phpbb_dispatcher->trigger_event('core.display_user_activity_modify_actives', compact($vars))); $userdata_ary = $userdata; unset($userdata); @@ -1289,7 +1292,7 @@ function display_user_activity(&$userdata_ary) 'ACTIVE_TOPIC_PCT' => sprintf($l_active_pct, $active_t_pct), 'U_ACTIVE_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $active_f_id), 'U_ACTIVE_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=' . $active_t_id), - 'S_SHOW_ACTIVITY' => true) + 'S_SHOW_ACTIVITY' => $show_user_activity) ); } @@ -1648,10 +1651,10 @@ function phpbb_show_profile($data, $user_notes_enabled = false, $warn_user_enabl ($data['user_type'] != USER_INACTIVE || $data['user_inactive_reason'] != INACTIVE_MANUAL) && // They must be able to read PMs - sizeof($auth->acl_get_list($user_id, 'u_readpm')) && + count($auth->acl_get_list($user_id, 'u_readpm')) && // They must not be permanently banned - !sizeof(phpbb_get_banned_user_ids($user_id, false)) && + !count(phpbb_get_banned_user_ids($user_id, false)) && // They must allow users to contact via PM (($auth->acl_gets('a_', 'm_') || $auth->acl_getf_global('m_')) || $data['user_allow_pm']) diff --git a/phpBB/includes/functions_download.php b/phpBB/includes/functions_download.php index e00be1e01a..1f409be58c 100644 --- a/phpBB/includes/functions_download.php +++ b/phpBB/includes/functions_download.php @@ -196,7 +196,7 @@ function send_file_to_browser($attachment, $upload_dir, $category) } // Now the tricky part... let's dance - header('Cache-Control: public'); + header('Cache-Control: private'); // Send out the Headers. Do not set Content-Disposition to inline please, it is a security measure for users using the Internet Explorer. header('Content-Type: ' . $attachment['mimetype']); @@ -451,7 +451,7 @@ function set_modified_headers($stamp, $browser) { send_status_line(304, 'Not Modified'); // seems that we need those too ... browsers - header('Cache-Control: public'); + header('Cache-Control: private'); header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 31536000) . ' GMT'); return true; } @@ -568,7 +568,7 @@ function phpbb_parse_range_request($request_array, $filesize) $range = explode('-', trim($range_string)); // "-" is invalid, "0-0" however is valid and means the very first byte. - if (sizeof($range) != 2 || $range[0] === '' && $range[1] === '') + if (count($range) != 2 || $range[0] === '' && $range[1] === '') { continue; } @@ -662,6 +662,8 @@ function phpbb_increment_downloads($db, $ids) */ function phpbb_download_handle_forum_auth($db, $auth, $topic_id) { + global $phpbb_container; + $sql_array = array( 'SELECT' => 't.topic_visibility, t.forum_id, f.forum_name, f.forum_password, f.parent_id', 'FROM' => array( @@ -677,7 +679,9 @@ function phpbb_download_handle_forum_auth($db, $auth, $topic_id) $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - if ($row && $row['topic_visibility'] != ITEM_APPROVED && !$auth->acl_get('m_approve', $row['forum_id'])) + $phpbb_content_visibility = $phpbb_container->get('content.visibility'); + + if ($row && !$phpbb_content_visibility->is_visible('topic', $row['forum_id'], $row)) { send_status_line(404, 'Not Found'); trigger_error('ERROR_NO_ATTACHMENT'); diff --git a/phpBB/includes/functions_jabber.php b/phpBB/includes/functions_jabber.php index cfe8c2a90e..cf0865e608 100644 --- a/phpBB/includes/functions_jabber.php +++ b/phpBB/includes/functions_jabber.php @@ -207,7 +207,7 @@ class jabber */ function login() { - if (!sizeof($this->features)) + if (!count($this->features)) { $this->add_to_log('Error: No feature information from server available.'); return false; @@ -293,7 +293,7 @@ class jabber */ function get_log() { - if ($this->enable_logging && sizeof($this->log_array)) + if ($this->enable_logging && count($this->log_array)) { return implode("<br /><br />", $this->log_array); } @@ -400,14 +400,14 @@ class jabber */ function response($xml) { - if (!is_array($xml) || !sizeof($xml)) + if (!is_array($xml) || !count($xml)) { return false; } // did we get multiple elements? do one after another // array('message' => ..., 'presence' => ...) - if (sizeof($xml) > 1) + if (count($xml) > 1) { foreach ($xml as $key => $value) { @@ -419,7 +419,7 @@ class jabber { // or even multiple elements of the same type? // array('message' => array(0 => ..., 1 => ...)) - if (sizeof(reset($xml)) > 1) + if (count(reset($xml)) > 1) { foreach (reset($xml) as $value) { @@ -858,14 +858,14 @@ class jabber array_push($children, $vals[$i]['value']); } - while (++$i < sizeof($vals)) + while (++$i < count($vals)) { switch ($vals[$i]['type']) { case 'open': $tagname = (isset($vals[$i]['tag'])) ? $vals[$i]['tag'] : ''; - $size = (isset($children[$tagname])) ? sizeof($children[$tagname]) : 0; + $size = (isset($children[$tagname])) ? count($children[$tagname]) : 0; if (isset($vals[$i]['attributes'])) { @@ -883,7 +883,7 @@ class jabber case 'complete': $tagname = $vals[$i]['tag']; - $size = (isset($children[$tagname])) ? sizeof($children[$tagname]) : 0; + $size = (isset($children[$tagname])) ? count($children[$tagname]) : 0; $children[$tagname][$size]['#'] = (isset($vals[$i]['value'])) ? $vals[$i]['value'] : array(); if (isset($vals[$i]['attributes'])) diff --git a/phpBB/includes/functions_mcp.php b/phpBB/includes/functions_mcp.php index dfe3fefbd0..75e24618de 100644 --- a/phpBB/includes/functions_mcp.php +++ b/phpBB/includes/functions_mcp.php @@ -22,12 +22,12 @@ if (!defined('IN_PHPBB')) /** * Functions used to generate additional URL paramters */ -function phpbb_module__url($mode, &$module_row) +function phpbb_module__url($mode, $module_row) { return phpbb_extra_url(); } -function phpbb_module_notes_url($mode, &$module_row) +function phpbb_module_notes_url($mode, $module_row) { if ($mode == 'front') { @@ -38,7 +38,7 @@ function phpbb_module_notes_url($mode, &$module_row) return ($user_id) ? "&u=$user_id" : ''; } -function phpbb_module_warn_url($mode, &$module_row) +function phpbb_module_warn_url($mode, $module_row) { if ($mode == 'front' || $mode == 'list') { @@ -64,27 +64,27 @@ function phpbb_module_warn_url($mode, &$module_row) } } -function phpbb_module_main_url($mode, &$module_row) +function phpbb_module_main_url($mode, $module_row) { return phpbb_extra_url(); } -function phpbb_module_logs_url($mode, &$module_row) +function phpbb_module_logs_url($mode, $module_row) { return phpbb_extra_url(); } -function phpbb_module_ban_url($mode, &$module_row) +function phpbb_module_ban_url($mode, $module_row) { return phpbb_extra_url(); } -function phpbb_module_queue_url($mode, &$module_row) +function phpbb_module_queue_url($mode, $module_row) { return phpbb_extra_url(); } -function phpbb_module_reports_url($mode, &$module_row) +function phpbb_module_reports_url($mode, $module_row) { return phpbb_extra_url(); } @@ -113,7 +113,7 @@ function phpbb_get_topic_data($topic_ids, $acl_list = false, $read_tracking = fa $topics = array(); - if (!sizeof($topic_ids)) + if (!count($topic_ids)) { return array(); } @@ -130,7 +130,7 @@ function phpbb_get_topic_data($topic_ids, $acl_list = false, $read_tracking = fa $cache_topic_ids = array(); } - if (sizeof($topic_ids)) + if (count($topic_ids)) { $sql_array = array( 'SELECT' => 't.*, f.*', @@ -197,11 +197,11 @@ function phpbb_get_topic_data($topic_ids, $acl_list = false, $read_tracking = fa */ function phpbb_get_post_data($post_ids, $acl_list = false, $read_tracking = false) { - global $db, $auth, $config, $user; + global $db, $auth, $config, $user, $phpbb_container; $rowset = array(); - if (!sizeof($post_ids)) + if (!count($post_ids)) { return array(); } @@ -246,6 +246,8 @@ function phpbb_get_post_data($post_ids, $acl_list = false, $read_tracking = fals $result = $db->sql_query($sql); unset($sql_array); + $phpbb_content_visibility = $phpbb_container->get('content.visibility'); + while ($row = $db->sql_fetchrow($result)) { if ($acl_list && !$auth->acl_gets($acl_list, $row['forum_id'])) @@ -253,7 +255,7 @@ function phpbb_get_post_data($post_ids, $acl_list = false, $read_tracking = fals continue; } - if ($row['post_visibility'] != ITEM_APPROVED && !$auth->acl_get('m_approve', $row['forum_id'])) + if (!$phpbb_content_visibility->is_visible('post', $row['forum_id'], $row)) { // Moderators without the permission to approve post should at least not see them. ;) continue; @@ -280,7 +282,7 @@ function phpbb_get_forum_data($forum_id, $acl_list = 'f_list', $read_tracking = $forum_id = array($forum_id); } - if (!sizeof($forum_id)) + if (!count($forum_id)) { return array(); } @@ -329,7 +331,7 @@ function phpbb_get_pm_data($pm_ids) $rowset = array(); - if (!sizeof($pm_ids)) + if (!count($pm_ids)) { return array(); } @@ -730,7 +732,7 @@ function phpbb_check_ids(&$ids, $table, $sql_id, $acl_list = false, $single_foru } $db->sql_freeresult($result); - if (!sizeof($ids)) + if (!count($ids)) { return false; } diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index ab7f00a65a..7f8238e1bf 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -24,8 +24,9 @@ if (!defined('IN_PHPBB')) */ class messenger { - var $msg, $extra_headers, $replyto, $from, $subject; + var $msg, $replyto, $from, $subject; var $addresses = array(); + var $extra_headers = array(); var $mail_priority = MAIL_NORMAL_PRIORITY; var $use_queue = true; @@ -36,7 +37,7 @@ class messenger /** * Constructor */ - function messenger($use_queue = true) + function __construct($use_queue = true) { global $config; @@ -84,7 +85,7 @@ class messenger return; } - $pos = isset($this->addresses['to']) ? sizeof($this->addresses['to']) : 0; + $pos = isset($this->addresses['to']) ? count($this->addresses['to']) : 0; $this->addresses['to'][$pos]['email'] = trim($address); @@ -109,7 +110,7 @@ class messenger return; } - $pos = isset($this->addresses['cc']) ? sizeof($this->addresses['cc']) : 0; + $pos = isset($this->addresses['cc']) ? count($this->addresses['cc']) : 0; $this->addresses['cc'][$pos]['email'] = trim($address); $this->addresses['cc'][$pos]['name'] = trim($realname); } @@ -124,7 +125,7 @@ class messenger return; } - $pos = isset($this->addresses['bcc']) ? sizeof($this->addresses['bcc']) : 0; + $pos = isset($this->addresses['bcc']) ? count($this->addresses['bcc']) : 0; $this->addresses['bcc'][$pos]['email'] = trim($address); $this->addresses['bcc'][$pos]['name'] = trim($realname); } @@ -140,7 +141,7 @@ class messenger return; } - $pos = isset($this->addresses['im']) ? sizeof($this->addresses['im']) : 0; + $pos = isset($this->addresses['im']) ? count($this->addresses['im']) : 0; $this->addresses['im'][$pos]['uid'] = trim($address); $this->addresses['im'][$pos]['name'] = trim($realname); } @@ -180,10 +181,9 @@ class messenger /** * Adds X-AntiAbuse headers * - * @param array $config Configuration array - * @param user $user A user object - * - * @return null + * @param \phpbb\config\config $config Config object + * @param \phpbb\user $user User object + * @return void */ function anti_abuse_headers($config, $user) { @@ -325,9 +325,26 @@ class messenger )); $subject = $this->subject; - $message = $this->msg; + $template = $this->template; + /** + * Event to modify the template before parsing + * + * @event core.modify_notification_template + * @var int method User notification method NOTIFY_EMAIL|NOTIFY_IM|NOTIFY_BOTH + * @var bool break Flag indicating if the function only formats the subject + * and the message without sending it + * @var string subject The message subject + * @var \phpbb\template\template template The (readonly) template object + * @since 3.2.4-RC1 + */ + $vars = array('method', 'break', 'subject', 'template'); + extract($phpbb_dispatcher->trigger_event('core.modify_notification_template', compact($vars))); + + // Parse message through template + $message = trim($this->template->assign_display('body')); + /** - * Event to modify notification message text before parsing + * Event to modify notification message text after parsing * * @event core.modify_notification_message * @var int method User notification method NOTIFY_EMAIL|NOTIFY_IM|NOTIFY_BOTH @@ -337,19 +354,12 @@ class messenger * @var string message The message text * @since 3.1.11-RC1 */ - $vars = array( - 'method', - 'break', - 'subject', - 'message', - ); + $vars = array('method', 'break', 'subject', 'message'); extract($phpbb_dispatcher->trigger_event('core.modify_notification_message', compact($vars))); + $this->subject = $subject; $this->msg = $message; - unset($subject, $message); - - // Parse message through template - $this->msg = trim($this->template->assign_display('body')); + unset($subject, $message, $template); // Because we use \n for newlines in the body message we need to fix line encoding errors for those admins who uploaded email template files in the wrong encoding $this->msg = str_replace("\r\n", "\n", $this->msg); @@ -368,6 +378,12 @@ class messenger $this->subject = (($this->subject != '') ? $this->subject : $user->lang['NO_EMAIL_SUBJECT']); } + if (preg_match('#^(List-Unsubscribe:(.*?))$#m', $this->msg, $match)) + { + $this->extra_headers[] = $match[1]; + $drop_header .= '[\r\n]*?' . preg_quote($match[1], '#'); + } + if ($drop_header) { $this->msg = trim(preg_replace('#' . $drop_header . '#s', '', $this->msg)); @@ -416,7 +432,7 @@ class messenger switch ($type) { case 'EMAIL': - $message = '<strong>EMAIL/' . (($config['smtp_delivery']) ? 'SMTP' : 'PHP/' . $config['email_function_name'] . '()') . '</strong>'; + $message = '<strong>EMAIL/' . (($config['smtp_delivery']) ? 'SMTP' : 'PHP/mail()') . '</strong>'; break; default: @@ -503,7 +519,7 @@ class messenger $vars = array('headers'); extract($phpbb_dispatcher->trigger_event('core.modify_email_headers', compact($vars))); - if (sizeof($this->extra_headers)) + if (count($this->extra_headers)) { $headers = array_merge($headers, $this->extra_headers); } @@ -516,7 +532,7 @@ class messenger */ function msg_email() { - global $config; + global $config, $phpbb_dispatcher; if (empty($config['email_enable'])) { @@ -544,6 +560,33 @@ class messenger $contact_name = htmlspecialchars_decode($config['board_contact_name']); $board_contact = (($contact_name !== '') ? '"' . mail_encode($contact_name) . '" ' : '') . '<' . $config['board_contact'] . '>'; + $break = false; + $addresses = $this->addresses; + $subject = $this->subject; + $msg = $this->msg; + /** + * Event to send message via external transport + * + * @event core.notification_message_email + * @var bool break Flag indicating if the function return after hook + * @var array addresses The message recipients + * @var string subject The message subject + * @var string msg The message text + * @since 3.2.4-RC1 + */ + $vars = array( + 'break', + 'addresses', + 'subject', + 'msg', + ); + extract($phpbb_dispatcher->trigger_event('core.notification_message_email', compact($vars))); + + if ($break) + { + return true; + } + if (empty($this->replyto)) { $this->replyto = $board_contact; @@ -749,7 +792,7 @@ class queue /** * constructor */ - function queue() + function __construct() { global $phpEx, $phpbb_root_path, $phpbb_filesystem, $phpbb_container; @@ -782,7 +825,7 @@ class queue */ function process() { - global $config, $phpEx, $phpbb_root_path, $user; + global $config, $phpEx, $phpbb_root_path, $user, $phpbb_dispatcher; $lock = new \phpbb\lock\flock($this->cache_file); $lock->acquire(); @@ -814,7 +857,7 @@ class queue } $package_size = $data_ary['package_size']; - $num_items = (!$package_size || sizeof($data_ary['data']) < $package_size) ? sizeof($data_ary['data']) : $package_size; + $num_items = (!$package_size || count($data_ary['data']) < $package_size) ? count($data_ary['data']) : $package_size; /* * This code is commented out because it causes problems on some web hosts. @@ -823,9 +866,9 @@ class queue * web host and the package size setting is wrong. // If the amount of emails to be sent is way more than package_size than we need to increase it to prevent backlogs... - if (sizeof($data_ary['data']) > $package_size * 2.5) + if (count($data_ary['data']) > $package_size * 2.5) { - $num_items = sizeof($data_ary['data']); + $num_items = count($data_ary['data']); } */ @@ -879,23 +922,45 @@ class queue switch ($object) { case 'email': - $err_msg = ''; - $to = (!$to) ? 'undisclosed-recipients:;' : $to; - - if ($config['smtp_delivery']) - { - $result = smtpmail($addresses, mail_encode($subject), wordwrap(utf8_wordwrap($msg), 997, "\n", true), $err_msg, $headers); - } - else + $break = false; + /** + * Event to send message via external transport + * + * @event core.notification_message_process + * @var bool break Flag indicating if the function return after hook + * @var array addresses The message recipients + * @var string subject The message subject + * @var string msg The message text + * @since 3.2.4-RC1 + */ + $vars = array( + 'break', + 'addresses', + 'subject', + 'msg', + ); + extract($phpbb_dispatcher->trigger_event('core.notification_message_process', compact($vars))); + + if (!$break) { - $result = phpbb_mail($to, $subject, $msg, $headers, PHP_EOL, $err_msg); - } + $err_msg = ''; + $to = (!$to) ? 'undisclosed-recipients:;' : $to; - if (!$result) - { - $messenger = new messenger(); - $messenger->error('EMAIL', $err_msg); - continue 2; + if ($config['smtp_delivery']) + { + $result = smtpmail($addresses, mail_encode($subject), wordwrap(utf8_wordwrap($msg), 997, "\n", true), $err_msg, $headers); + } + else + { + $result = phpbb_mail($to, $subject, $msg, $headers, PHP_EOL, $err_msg); + } + + if (!$result) + { + $messenger = new messenger(); + $messenger->error('EMAIL', $err_msg); + continue 2; + } } break; @@ -914,7 +979,7 @@ class queue } // No more data for this object? Unset it - if (!sizeof($this->queue_data[$object]['data'])) + if (!count($this->queue_data[$object]['data'])) { unset($this->queue_data[$object]); } @@ -930,7 +995,7 @@ class queue } } - if (!sizeof($this->queue_data)) + if (!count($this->queue_data)) { @unlink($this->cache_file); } @@ -965,7 +1030,7 @@ class queue */ function save() { - if (!sizeof($this->data)) + if (!count($this->data)) { return; } @@ -979,7 +1044,7 @@ class queue foreach ($this->queue_data as $object => $data_ary) { - if (isset($this->data[$object]) && sizeof($this->data[$object])) + if (isset($this->data[$object]) && count($this->data[$object])) { $this->data[$object]['data'] = array_merge($data_ary['data'], $this->data[$object]['data']); } @@ -1067,7 +1132,7 @@ function smtpmail($addresses, $subject, $message, &$err_msg, $headers = false) $mail_rcpt = $mail_to = $mail_cc = array(); // Build correct addresses for RCPT TO command and the client side display (TO, CC) - if (isset($addresses['to']) && sizeof($addresses['to'])) + if (isset($addresses['to']) && count($addresses['to'])) { foreach ($addresses['to'] as $which_ary) { @@ -1076,7 +1141,7 @@ function smtpmail($addresses, $subject, $message, &$err_msg, $headers = false) } } - if (isset($addresses['bcc']) && sizeof($addresses['bcc'])) + if (isset($addresses['bcc']) && count($addresses['bcc'])) { foreach ($addresses['bcc'] as $which_ary) { @@ -1084,7 +1149,7 @@ function smtpmail($addresses, $subject, $message, &$err_msg, $headers = false) } } - if (isset($addresses['cc']) && sizeof($addresses['cc'])) + if (isset($addresses['cc']) && count($addresses['cc'])) { foreach ($addresses['cc'] as $which_ary) { @@ -1263,7 +1328,7 @@ class smtp_class var $backtrace = false; var $backtrace_log = array(); - function smtp_class() + function __construct() { // Always create a backtrace for admins to identify SMTP problems $this->backtrace = true; @@ -1516,6 +1581,14 @@ class smtp_class */ protected function starttls() { + global $config; + + // allow SMTPS (what was used by phpBB 3.0) if hostname is prefixed with tls:// or ssl:// + if (strpos($config['smtp_host'], 'tls://') === 0 || strpos($config['smtp_host'], 'ssl://') === 0) + { + return true; + } + if (!function_exists('stream_socket_enable_crypto')) { return false; @@ -1538,7 +1611,9 @@ class smtp_class if (socket_set_blocking($this->socket, 1)) { - $result = stream_socket_enable_crypto($this->socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT); + // https://secure.php.net/manual/en/function.stream-socket-enable-crypto.php#119122 + $crypto = (phpbb_version_compare(PHP_VERSION, '5.6.7', '<')) ? STREAM_CRYPTO_METHOD_TLS_CLIENT : STREAM_CRYPTO_METHOD_SSLv23_CLIENT; + $result = stream_socket_enable_crypto($this->socket, true, $crypto); socket_set_blocking($this->socket, (int) $stream_meta['blocked']); } @@ -1802,11 +1877,11 @@ function mail_encode($str, $eol = "\r\n") $array = utf8_str_split($str); $str = ''; - while (sizeof($array)) + while (count($array)) { $text = ''; - while (sizeof($array) && intval((strlen($text . $array[0]) + 2) / 3) << 2 <= $split_length) + while (count($array) && intval((strlen($text . $array[0]) + 2) / 3) << 2 <= $split_length) { $text .= array_shift($array); } @@ -1839,7 +1914,8 @@ function phpbb_mail($to, $subject, $msg, $headers, $eol, &$err_msg) // On some PHP Versions mail() *may* fail if there are newlines within the subject. // Newlines are used as a delimiter for lines in mail_encode() according to RFC 2045 section 6.8. // Because PHP can't decide what is wanted we revert back to the non-RFC-compliant way of separating by one space (Use '' as parameter to mail_encode() results in SPACE used) - $result = $config['email_function_name']($to, mail_encode($subject, ''), wordwrap(utf8_wordwrap($msg), 997, "\n", true), $headers); + $additional_parameters = $config['email_force_sender'] ? '-f' . $config['board_email'] : ''; + $result = mail($to, mail_encode($subject, ''), wordwrap(utf8_wordwrap($msg), 997, "\n", true), $headers, $additional_parameters); $collector->uninstall(); $err_msg = $collector->format_errors(); diff --git a/phpBB/includes/functions_module.php b/phpBB/includes/functions_module.php index 7a1991d69a..88dafc4300 100644 --- a/phpBB/includes/functions_module.php +++ b/phpBB/includes/functions_module.php @@ -40,7 +40,7 @@ class p_master * Constuctor * Set module include path */ - function p_master($include_path = false) + function __construct($include_path = false) { global $phpbb_root_path; @@ -243,7 +243,7 @@ class p_master } } - $depth = sizeof($this->module_cache['parents'][$row['module_id']]); + $depth = count($this->module_cache['parents'][$row['module_id']]); // We need to prefix the functions to not create a naming conflict @@ -279,7 +279,7 @@ class p_master 'parent' => (int) $row['parent_id'], 'cat' => ($row['right_id'] > $row['left_id'] + 1) ? true : false, - 'is_duplicate' => ($row['module_basename'] && sizeof($names[$row['module_basename'] . '_' . $row['module_mode']]) > 1) ? true : false, + 'is_duplicate' => ($row['module_basename'] && count($names[$row['module_basename'] . '_' . $row['module_mode']]) > 1) ? true : false, 'name' => (string) $row['module_basename'], 'mode' => (string) $row['module_mode'], @@ -431,7 +431,7 @@ class p_master extract($phpbb_dispatcher->trigger_event('core.module_auth', compact($vars))); $tokens = $match[0]; - for ($i = 0, $size = sizeof($tokens); $i < $size; $i++) + for ($i = 0, $size = count($tokens); $i < $size; $i++) { $token = &$tokens[$i]; diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index d9f395efb3..2cce77e092 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -114,7 +114,7 @@ function generate_smilies($mode, $forum_id) } $db->sql_freeresult($result); - if (sizeof($smilies)) + if (count($smilies)) { $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_path_helper->get_web_root_path(); @@ -200,13 +200,15 @@ function update_post_information($type, $ids, $return_update_sql = false) $topic_condition = ''; } - if (sizeof($ids) == 1) + if (count($ids) == 1) { - $sql = 'SELECT MAX(p.post_id) as last_post_id + $sql = 'SELECT p.post_id as last_post_id FROM ' . POSTS_TABLE . " p $topic_join WHERE " . $db->sql_in_set('p.' . $type . '_id', $ids) . " $topic_condition - AND p.post_visibility = " . ITEM_APPROVED; + AND p.post_visibility = " . ITEM_APPROVED . " + ORDER BY p.post_id DESC"; + $result = $db->sql_query_limit($sql, 1); } else { @@ -216,13 +218,13 @@ function update_post_information($type, $ids, $return_update_sql = false) $topic_condition AND p.post_visibility = " . ITEM_APPROVED . " GROUP BY p.{$type}_id"; + $result = $db->sql_query($sql); } - $result = $db->sql_query($sql); $last_post_ids = array(); while ($row = $db->sql_fetchrow($result)) { - if (sizeof($ids) == 1) + if (count($ids) == 1) { $row[$type . '_id'] = $ids[0]; } @@ -256,7 +258,7 @@ function update_post_information($type, $ids, $return_update_sql = false) } } - if (sizeof($last_post_ids)) + if (count($last_post_ids)) { $sql = 'SELECT p.' . $type . '_id, p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u @@ -277,7 +279,7 @@ function update_post_information($type, $ids, $return_update_sql = false) } unset($empty_forums, $ids, $last_post_ids); - if ($return_update_sql || !sizeof($update_sql)) + if ($return_update_sql || !count($update_sql)) { return $update_sql; } @@ -310,7 +312,7 @@ function posting_gen_topic_icons($mode, $icon_id) $template->assign_var('S_NO_ICON_CHECKED', ' checked="checked"'); } - if (sizeof($icons)) + if (count($icons)) { $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_root_path; @@ -519,7 +521,7 @@ function get_supported_image_types($type = false) */ function create_thumbnail($source, $destination, $mimetype) { - global $config, $phpbb_filesystem; + global $config, $phpbb_filesystem, $phpbb_dispatcher; $min_filesize = (int) $config['img_min_thumb_filesize']; $img_filesize = (file_exists($source)) ? @filesize($source) : false; @@ -551,25 +553,31 @@ function create_thumbnail($source, $destination, $mimetype) return false; } - $used_imagick = false; - - // Only use ImageMagick if defined and the passthru function not disabled - if ($config['img_imagick'] && function_exists('passthru')) - { - if (substr($config['img_imagick'], -1) !== '/') - { - $config['img_imagick'] .= '/'; - } - - @passthru(escapeshellcmd($config['img_imagick']) . 'convert' . ((defined('PHP_OS') && preg_match('#^win#i', PHP_OS)) ? '.exe' : '') . ' -quality 85 -geometry ' . $new_width . 'x' . $new_height . ' "' . str_replace('\\', '/', $source) . '" "' . str_replace('\\', '/', $destination) . '"'); + $thumbnail_created = false; - if (file_exists($destination)) - { - $used_imagick = true; - } - } + /** + * Create thumbnail event to replace GD thumbnail creation with for example ImageMagick + * + * @event core.thumbnail_create_before + * @var string source Image source path + * @var string destination Thumbnail destination path + * @var string mimetype Image mime type + * @var float new_width Calculated thumbnail width + * @var float new_height Calculated thumbnail height + * @var bool thumbnail_created Set to true to skip default GD thumbnail creation + * @since 3.2.4 + */ + $vars = array( + 'source', + 'destination', + 'mimetype', + 'new_width', + 'new_height', + 'thumbnail_created', + ); + extract($phpbb_dispatcher->trigger_event('core.thumbnail_create_before', compact($vars))); - if (!$used_imagick) + if (!$thumbnail_created) { $type = get_supported_image_types($type); @@ -690,7 +698,7 @@ function posting_gen_inline_attachments(&$attachment_data) { global $template; - if (sizeof($attachment_data)) + if (count($attachment_data)) { $s_inline_attachment_options = ''; @@ -717,20 +725,21 @@ function posting_gen_attachment_entry($attachment_data, &$filename_data, $show_a // Some default template variables $template->assign_vars(array( 'S_SHOW_ATTACH_BOX' => $show_attach_box, - 'S_HAS_ATTACHMENTS' => sizeof($attachment_data), + 'S_HAS_ATTACHMENTS' => count($attachment_data), 'FILESIZE' => $config['max_filesize'], 'FILE_COMMENT' => (isset($filename_data['filecomment'])) ? $filename_data['filecomment'] : '', )); - if (sizeof($attachment_data)) + if (count($attachment_data)) { // We display the posted attachments within the desired order. ($config['display_order']) ? krsort($attachment_data) : ksort($attachment_data); + $attachrow_template_vars = []; + foreach ($attachment_data as $count => $attach_row) { $hidden = ''; - $attachrow_template_vars = array(); $attach_row['real_filename'] = utf8_basename($attach_row['real_filename']); foreach ($attach_row as $key => $value) @@ -768,7 +777,7 @@ function posting_gen_attachment_entry($attachment_data, &$filename_data, $show_a $template->assign_block_vars_array('attach_row', $attachrow_template_vars); } - return sizeof($attachment_data); + return count($attachment_data); } // @@ -816,13 +825,13 @@ function load_drafts($topic_id = 0, $forum_id = 0, $id = 0, $pm_action = '', $ms } $db->sql_freeresult($result); - if (!sizeof($draft_rows)) + if (!count($draft_rows)) { return; } $topic_rows = array(); - if (sizeof($topic_ids)) + if (count($topic_ids)) { $sql = 'SELECT topic_id, forum_id, topic_title, topic_poster FROM ' . TOPICS_TABLE . ' @@ -935,7 +944,7 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id $db->sql_freeresult($result); - if (!sizeof($post_list)) + if (!count($post_list)) { return false; } @@ -969,6 +978,30 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id AND u.user_id = p.poster_id', ); + /** + * Event to modify the SQL query for topic reviews + * + * @event core.topic_review_modify_sql_ary + * @var int topic_id The topic ID that is being reviewed + * @var int forum_id The topic's forum ID + * @var string mode The topic review mode + * @var int cur_post_id Post offset ID + * @var bool show_quote_button Flag indicating if the quote button should be displayed + * @var array post_list Array with the post IDs + * @var array sql_ary Array with the SQL query + * @since 3.2.8-RC1 + */ + $vars = array( + 'topic_id', + 'forum_id', + 'mode', + 'cur_post_id', + 'show_quote_button', + 'post_list', + 'sql_ary', + ); + extract($phpbb_dispatcher->trigger_event('core.topic_review_modify_sql_ary', compact($vars))); + $sql = $db->sql_build_query('SELECT', $sql_ary); $result = $db->sql_query($sql); @@ -1030,7 +1063,7 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id ); extract($phpbb_dispatcher->trigger_event('core.topic_review_modify_post_list', compact($vars))); - for ($i = 0, $end = sizeof($post_list); $i < $end; ++$i) + for ($i = 0, $end = count($post_list); $i < $end; ++$i) { // A non-existing rowset only happens if there was no user present for the entered poster_id // This could be a broken posts table. @@ -1257,7 +1290,7 @@ function delete_post($forum_id, $topic_id, $post_id, &$data, $is_soft = false, $ foreach ($shadow_forum_ids as $updated_forum => $topic_count) { - // counting is fun! we only have to do sizeof($forum_ids) number of queries, + // counting is fun! we only have to do count($forum_ids) number of queries, // even if the topic is moved back to where its shadow lives (we count how many times it is in a forum) $sql = 'UPDATE ' . FORUMS_TABLE . ' SET forum_topics_approved = forum_topics_approved - ' . $topic_count . ' @@ -1275,9 +1308,10 @@ function delete_post($forum_id, $topic_id, $post_id, &$data, $is_soft = false, $ delete_topics('topic_id', array($topic_id), false); $phpbb_content_visibility->remove_topic_from_statistic($data, $sql_data); + $config->increment('num_posts', -1, false); $update_sql = update_post_information('forum', $forum_id, true); - if (sizeof($update_sql)) + if (count($update_sql)) { $sql_data[FORUMS_TABLE] .= ($sql_data[FORUMS_TABLE]) ? ', ' : ''; $sql_data[FORUMS_TABLE] .= implode(', ', $update_sql[$forum_id]); @@ -1326,7 +1360,7 @@ function delete_post($forum_id, $topic_id, $post_id, &$data, $is_soft = false, $ { // Update last post information when hard deleting. Soft delete already did that by itself. $update_sql = update_post_information('forum', $forum_id, true); - if (sizeof($update_sql)) + if (count($update_sql)) { $sql_data[FORUMS_TABLE] = (($sql_data[FORUMS_TABLE]) ? $sql_data[FORUMS_TABLE] . ', ' : '') . implode(', ', $update_sql[$forum_id]); } @@ -1968,7 +2002,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll_ary, &$data $sql_insert_ary = array(); - for ($i = 0, $size = sizeof($poll_ary['poll_options']); $i < $size; $i++) + for ($i = 0, $size = count($poll_ary['poll_options']); $i < $size; $i++) { if (strlen(trim($poll_ary['poll_options'][$i]))) { @@ -1976,7 +2010,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll_ary, &$data { // If we add options we need to put them to the end to be able to preserve votes... $sql_insert_ary[] = array( - 'poll_option_id' => (int) sizeof($cur_poll_options) + 1 + sizeof($sql_insert_ary), + 'poll_option_id' => (int) count($cur_poll_options) + 1 + count($sql_insert_ary), 'topic_id' => (int) $data_ary['topic_id'], 'poll_option_text' => (string) $poll_ary['poll_options'][$i] ); @@ -1994,16 +2028,16 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll_ary, &$data $db->sql_multi_insert(POLL_OPTIONS_TABLE, $sql_insert_ary); - if (sizeof($poll_ary['poll_options']) < sizeof($cur_poll_options)) + if (count($poll_ary['poll_options']) < count($cur_poll_options)) { $sql = 'DELETE FROM ' . POLL_OPTIONS_TABLE . ' - WHERE poll_option_id > ' . sizeof($poll_ary['poll_options']) . ' + WHERE poll_option_id > ' . count($poll_ary['poll_options']) . ' AND topic_id = ' . $data_ary['topic_id']; $db->sql_query($sql); } // If edited, we would need to reset votes (since options can be re-ordered above, you can't be sure if the change is for changing the text or adding an option - if ($mode == 'edit' && sizeof($poll_ary['poll_options']) != sizeof($cur_poll_options)) + if ($mode == 'edit' && count($poll_ary['poll_options']) != count($cur_poll_options)) { $db->sql_query('DELETE FROM ' . POLL_VOTES_TABLE . ' WHERE topic_id = ' . $data_ary['topic_id']); $db->sql_query('UPDATE ' . POLL_OPTIONS_TABLE . ' SET poll_option_total = 0 WHERE topic_id = ' . $data_ary['topic_id']); @@ -2021,7 +2055,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll_ary, &$data $orphan_rows[(int) $attach_row['attach_id']] = array(); } - if (sizeof($orphan_rows)) + if (count($orphan_rows)) { $sql = 'SELECT attach_id, filesize, physical_filename FROM ' . ATTACHMENTS_TABLE . ' @@ -2045,6 +2079,11 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll_ary, &$data continue; } + if (preg_match('/[\x{10000}-\x{10FFFF}]/u', $attach_row['attach_comment'])) + { + trigger_error('ATTACH_COMMENT_NO_EMOJIS'); + } + if (!$attach_row['is_orphan']) { // update entry in db if attachment already stored in db and filespace @@ -2281,6 +2320,19 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll_ary, &$data 'post_subject' => $subject, )); + /** + * This event allows you to modify the notification data upon submission + * + * @event core.modify_submit_notification_data + * @var array notification_data The notification data to be inserted in to the database + * @var array data_ary The data array with a lot of the post submission data + * @var string mode The posting mode + * @var int poster_id The poster id + * @since 3.2.4-RC1 + */ + $vars = array('notification_data', 'data_ary', 'mode', 'poster_id'); + extract($phpbb_dispatcher->trigger_event('core.modify_submit_notification_data', compact($vars))); + /* @var $phpbb_notifications \phpbb\notification\manager */ $phpbb_notifications = $phpbb_container->get('notification_manager'); @@ -2308,8 +2360,14 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll_ary, &$data case 'edit_first_post': case 'edit': case 'edit_last_post': + if ($user->data['user_id'] == $poster_id) + { + $phpbb_notifications->update_notifications(array( + 'notification.type.quote', + ), $notification_data); + } + $phpbb_notifications->update_notifications(array( - 'notification.type.quote', 'notification.type.bookmark', 'notification.type.topic', 'notification.type.post', diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php index ff962075a8..f07512d623 100644 --- a/phpBB/includes/functions_privmsgs.php +++ b/phpBB/includes/functions_privmsgs.php @@ -466,7 +466,7 @@ function place_pm_into_folder(&$global_privmsgs_rules, $release = false) $user_rules = $db->sql_fetchrowset($result); $db->sql_freeresult($result); - if (sizeof($user_rules)) + if (count($user_rules)) { $sql = 'SELECT zebra_id, friend, foe FROM ' . ZEBRA_TABLE . " @@ -490,7 +490,7 @@ function place_pm_into_folder(&$global_privmsgs_rules, $release = false) 'bcc' => explode(':', $row['bcc_address']), 'friend' => (isset($zebra[$row['author_id']])) ? $zebra[$row['author_id']]['friend'] : 0, 'foe' => (isset($zebra[$row['author_id']])) ? $zebra[$row['author_id']]['foe'] : 0, - 'user_in_group' => array($user->data['group_id']), + 'user_in_group' => $user->data['group_id'], 'author_in_group' => array()) ); @@ -499,7 +499,7 @@ function place_pm_into_folder(&$global_privmsgs_rules, $release = false) $db->sql_freeresult($result); // Retrieve user memberships - if (sizeof($user_ids)) + if (count($user_ids)) { $sql = 'SELECT * FROM ' . USER_GROUP_TABLE . ' @@ -600,14 +600,14 @@ function place_pm_into_folder(&$global_privmsgs_rules, $release = false) // only gone through if new messages arrive. // Delete messages - if (sizeof($delete_ids)) + if (count($delete_ids)) { - $num_removed += sizeof($delete_ids); + $num_removed += count($delete_ids); delete_pm($user_id, $delete_ids, PRIVMSGS_NO_BOX); } // Set messages to Unread - if (sizeof($unread_ids)) + if (count($unread_ids)) { $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' SET pm_unread = 0 @@ -618,7 +618,7 @@ function place_pm_into_folder(&$global_privmsgs_rules, $release = false) } // mark messages as important - if (sizeof($important_ids)) + if (count($important_ids)) { $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' SET pm_marked = 1 - pm_marked @@ -631,7 +631,7 @@ function place_pm_into_folder(&$global_privmsgs_rules, $release = false) // Move into folder $folder = array(); - if (sizeof($move_into_folder)) + if (count($move_into_folder)) { // Determine Full Folder Action - we need the move to folder id later eventually $full_folder_action = ($user->data['user_full_folder'] == FULL_FOLDER_NONE) ? ($config['full_folder_action'] - (FULL_FOLDER_NONE*(-1))) : $user->data['user_full_folder']; @@ -676,12 +676,12 @@ function place_pm_into_folder(&$global_privmsgs_rules, $release = false) // Check Message Limit - we calculate with the complete array, most of the time it is one message // But we are making sure that the other way around works too (more messages in queue than allowed to be stored) - if ($user->data['message_limit'] && $folder[$folder_id] && ($folder[$folder_id] + sizeof($msg_ary)) > $user->data['message_limit']) + if ($user->data['message_limit'] && $folder[$folder_id] && ($folder[$folder_id] + count($msg_ary)) > $user->data['message_limit']) { $full_folder_action = ($user->data['user_full_folder'] == FULL_FOLDER_NONE) ? ($config['full_folder_action'] - (FULL_FOLDER_NONE*(-1))) : $user->data['user_full_folder']; // If destination folder itself is full... - if ($full_folder_action >= 0 && ($folder[$full_folder_action] + sizeof($msg_ary)) > $user->data['message_limit']) + if ($full_folder_action >= 0 && ($folder[$full_folder_action] + count($msg_ary)) > $user->data['message_limit']) { $full_folder_action = $config['full_folder_action'] - (FULL_FOLDER_NONE*(-1)); } @@ -699,7 +699,7 @@ function place_pm_into_folder(&$global_privmsgs_rules, $release = false) WHERE user_id = $user_id AND folder_id = $dest_folder ORDER BY msg_id ASC"; - $result = $db->sql_query_limit($sql, (($folder[$dest_folder] + sizeof($msg_ary)) - $user->data['message_limit'])); + $result = $db->sql_query_limit($sql, (($folder[$dest_folder] + count($msg_ary)) - $user->data['message_limit'])); $delete_ids = array(); while ($row = $db->sql_fetchrow($result)) @@ -708,7 +708,7 @@ function place_pm_into_folder(&$global_privmsgs_rules, $release = false) } $db->sql_freeresult($result); - $num_removed += sizeof($delete_ids); + $num_removed += count($delete_ids); delete_pm($user_id, $delete_ids, $dest_folder); } } @@ -744,7 +744,7 @@ function place_pm_into_folder(&$global_privmsgs_rules, $release = false) } } - if (sizeof($action_ary)) + if (count($action_ary)) { // Move from OUTBOX to SENTBOX // We are not checking any full folder status here... SENTBOX is a special treatment (old messages get deleted) @@ -785,7 +785,7 @@ function move_pm($user_id, $message_limit, $move_msg_ids, $dest_folder, $cur_fol $move_msg_ids = array($move_msg_ids); } - if (sizeof($move_msg_ids) && !in_array($dest_folder, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX)) && + if (count($move_msg_ids) && !in_array($dest_folder, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX)) && !in_array($cur_folder_id, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX)) && $cur_folder_id != $dest_folder) { // We have to check the destination folder ;) @@ -805,7 +805,7 @@ function move_pm($user_id, $message_limit, $move_msg_ids, $dest_folder, $cur_fol trigger_error('NOT_AUTHORISED'); } - if ($message_limit && $row['pm_count'] + sizeof($move_msg_ids) > $message_limit) + if ($message_limit && $row['pm_count'] + count($move_msg_ids) > $message_limit) { $message = sprintf($user->lang['NOT_ENOUGH_SPACE_FOLDER'], $row['folder_name']) . '<br /><br />'; $message .= sprintf($user->lang['CLICK_RETURN_FOLDER'], '<a href="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&folder=' . $row['folder_id']) . '">', '</a>', $row['folder_name']); @@ -822,7 +822,7 @@ function move_pm($user_id, $message_limit, $move_msg_ids, $dest_folder, $cur_fol $num_messages = (int) $db->sql_fetchfield('num_messages'); $db->sql_freeresult($result); - if ($message_limit && $num_messages + sizeof($move_msg_ids) > $message_limit) + if ($message_limit && $num_messages + count($move_msg_ids) > $message_limit) { $message = sprintf($user->lang['NOT_ENOUGH_SPACE_FOLDER'], $user->lang['PM_INBOX']) . '<br /><br />'; $message .= sprintf($user->lang['CLICK_RETURN_FOLDER'], '<a href="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&folder=inbox') . '">', '</a>', $user->lang['PM_INBOX']); @@ -949,7 +949,7 @@ function handle_mark_actions($user_id, $mark_action) $msg_ids = $request->variable('marked_msg_id', array(0)); $cur_folder_id = $request->variable('cur_folder_id', PRIVMSGS_NO_BOX); - if (!sizeof($msg_ids)) + if (!count($msg_ids)) { return false; } @@ -981,7 +981,7 @@ function handle_mark_actions($user_id, $mark_action) { delete_pm($user_id, $msg_ids, $cur_folder_id); - $success_msg = (sizeof($msg_ids) == 1) ? 'MESSAGE_DELETED' : 'MESSAGES_DELETED'; + $success_msg = (count($msg_ids) == 1) ? 'MESSAGE_DELETED' : 'MESSAGES_DELETED'; $redirect = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&folder=' . $cur_folder_id); meta_refresh(3, $redirect); @@ -1032,7 +1032,7 @@ function delete_pm($user_id, $msg_ids, $folder_id) $msg_ids = array($msg_ids); } - if (!sizeof($msg_ids)) + if (!count($msg_ids)) { return false; } @@ -1069,7 +1069,7 @@ function delete_pm($user_id, $msg_ids, $folder_id) $db->sql_freeresult($result); unset($msg_ids); - if (!sizeof($delete_rows)) + if (!count($delete_rows)) { return false; } @@ -1156,7 +1156,7 @@ function delete_pm($user_id, $msg_ids, $folder_id) $delete_ids = array_keys($delete_rows); - if (sizeof($delete_ids)) + if (count($delete_ids)) { // Check if there are any attachments we need to remove /** @var \phpbb\attachment\manager $attachment_manager */ @@ -1289,7 +1289,7 @@ function phpbb_delete_users_pms($user_ids) $num_pms = (int) $row['num_undelivered_privmsgs']; $undelivered_user[$num_pms][] = (int) $row['user_id']; - if (sizeof($undelivered_user[$num_pms]) > 50) + if (count($undelivered_user[$num_pms]) > 50) { // If there are too many users affected the query might get // too long, so we update the value for the first bunch here. @@ -1416,7 +1416,7 @@ function rebuild_header($check_ary) $_types = array('u', 'g'); foreach ($_types as $type) { - if (sizeof(${$type})) + if (count(${$type})) { foreach (${$type} as $id) { @@ -1461,7 +1461,7 @@ function write_pm_addresses($check_ary, $author_id, $plaintext = false) } $address = array(); - if (sizeof($u)) + if (count($u)) { $sql = 'SELECT user_id, username, user_colour FROM ' . USERS_TABLE . ' @@ -1485,7 +1485,7 @@ function write_pm_addresses($check_ary, $author_id, $plaintext = false) $db->sql_freeresult($result); } - if (sizeof($g)) + if (count($g)) { if ($plaintext) { @@ -1532,7 +1532,7 @@ function write_pm_addresses($check_ary, $author_id, $plaintext = false) } } - if (sizeof($address) && !$plaintext) + if (count($address) && !$plaintext) { $template->assign_var('S_' . strtoupper($check_type) . '_RECIPIENT', true); @@ -1651,7 +1651,7 @@ function submit_pm($mode, $subject, &$data_ary, $put_in_outbox = true) $_types = array('u', 'g'); foreach ($_types as $ug_type) { - if (isset($data_ary['address_list'][$ug_type]) && sizeof($data_ary['address_list'][$ug_type])) + if (isset($data_ary['address_list'][$ug_type]) && count($data_ary['address_list'][$ug_type])) { foreach ($data_ary['address_list'][$ug_type] as $id => $field) { @@ -1673,7 +1673,7 @@ function submit_pm($mode, $subject, &$data_ary, $put_in_outbox = true) } } - if (isset($data_ary['address_list']['g']) && sizeof($data_ary['address_list']['g'])) + if (isset($data_ary['address_list']['g']) && count($data_ary['address_list']['g'])) { // We need to check the PM status of group members (do they want to receive PM's?) // Only check if not a moderator or admin, since they are allowed to override this user setting @@ -1696,7 +1696,7 @@ function submit_pm($mode, $subject, &$data_ary, $put_in_outbox = true) $db->sql_freeresult($result); } - if (!sizeof($recipients)) + if (!count($recipients)) { trigger_error('NO_RECIPIENT'); } @@ -1764,7 +1764,7 @@ function submit_pm($mode, $subject, &$data_ary, $put_in_outbox = true) break; } - if (sizeof($sql_data)) + if (count($sql_data)) { if ($mode == 'post' || $mode == 'reply' || $mode == 'quote' || $mode == 'quotepost' || $mode == 'forward') { @@ -1844,7 +1844,7 @@ function submit_pm($mode, $subject, &$data_ary, $put_in_outbox = true) $orphan_rows[(int) $attach_row['attach_id']] = array(); } - if (sizeof($orphan_rows)) + if (count($orphan_rows)) { $sql = 'SELECT attach_id, filesize, physical_filename FROM ' . ATTACHMENTS_TABLE . ' @@ -1966,7 +1966,7 @@ function submit_pm($mode, $subject, &$data_ary, $put_in_outbox = true) */ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode = false) { - global $db, $user, $template, $phpbb_root_path, $phpEx, $auth; + global $db, $user, $template, $phpbb_root_path, $phpEx, $auth, $phpbb_dispatcher; // Select all receipts and the author from the pm we currently view, to only display their pm-history $sql = 'SELECT author_id, user_id @@ -1985,9 +1985,7 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode $recipients = array_unique($recipients); // Get History Messages (could be newer) - $sql = 'SELECT t.*, p.*, u.* - FROM ' . PRIVMSGS_TABLE . ' p, ' . PRIVMSGS_TO_TABLE . ' t, ' . USERS_TABLE . ' u - WHERE t.msg_id = p.msg_id + $sql_where = 't.msg_id = p.msg_id AND p.author_id = u.user_id AND t.folder_id NOT IN (' . PRIVMSGS_NO_BOX . ', ' . PRIVMSGS_HOLD_BOX . ') AND ' . $db->sql_in_set('t.author_id', $recipients, false, true) . " @@ -1998,13 +1996,37 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode if (!$message_row['root_level']) { - $sql .= " AND (p.root_level = $msg_id OR (p.root_level = 0 AND p.msg_id = $msg_id))"; + $sql_where .= " AND (p.root_level = $msg_id OR (p.root_level = 0 AND p.msg_id = $msg_id))"; } else { - $sql .= " AND (p.root_level = " . $message_row['root_level'] . ' OR p.msg_id = ' . $message_row['root_level'] . ')'; + $sql_where .= " AND (p.root_level = " . $message_row['root_level'] . ' OR p.msg_id = ' . $message_row['root_level'] . ')'; } - $sql .= ' ORDER BY p.message_time DESC'; + + $sql_ary = array( + 'SELECT' => 't.*, p.*, u.*', + 'FROM' => array( + PRIVMSGS_TABLE => 'p', + PRIVMSGS_TO_TABLE => 't', + USERS_TABLE => 'u' + ), + 'LEFT_JOIN' => array(), + 'WHERE' => $sql_where, + 'ORDER_BY' => 'p.message_time DESC', + ); + + /** + * Event to modify the SQL query before the message history in private message is queried + * + * @event core.message_history_modify_sql_ary + * @var array sql_ary The SQL array to get the data of the message history in private message + * @since 3.2.8-RC1 + */ + $vars = array('sql_ary'); + extract($phpbb_dispatcher->trigger_event('core.message_history_modify_sql_ary', compact($vars))); + + $sql = $db->sql_build_query('SELECT', $sql_ary); + unset($sql_ary); $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); @@ -2038,7 +2060,7 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode while ($row = $db->sql_fetchrow($result)); $db->sql_freeresult($result); - if (sizeof($rowset) == 1 && !$in_post_mode) + if (count($rowset) == 1 && !$in_post_mode) { return false; } @@ -2051,7 +2073,7 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode // Re-order rowset to be able to get the next/prev message rows... $rowset = array_values($rowset); - for ($i = 0, $size = sizeof($rowset); $i < $size; $i++) + for ($i = 0, $size = count($rowset); $i < $size; $i++) { $row = &$rowset[$i]; $id = (int) $row['msg_id']; @@ -2087,7 +2109,7 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode $previous_history_pm = $prev_id; } - $template->assign_block_vars('history_row', array( + $template_vars = array( 'MESSAGE_AUTHOR_QUOTE' => (($decoded_message) ? addslashes(get_username_string('username', $author_id, $row['username'], $row['user_colour'], $row['username'])) : ''), 'MESSAGE_AUTHOR_FULL' => get_username_string('full', $author_id, $row['username'], $row['user_colour'], $row['username']), 'MESSAGE_AUTHOR_COLOUR' => get_username_string('colour', $author_id, $row['username'], $row['user_colour'], $row['username']), @@ -2109,8 +2131,25 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode 'USER_ID' => $row['user_id'], 'U_VIEW_MESSAGE' => "$url&f=$folder_id&p=" . $row['msg_id'], 'U_QUOTE' => (!$in_post_mode && $auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&mode=compose&action=quote&f=" . $folder_id . "&p=" . $row['msg_id'] : '', - 'U_POST_REPLY_PM' => ($author_id != $user->data['user_id'] && $author_id != ANONYMOUS && $auth->acl_get('u_sendpm')) ? "$url&mode=compose&action=reply&f=$folder_id&p=" . $row['msg_id'] : '') + 'U_POST_REPLY_PM' => ($author_id != $user->data['user_id'] && $author_id != ANONYMOUS && $auth->acl_get('u_sendpm')) ? "$url&mode=compose&action=reply&f=$folder_id&p=" . $row['msg_id'] : '' + ); + + /** + * Modify the template vars for displaying the message history in private message + * + * @event core.message_history_modify_template_vars + * @var array template_vars Array containing the query + * @var array row Array containing the action user row + * @since 3.2.8-RC1 + */ + $vars = array( + 'template_vars', + 'row', ); + extract($phpbb_dispatcher->trigger_event('core.message_history_modify_template_vars', compact($vars))); + + $template->assign_block_vars('history_row', $template_vars); + unset($rowset[$i]); $prev_id = $id; } @@ -2197,7 +2236,7 @@ function get_recipient_strings($pm_by_id) foreach ($_types as $ug_type) { - if (isset($address[$message_id][$ug_type]) && sizeof($address[$message_id][$ug_type])) + if (isset($address[$message_id][$ug_type]) && count($address[$message_id][$ug_type])) { foreach ($address[$message_id][$ug_type] as $ug_id => $in_to) { diff --git a/phpBB/includes/functions_transfer.php b/phpBB/includes/functions_transfer.php index 0fc8a7eea5..7427b89917 100644 --- a/phpBB/includes/functions_transfer.php +++ b/phpBB/includes/functions_transfer.php @@ -38,7 +38,7 @@ class transfer /** * Constructor - init some basic values */ - function transfer() + function __construct() { global $phpbb_root_path; @@ -112,7 +112,7 @@ class transfer $dir = explode('/', $dir); $dirs = ''; - for ($i = 0, $total = sizeof($dir); $i < $total; $i++) + for ($i = 0, $total = count($dir); $i < $total; $i++) { $result = true; @@ -264,7 +264,7 @@ class ftp extends transfer /** * Standard parameters for FTP session */ - function ftp($host, $username, $password, $root_path, $port = 21, $timeout = 10) + function __construct($host, $username, $password, $root_path, $port = 21, $timeout = 10) { $this->host = $host; $this->port = $port; @@ -512,7 +512,7 @@ class ftp_fsock extends transfer /** * Standard parameters for FTP session */ - function ftp_fsock($host, $username, $password, $root_path, $port = 21, $timeout = 10) + function __construct($host, $username, $password, $root_path, $port = 21, $timeout = 10) { $this->host = $host; $this->port = $port; @@ -529,7 +529,7 @@ class ftp_fsock extends transfer } // Init some needed values - $this->transfer(); + parent::__construct(); return; } diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index c746bd0e4c..3bf4aa16b7 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -26,8 +26,10 @@ if (!defined('IN_PHPBB')) * @param array &$user_id_ary The user ids to check or empty if usernames used * @param array &$username_ary The usernames to check or empty if user ids used * @param mixed $user_type Array of user types to check, false if not restricting by user type +* @param boolean $update_references If false, the supplied array is unset and appears unchanged from where it was called +* @return boolean|string Returns false on success, error string on failure */ -function user_get_id_name(&$user_id_ary, &$username_ary, $user_type = false) +function user_get_id_name(&$user_id_ary, &$username_ary, $user_type = false, $update_references = false) { global $db; @@ -50,7 +52,13 @@ function user_get_id_name(&$user_id_ary, &$username_ary, $user_type = false) } $sql_in = ($which_ary == 'user_id_ary') ? array_map('intval', ${$which_ary}) : array_map('utf8_clean_string', ${$which_ary}); - unset(${$which_ary}); + + // By unsetting the array here, the values passed in at the point user_get_id_name() was called will be retained. + // Otherwise, if we don't unset (as the array was passed by reference) the original array will be updated below. + if ($update_references === false) + { + unset(${$which_ary}); + } $user_id_ary = $username_ary = array(); @@ -170,7 +178,7 @@ function user_update_name($old_name, $new_name) * Adds an user * * @param mixed $user_row An array containing the following keys (and the appropriate values): username, group_id (the group to place the user in), user_email and the user_type(usually 0). Additional entries not overridden by defaults will be forwarded. -* @param string $cp_data custom profile fields, see custom_profile::build_insert_sql_array +* @param array $cp_data custom profile fields, see custom_profile::build_insert_sql_array * @param array $notifications_data The notifications settings for the new user * @return the new user's ID. */ @@ -260,7 +268,7 @@ function user_add($user_row, $cp_data = false, $notifications_data = null) $remaining_vars = array_diff(array_keys($user_row), array_keys($sql_ary)); // Now fill our sql array with the remaining vars - if (sizeof($remaining_vars)) + if (count($remaining_vars)) { foreach ($remaining_vars as $key) { @@ -272,8 +280,8 @@ function user_add($user_row, $cp_data = false, $notifications_data = null) * Use this event to modify the values to be inserted when a user is added * * @event core.user_add_modify_data - * @var array user_row Array of user details submited to user_add - * @var array cp_data Array of Custom profile fields submited to user_add + * @var array user_row Array of user details submitted to user_add + * @var array cp_data Array of Custom profile fields submitted to user_add * @var array sql_ary Array of data to be inserted when a user is added * @var array notifications_data Array of notification data to be inserted when a user is added * @since 3.1.0-a1 @@ -289,7 +297,7 @@ function user_add($user_row, $cp_data = false, $notifications_data = null) $user_id = $db->sql_nextid(); // Insert Custom Profile Fields - if ($cp_data !== false && sizeof($cp_data)) + if ($cp_data !== false && count($cp_data)) { $cp_data['user_id'] = (int) $user_id; @@ -376,6 +384,19 @@ function user_add($user_row, $cp_data = false, $notifications_data = null) ); } + /** + * Modify the notifications data to be inserted in the database when a user is added + * + * @event core.user_add_modify_notifications_data + * @var array user_row Array of user details submitted to user_add + * @var array cp_data Array of Custom profile fields submitted to user_add + * @var array sql_ary Array of data to be inserted when a user is added + * @var array notifications_data Array of notification data to be inserted when a user is added + * @since 3.2.2-RC1 + */ + $vars = array('user_row', 'cp_data', 'sql_ary', 'notifications_data'); + extract($phpbb_dispatcher->trigger_event('core.user_add_modify_notifications_data', compact($vars))); + // Subscribe user to notifications if necessary if (!empty($notifications_data)) { @@ -388,12 +409,12 @@ function user_add($user_row, $cp_data = false, $notifications_data = null) } /** - * Event that returns user id, user detals and user CPF of newly registared user + * Event that returns user id, user details and user CPF of newly registered user * * @event core.user_add_after - * @var int user_id User id of newly registared user - * @var array user_row Array of user details submited to user_add - * @var array cp_data Array of Custom profile fields submited to user_add + * @var int user_id User id of newly registered user + * @var array user_row Array of user details submitted to user_add + * @var array cp_data Array of Custom profile fields submitted to user_add * @since 3.1.0-b5 */ $vars = array('user_id', 'user_row', 'cp_data'); @@ -448,9 +469,11 @@ function user_delete($mode, $user_ids, $retain_username = true) * @var array user_ids IDs of the deleted user * @var mixed retain_username True if username should be retained * or false if not + * @var array user_rows Array containing data of the deleted users * @since 3.1.0-a1 + * @changed 3.2.4-RC1 Added user_rows */ - $vars = array('mode', 'user_ids', 'retain_username'); + $vars = array('mode', 'user_ids', 'retain_username', 'user_rows'); extract($phpbb_dispatcher->trigger_event('core.delete_user_before', compact($vars))); // Before we begin, we will remove the reports the user issued. @@ -468,7 +491,7 @@ function user_delete($mode, $user_ids, $retain_username = true) } $db->sql_freeresult($result); - if (sizeof($report_posts)) + if (count($report_posts)) { $report_posts = array_unique($report_posts); $report_topics = array_unique($report_topics); @@ -488,7 +511,7 @@ function user_delete($mode, $user_ids, $retain_username = true) } $db->sql_freeresult($result); - if (sizeof($keep_report_topics)) + if (count($keep_report_topics)) { $report_topics = array_diff($report_topics, $keep_report_topics); } @@ -500,7 +523,7 @@ function user_delete($mode, $user_ids, $retain_username = true) WHERE ' . $db->sql_in_set('post_id', $report_posts); $db->sql_query($sql); - if (sizeof($report_topics)) + if (count($report_topics)) { $sql = 'UPDATE ' . TOPICS_TABLE . ' SET topic_reported = 0 @@ -651,8 +674,30 @@ function user_delete($mode, $user_ids, $retain_username = true) delete_posts('poster_id', $user_ids); } - $table_ary = array(USERS_TABLE, USER_GROUP_TABLE, TOPICS_WATCH_TABLE, FORUMS_WATCH_TABLE, ACL_USERS_TABLE, TOPICS_TRACK_TABLE, TOPICS_POSTED_TABLE, FORUMS_TRACK_TABLE, PROFILE_FIELDS_DATA_TABLE, MODERATOR_CACHE_TABLE, DRAFTS_TABLE, BOOKMARKS_TABLE, SESSIONS_KEYS_TABLE, PRIVMSGS_FOLDER_TABLE, PRIVMSGS_RULES_TABLE); - + $table_ary = [ + USERS_TABLE, + USER_GROUP_TABLE, + TOPICS_WATCH_TABLE, + FORUMS_WATCH_TABLE, + ACL_USERS_TABLE, + TOPICS_TRACK_TABLE, + TOPICS_POSTED_TABLE, + FORUMS_TRACK_TABLE, + PROFILE_FIELDS_DATA_TABLE, + MODERATOR_CACHE_TABLE, + DRAFTS_TABLE, + BOOKMARKS_TABLE, + SESSIONS_KEYS_TABLE, + PRIVMSGS_FOLDER_TABLE, + PRIVMSGS_RULES_TABLE, + $phpbb_container->getParameter('tables.auth_provider_oauth_token_storage'), + $phpbb_container->getParameter('tables.auth_provider_oauth_states'), + $phpbb_container->getParameter('tables.auth_provider_oauth_account_assoc'), + $phpbb_container->getParameter('tables.user_notifications') + ]; + + // Ignore errors on deleting from non-existent tables, e.g. when migrating + $db->sql_return_on_error(true); // Delete the miscellaneous (non-post) data for the user foreach ($table_ary as $table) { @@ -660,6 +705,7 @@ function user_delete($mode, $user_ids, $retain_username = true) WHERE " . $user_id_sql; $db->sql_query($sql); } + $db->sql_return_on_error(); $cache->destroy('sql', MODERATOR_CACHE_TABLE); @@ -767,7 +813,7 @@ function user_active_flip($mode, $user_id_ary, $reason = INACTIVE_MANUAL) $user_id_ary = array($user_id_ary); } - if (!sizeof($user_id_ary)) + if (!count($user_id_ary)) { return; } @@ -825,7 +871,7 @@ function user_active_flip($mode, $user_id_ary, $reason = INACTIVE_MANUAL) $vars = array('mode', 'reason', 'activated', 'deactivated', 'user_id_ary', 'sql_statements'); extract($phpbb_dispatcher->trigger_event('core.user_active_flip_before', compact($vars))); - if (sizeof($sql_statements)) + if (count($sql_statements)) { foreach ($sql_statements as $user_id => $sql_ary) { @@ -903,7 +949,7 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas else { $ban_other = explode('-', $ban_len_other); - if (sizeof($ban_other) == 3 && ((int) $ban_other[0] < 9999) && + if (count($ban_other) == 3 && ((int) $ban_other[0] < 9999) && (strlen($ban_other[0]) == 4) && (strlen($ban_other[1]) == 2) && (strlen($ban_other[2]) == 2)) { $ban_end = max($current_time, $user->create_datetime() @@ -971,7 +1017,7 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas } // Make sure we have been given someone to ban - if (!sizeof($sql_usernames)) + if (!count($sql_usernames)) { trigger_error('NO_USER_SPECIFIED', E_USER_WARNING); } @@ -982,7 +1028,7 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas // Do not allow banning yourself, the guest account, or founders. $non_bannable = array($user->data['user_id'], ANONYMOUS); - if (sizeof($founder)) + if (count($founder)) { $sql .= ' AND ' . $db->sql_in_set('user_id', array_merge(array_keys($founder), $non_bannable), true); } @@ -1122,14 +1168,14 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas continue; } - if (!sizeof($founder) || !in_array($ban_item, $founder)) + if (!count($founder) || !in_array($ban_item, $founder)) { $banlist_ary[] = $ban_item; } } } - if (sizeof($ban_list) == 0) + if (count($ban_list) == 0) { trigger_error('NO_EMAILS_DEFINED', E_USER_WARNING); } @@ -1176,7 +1222,7 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas $banlist_ary_tmp = array_intersect($banlist_ary, $banlist_ary_tmp); - if (sizeof($banlist_ary_tmp)) + if (count($banlist_ary_tmp)) { // One or more entities are already banned/excluded, delete the existing bans, so they can be re-inserted with the given new length $sql = 'DELETE FROM ' . BANLIST_TABLE . ' @@ -1190,7 +1236,7 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas $db->sql_freeresult($result); // We have some entities to ban - if (sizeof($banlist_ary)) + if (count($banlist_ary)) { $sql_ary = array(); @@ -1318,7 +1364,7 @@ function user_unban($mode, $ban) $unban_sql = array_map('intval', $ban); - if (sizeof($unban_sql)) + if (count($unban_sql)) { // Grab details of bans for logging information later switch ($mode) @@ -1414,21 +1460,14 @@ function user_ipwhois($ip) return ''; } - if (preg_match(get_preg_expression('ipv4'), $ip)) - { - // IPv4 address - $whois_host = 'whois.arin.net.'; - } - else if (preg_match(get_preg_expression('ipv6'), $ip)) - { - // IPv6 address - $whois_host = 'whois.sixxs.net.'; - } - else + if (!preg_match(get_preg_expression('ipv4'), $ip) && !preg_match(get_preg_expression('ipv6'), $ip)) { return ''; } + // IPv4 & IPv6 addresses + $whois_host = 'whois.arin.net.'; + $ipwhois = ''; if (($fsk = @fsockopen($whois_host, 43))) @@ -1582,7 +1621,7 @@ function validate_num($num, $optional = false, $min = 0, $max = 1E99) function validate_date($date_string, $optional = false) { $date = explode('-', $date_string); - if ((empty($date) || sizeof($date) != 3) && $optional) + if ((empty($date) || count($date) != 3) && $optional) { return false; } @@ -1604,7 +1643,7 @@ function validate_date($date_string, $optional = false) } } - if (sizeof($date) != 3 || !checkdate($date[1], $date[0], $date[2])) + if (count($date) != 3 || !checkdate($date[1], $date[0], $date[2])) { return 'INVALID'; } @@ -1679,17 +1718,21 @@ function phpbb_validate_timezone($timezone) return (in_array($timezone, phpbb_get_timezone_identifiers($timezone))) ? false : 'TIMEZONE_INVALID'; } -/** -* Check to see if the username has been taken, or if it is disallowed. -* Also checks if it includes the " character, which we don't allow in usernames. -* Used for registering, changing names, and posting anonymously with a username -* -* @param string $username The username to check -* @param string $allowed_username An allowed username, default being $user->data['username'] -* -* @return mixed Either false if validation succeeded or a string which will be used as the error message (with the variable name appended) -*/ -function validate_username($username, $allowed_username = false) +/*** + * Validate Username + * + * Check to see if the username has been taken, or if it is disallowed. + * Also checks if it includes the " character or the 4-bytes Unicode ones + * (aka emojis) which we don't allow in usernames. + * Used for registering, changing names, and posting anonymously with a username + * + * @param string $username The username to check + * @param string $allowed_username An allowed username, default being $user->data['username'] + * + * @return mixed Either false if validation succeeded or a string which will be + * used as the error message (with the variable name appended) + */ +function validate_username($username, $allowed_username = false, $allow_all_names = false) { global $config, $db, $user, $cache; @@ -1701,6 +1744,14 @@ function validate_username($username, $allowed_username = false) return false; } + // The very first check is for + // out-of-bounds characters that are currently + // not supported by utf8_bin in MySQL + if (preg_match('/[\x{10000}-\x{10FFFF}]/u', $username)) + { + return 'INVALID_EMOJIS'; + } + // ... fast checks first. if (strpos($username, '"') !== false || strpos($username, '"') !== false || empty($clean_username)) { @@ -1764,13 +1815,16 @@ function validate_username($username, $allowed_username = false) return 'USERNAME_TAKEN'; } - $bad_usernames = $cache->obtain_disallowed_usernames(); - - foreach ($bad_usernames as $bad_username) + if (!$allow_all_names) { - if (preg_match('#^' . $bad_username . '$#', $clean_username)) + $bad_usernames = $cache->obtain_disallowed_usernames(); + + foreach ($bad_usernames as $bad_username) { - return 'USERNAME_DISALLOWED'; + if (preg_match('#^' . $bad_username . '$#', $clean_username)) + { + return 'USERNAME_DISALLOWED'; + } } } @@ -1891,9 +1945,9 @@ function validate_user_email($email, $allowed_email = false) return $validate_email; } - if (($ban_reason = $user->check_ban(false, false, $email, true)) !== false) + if (($ban = $user->check_ban(false, false, $email, true)) !== false) { - return ($ban_reason === true) ? 'EMAIL_BANNED' : $ban_reason; + return ($ban === true) ? 'EMAIL_BANNED' : (!empty($ban['ban_give_reason']) ? $ban['ban_give_reason'] : $ban); } if (!$config['allow_emailreuse']) @@ -1944,7 +1998,7 @@ function validate_jabber($jid) $arr = explode('.', $realm); - if (sizeof($arr) == 0) + if (count($arr) == 0) { return 'WRONG_DATA'; } @@ -2268,7 +2322,7 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow $group_teampage = !empty($group_attributes['group_teampage']); unset($group_attributes['group_teampage']); - if (!sizeof($error)) + if (!count($error)) { $current_legend = \phpbb\groupposition\legend::GROUP_DISABLED; $current_teampage = \phpbb\groupposition\teampage::GROUP_DISABLED; @@ -2341,7 +2395,7 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow generate_text_for_storage($sql_ary['group_desc'], $sql_ary['group_desc_uid'], $sql_ary['group_desc_bitfield'], $sql_ary['group_desc_options'], $allow_desc_bbcode, $allow_desc_urls, $allow_desc_smilies); } - if (sizeof($group_attributes)) + if (count($group_attributes)) { // Merge them with $sql_ary to properly update the group $sql_ary = array_merge($sql_ary, $group_attributes); @@ -2467,7 +2521,7 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow // Set user attributes $sql_ary = array(); - if (sizeof($group_attributes)) + if (count($group_attributes)) { // Go through the user attributes array, check if a group attribute matches it and then set it. ;) foreach ($user_attribute_ary as $attribute) @@ -2487,7 +2541,7 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow } } - if (sizeof($sql_ary) && sizeof($user_ary)) + if (count($sql_ary) && count($user_ary)) { group_set_user_default($group_id, $user_ary, $sql_ary); } @@ -2498,7 +2552,7 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow group_update_listings($group_id); } - return (sizeof($error)) ? $error : false; + return (count($error)) ? $error : false; } @@ -2663,11 +2717,18 @@ function group_user_add($group_id, $user_id_ary = false, $username_ary = false, // We need both username and user_id info $result = user_get_id_name($user_id_ary, $username_ary); - if (!sizeof($user_id_ary) || $result !== false) + if (empty($user_id_ary) || $result !== false) { return 'NO_USER'; } + // Because the item that gets passed into the previous function is unset, the reference is lost and our original + // array is retained - so we know there's a problem if there's a different number of ids to usernames now. + if (count($user_id_ary) != count($username_ary)) + { + return 'GROUP_USERS_INVALID'; + } + // Remove users who are already members of this group $sql = 'SELECT user_id, group_leader FROM ' . USER_GROUP_TABLE . ' @@ -2691,7 +2752,7 @@ function group_user_add($group_id, $user_id_ary = false, $username_ary = false, $add_id_ary = array_diff($user_id_ary, $add_id_ary); // If we have no users - if (!sizeof($add_id_ary) && !sizeof($update_id_ary)) + if (!count($add_id_ary) && !count($update_id_ary)) { return 'GROUP_USERS_EXIST'; } @@ -2699,7 +2760,7 @@ function group_user_add($group_id, $user_id_ary = false, $username_ary = false, $db->sql_transaction('begin'); // Insert the new users - if (sizeof($add_id_ary)) + if (count($add_id_ary)) { $sql_ary = array(); @@ -2716,7 +2777,7 @@ function group_user_add($group_id, $user_id_ary = false, $username_ary = false, $db->sql_multi_insert(USER_GROUP_TABLE, $sql_ary); } - if (sizeof($update_id_ary)) + if (count($update_id_ary)) { $sql = 'UPDATE ' . USER_GROUP_TABLE . ' SET group_leader = 1 @@ -2808,7 +2869,7 @@ function group_user_del($group_id, $user_id_ary = false, $username_ary = false, // We need both username and user_id info $result = user_get_id_name($user_id_ary, $username_ary); - if (!sizeof($user_id_ary) || $result !== false) + if (empty($user_id_ary) || $result !== false) { return 'NO_USER'; } @@ -2884,7 +2945,7 @@ function group_user_del($group_id, $user_id_ary = false, $username_ary = false, foreach ($special_group_data as $gid => $default_data_ary) { - if (isset($sql_where_ary[$gid]) && sizeof($sql_where_ary[$gid])) + if (isset($sql_where_ary[$gid]) && count($sql_where_ary[$gid])) { remove_default_rank($group_id, $sql_where_ary[$gid]); remove_default_avatar($group_id, $sql_where_ary[$gid]); @@ -3043,7 +3104,7 @@ function group_user_attributes($action, $group_id, $user_id_ary = false, $userna // We need both username and user_id info $result = user_get_id_name($user_id_ary, $username_ary); - if (!sizeof($user_id_ary) || $result !== false) + if (empty($user_id_ary) || $result !== false) { return 'NO_USERS'; } @@ -3098,7 +3159,7 @@ function group_user_attributes($action, $group_id, $user_id_ary = false, $userna } $db->sql_freeresult($result); - if (!sizeof($user_id_ary)) + if (!count($user_id_ary)) { return false; } @@ -3139,7 +3200,7 @@ function group_user_attributes($action, $group_id, $user_id_ary = false, $userna $db->sql_freeresult($result); $result = user_get_id_name($user_id_ary, $username_ary); - if (!sizeof($user_id_ary) || $result !== false) + if (!count($user_id_ary) || $result !== false) { return 'NO_USERS'; } @@ -3502,7 +3563,7 @@ function group_update_listings($group_id) $hold_ary = $auth->acl_group_raw_data($group_id, array('a_', 'm_')); - if (!sizeof($hold_ary)) + if (empty($hold_ary)) { return; } @@ -3589,11 +3650,6 @@ function remove_newly_registered($user_id, $user_data = false) } } - if (empty($user_data['user_new'])) - { - return false; - } - $sql = 'SELECT group_id FROM ' . GROUPS_TABLE . " WHERE group_name = 'NEWLY_REGISTERED' diff --git a/phpBB/includes/hooks/index.php b/phpBB/includes/hooks/index.php index 805e0eea1a..821242cbf4 100644 --- a/phpBB/includes/hooks/index.php +++ b/phpBB/includes/hooks/index.php @@ -44,7 +44,7 @@ class phpbb_hook * * @param array $valid_hooks array containing the hookable functions/methods */ - function phpbb_hook($valid_hooks) + function __construct($valid_hooks) { foreach ($valid_hooks as $_null => $method) { diff --git a/phpBB/includes/mcp/mcp_ban.php b/phpBB/includes/mcp/mcp_ban.php index 2f3405f915..6f748f5433 100644 --- a/phpBB/includes/mcp/mcp_ban.php +++ b/phpBB/includes/mcp/mcp_ban.php @@ -34,7 +34,10 @@ class mcp_ban } // Include the admin banning interface... - include($phpbb_root_path . 'includes/acp/acp_ban.' . $phpEx); + if (!class_exists('acp_ban')) + { + include($phpbb_root_path . 'includes/acp/acp_ban.' . $phpEx); + } $bansubmit = $request->is_set_post('bansubmit'); $unbansubmit = $request->is_set_post('unbansubmit'); @@ -266,9 +269,9 @@ class mcp_ban } else if ($post_id) { - $post_info = phpbb_get_post_data($post_id, 'm_ban'); + $post_info = phpbb_get_post_data(array($post_id), 'm_ban'); - if (sizeof($post_info) && !empty($post_info[$post_id])) + if (count($post_info) && !empty($post_info[$post_id])) { switch ($mode) { diff --git a/phpBB/includes/mcp/mcp_forum.php b/phpBB/includes/mcp/mcp_forum.php index 3e214797c8..19f71e092a 100644 --- a/phpBB/includes/mcp/mcp_forum.php +++ b/phpBB/includes/mcp/mcp_forum.php @@ -96,14 +96,14 @@ function mcp_forum_view($id, $mode, $action, $forum_info) $pagination = $phpbb_container->get('pagination'); $selected_ids = ''; - if (sizeof($post_id_list) && $action != 'merge_topics') + if (count($post_id_list) && $action != 'merge_topics') { foreach ($post_id_list as $num => $post_id) { $selected_ids .= '&post_id_list[' . $num . ']=' . $post_id; } } - else if (sizeof($topic_id_list) && $action == 'merge_topics') + else if (count($topic_id_list) && $action == 'merge_topics') { foreach ($topic_id_list as $num => $topic_id) { @@ -221,13 +221,13 @@ function mcp_forum_view($id, $mode, $action, $forum_info) $db->sql_freeresult($result); // If there is more than one page, but we have no topic list, then the start parameter is... erm... out of sync - if (!sizeof($topic_list) && $forum_topics && $start > 0) + if (!count($topic_list) && $forum_topics && $start > 0) { redirect($url . "&i=$id&action=$action&mode=$mode"); } // Get topic tracking info - if (sizeof($topic_list)) + if (count($topic_list)) { if ($config['load_db_lastread']) { @@ -358,7 +358,7 @@ function mcp_resync_topics($topic_ids) { global $db, $user, $phpbb_log, $request; - if (!sizeof($topic_ids)) + if (!count($topic_ids)) { trigger_error('NO_TOPIC_SELECTED'); } @@ -389,7 +389,7 @@ function mcp_resync_topics($topic_ids) } $db->sql_freeresult($result); - $msg = (sizeof($topic_ids) == 1) ? $user->lang['TOPIC_RESYNC_SUCCESS'] : $user->lang['TOPICS_RESYNC_SUCCESS']; + $msg = (count($topic_ids) == 1) ? $user->lang['TOPIC_RESYNC_SUCCESS'] : $user->lang['TOPICS_RESYNC_SUCCESS']; $redirect = $request->variable('redirect', $user->data['session_page']); @@ -406,7 +406,7 @@ function merge_topics($forum_id, $topic_ids, $to_topic_id) { global $db, $template, $user, $phpEx, $phpbb_root_path, $phpbb_log, $request, $phpbb_dispatcher; - if (!sizeof($topic_ids)) + if (!count($topic_ids)) { $template->assign_var('MESSAGE', $user->lang['NO_TOPIC_SELECTED']); return; @@ -421,7 +421,7 @@ function merge_topics($forum_id, $topic_ids, $to_topic_id) $all_topic_data = phpbb_get_topic_data($sync_topics, 'm_merge'); - if (!sizeof($all_topic_data) || empty($all_topic_data[$to_topic_id])) + if (!count($all_topic_data) || empty($all_topic_data[$to_topic_id])) { $template->assign_var('MESSAGE', $user->lang['NO_FINAL_TOPIC_SELECTED']); return; @@ -440,7 +440,7 @@ function merge_topics($forum_id, $topic_ids, $to_topic_id) $post_id_list = $request->variable('post_id_list', array(0)); $start = $request->variable('start', 0); - if (!sizeof($post_id_list) && sizeof($topic_ids)) + if (!count($post_id_list) && count($topic_ids)) { $sql = 'SELECT post_id FROM ' . POSTS_TABLE . ' @@ -455,7 +455,7 @@ function merge_topics($forum_id, $topic_ids, $to_topic_id) $db->sql_freeresult($result); } - if (!sizeof($post_id_list)) + if (!count($post_id_list)) { $template->assign_var('MESSAGE', $user->lang['NO_POST_SELECTED']); return; diff --git a/phpBB/includes/mcp/mcp_front.php b/phpBB/includes/mcp/mcp_front.php index aeb716c1f9..918a98734b 100644 --- a/phpBB/includes/mcp/mcp_front.php +++ b/phpBB/includes/mcp/mcp_front.php @@ -290,7 +290,10 @@ function mcp_front_view($id, $mode, $action) if ($total) { - include($phpbb_root_path . 'includes/functions_privmsgs.' . $phpEx); + if (!function_exists('get_recipient_strings')) + { + include($phpbb_root_path . 'includes/functions_privmsgs.' . $phpEx); + } $sql_ary = array( 'SELECT' => 'r.report_id, r.report_time, p.msg_id, p.message_subject, p.message_time, p.to_address, p.bcc_address, p.message_attachment, u.username, u.username_clean, u.user_colour, u.user_id, u2.username as author_name, u2.username_clean as author_name_clean, u2.user_colour as author_colour, u2.user_id as author_id', diff --git a/phpBB/includes/mcp/mcp_logs.php b/phpBB/includes/mcp/mcp_logs.php index c34c915a40..79f9d35ebe 100644 --- a/phpBB/includes/mcp/mcp_logs.php +++ b/phpBB/includes/mcp/mcp_logs.php @@ -28,9 +28,9 @@ class mcp_logs var $u_action; var $p_master; - function mcp_logs(&$p_master) + function __construct($p_master) { - $this->p_master = &$p_master; + $this->p_master = $p_master; } function main($id, $mode) @@ -115,7 +115,7 @@ class mcp_logs { if (confirm_box(true)) { - if ($deletemark && sizeof($marked)) + if ($deletemark && count($marked)) { $conditions = array( 'forum_id' => array('IN' => $forum_list), @@ -221,7 +221,7 @@ class mcp_logs 'IP' => $row['ip'], 'DATE' => $user->format_date($row['time']), 'ACTION' => $row['action'], - 'DATA' => (sizeof($data)) ? implode(' | ', $data) : '', + 'DATA' => (count($data)) ? implode(' | ', $data) : '', 'ID' => $row['id'], ) ); diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php index 3d56bba21c..744eaebd7d 100644 --- a/phpBB/includes/mcp/mcp_main.php +++ b/phpBB/includes/mcp/mcp_main.php @@ -28,9 +28,9 @@ class mcp_main var $p_master; var $u_action; - function mcp_main(&$p_master) + function __construct($p_master) { - $this->p_master = &$p_master; + $this->p_master = $p_master; } function main($id, $mode) @@ -41,13 +41,29 @@ class mcp_main $quickmod = ($mode == 'quickmod') ? true : false; + /** + * Event to perform additional actions before an MCP action is executed. + * + * @event core.mcp_main_before + * @var string action The action that is about to be performed + * @var string mode The mode in which the MCP is accessed, e.g. front, forum_view, topic_view, post_details, quickmod + * @var boolean quickmod Whether or not the action is performed via QuickMod + * @since 3.2.8-RC1 + */ + $vars = [ + 'action', + 'mode', + 'quickmod', + ]; + extract($phpbb_dispatcher->trigger_event('core.mcp_main_before', compact($vars))); + switch ($action) { case 'lock': case 'unlock': $topic_ids = (!$quickmod) ? $request->variable('topic_id_list', array(0)) : array($request->variable('t', 0)); - if (!sizeof($topic_ids)) + if (!count($topic_ids)) { trigger_error('NO_TOPIC_SELECTED'); } @@ -60,7 +76,7 @@ class mcp_main $post_ids = (!$quickmod) ? $request->variable('post_id_list', array(0)) : array($request->variable('p', 0)); - if (!sizeof($post_ids)) + if (!count($post_ids)) { trigger_error('NO_POST_SELECTED'); } @@ -75,7 +91,7 @@ class mcp_main $topic_ids = (!$quickmod) ? $request->variable('topic_id_list', array(0)) : array($request->variable('t', 0)); - if (!sizeof($topic_ids)) + if (!count($topic_ids)) { trigger_error('NO_TOPIC_SELECTED'); } @@ -88,7 +104,7 @@ class mcp_main $topic_ids = (!$quickmod) ? $request->variable('topic_id_list', array(0)) : array($request->variable('t', 0)); - if (!sizeof($topic_ids)) + if (!count($topic_ids)) { trigger_error('NO_TOPIC_SELECTED'); } @@ -101,7 +117,7 @@ class mcp_main $topic_ids = (!$quickmod) ? $request->variable('topic_id_list', array(0)) : array($request->variable('t', 0)); - if (!sizeof($topic_ids)) + if (!count($topic_ids)) { trigger_error('NO_TOPIC_SELECTED'); } @@ -118,7 +134,7 @@ class mcp_main $topic_ids = (!$quickmod) ? $request->variable('topic_id_list', array(0)) : array($request->variable('t', 0)); $soft_delete = (($request->is_set_post('confirm') && !$request->is_set_post('delete_permanent')) || !$auth->acl_get('m_delete', $forum_id)) ? true : false; - if (!sizeof($topic_ids)) + if (!count($topic_ids)) { trigger_error('NO_TOPIC_SELECTED'); } @@ -135,7 +151,7 @@ class mcp_main $post_ids = (!$quickmod) ? $request->variable('post_id_list', array(0)) : array($request->variable('p', 0)); $soft_delete = (($request->is_set_post('confirm') && !$request->is_set_post('delete_permanent')) || !$auth->acl_get('m_delete', $forum_id)) ? true : false; - if (!sizeof($post_ids)) + if (!count($post_ids)) { trigger_error('NO_POST_SELECTED'); } @@ -148,7 +164,7 @@ class mcp_main $topic_ids = (!$quickmod) ? $request->variable('topic_id_list', array(0)) : array($request->variable('t', 0)); - if (!sizeof($topic_ids)) + if (!count($topic_ids)) { trigger_error('NO_TOPIC_SELECTED'); } @@ -174,7 +190,10 @@ class mcp_main switch ($mode) { case 'front': - include($phpbb_root_path . 'includes/mcp/mcp_front.' . $phpEx); + if (!function_exists('mcp_front_view')) + { + include($phpbb_root_path . 'includes/mcp/mcp_front.' . $phpEx); + } $user->add_lang('acp/common'); @@ -185,7 +204,10 @@ class mcp_main break; case 'forum_view': - include($phpbb_root_path . 'includes/mcp/mcp_forum.' . $phpEx); + if (!function_exists('mcp_forum_view')) + { + include($phpbb_root_path . 'includes/mcp/mcp_forum.' . $phpEx); + } $user->add_lang('viewforum'); @@ -193,7 +215,7 @@ class mcp_main $forum_info = phpbb_get_forum_data($forum_id, 'm_', true); - if (!sizeof($forum_info)) + if (!count($forum_info)) { $this->main('main', 'front'); return; @@ -208,7 +230,10 @@ class mcp_main break; case 'topic_view': - include($phpbb_root_path . 'includes/mcp/mcp_topic.' . $phpEx); + if (!function_exists('mcp_topic_view')) + { + include($phpbb_root_path . 'includes/mcp/mcp_topic.' . $phpEx); + } mcp_topic_view($id, $mode, $action); @@ -217,7 +242,10 @@ class mcp_main break; case 'post_details': - include($phpbb_root_path . 'includes/mcp/mcp_post.' . $phpEx); + if (!function_exists('mcp_post_details')) + { + include($phpbb_root_path . 'includes/mcp/mcp_post.' . $phpEx); + } mcp_post_details($id, $mode, $action); @@ -342,7 +370,7 @@ function lock_unlock($action, $ids) ); extract($phpbb_dispatcher->trigger_event('core.mcp_lock_unlock_after', compact($vars))); - $success_msg = $l_prefix . ((sizeof($ids) == 1) ? '' : 'S') . '_' . (($action == 'lock' || $action == 'lock_post') ? 'LOCKED' : 'UNLOCKED') . '_SUCCESS'; + $success_msg = $l_prefix . ((count($ids) == 1) ? '' : 'S') . '_' . (($action == 'lock' || $action == 'lock_post') ? 'LOCKED' : 'UNLOCKED') . '_SUCCESS'; meta_refresh(2, $redirect); $message = $user->lang[$success_msg]; @@ -355,7 +383,7 @@ function lock_unlock($action, $ids) } else { - confirm_box(false, strtoupper($action) . '_' . $l_prefix . ((sizeof($ids) == 1) ? '' : 'S'), $s_hidden_fields); + confirm_box(false, strtoupper($action) . '_' . $l_prefix . ((count($ids) == 1) ? '' : 'S'), $s_hidden_fields); } redirect($redirect); @@ -366,32 +394,32 @@ function lock_unlock($action, $ids) */ function change_topic_type($action, $topic_ids) { - global $user, $db, $request, $phpbb_log; + global $user, $db, $request, $phpbb_log, $phpbb_dispatcher; switch ($action) { case 'make_announce': $new_topic_type = POST_ANNOUNCE; $check_acl = 'f_announce'; - $l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_ANNOUNCEMENT' : 'MCP_MAKE_ANNOUNCEMENTS'; + $l_new_type = (count($topic_ids) == 1) ? 'MCP_MAKE_ANNOUNCEMENT' : 'MCP_MAKE_ANNOUNCEMENTS'; break; case 'make_global': $new_topic_type = POST_GLOBAL; $check_acl = 'f_announce_global'; - $l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_GLOBAL' : 'MCP_MAKE_GLOBALS'; + $l_new_type = (count($topic_ids) == 1) ? 'MCP_MAKE_GLOBAL' : 'MCP_MAKE_GLOBALS'; break; case 'make_sticky': $new_topic_type = POST_STICKY; $check_acl = 'f_sticky'; - $l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_STICKY' : 'MCP_MAKE_STICKIES'; + $l_new_type = (count($topic_ids) == 1) ? 'MCP_MAKE_STICKY' : 'MCP_MAKE_STICKIES'; break; default: $new_topic_type = POST_NORMAL; $check_acl = false; - $l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_NORMAL' : 'MCP_MAKE_NORMALS'; + $l_new_type = (count($topic_ids) == 1) ? 'MCP_MAKE_NORMAL' : 'MCP_MAKE_NORMALS'; break; } @@ -414,27 +442,43 @@ function change_topic_type($action, $topic_ids) if (confirm_box(true)) { + + /** + * Perform additional actions before changing topic(s) type + * + * @event core.mcp_change_topic_type_before + * @var int new_topic_type The candidated topic type. + * @var int forum_id The forum ID for the topic ID(s). + * @var array topic_ids Array containing the topic ID(s) that will be changed + * @since 3.2.6-RC1 + */ + $vars = array( + 'new_topic_type', + 'forum_id', + 'topic_ids', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_change_topic_type_before', compact($vars))); + + $db->sql_transaction('begin'); + $sql = 'UPDATE ' . TOPICS_TABLE . " SET topic_type = $new_topic_type WHERE " . $db->sql_in_set('topic_id', $topic_ids); $db->sql_query($sql); - if (($new_topic_type == POST_GLOBAL) && sizeof($topic_ids)) + if (($new_topic_type == POST_GLOBAL) && count($topic_ids)) { // Delete topic shadows for global announcements $sql = 'DELETE FROM ' . TOPICS_TABLE . ' WHERE ' . $db->sql_in_set('topic_moved_id', $topic_ids); $db->sql_query($sql); - - $sql = 'UPDATE ' . TOPICS_TABLE . " - SET topic_type = $new_topic_type - WHERE " . $db->sql_in_set('topic_id', $topic_ids); - $db->sql_query($sql); } - $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_TYPE_CHANGED' : 'TOPICS_TYPE_CHANGED'; + $db->sql_transaction('commit'); + + $success_msg = (count($topic_ids) == 1) ? 'TOPIC_TYPE_CHANGED' : 'TOPICS_TYPE_CHANGED'; - if (sizeof($topic_ids)) + if (count($topic_ids)) { $data = phpbb_get_topic_data($topic_ids); @@ -448,6 +492,22 @@ function change_topic_type($action, $topic_ids) } } + /** + * Perform additional actions after changing topic types + * + * @event core.mcp_change_topic_type_after + * @var int new_topic_type The newly changed topic type. + * @var int forum_id The forum ID where the newly changed topic type belongs to. + * @var array topic_ids Array containing the topic IDs that have been changed + * @since 3.2.6-RC1 + */ + $vars = array( + 'new_topic_type', + 'forum_id', + 'topic_ids', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_change_topic_type_after', compact($vars))); + meta_refresh(2, $redirect); $message = $user->lang[$success_msg]; @@ -496,7 +556,7 @@ function mcp_move_topic($topic_ids) { $forum_data = phpbb_get_forum_data($to_forum_id, 'f_post'); - if (!sizeof($forum_data)) + if (!count($forum_data)) { $additional_msg = $user->lang['FORUM_NOT_EXIST']; } @@ -691,7 +751,7 @@ function mcp_move_topic($topic_ids) $sync_sql[$forum_id][] = 'forum_topics_softdeleted = forum_topics_softdeleted - ' . (int) $topics_moved_softdeleted; } - $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_MOVED_SUCCESS' : 'TOPICS_MOVED_SUCCESS'; + $success_msg = (count($topic_ids) == 1) ? 'TOPIC_MOVED_SUCCESS' : 'TOPICS_MOVED_SUCCESS'; foreach ($sync_sql as $forum_id_key => $array) { @@ -714,7 +774,7 @@ function mcp_move_topic($topic_ids) 'ADDITIONAL_MSG' => $additional_msg) ); - confirm_box(false, 'MOVE_TOPIC' . ((sizeof($topic_ids) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_move.html'); + confirm_box(false, 'MOVE_TOPIC' . ((count($topic_ids) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_move.html'); } $redirect = $request->variable('redirect', "index.$phpEx"); @@ -762,7 +822,7 @@ function mcp_restore_topic($topic_ids) if (confirm_box(true)) { - $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_RESTORED_SUCCESS' : 'TOPICS_RESTORED_SUCCESS'; + $success_msg = (count($topic_ids) == 1) ? 'TOPIC_RESTORED_SUCCESS' : 'TOPICS_RESTORED_SUCCESS'; $data = phpbb_get_topic_data($topic_ids); @@ -784,7 +844,7 @@ function mcp_restore_topic($topic_ids) } else { - confirm_box(false, (sizeof($topic_ids) == 1) ? 'RESTORE_TOPIC' : 'RESTORE_TOPICS', $s_hidden_fields); + confirm_box(false, (count($topic_ids) == 1) ? 'RESTORE_TOPIC' : 'RESTORE_TOPICS', $s_hidden_fields); } $topic_id = $request->variable('t', 0); @@ -842,7 +902,7 @@ function mcp_delete_topic($topic_ids, $is_soft = false, $soft_delete_reason = '' if (confirm_box(true)) { - $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_DELETED_SUCCESS' : 'TOPICS_DELETED_SUCCESS'; + $success_msg = (count($topic_ids) == 1) ? 'TOPIC_DELETED_SUCCESS' : 'TOPICS_DELETED_SUCCESS'; $data = phpbb_get_topic_data($topic_ids); @@ -927,13 +987,14 @@ function mcp_delete_topic($topic_ids, $is_soft = false, $soft_delete_reason = '' 'S_TOPIC_MODE' => true, 'S_ALLOWED_DELETE' => $auth->acl_get('m_delete', $forum_id), 'S_ALLOWED_SOFTDELETE' => $auth->acl_get('m_softdelete', $forum_id), - 'DELETE_TOPIC_PERMANENTLY_EXPLAIN' => $user->lang('DELETE_TOPIC_PERMANENTLY', sizeof($topic_ids)), + 'DELETE_TOPIC_PERMANENTLY_EXPLAIN' => $user->lang('DELETE_TOPIC_PERMANENTLY', count($topic_ids)), )); - $l_confirm = (sizeof($topic_ids) == 1) ? 'DELETE_TOPIC' : 'DELETE_TOPICS'; + $count = count($topic_ids); + $l_confirm = $count === 1 ? 'DELETE_TOPIC' : 'DELETE_TOPICS'; if ($only_softdeleted) { - $l_confirm .= '_PERMANENTLY'; + $l_confirm = array($l_confirm . '_PERMANENTLY', $count); $s_hidden_fields['delete_permanent'] = '1'; } else if ($only_shadow || !$auth->acl_get('m_softdelete', $forum_id)) @@ -1042,11 +1103,11 @@ function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '', { $phpbb_content_visibility->set_post_visibility(ITEM_DELETED, $topic_data['posts'], $topic_id, $topic_data['forum_id'], $user->data['user_id'], time(), $soft_delete_reason, isset($topic_data['first_post']), isset($topic_data['last_post'])); } - $affected_topics = sizeof($topic_info); + $affected_topics = count($topic_info); // None of the topics is really deleted, so a redirect won't hurt much. $deleted_topics = 0; - $success_msg = (sizeof($post_info) == 1) ? $user->lang['POST_DELETED_SUCCESS'] : $user->lang['POSTS_DELETED_SUCCESS']; + $success_msg = (count($post_info) == 1) ? $user->lang['POST_DELETED_SUCCESS'] : $user->lang['POSTS_DELETED_SUCCESS']; foreach ($approve_log as $row) { @@ -1093,7 +1154,7 @@ function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '', { $topic_id_list[] = $row['topic_id']; } - $affected_topics = sizeof($topic_id_list); + $affected_topics = count($topic_id_list); $db->sql_freeresult($result); $post_data = phpbb_get_post_data($post_ids); @@ -1132,7 +1193,7 @@ function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '', } $return_link[] = sprintf($user->lang['RETURN_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id) . '">', '</a>'); - if (sizeof($post_ids) == 1) + if (count($post_ids) == 1) { if ($deleted_topics) { @@ -1181,13 +1242,14 @@ function mcp_delete_post($post_ids, $is_soft = false, $soft_delete_reason = '', 'S_SOFTDELETED' => $only_softdeleted, 'S_ALLOWED_DELETE' => $auth->acl_get('m_delete', $forum_id), 'S_ALLOWED_SOFTDELETE' => $auth->acl_get('m_softdelete', $forum_id), - 'DELETE_POST_PERMANENTLY_EXPLAIN' => $user->lang('DELETE_POST_PERMANENTLY', sizeof($post_ids)), + 'DELETE_POST_PERMANENTLY_EXPLAIN' => $user->lang('DELETE_POST_PERMANENTLY', count($post_ids)), )); - $l_confirm = (sizeof($post_ids) == 1) ? 'DELETE_POST' : 'DELETE_POSTS'; + $count = count($post_ids); + $l_confirm = $count === 1 ? 'DELETE_POST' : 'DELETE_POSTS'; if ($only_softdeleted) { - $l_confirm .= '_PERMANENTLY'; + $l_confirm = array($l_confirm . '_PERMANENTLY', $count); $s_hidden_fields['delete_permanent'] = '1'; } else if (!$auth->acl_get('m_softdelete', $forum_id)) @@ -1247,11 +1309,11 @@ function mcp_fork_topic($topic_ids) { $forum_data = phpbb_get_forum_data($to_forum_id, 'f_post'); - if (!sizeof($topic_ids)) + if (!count($topic_ids)) { $additional_msg = $user->lang['NO_TOPIC_SELECTED']; } - else if (!sizeof($forum_data)) + else if (!count($forum_data)) { $additional_msg = $user->lang['FORUM_NOT_EXIST']; } @@ -1409,7 +1471,7 @@ function mcp_fork_topic($topic_ids) } $db->sql_freeresult($result); - if (!sizeof($post_rows)) + if (!count($post_rows)) { continue; } @@ -1458,6 +1520,24 @@ function mcp_fork_topic($topic_ids) $db->sql_query('INSERT INTO ' . POSTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); $new_post_id = $db->sql_nextid(); + /** + * Perform actions after forked topic is created. + * + * @event core.mcp_main_fork_sql_after + * @var int new_topic_id The newly created topic ID + * @var int to_forum_id The forum ID where the forked topic has been moved to + * @var int new_post_id The newly created post ID + * @var array row Post data + * @since 3.2.4-RC1 + */ + $vars = array( + 'new_topic_id', + 'to_forum_id', + 'new_post_id', + 'row', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_main_fork_sql_after', compact($vars))); + switch ($row['post_visibility']) { case ITEM_APPROVED: @@ -1512,7 +1592,7 @@ function mcp_fork_topic($topic_ids) } $db->sql_freeresult($result); - if (sizeof($sql_ary)) + if (count($sql_ary)) { $db->sql_multi_insert(ATTACHMENTS_TABLE, $sql_ary); } @@ -1536,7 +1616,7 @@ function mcp_fork_topic($topic_ids) } $db->sql_freeresult($result); - if (sizeof($sql_ary)) + if (count($sql_ary)) { $db->sql_multi_insert(TOPICS_WATCH_TABLE, $sql_ary); } @@ -1557,7 +1637,7 @@ function mcp_fork_topic($topic_ids) } $db->sql_freeresult($result); - if (sizeof($sql_ary)) + if (count($sql_ary)) { $db->sql_multi_insert(BOOKMARKS_TABLE, $sql_ary); } @@ -1589,7 +1669,7 @@ function mcp_fork_topic($topic_ids) sync('topic', 'topic_id', $new_topic_id_list); sync('forum', 'forum_id', $to_forum_id); - $config->increment('num_topics', sizeof($new_topic_id_list), false); + $config->increment('num_topics', count($new_topic_id_list), false); $config->increment('num_posts', $total_posts, false); foreach ($new_topic_id_list as $topic_id => $new_topic_id) @@ -1601,7 +1681,7 @@ function mcp_fork_topic($topic_ids) )); } - $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_FORKED_SUCCESS' : 'TOPICS_FORKED_SUCCESS'; + $success_msg = (count($topic_ids) == 1) ? 'TOPIC_FORKED_SUCCESS' : 'TOPICS_FORKED_SUCCESS'; } else { @@ -1611,7 +1691,7 @@ function mcp_fork_topic($topic_ids) 'ADDITIONAL_MSG' => $additional_msg) ); - confirm_box(false, 'FORK_TOPIC' . ((sizeof($topic_ids) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_move.html'); + confirm_box(false, 'FORK_TOPIC' . ((count($topic_ids) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_move.html'); } $redirect = $request->variable('redirect', "index.$phpEx"); diff --git a/phpBB/includes/mcp/mcp_notes.php b/phpBB/includes/mcp/mcp_notes.php index 67f59bd618..a4c2356a43 100644 --- a/phpBB/includes/mcp/mcp_notes.php +++ b/phpBB/includes/mcp/mcp_notes.php @@ -28,9 +28,9 @@ class mcp_notes var $p_master; var $u_action; - function mcp_notes(&$p_master) + function __construct($p_master) { - $this->p_master = &$p_master; + $this->p_master = $p_master; } function main($id, $mode) diff --git a/phpBB/includes/mcp/mcp_pm_reports.php b/phpBB/includes/mcp/mcp_pm_reports.php index 67a1a959e4..eecfe9cbc8 100644 --- a/phpBB/includes/mcp/mcp_pm_reports.php +++ b/phpBB/includes/mcp/mcp_pm_reports.php @@ -28,9 +28,9 @@ class mcp_pm_reports var $p_master; var $u_action; - function mcp_pm_reports(&$p_master) + function __construct($p_master) { - $this->p_master = &$p_master; + $this->p_master = $p_master; } function main($id, $mode) @@ -55,7 +55,7 @@ class mcp_pm_reports $report_id_list = $request->variable('report_id_list', array(0)); - if (!sizeof($report_id_list)) + if (!count($report_id_list)) { trigger_error('NO_REPORT_SELECTED'); } @@ -104,7 +104,7 @@ class mcp_pm_reports $pm_info = phpbb_get_pm_data(array($pm_id)); - if (!sizeof($pm_info)) + if (!count($pm_info)) { trigger_error('NO_REPORT_SELECTED'); } @@ -141,7 +141,7 @@ class mcp_pm_reports } $db->sql_freeresult($result); - if (sizeof($attachments)) + if (count($attachments)) { $update_count = array(); parse_attachments(0, $message, $attachments, $update_count); @@ -251,7 +251,7 @@ class mcp_pm_reports } $db->sql_freeresult($result); - if (sizeof($report_ids)) + if (count($report_ids)) { $sql = 'SELECT p.*, u.username, u.username_clean, u.user_colour, r.user_id as reporter_id, ru.username as reporter_name, ru.user_colour as reporter_colour, r.report_time, r.report_id FROM ' . REPORTS_TABLE . ' r, ' . PRIVMSGS_TABLE . ' p, ' . USERS_TABLE . ' u, ' . USERS_TABLE . ' ru @@ -270,7 +270,7 @@ class mcp_pm_reports } $db->sql_freeresult($result); - if (sizeof($pm_list)) + if (count($pm_list)) { $address_list = get_recipient_strings($pm_by_id); diff --git a/phpBB/includes/mcp/mcp_post.php b/phpBB/includes/mcp/mcp_post.php index 60ec3b8f5a..8d278079fb 100644 --- a/phpBB/includes/mcp/mcp_post.php +++ b/phpBB/includes/mcp/mcp_post.php @@ -38,7 +38,7 @@ function mcp_post_details($id, $mode, $action) add_form_key('mcp_post_details'); - if (!sizeof($post_info)) + if (!count($post_info)) { trigger_error('POST_NOT_EXIST'); } @@ -165,7 +165,7 @@ function mcp_post_details($id, $mode, $action) } $db->sql_freeresult($result); - if (sizeof($attachments)) + if (count($attachments)) { $user->add_lang('viewtopic'); $update_count = array(); @@ -213,6 +213,10 @@ function mcp_post_details($id, $mode, $action) $l_deleted_by = ''; } + // parse signature + $parse_flags = ($post_info['user_sig_bbcode_bitfield'] ? OPTION_FLAG_BBCODE : 0) | OPTION_FLAG_SMILIES; + $post_info['user_sig'] = generate_text_for_display($post_info['user_sig'], $post_info['user_sig_bbcode_uid'], $post_info['user_sig_bbcode_bitfield'], $parse_flags, true); + $mcp_post_template_data = array( 'U_MCP_ACTION' => "$url&i=main&quickmod=1&mode=post_details", // Use this for mode paramaters 'U_POST_ACTION' => "$url&i=$id&mode=post_details", // Use this for action parameters @@ -262,6 +266,7 @@ function mcp_post_details($id, $mode, $action) 'POST_IP' => $post_info['poster_ip'], 'POST_IPADDR' => ($auth->acl_get('m_info', $post_info['forum_id']) && $request->variable('lookup', '')) ? @gethostbyaddr($post_info['poster_ip']) : '', 'POST_ID' => $post_info['post_id'], + 'SIGNATURE' => $post_info['user_sig'], 'U_LOOKUP_IP' => ($auth->acl_get('m_info', $post_info['forum_id'])) ? "$url&i=$id&mode=$mode&lookup={$post_info['poster_ip']}#ip" : '', 'U_WHOIS' => ($auth->acl_get('m_info', $post_info['forum_id'])) ? append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&mode=$mode&action=whois&p=$post_id&ip={$post_info['poster_ip']}") : '', @@ -409,7 +414,7 @@ function mcp_post_details($id, $mode, $action) ); } - if (sizeof($users_ary)) + if (count($users_ary)) { // Get the usernames $sql = 'SELECT user_id, username @@ -495,7 +500,7 @@ function mcp_post_details($id, $mode, $action) $user_select = ''; - if (sizeof($usernames_ary)) + if (count($usernames_ary)) { ksort($usernames_ary); @@ -656,7 +661,7 @@ function change_poster(&$post_info, $userdata) // Renew post info $post_info = phpbb_get_post_data(array($post_id), false, true); - if (!sizeof($post_info)) + if (!count($post_info)) { trigger_error('POST_NOT_EXIST'); } diff --git a/phpBB/includes/mcp/mcp_queue.php b/phpBB/includes/mcp/mcp_queue.php index f379392b12..dec583f6f4 100644 --- a/phpBB/includes/mcp/mcp_queue.php +++ b/phpBB/includes/mcp/mcp_queue.php @@ -28,9 +28,9 @@ class mcp_queue var $p_master; var $u_action; - public function mcp_queue(&$p_master) + public function __construct($p_master) { - $this->p_master = &$p_master; + $this->p_master = $p_master; } public function main($id, $mode) @@ -179,7 +179,7 @@ class mcp_queue $post_info = phpbb_get_post_data(array($post_id), 'm_approve', true); - if (!sizeof($post_info)) + if (!count($post_info)) { trigger_error('NO_POST_SELECTED'); } @@ -230,7 +230,7 @@ class mcp_queue } $db->sql_freeresult($result); - if (sizeof($attachments)) + if (count($attachments)) { $update_count = array(); parse_attachments($post_info['forum_id'], $message, $attachments, $update_count); @@ -280,7 +280,7 @@ class mcp_queue $post_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $post_info['forum_id'] . '&p=' . $post_info['post_id'] . '#p' . $post_info['post_id']); $topic_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $post_info['forum_id'] . '&t=' . $post_info['topic_id']); - $template->assign_vars(array( + $post_data = array( 'S_MCP_QUEUE' => true, 'U_APPROVE_ACTION' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=queue&p=$post_id&f=$forum_id"), 'S_CAN_DELETE_POST' => $auth->acl_get('m_delete', $post_info['forum_id']), @@ -324,7 +324,35 @@ class mcp_queue 'S_FIRST_POST' => ($post_info['topic_first_post_id'] == $post_id), 'U_LOOKUP_IP' => ($auth->acl_get('m_info', $post_info['forum_id'])) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&mode=approve_details&f=' . $post_info['forum_id'] . '&p=' . $post_id . '&lookup=' . $post_info['poster_ip']) . '#ip' : '', - )); + ); + + /** + * Alter post awaiting approval template before it is rendered + * + * @event core.mcp_queue_approve_details_template + * @var int post_id Post ID + * @var int topic_id Topic ID + * @var array topic_info Topic data + * @var array post_info Post data + * @var array post_data Post template data + * @var string message Post message + * @var string post_url Post URL + * @var string topic_url Topic URL + * @since 3.2.2-RC1 + */ + $vars = array( + 'post_id', + 'topic_id', + 'topic_info', + 'post_info', + 'post_data', + 'message', + 'post_url', + 'topic_url', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_queue_approve_details_template', compact($vars))); + + $template->assign_vars($post_data); break; @@ -349,7 +377,7 @@ class mcp_queue { $topic_info = phpbb_get_topic_data(array($topic_id)); - if (!sizeof($topic_info)) + if (!count($topic_info)) { trigger_error('TOPIC_NOT_EXIST'); } @@ -379,7 +407,7 @@ class mcp_queue $forum_list[] = $row['forum_id']; } - if (!sizeof($forum_list)) + if (!count($forum_list)) { trigger_error('NOT_MODERATOR'); } @@ -395,7 +423,7 @@ class mcp_queue { $forum_info = phpbb_get_forum_data(array($forum_id), $m_perm); - if (!sizeof($forum_info)) + if (!count($forum_info)) { trigger_error('NOT_MODERATOR'); } @@ -465,7 +493,7 @@ class mcp_queue } $db->sql_freeresult($result); - if (sizeof($post_ids)) + if (count($post_ids)) { $sql = 'SELECT t.topic_id, t.topic_title, t.forum_id, p.post_id, p.post_subject, p.post_username, p.poster_id, p.post_time, p.post_attachment, u.username, u.username_clean, u.user_colour FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t, ' . USERS_TABLE . ' u @@ -473,6 +501,29 @@ class mcp_queue AND t.topic_id = p.topic_id AND u.user_id = p.poster_id ORDER BY ' . $sort_order_sql; + + /** + * Alter sql query to get information on all posts in queue + * + * @event core.mcp_queue_get_posts_for_posts_query_before + * @var string sql String with the query to be executed + * @var array forum_list List of forums that contain the posts + * @var int visibility_const Integer with one of the possible ITEM_* constant values + * @var int topic_id topic_id in the page request + * @var string limit_time_sql String with the SQL code to limit the time interval of the post (Note: May be empty string) + * @var string sort_order_sql String with the ORDER BY SQL code used in this query + * @since 3.2.3-RC2 + */ + $vars = array( + 'sql', + 'forum_list', + 'visibility_const', + 'topic_id', + 'limit_time_sql', + 'sort_order_sql', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_queue_get_posts_for_posts_query_before', compact($vars))); + $result = $db->sql_query($sql); $post_data = $rowset = array(); @@ -537,7 +588,7 @@ class mcp_queue $db->sql_freeresult($result); } - if (sizeof($forum_names)) + if (count($forum_names)) { // Select the names for the forum_ids $sql = 'SELECT forum_id, forum_name @@ -560,7 +611,7 @@ class mcp_queue $row['post_username'] = $row['username'] ?: $user->lang['GUEST']; } - $template->assign_block_vars('postrow', array( + $post_row = array( 'U_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $row['forum_id'] . '&t=' . $row['topic_id']), 'U_VIEWFORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $row['forum_id']), 'U_VIEWPOST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $row['forum_id'] . '&p=' . $row['post_id']) . (($mode == 'unapproved_posts') ? '#p' . $row['post_id'] : ''), @@ -578,7 +629,25 @@ class mcp_queue 'TOPIC_TITLE' => $row['topic_title'], 'POST_TIME' => $user->format_date($row['post_time']), 'S_HAS_ATTACHMENTS' => $auth->acl_get('u_download') && $auth->acl_get('f_download', $row['forum_id']) && $row['post_attachment'], - )); + ); + + /** + * Alter sql query to get information on all topics in the list of forums provided. + * + * @event core.mcp_queue_get_posts_modify_post_row + * @var array post_row Template variables for current post + * @var array row Post data + * @var array forum_names Forum names + * @since 3.2.3-RC2 + */ + $vars = array( + 'post_row', + 'row', + 'forum_names', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_queue_get_posts_modify_post_row', compact($vars))); + + $template->assign_block_vars('postrow', $post_row); } unset($rowset, $forum_names); @@ -771,7 +840,7 @@ class mcp_queue } else { - $success_msg = (sizeof($post_info) == 1) ? 'POST_' . strtoupper($action) . 'D_SUCCESS' : 'POSTS_' . strtoupper($action) . 'D_SUCCESS'; + $success_msg = (count($post_info) == 1) ? 'POST_' . strtoupper($action) . 'D_SUCCESS' : 'POSTS_' . strtoupper($action) . 'D_SUCCESS'; } /** @@ -814,7 +883,7 @@ class mcp_queue $message .= '<br /><br />' . $user->lang('RETURN_PAGE', '<a href="' . $redirect . '">', '</a>'); // If approving one post, also give links back to post... - if (sizeof($post_info) == 1 && $post_url) + if (count($post_info) == 1 && $post_url) { $message .= '<br /><br />' . $user->lang('RETURN_POST', '<a href="' . $post_url . '">', '</a>'); } @@ -847,14 +916,14 @@ class mcp_queue // Create the confirm box message $action_msg = strtoupper($action); - $num_posts = sizeof($post_id_list) - $num_topics; + $num_posts = count($post_id_list) - $num_topics; if ($num_topics > 0 && $num_posts <= 0) { $action_msg .= '_TOPIC' . (($num_topics == 1) ? '' : 'S'); } else { - $action_msg .= '_POST' . ((sizeof($post_id_list) == 1) ? '' : 'S'); + $action_msg .= '_POST' . ((count($post_id_list) == 1) ? '' : 'S'); } confirm_box(false, $action_msg, $s_hidden_fields, 'mcp_approve.html'); } @@ -919,9 +988,9 @@ class mcp_queue ); } - if (sizeof($topic_info) >= 1) + if (count($topic_info) >= 1) { - $success_msg = (sizeof($topic_info) == 1) ? 'TOPIC_' . strtoupper($action) . 'D_SUCCESS' : 'TOPICS_' . strtoupper($action) . 'D_SUCCESS'; + $success_msg = (count($topic_info) == 1) ? 'TOPIC_' . strtoupper($action) . 'D_SUCCESS' : 'TOPICS_' . strtoupper($action) . 'D_SUCCESS'; } foreach ($approve_log as $log_data) @@ -1024,7 +1093,7 @@ class mcp_queue $message .= '<br /><br />' . $user->lang('RETURN_PAGE', '<a href="' . $redirect . '">', '</a>'); // If approving one topic, also give links back to topic... - if (sizeof($topic_info) == 1 && $topic_url) + if (count($topic_info) == 1 && $topic_url) { $message .= '<br /><br />' . $user->lang('RETURN_TOPIC', '<a href="' . $topic_url . '">', '</a>'); } @@ -1055,7 +1124,7 @@ class mcp_queue 'S_' . strtoupper($action) => true, )); - confirm_box(false, strtoupper($action) . '_TOPIC' . ((sizeof($topic_id_list) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_approve.html'); + confirm_box(false, strtoupper($action) . '_TOPIC' . ((count($topic_id_list) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_approve.html'); } redirect($redirect); @@ -1206,8 +1275,8 @@ class mcp_queue } // Get disapproved posts/topics counts separately - $num_disapproved_topics = sizeof($disapprove_log_topics); - $num_disapproved_posts = sizeof($disapprove_log_posts); + $num_disapproved_topics = count($disapprove_log_topics); + $num_disapproved_posts = count($disapprove_log_posts); // Build the whole log $disapprove_log = array_merge($disapprove_log_topics, $disapprove_log_posts); @@ -1216,7 +1285,7 @@ class mcp_queue unset($post_data, $disapprove_log_topics, $disapprove_log_posts); // Let's do the job - delete disapproved posts - if (sizeof($post_disapprove_list)) + if (count($post_disapprove_list)) { if (!function_exists('delete_posts')) { @@ -1444,7 +1513,7 @@ class mcp_queue $l_confirm_msg = 'DELETE_POST_PERMANENTLY'; $confirm_template = 'confirm_delete_body.html'; } - $l_confirm_msg .= ((sizeof($post_id_list) == 1) ? '' : 'S'); + $l_confirm_msg .= ((count($post_id_list) == 1) ? '' : 'S'); $template->assign_vars(array( 'S_NOTIFY_POSTER' => $show_notify, diff --git a/phpBB/includes/mcp/mcp_reports.php b/phpBB/includes/mcp/mcp_reports.php index 1462acf110..4600257344 100644 --- a/phpBB/includes/mcp/mcp_reports.php +++ b/phpBB/includes/mcp/mcp_reports.php @@ -28,9 +28,9 @@ class mcp_reports var $p_master; var $u_action; - function mcp_reports(&$p_master) + function __construct($p_master) { - $this->p_master = &$p_master; + $this->p_master = $p_master; } function main($id, $mode) @@ -53,7 +53,7 @@ class mcp_reports $report_id_list = $request->variable('report_id_list', array(0)); - if (!sizeof($report_id_list)) + if (!count($report_id_list)) { trigger_error('NO_REPORT_SELECTED'); } @@ -158,7 +158,7 @@ class mcp_reports $post_info = phpbb_get_post_data(array($post_id), 'm_report', true); - if (!sizeof($post_info)) + if (!count($post_info)) { trigger_error('NO_REPORT_SELECTED'); } @@ -222,7 +222,7 @@ class mcp_reports } $db->sql_freeresult($result); - if (sizeof($attachments)) + if (count($attachments)) { $update_count = array(); parse_attachments($post_info['forum_id'], $message, $attachments, $update_count); @@ -242,7 +242,14 @@ class mcp_reports } } - $template->assign_vars(array( + // parse signature + $parse_flags = ($post_info['user_sig_bbcode_bitfield'] ? OPTION_FLAG_BBCODE : 0) | OPTION_FLAG_SMILIES; + $post_info['user_sig'] = generate_text_for_display($post_info['user_sig'], $post_info['user_sig_bbcode_uid'], $post_info['user_sig_bbcode_bitfield'], $parse_flags, true); + + $topic_id = (int) $post_info['topic_id']; + + // So it can be sent through the event below. + $report_template = array( 'S_MCP_REPORT' => true, 'S_CLOSE_ACTION' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports&mode=report_details&f=' . $post_info['forum_id'] . '&p=' . $post_id), 'S_CAN_VIEWIP' => $auth->acl_get('m_info', $post_info['forum_id']), @@ -291,9 +298,36 @@ class mcp_reports 'POST_IP' => $post_info['poster_ip'], 'POST_IPADDR' => ($auth->acl_get('m_info', $post_info['forum_id']) && $request->variable('lookup', '')) ? @gethostbyaddr($post_info['poster_ip']) : '', 'POST_ID' => $post_info['post_id'], + 'SIGNATURE' => $post_info['user_sig'], 'U_LOOKUP_IP' => ($auth->acl_get('m_info', $post_info['forum_id'])) ? $this->u_action . '&r=' . $report_id . '&p=' . $post_id . '&f=' . $forum_id . '&lookup=' . $post_info['poster_ip'] . '#ip' : '', - )); + ); + + /** + * Event to add/modify MCP report details template data. + * + * @event core.mcp_report_template_data + * @var int forum_id The forum_id, the number in the f GET parameter + * @var int topic_id The topic_id of the report being viewed + * @var int post_id The post_id of the report being viewed (if 0, it is meaningless) + * @var int report_id The report_id of the report being viewed + * @var array report Array with the report data + * @var array report_template Array with the report template data + * @var array post_info Array with the reported post data + * @since 3.2.5-RC1 + */ + $vars = array( + 'forum_id', + 'topic_id', + 'post_id', + 'report_id', + 'report', + 'report_template', + 'post_info', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_report_template_data', compact($vars))); + + $template->assign_vars($report_template); $this->tpl_name = 'mcp_post'; @@ -321,7 +355,7 @@ class mcp_reports { $topic_info = phpbb_get_topic_data(array($topic_id)); - if (!sizeof($topic_info)) + if (!count($topic_info)) { trigger_error('TOPIC_NOT_EXIST'); } @@ -346,7 +380,7 @@ class mcp_reports $forum_list[] = $row['forum_id']; } - if (!sizeof($forum_list)) + if (!count($forum_list)) { trigger_error('NOT_MODERATOR'); } @@ -362,7 +396,7 @@ class mcp_reports { $forum_info = phpbb_get_forum_data(array($forum_id), 'm_report'); - if (!sizeof($forum_info)) + if (!count($forum_info)) { trigger_error('NOT_MODERATOR'); } @@ -443,7 +477,7 @@ class mcp_reports } $db->sql_freeresult($result); - if (sizeof($report_ids)) + if (count($report_ids)) { $sql = 'SELECT t.forum_id, t.topic_id, t.topic_title, p.post_id, p.post_subject, p.post_username, p.poster_id, p.post_time, p.post_attachment, u.username, u.username_clean, u.user_colour, r.user_id as reporter_id, ru.username as reporter_name, ru.user_colour as reporter_colour, r.report_time, r.report_id FROM ' . REPORTS_TABLE . ' r, ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t, ' . USERS_TABLE . ' u, ' . USERS_TABLE . ' ru @@ -617,12 +651,12 @@ function close_report($report_id_list, $mode, $action, $pm = false) } $db->sql_freeresult($result); - if (sizeof($reports)) + if (count($reports)) { $close_report_posts = array_unique($close_report_posts); $close_report_topics = array_unique($close_report_topics); - if (!$pm && sizeof($close_report_posts)) + if (!$pm && count($close_report_posts)) { // Get a list of topics that still contain reported posts $sql = 'SELECT DISTINCT topic_id @@ -658,7 +692,7 @@ function close_report($report_id_list, $mode, $action, $pm = false) } $db->sql_query($sql); - if (sizeof($close_report_posts)) + if (count($close_report_posts)) { if ($pm) { @@ -679,7 +713,7 @@ function close_report($report_id_list, $mode, $action, $pm = false) WHERE ' . $db->sql_in_set('post_id', $close_report_posts); $db->sql_query($sql); - if (sizeof($close_report_topics)) + if (count($close_report_topics)) { $sql = 'UPDATE ' . TOPICS_TABLE . ' SET topic_reported = 0 @@ -721,7 +755,7 @@ function close_report($report_id_list, $mode, $action, $pm = false) } // Notify reporters - if (sizeof($notify_reporters)) + if (count($notify_reporters)) { foreach ($notify_reporters as $report_id => $reporter) { @@ -761,11 +795,11 @@ function close_report($report_id_list, $mode, $action, $pm = false) unset($notify_reporters, $post_info, $reports); - $success_msg = (sizeof($report_id_list) == 1) ? "{$pm_prefix}REPORT_" . strtoupper($action) . 'D_SUCCESS' : "{$pm_prefix}REPORTS_" . strtoupper($action) . 'D_SUCCESS'; + $success_msg = (count($report_id_list) == 1) ? "{$pm_prefix}REPORT_" . strtoupper($action) . 'D_SUCCESS' : "{$pm_prefix}REPORTS_" . strtoupper($action) . 'D_SUCCESS'; } else { - confirm_box(false, $user->lang[strtoupper($action) . "_{$pm_prefix}REPORT" . ((sizeof($report_id_list) == 1) ? '' : 'S') . '_CONFIRM'], $s_hidden_fields); + confirm_box(false, $user->lang[strtoupper($action) . "_{$pm_prefix}REPORT" . ((count($report_id_list) == 1) ? '' : 'S') . '_CONFIRM'], $s_hidden_fields); } $redirect = $request->variable('redirect', "index.$phpEx"); @@ -784,12 +818,12 @@ function close_report($report_id_list, $mode, $action, $pm = false) if (!$pm) { - if (sizeof($forum_ids) === 1) + if (count($forum_ids) === 1) { $return_forum = sprintf($user->lang['RETURN_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . current($forum_ids)) . '">', '</a>') . '<br /><br />'; } - if (sizeof($topic_ids) === 1) + if (count($topic_ids) === 1) { $return_topic = sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=' . current($topic_ids) . '&f=' . current($forum_ids)) . '">', '</a>') . '<br /><br />'; } diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php index 76df5b3a5e..83ad56f3e4 100644 --- a/phpBB/includes/mcp/mcp_topic.php +++ b/phpBB/includes/mcp/mcp_topic.php @@ -36,7 +36,7 @@ function mcp_topic_view($id, $mode, $action) $topic_id = $request->variable('t', 0); $topic_info = phpbb_get_topic_data(array($topic_id), false, true); - if (!sizeof($topic_info)) + if (!count($topic_info)) { trigger_error('TOPIC_NOT_EXIST'); } @@ -93,11 +93,15 @@ function mcp_topic_view($id, $mode, $action) // Restore or pprove posts? if (($action == 'restore' || $action == 'approve') && $auth->acl_get('m_approve', $topic_info['forum_id'])) { - include($phpbb_root_path . 'includes/mcp/mcp_queue.' . $phpEx); + if (!class_exists('mcp_queue')) + { + include($phpbb_root_path . 'includes/mcp/mcp_queue.' . $phpEx); + } + include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx); include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); - if (!sizeof($post_id_list)) + if (!count($post_id_list)) { trigger_error('NO_POST_SELECTED'); } @@ -138,14 +142,36 @@ function mcp_topic_view($id, $mode, $action) } $start = $pagination->validate_start($start, $posts_per_page, $total); - $sql = 'SELECT u.username, u.username_clean, u.user_colour, p.* - FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u - WHERE ' . (($action == 'reports') ? 'p.post_reported = 1 AND ' : '') . ' + $sql_where = (($action == 'reports') ? 'p.post_reported = 1 AND ' : '') . ' p.topic_id = ' . $topic_id . ' AND ' . $phpbb_content_visibility->get_visibility_sql('post', $topic_info['forum_id'], 'p.') . ' AND p.poster_id = u.user_id ' . - $limit_time_sql . ' - ORDER BY ' . $sort_order_sql; + $limit_time_sql; + + $sql_ary = array( + 'SELECT' => 'u.username, u.username_clean, u.user_colour, p.*', + 'FROM' => array( + POSTS_TABLE => 'p', + USERS_TABLE => 'u' + ), + 'LEFT_JOIN' => array(), + 'WHERE' => $sql_where, + 'ORDER_BY' => $sort_order_sql, + ); + + /** + * Event to modify the SQL query before the MCP topic review posts is queried + * + * @event core.mcp_topic_modify_sql_ary + * @var array sql_ary The SQL array to get the data of the MCP topic review posts + * @since 3.2.8-RC1 + */ + $vars = array('sql_ary'); + extract($phpbb_dispatcher->trigger_event('core.mcp_topic_modify_sql_ary', compact($vars))); + + $sql = $db->sql_build_query('SELECT', $sql_ary); + unset($sql_ary); + $result = $db->sql_query_limit($sql, $posts_per_page, $start); $rowset = $post_id_list = array(); @@ -172,7 +198,7 @@ function mcp_topic_view($id, $mode, $action) // Grab extensions $attachments = array(); - if ($topic_info['topic_attachment'] && sizeof($post_id_list)) + if ($topic_info['topic_attachment'] && count($post_id_list)) { // Get attachments... if ($auth->acl_get('u_download') && $auth->acl_get('f_download', $topic_info['forum_id'])) @@ -326,7 +352,7 @@ function mcp_topic_view($id, $mode, $action) { $to_topic_info = phpbb_get_topic_data(array($to_topic_id), 'm_merge'); - if (!sizeof($to_topic_info)) + if (!count($to_topic_info)) { $to_topic_id = 0; } @@ -408,7 +434,7 @@ function split_topic($action, $topic_id, $to_forum_id, $subject) $forum_id = $request->variable('forum_id', 0); $start = $request->variable('start', 0); - if (!sizeof($post_id_list)) + if (!count($post_id_list)) { $template->assign_var('MESSAGE', $user->lang['NO_POST_SELECTED']); return; @@ -422,7 +448,7 @@ function split_topic($action, $topic_id, $to_forum_id, $subject) $post_id = $post_id_list[0]; $post_info = phpbb_get_post_data(array($post_id)); - if (!sizeof($post_info)) + if (!count($post_info)) { $template->assign_var('MESSAGE', $user->lang['NO_POST_SELECTED']); return; @@ -446,7 +472,7 @@ function split_topic($action, $topic_id, $to_forum_id, $subject) $forum_info = phpbb_get_forum_data(array($to_forum_id), 'f_post'); - if (!sizeof($forum_info)) + if (!count($forum_info)) { $template->assign_var('MESSAGE', $user->lang['USER_CANNOT_POST']); return; @@ -530,7 +556,7 @@ function split_topic($action, $topic_id, $to_forum_id, $subject) $db->sql_freeresult($result); } - if (!sizeof($post_id_list)) + if (!count($post_id_list)) { trigger_error('NO_POST_SELECTED'); } @@ -628,7 +654,7 @@ function split_topic($action, $topic_id, $to_forum_id, $subject) } $db->sql_freeresult($result); - if (sizeof($sql_ary)) + if (count($sql_ary)) { $db->sql_multi_insert(TOPICS_WATCH_TABLE, $sql_ary); } @@ -649,7 +675,7 @@ function split_topic($action, $topic_id, $to_forum_id, $subject) } $db->sql_freeresult($result); - if (sizeof($sql_ary)) + if (count($sql_ary)) { $db->sql_multi_insert(BOOKMARKS_TABLE, $sql_ary); } @@ -690,7 +716,7 @@ function merge_posts($topic_id, $to_topic_id) $topic_data = phpbb_get_topic_data($sync_topics, 'm_merge'); - if (!sizeof($topic_data) || empty($topic_data[$to_topic_id])) + if (!count($topic_data) || empty($topic_data[$to_topic_id])) { $template->assign_var('MESSAGE', $user->lang['NO_FINAL_TOPIC_SELECTED']); return; @@ -707,7 +733,7 @@ function merge_posts($topic_id, $to_topic_id) $post_id_list = $request->variable('post_id_list', array(0)); $start = $request->variable('start', 0); - if (!sizeof($post_id_list)) + if (!count($post_id_list)) { $template->assign_var('MESSAGE', $user->lang['NO_POST_SELECTED']); return; diff --git a/phpBB/includes/mcp/mcp_warn.php b/phpBB/includes/mcp/mcp_warn.php index 0e80372f43..df175133fc 100644 --- a/phpBB/includes/mcp/mcp_warn.php +++ b/phpBB/includes/mcp/mcp_warn.php @@ -28,9 +28,9 @@ class mcp_warn var $p_master; var $u_action; - function mcp_warn(&$p_master) + function __construct($p_master) { - $this->p_master = &$p_master; + $this->p_master = $p_master; } function main($id, $mode) diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index 45f00c9ee1..0b79cca864 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -705,10 +705,10 @@ class bbcode_firstpass extends bbcode if ($tok == ']') { // if $tok is ']' the buffer holds a tag - if (strtolower($buffer) == '/list' && sizeof($list_end_tags)) + if (strtolower($buffer) == '/list' && count($list_end_tags)) { // valid [/list] tag, check nesting so that we don't hit false positives - if (sizeof($item_end_tags) && sizeof($item_end_tags) >= sizeof($list_end_tags)) + if (count($item_end_tags) && count($item_end_tags) >= count($list_end_tags)) { // current li tag has not been closed $out = preg_replace('/\n?\[$/', '[', $out) . array_pop($item_end_tags) . ']['; @@ -733,10 +733,10 @@ class bbcode_firstpass extends bbcode } else { - if (($buffer == '*' || substr($buffer, -2) == '[*') && sizeof($list_end_tags)) + if (($buffer == '*' || substr($buffer, -2) == '[*') && count($list_end_tags)) { // the buffer holds a bullet tag and we have a [list] tag open - if (sizeof($item_end_tags) >= sizeof($list_end_tags)) + if (count($item_end_tags) >= count($list_end_tags)) { if (substr($buffer, -2) == '[*') { @@ -780,11 +780,11 @@ class bbcode_firstpass extends bbcode while ($in); // do we have some tags open? close them now - if (sizeof($item_end_tags)) + if (count($item_end_tags)) { $out .= '[' . implode('][', $item_end_tags) . ']'; } - if (sizeof($list_end_tags)) + if (count($list_end_tags)) { $out .= '[' . implode('][', $list_end_tags) . ']'; } @@ -835,7 +835,7 @@ class bbcode_firstpass extends bbcode if ($tok == ']') { - if (strtolower($buffer) == '/quote' && sizeof($close_tags) && substr($out, -1, 1) == '[') + if (strtolower($buffer) == '/quote' && count($close_tags) && substr($out, -1, 1) == '[') { // we have found a closing tag $out .= array_pop($close_tags) . ']'; @@ -949,7 +949,7 @@ class bbcode_firstpass extends bbcode $out .= $buffer; - if (sizeof($close_tags)) + if (count($close_tags)) { $out .= '[' . implode('][', $close_tags) . ']'; } @@ -1139,7 +1139,7 @@ class parse_message extends bbcode_firstpass /** * Init - give message here or manually */ - function parse_message($message = '') + function __construct($message = '') { // Init BBCode UID $this->bbcode_uid = substr(base_convert(unique_id(), 16, 36), 0, BBCODE_UID_LEN); @@ -1500,7 +1500,7 @@ class parse_message extends bbcode_firstpass $db->sql_freeresult($result); } - if (sizeof($match)) + if (count($match)) { if ($max_smilies) { @@ -1534,7 +1534,7 @@ class parse_message extends bbcode_firstpass $error = array(); - $num_attachments = sizeof($this->attachment_data); + $num_attachments = count($this->attachment_data); $this->filename_data['filecomment'] = $request->variable('filecomment', '', true); $upload = $request->file($form_name); $upload_file = (!empty($upload) && $upload['name'] !== 'none' && trim($upload['name'])); @@ -1571,7 +1571,7 @@ class parse_message extends bbcode_firstpass $filedata = $attachment_manager->upload($form_name, $forum_id, false, '', $is_message); $error = $filedata['error']; - if ($filedata['post_attach'] && !sizeof($error)) + if ($filedata['post_attach'] && !count($error)) { $sql_ary = array( 'physical_filename' => $filedata['physical_filename'], @@ -1587,6 +1587,16 @@ class parse_message extends bbcode_firstpass 'poster_id' => $user->data['user_id'], ); + /** + * Modify attachment sql array on submit + * + * @event core.modify_attachment_sql_ary_on_submit + * @var array sql_ary Array containing SQL data + * @since 3.2.6-RC1 + */ + $vars = array('sql_ary'); + extract($phpbb_dispatcher->trigger_event('core.modify_attachment_sql_ary_on_submit', compact($vars))); + $db->sql_query('INSERT INTO ' . ATTACHMENTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); $new_entry = array( @@ -1635,7 +1645,7 @@ class parse_message extends bbcode_firstpass } } - if ($preview || $refresh || sizeof($error)) + if ($preview || $refresh || count($error)) { if (isset($this->plupload) && $this->plupload->is_active()) { @@ -1706,7 +1716,7 @@ class parse_message extends bbcode_firstpass $filedata = $attachment_manager->upload($form_name, $forum_id, false, '', $is_message); $error = array_merge($error, $filedata['error']); - if (!sizeof($error)) + if (!count($error)) { $sql_ary = array( 'physical_filename' => $filedata['physical_filename'], @@ -1722,6 +1732,16 @@ class parse_message extends bbcode_firstpass 'poster_id' => $user->data['user_id'], ); + /** + * Modify attachment sql array on upload + * + * @event core.modify_attachment_sql_ary_on_upload + * @var array sql_ary Array containing SQL data + * @since 3.2.6-RC1 + */ + $vars = array('sql_ary'); + extract($phpbb_dispatcher->trigger_event('core.modify_attachment_sql_ary_on_upload', compact($vars))); + $db->sql_query('INSERT INTO ' . ATTACHMENTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); $new_entry = array( @@ -1802,7 +1822,7 @@ class parse_message extends bbcode_firstpass $check_user_id = ($check_user_id === false) ? $user->data['user_id'] : $check_user_id; - if (!sizeof($attachment_data)) + if (!count($attachment_data)) { return; } @@ -1822,7 +1842,7 @@ class parse_message extends bbcode_firstpass } // Regenerate already posted attachments - if (sizeof($not_orphan)) + if (count($not_orphan)) { // Get the attachment data, based on the poster id... $sql = 'SELECT attach_id, is_orphan, real_filename, attach_comment, filesize @@ -1842,13 +1862,13 @@ class parse_message extends bbcode_firstpass $db->sql_freeresult($result); } - if (sizeof($not_orphan)) + if (count($not_orphan)) { trigger_error('NO_ACCESS_ATTACHMENT', E_USER_ERROR); } // Regenerate newly uploaded attachments - if (sizeof($orphan)) + if (count($orphan)) { $sql = 'SELECT attach_id, is_orphan, real_filename, attach_comment, filesize FROM ' . ATTACHMENTS_TABLE . ' @@ -1868,7 +1888,7 @@ class parse_message extends bbcode_firstpass $db->sql_freeresult($result); } - if (sizeof($orphan)) + if (count($orphan)) { trigger_error('NO_ACCESS_ATTACHMENT', E_USER_ERROR); } @@ -1889,7 +1909,7 @@ class parse_message extends bbcode_firstpass $tmp_message = $this->message; $poll['poll_options'] = preg_split('/\s*?\n\s*/', trim($poll['poll_option_text'])); - $poll['poll_options_size'] = sizeof($poll['poll_options']); + $poll['poll_options_size'] = count($poll['poll_options']); foreach ($poll['poll_options'] as &$poll_option) { @@ -1918,7 +1938,7 @@ class parse_message extends bbcode_firstpass } } - if (sizeof($poll['poll_options']) == 1) + if (count($poll['poll_options']) == 1) { $this->warn_msg[] = $user->lang['TOO_FEW_POLL_OPTIONS']; } diff --git a/phpBB/includes/questionnaire/questionnaire.php b/phpBB/includes/questionnaire/questionnaire.php index 9699843db4..2f80582918 100644 --- a/phpBB/includes/questionnaire/questionnaire.php +++ b/phpBB/includes/questionnaire/questionnaire.php @@ -40,7 +40,7 @@ class phpbb_questionnaire_data_collector * * @param string */ - function phpbb_questionnaire_data_collector($install_id) + function __construct($install_id) { $this->install_id = $install_id; $this->providers = array(); @@ -223,7 +223,7 @@ class phpbb_questionnaire_phpbb_data_provider * * @param array $config */ - function phpbb_questionnaire_phpbb_data_provider($config) + function __construct($config) { // generate a unique id if necessary if (empty($config['questionnaire_unique_id'])) @@ -337,7 +337,7 @@ class phpbb_questionnaire_phpbb_data_provider 'edit_time' => true, 'email_check_mx' => true, 'email_enable' => true, - 'email_function_name' => true, + 'email_force_sender' => true, 'email_package_size' => true, 'enable_confirm' => true, 'enable_pm_icons' => true, @@ -369,7 +369,6 @@ class phpbb_questionnaire_phpbb_data_provider 'hot_threshold' => true, 'img_create_thumbnail' => true, 'img_display_inlined' => true, - 'img_imagick' => true, 'img_link_height' => true, 'img_link_width' => true, 'img_max_height' => true, diff --git a/phpBB/includes/sphinxapi.php b/phpBB/includes/sphinxapi.php index 5e1f131ac2..b63a85a90f 100644 --- a/phpBB/includes/sphinxapi.php +++ b/phpBB/includes/sphinxapi.php @@ -126,7 +126,7 @@ define ( "SPH_GROUPBY_ATTRPAIR", 5 ); function sphPackI64 ( $v ) { assert ( is_numeric($v) ); - + // x64 if ( PHP_INT_SIZE>=8 ) { @@ -138,7 +138,7 @@ function sphPackI64 ( $v ) if ( is_int($v) ) return pack ( "NN", $v < 0 ? -1 : 0, $v ); - // x32, bcmath + // x32, bcmath if ( function_exists("bcmul") ) { if ( bccomp ( $v, 0 ) == -1 ) @@ -175,16 +175,16 @@ function sphPackI64 ( $v ) 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") ) { @@ -192,12 +192,12 @@ function sphPackU64 ( $v ) $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); @@ -208,7 +208,7 @@ function sphPackU64 ( $v ) // x32, int if ( is_int($v) ) return pack ( "NN", 0, $v ); - + // x32, bcmath if ( function_exists("bcmul") ) { @@ -221,7 +221,7 @@ function sphPackU64 ( $v ) $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); @@ -277,11 +277,11 @@ function sphUnpackU64 ( $v ) // 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; @@ -324,7 +324,7 @@ function sphUnpackI64 ( $v ) return $lo; return sprintf ( "%.0f", $lo - 4294967296.0 ); } - + $neg = ""; $c = 0; if ( $hi<0 ) @@ -333,7 +333,7 @@ function sphUnpackI64 ( $v ) $lo = ~$lo; $c = 1; $neg = "-"; - } + } $hi = sprintf ( "%u", $hi ); $lo = sprintf ( "%u", $lo ); @@ -345,7 +345,7 @@ function sphUnpackI64 ( $v ) // x32, no-bcmath $hi = (float)$hi; $lo = (float)$lo; - + $q = floor($hi/10000000.0); $r = $hi - $q*10000000.0; $m = $lo + $r*4967296.0; @@ -427,7 +427,7 @@ class SphinxClient ///////////////////////////////////////////////////////////////////////////// /// create a new client object and fill defaults - function SphinxClient () + function __construct () { // per-client-object settings $this->_host = "localhost"; @@ -510,7 +510,7 @@ class SphinxClient $this->_path = $host; return; } - + assert ( is_int($port) ); $this->_host = $host; $this->_port = $port; @@ -590,14 +590,14 @@ class SphinxClient $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; @@ -1236,7 +1236,7 @@ class SphinxClient if ( $type==SPH_ATTR_FLOAT ) { list(,$uval) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4; - list(,$fval) = unpack ( "f*", pack ( "L", $uval ) ); + list(,$fval) = unpack ( "f*", pack ( "L", $uval ) ); $attrvals[$attr] = $fval; continue; } @@ -1264,7 +1264,7 @@ class SphinxClient } else if ( $type==SPH_ATTR_STRING ) { $attrvals[$attr] = substr ( $response, $p, $val ); - $p += $val; + $p += $val; } else { $attrvals[$attr] = sphFixUint($val); @@ -1345,7 +1345,7 @@ class SphinxClient 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 @@ -1634,7 +1634,7 @@ class SphinxClient fclose ( $this->_socket ); $this->_socket = false; - + return true; } diff --git a/phpBB/includes/ucp/ucp_activate.php b/phpBB/includes/ucp/ucp_activate.php index 1e54c18dc1..7a90f2e3b1 100644 --- a/phpBB/includes/ucp/ucp_activate.php +++ b/phpBB/includes/ucp/ucp_activate.php @@ -87,6 +87,8 @@ class ucp_activate WHERE user_id = ' . $user_row['user_id']; $db->sql_query($sql); + $user->reset_login_keys($user_row['user_id']); + $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_NEW_PASSWORD', false, array( 'reportee_id' => $user_row['user_id'], $user_row['username'] diff --git a/phpBB/includes/ucp/ucp_attachments.php b/phpBB/includes/ucp/ucp_attachments.php index 66c3109b3d..7808fed325 100644 --- a/phpBB/includes/ucp/ucp_attachments.php +++ b/phpBB/includes/ucp/ucp_attachments.php @@ -29,7 +29,7 @@ class ucp_attachments function main($id, $mode) { - global $template, $user, $db, $config, $phpEx, $phpbb_root_path, $phpbb_container, $request; + global $template, $user, $db, $config, $phpEx, $phpbb_root_path, $phpbb_container, $request, $auth; $start = $request->variable('start', 0); $sort_key = $request->variable('sk', 'a'); @@ -38,25 +38,36 @@ class ucp_attachments $delete = (isset($_POST['delete'])) ? true : false; $delete_ids = array_keys($request->variable('attachment', array(0))); - if ($delete && sizeof($delete_ids)) + if ($delete && count($delete_ids)) { // Validate $delete_ids... - $sql = 'SELECT attach_id - FROM ' . ATTACHMENTS_TABLE . ' - WHERE poster_id = ' . $user->data['user_id'] . ' - AND is_orphan = 0 - AND ' . $db->sql_in_set('attach_id', $delete_ids); + $sql = 'SELECT a.attach_id, p.post_edit_locked, t.topic_status, f.forum_id, f.forum_status + FROM ' . ATTACHMENTS_TABLE . ' a + LEFT JOIN ' . POSTS_TABLE . ' p + ON (a.post_msg_id = p.post_id AND a.in_message = 0) + LEFT JOIN ' . TOPICS_TABLE . ' t + ON (t.topic_id = p.topic_id AND a.in_message = 0) + LEFT JOIN ' . FORUMS_TABLE . ' f + ON (f.forum_id = t.forum_id AND a.in_message = 0) + WHERE a.poster_id = ' . $user->data['user_id'] . ' + AND a.is_orphan = 0 + AND ' . $db->sql_in_set('a.attach_id', $delete_ids); $result = $db->sql_query($sql); $delete_ids = array(); while ($row = $db->sql_fetchrow($result)) { + if (!$auth->acl_get('m_edit', $row['forum_id']) && ($row['forum_status'] == ITEM_LOCKED || $row['topic_status'] == ITEM_LOCKED || $row['post_edit_locked'])) + { + continue; + } + $delete_ids[] = $row['attach_id']; } $db->sql_freeresult($result); } - if ($delete && sizeof($delete_ids)) + if ($delete && count($delete_ids)) { $s_hidden_fields = array( 'delete' => 1 @@ -75,12 +86,12 @@ class ucp_attachments unset($attachment_manager); meta_refresh(3, $this->u_action); - $message = ((sizeof($delete_ids) == 1) ? $user->lang['ATTACHMENT_DELETED'] : $user->lang['ATTACHMENTS_DELETED']) . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); + $message = ((count($delete_ids) == 1) ? $user->lang['ATTACHMENT_DELETED'] : $user->lang['ATTACHMENTS_DELETED']) . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); trigger_error($message); } else { - confirm_box(false, (sizeof($delete_ids) == 1) ? 'DELETE_ATTACHMENT' : 'DELETE_ATTACHMENTS', build_hidden_fields($s_hidden_fields)); + confirm_box(false, (count($delete_ids) == 1) ? 'DELETE_ATTACHMENT' : 'DELETE_ATTACHMENTS', build_hidden_fields($s_hidden_fields)); } } @@ -124,10 +135,12 @@ class ucp_attachments $pagination = $phpbb_container->get('pagination'); $start = $pagination->validate_start($start, $config['topics_per_page'], $num_attachments); - $sql = 'SELECT a.*, t.topic_title, p.message_subject as message_title + $sql = 'SELECT a.*, t.topic_title, pr.message_subject as message_title, p.post_edit_locked, t.topic_status, f.forum_id, f.forum_status FROM ' . ATTACHMENTS_TABLE . ' a + LEFT JOIN ' . POSTS_TABLE . ' p ON (a.post_msg_id = p.post_id AND a.in_message = 0) LEFT JOIN ' . TOPICS_TABLE . ' t ON (a.topic_id = t.topic_id AND a.in_message = 0) - LEFT JOIN ' . PRIVMSGS_TABLE . ' p ON (a.post_msg_id = p.msg_id AND a.in_message = 1) + LEFT JOIN ' . FORUMS_TABLE . ' f ON (f.forum_id = t.forum_id AND a.in_message = 0) + LEFT JOIN ' . PRIVMSGS_TABLE . ' pr ON (a.post_msg_id = pr.msg_id AND a.in_message = 1) WHERE a.poster_id = ' . $user->data['user_id'] . " AND a.is_orphan = 0 ORDER BY $order_by"; @@ -164,6 +177,7 @@ class ucp_attachments 'TOPIC_ID' => $row['topic_id'], 'S_IN_MESSAGE' => $row['in_message'], + 'S_LOCKED' => !$row['in_message'] && !$auth->acl_get('m_edit', $row['forum_id']) && ($row['forum_status'] == ITEM_LOCKED || $row['topic_status'] == ITEM_LOCKED || $row['post_edit_locked']), 'U_VIEW_ATTACHMENT' => append_sid("{$phpbb_root_path}download/file.$phpEx", 'id=' . $row['attach_id']), 'U_VIEW_TOPIC' => $view_topic) diff --git a/phpBB/includes/ucp/ucp_auth_link.php b/phpBB/includes/ucp/ucp_auth_link.php index 08aacdef3a..e069f15eb2 100644 --- a/phpBB/includes/ucp/ucp_auth_link.php +++ b/phpBB/includes/ucp/ucp_auth_link.php @@ -55,14 +55,14 @@ class ucp_auth_link $submit = $request->variable('submit', false, false, \phpbb\request\request_interface::POST); // This path is only for primary actions - if (!sizeof($error) && $submit) + if (!count($error) && $submit) { if (!check_form_key('ucp_auth_link')) { $error[] = 'FORM_INVALID'; } - if (!sizeof($error)) + if (!count($error)) { // Any post data could be necessary for auth (un)linking $link_data = $request->get_super_global(\phpbb\request\request_interface::POST); diff --git a/phpBB/includes/ucp/ucp_groups.php b/phpBB/includes/ucp/ucp_groups.php index 352b7d1ec3..2423af86be 100644 --- a/phpBB/includes/ucp/ucp_groups.php +++ b/phpBB/includes/ucp/ucp_groups.php @@ -32,6 +32,9 @@ class ucp_groups global $db, $user, $auth, $cache, $template; global $request, $phpbb_container, $phpbb_log; + /** @var \phpbb\language\language $language Language object */ + $language = $phpbb_container->get('language'); + $user->add_lang('groups'); $return_page = '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $this->u_action . '">', '</a>'); @@ -71,7 +74,7 @@ class ucp_groups } $db->sql_freeresult($result); - if (!sizeof($group_row)) + if (!count($group_row)) { trigger_error('GROUP_NOT_EXIST'); } @@ -330,7 +333,7 @@ class ucp_groups $sql = 'SELECT group_id, group_name, group_colour, group_desc, group_desc_uid, group_desc_bitfield, group_desc_options, group_type, group_founder_manage FROM ' . GROUPS_TABLE . ' - WHERE ' . ((sizeof($group_id_ary)) ? $db->sql_in_set('group_id', $group_id_ary, true) . ' AND ' : '') . " + WHERE ' . ((count($group_id_ary)) ? $db->sql_in_set('group_id', $group_id_ary, true) . ' AND ' : '') . " group_type $sql_and ORDER BY group_type DESC, group_name"; $result = $db->sql_query($sql); @@ -396,7 +399,10 @@ class ucp_groups $action = (isset($_POST['addusers'])) ? 'addusers' : $request->variable('action', ''); $group_id = $request->variable('g', 0); - include($phpbb_root_path . 'includes/functions_display.' . $phpEx); + if (!function_exists('phpbb_get_user_rank')) + { + include($phpbb_root_path . 'includes/functions_display.' . $phpEx); + } add_form_key('ucp_groups'); @@ -562,7 +568,7 @@ class ucp_groups $error = array_merge($error, $colour_error); } - if (!sizeof($error)) + if (!count($error)) { // Only set the rank, colour, etc. if it's changed or if we're adding a new // group. This prevents existing group members being updated if no changes @@ -605,7 +611,7 @@ class ucp_groups } } - if (sizeof($error)) + if (count($error)) { $error = array_map(array(&$user, 'lang'), $error); $group_rank = $submit_ary['rank']; @@ -703,12 +709,12 @@ class ucp_groups 'S_EDIT' => true, 'S_INCLUDE_SWATCH' => true, 'S_FORM_ENCTYPE' => ' enctype="multipart/form-data"', - 'S_ERROR' => (sizeof($error)) ? true : false, + 'S_ERROR' => (count($error)) ? true : false, 'S_SPECIAL_GROUP' => ($group_type == GROUP_SPECIAL) ? true : false, 'S_AVATARS_ENABLED' => ($config['allow_avatar'] && $avatars_enabled), 'S_GROUP_MANAGE' => true, - 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', + 'ERROR_MSG' => (count($error)) ? implode('<br />', $error) : '', 'GROUP_RECEIVE_PM' => (isset($group_row['group_receive_pm']) && $group_row['group_receive_pm']) ? ' checked="checked"' : '', 'GROUP_MESSAGE_LIMIT' => (isset($group_row['group_message_limit'])) ? $group_row['group_message_limit'] : 0, 'GROUP_MAX_RECIPIENTS' => (isset($group_row['group_max_recipients'])) ? $group_row['group_max_recipients'] : 0, @@ -911,7 +917,7 @@ class ucp_groups if (confirm_box(true)) { - if (!sizeof($mark_ary)) + if (!count($mark_ary)) { $start = 0; @@ -934,7 +940,7 @@ class ucp_groups group_user_attributes('default', $group_id, $mark_ary, false, $group_row['group_name'], $group_row); - $start = (sizeof($mark_ary) < 200) ? 0 : $start + 200; + $start = (count($mark_ary) < 200) ? 0 : $start + 200; } else { @@ -1054,13 +1060,27 @@ class ucp_groups if (confirm_box(true)) { + $return_manage_page = '<br /><br />' . $language->lang('RETURN_PAGE', '<a href="' . $this->u_action . '&action=list&g=' . $group_id . '">', '</a>'); + // Add user/s to group if ($error = group_user_add($group_id, false, $name_ary, $group_name, $default, 0, 0, $group_row)) { - trigger_error($user->lang[$error] . $return_page); + $display_message = $language->lang($error); + + if ($error == 'GROUP_USERS_INVALID') + { + // Find which users don't exist + $actual_name_ary = $name_ary; + $actual_user_id_ary = []; + user_get_id_name($actual_user_id_ary, $actual_name_ary, false, true); + + $display_message = $language->lang('GROUP_USERS_INVALID', implode($language->lang('COMMA_SEPARATOR'), array_udiff($name_ary, $actual_name_ary, 'strcasecmp'))); + } + + trigger_error($display_message . $return_manage_page); } - trigger_error($user->lang['GROUP_USERS_ADDED'] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $this->u_action . '&action=list&g=' . $group_id . '">', '</a>')); + trigger_error($language->lang('GROUP_USERS_ADDED') . $return_manage_page); } else { @@ -1073,7 +1093,7 @@ class ucp_groups 'action' => $action ); - confirm_box(false, $user->lang('GROUP_CONFIRM_ADD_USERS', sizeof($name_ary), implode($user->lang['COMMA_SEPARATOR'], $name_ary)), build_hidden_fields($s_hidden_fields)); + confirm_box(false, $user->lang('GROUP_CONFIRM_ADD_USERS', count($name_ary), implode($user->lang['COMMA_SEPARATOR'], $name_ary)), build_hidden_fields($s_hidden_fields)); } trigger_error($user->lang['NO_USERS_ADDED'] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $this->u_action . '&action=list&g=' . $group_id . '">', '</a>')); diff --git a/phpBB/includes/ucp/ucp_login_link.php b/phpBB/includes/ucp/ucp_login_link.php index f4d47e30bb..c1f307eeb5 100644 --- a/phpBB/includes/ucp/ucp_login_link.php +++ b/phpBB/includes/ucp/ucp_login_link.php @@ -39,7 +39,7 @@ class ucp_login_link */ function main($id, $mode) { - global $phpbb_container, $request, $template, $user; + global $phpbb_container, $request, $template, $user, $phpbb_dispatcher; global $phpbb_root_path, $phpEx; // Initialize necessary variables @@ -108,7 +108,7 @@ class ucp_login_link } } - $template->assign_vars(array( + $tpl_ary = array( // Common template elements 'LOGIN_LINK_ERROR' => $login_link_error, 'PASSWORD_CREDENTIAL' => 'login_password', @@ -121,7 +121,24 @@ class ucp_login_link // Login elements 'LOGIN_ERROR' => $login_error, 'LOGIN_USERNAME' => $login_username, - )); + ); + + /** + * Event to perform additional actions before ucp_login_link is displayed + * + * @event core.ucp_login_link_template_after + * @var array data Login link data + * @var \phpbb\auth\provider_interface auth_provider Auth provider + * @var string login_link_error Login link error + * @var string login_error Login error + * @var string login_username Login username + * @var array tpl_ary Template variables + * @since 3.2.4-RC1 + */ + $vars = array('data', 'auth_provider', 'login_link_error', 'login_error', 'login_username', 'tpl_ary'); + extract($phpbb_dispatcher->trigger_event('core.ucp_login_link_template_after', compact($vars))); + + $template->assign_vars($tpl_ary); $this->tpl_name = 'ucp_login_link'; $this->page_title = 'UCP_LOGIN_LINK'; diff --git a/phpBB/includes/ucp/ucp_main.php b/phpBB/includes/ucp/ucp_main.php index 77ac1dfb54..36f45f3f46 100644 --- a/phpBB/includes/ucp/ucp_main.php +++ b/phpBB/includes/ucp/ucp_main.php @@ -28,9 +28,9 @@ class ucp_main var $p_master; var $u_action; - function ucp_main(&$p_master) + function __construct($p_master) { - $this->p_master = &$p_master; + $this->p_master = $p_master; } function main($id, $mode) @@ -77,6 +77,22 @@ class ucp_main // If the user can't see any forums, he can't read any posts because fid of 0 is invalid if (!empty($forum_ary)) { + /** + * Modify sql variables before query is processed + * + * @event core.ucp_main_front_modify_sql + * @var string sql_select SQL select + * @var string sql_from SQL from + * @var array forum_ary Forum array + * @since 3.2.4-RC1 + */ + $vars = array( + 'sql_select', + 'sql_from', + 'forum_ary', + ); + extract($phpbb_dispatcher->trigger_event('core.ucp_main_front_modify_sql', compact($vars))); + $sql = "SELECT t.* $sql_select FROM $sql_from WHERE t.topic_type = " . POST_GLOBAL . ' @@ -144,7 +160,7 @@ class ucp_main $folder_img .= '_mine'; } - $template->assign_block_vars('topicrow', array( + $topicrow = array( 'FORUM_ID' => $forum_id, 'TOPIC_ID' => $topic_id, 'TOPIC_AUTHOR' => get_username_string('username', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), @@ -171,8 +187,30 @@ class ucp_main 'U_LAST_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=$topic_id&p=" . $row['topic_last_post_id']) . '#p' . $row['topic_last_post_id'], 'U_LAST_POST_AUTHOR' => get_username_string('profile', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), 'U_NEWEST_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=$topic_id&view=unread") . '#unread', - 'U_VIEW_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=$topic_id")) + 'U_VIEW_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=$topic_id"), + ); + + /** + * Add template variables to a front topics row. + * + * @event core.ucp_main_front_modify_template_vars + * @var array topicrow Array containing the template variables for the row + * @var array row Array containing the subscribed forum row data + * @var int forum_id Forum ID + * @var string folder_img Folder image + * @var string folder_alt Alt text for the folder image + * @since 3.2.4-RC1 + */ + $vars = array( + 'topicrow', + 'row', + 'forum_id', + 'folder_img', + 'folder_alt', ); + extract($phpbb_dispatcher->trigger_event('core.ucp_main_front_modify_template_vars', compact($vars))); + + $template->assign_block_vars('topicrow', $topicrow); } if ($config['load_user_activity']) @@ -207,7 +245,10 @@ class ucp_main case 'subscribed': - include($phpbb_root_path . 'includes/functions_display.' . $phpEx); + if (!function_exists('topic_status')) + { + include($phpbb_root_path . 'includes/functions_display.' . $phpEx); + } $user->add_lang('viewforum'); @@ -230,10 +271,10 @@ class ucp_main $forums = array_keys($request->variable('f', array(0 => 0))); $topics = array_keys($request->variable('t', array(0 => 0))); - if (sizeof($forums) || sizeof($topics)) + if (count($forums) || count($topics)) { $l_unwatch = ''; - if (sizeof($forums)) + if (count($forums)) { $sql = 'DELETE FROM ' . FORUMS_WATCH_TABLE . ' WHERE ' . $db->sql_in_set('forum_id', $forums) . ' @@ -243,7 +284,7 @@ class ucp_main $l_unwatch .= '_FORUMS'; } - if (sizeof($topics)) + if (count($topics)) { $sql = 'DELETE FROM ' . TOPICS_WATCH_TABLE . ' WHERE ' . $db->sql_in_set('topic_id', $topics) . ' @@ -443,7 +484,10 @@ class ucp_main break; } - include($phpbb_root_path . 'includes/functions_display.' . $phpEx); + if (!function_exists('topic_status')) + { + include($phpbb_root_path . 'includes/functions_display.' . $phpEx); + } $user->add_lang('viewforum'); @@ -453,7 +497,7 @@ class ucp_main $topics = (isset($_POST['t'])) ? array_keys($request->variable('t', array(0 => 0))) : array(); $url = $this->u_action; - if (!sizeof($topics)) + if (!count($topics)) { trigger_error('NO_BOOKMARKS_SELECTED'); } @@ -502,13 +546,16 @@ class ucp_main $draft_subject = $draft_message = ''; add_form_key('ucp_draft'); + include_once($phpbb_root_path . 'includes/message_parser.' . $phpEx); + $message_parser = new parse_message(); + if ($delete) { if (check_form_key('ucp_draft')) { $drafts = array_keys($request->variable('d', array(0 => 0))); - if (sizeof($drafts)) + if (count($drafts)) { $sql = 'DELETE FROM ' . DRAFTS_TABLE . ' WHERE ' . $db->sql_in_set('draft_id', $drafts) . ' @@ -535,9 +582,19 @@ class ucp_main { if ($draft_message && $draft_subject) { + // $auth->acl_gets can't be used here because it will check for global forum permissions in this case + // In general we don't need too harsh checking here for permissions, as this will be handled later when submitting + $bbcode_status = $auth->acl_get('u_pm_bbcode') || $auth->acl_getf_global('f_bbcode'); + $smilies_status = $auth->acl_get('u_pm_smilies') || $auth->acl_getf_global('f_smilies'); + $img_status = $auth->acl_get('u_pm_img') || $auth->acl_getf_global('f_img'); + $flash_status = $auth->acl_get('u_pm_flash') || $auth->acl_getf_global('f_flash'); + + $message_parser->message = $draft_message; + $message_parser->parse($bbcode_status, $config['allow_post_links'], $smilies_status, $img_status, $flash_status, true, $config['allow_post_links']); + $draft_row = array( 'draft_subject' => $draft_subject, - 'draft_message' => $draft_message + 'draft_message' => $message_parser->message, ); $sql = 'UPDATE ' . DRAFTS_TABLE . ' @@ -594,7 +651,7 @@ class ucp_main } $db->sql_freeresult($result); - if (sizeof($topic_ids)) + if (count($topic_ids)) { $sql = 'SELECT topic_id, forum_id, topic_title FROM ' . TOPICS_TABLE . ' @@ -639,9 +696,16 @@ class ucp_main $insert_url = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=$id&mode=compose&d=" . $draft['draft_id']); } + if (!$submit) + { + $message_parser->message = $draft['draft_message']; + $message_parser->decode_message(); + $draft_message = $message_parser->message; + } + $template_row = array( 'DATE' => $user->format_date($draft['save_time']), - 'DRAFT_MESSAGE' => ($submit) ? $draft_message : $draft['draft_message'], + 'DRAFT_MESSAGE' => $draft_message, 'DRAFT_SUBJECT' => ($submit) ? $draft_subject : $draft['draft_subject'], 'TITLE' => $title, diff --git a/phpBB/includes/ucp/ucp_notifications.php b/phpBB/includes/ucp/ucp_notifications.php index 029588bb23..a6d925f95e 100644 --- a/phpBB/includes/ucp/ucp_notifications.php +++ b/phpBB/includes/ucp/ucp_notifications.php @@ -205,7 +205,7 @@ class ucp_notifications } $template->assign_vars(array( - strtoupper($block) . '_COLS' => sizeof($notification_methods) + 1, + strtoupper($block) . '_COLS' => count($notification_methods) + 1, )); } diff --git a/phpBB/includes/ucp/ucp_pm.php b/phpBB/includes/ucp/ucp_pm.php index d145d66f59..4d02620e89 100644 --- a/phpBB/includes/ucp/ucp_pm.php +++ b/phpBB/includes/ucp/ucp_pm.php @@ -82,7 +82,10 @@ class ucp_pm $mode = 'view'; } - include($phpbb_root_path . 'includes/functions_privmsgs.' . $phpEx); + if (!function_exists('get_folder')) + { + include($phpbb_root_path . 'includes/functions_privmsgs.' . $phpEx); + } switch ($mode) { @@ -104,7 +107,10 @@ class ucp_pm break; } - include($phpbb_root_path . 'includes/ucp/ucp_pm_compose.' . $phpEx); + if (!function_exists('compose_pm')) + { + include($phpbb_root_path . 'includes/ucp/ucp_pm_compose.' . $phpEx); + } compose_pm($id, $mode, $action, $user_folders); $tpl_file = 'posting_body'; @@ -114,7 +120,10 @@ class ucp_pm set_user_message_limit(); get_folder($user->data['user_id']); - include($phpbb_root_path . 'includes/ucp/ucp_pm_options.' . $phpEx); + if (!function_exists('message_options')) + { + include($phpbb_root_path . 'includes/ucp/ucp_pm_options.' . $phpEx); + } message_options($id, $mode, $global_privmsgs_rules, $global_rule_conditions); $tpl_file = 'ucp_pm_options'; @@ -125,8 +134,10 @@ class ucp_pm get_folder($user->data['user_id']); $this->p_name = 'pm'; - // Call another module... please do not try this at home... Hoochie Coochie Man - include($phpbb_root_path . 'includes/ucp/ucp_main.' . $phpEx); + if (!class_exists('ucp_main')) + { + include($phpbb_root_path . 'includes/ucp/ucp_main.' . $phpEx); + } $module = new ucp_main($this); $module->u_action = $this->u_action; @@ -170,6 +181,12 @@ class ucp_pm trigger_error('NO_AUTH_READ_MESSAGE'); } + if ($view == 'print' && (!$config['print_pm'] || !$auth->acl_get('u_pm_printpm'))) + { + send_status_line(403, 'Forbidden'); + trigger_error('NO_AUTH_PRINT_MESSAGE'); + } + // Do not allow hold messages to be seen if ($folder_id == PRIVMSGS_HOLD_BOX) { @@ -369,7 +386,10 @@ class ucp_pm if ($action == 'view_folder') { - include($phpbb_root_path . 'includes/ucp/ucp_pm_viewfolder.' . $phpEx); + if (!function_exists('view_folder')) + { + include($phpbb_root_path . 'includes/ucp/ucp_pm_viewfolder.' . $phpEx); + } view_folder($id, $mode, $folder_id, $folder); $tpl_file = 'ucp_pm_viewfolder'; @@ -387,7 +407,10 @@ class ucp_pm trigger_error('NO_MESSAGE'); } - include($phpbb_root_path . 'includes/ucp/ucp_pm_viewmessage.' . $phpEx); + if (!function_exists('view_message')) + { + include($phpbb_root_path . 'includes/ucp/ucp_pm_viewmessage.' . $phpEx); + } view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row); $tpl_file = ($view == 'print') ? 'ucp_pm_viewmessage_print' : 'ucp_pm_viewmessage'; diff --git a/phpBB/includes/ucp/ucp_pm_compose.php b/phpBB/includes/ucp/ucp_pm_compose.php index 86cdb090c8..cb45112b01 100644 --- a/phpBB/includes/ucp/ucp_pm_compose.php +++ b/phpBB/includes/ucp/ucp_pm_compose.php @@ -33,9 +33,20 @@ function compose_pm($id, $mode, $action, $user_folders = array()) // Needed for handle_message_list_actions() global $refresh, $submit, $preview; - include($phpbb_root_path . 'includes/functions_posting.' . $phpEx); - include($phpbb_root_path . 'includes/functions_display.' . $phpEx); - include($phpbb_root_path . 'includes/message_parser.' . $phpEx); + if (!function_exists('generate_smilies')) + { + include($phpbb_root_path . 'includes/functions_posting.' . $phpEx); + } + + if (!function_exists('display_custom_bbcodes')) + { + include($phpbb_root_path . 'includes/functions_display.' . $phpEx); + } + + if (!class_exists('parse_message')) + { + include($phpbb_root_path . 'includes/message_parser.' . $phpEx); + } if (!$action) { @@ -48,7 +59,6 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $to_group_id = $request->variable('g', 0); $msg_id = $request->variable('p', 0); $draft_id = $request->variable('d', 0); - $lastclick = $request->variable('lastclick', 0); // Reply to all triggered (quote/reply) $reply_to_all = $request->variable('reply_to_all', 0); @@ -80,7 +90,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $group_helper = $phpbb_container->get('group_helper'); // Was cancel pressed? If so then redirect to the appropriate page - if ($cancel || ($current_time - $lastclick < 2 && $submit)) + if ($cancel) { if ($msg_id) { @@ -125,7 +135,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) // Add groups to PM box if ($config['allow_mass_pm'] && $auth->acl_get('u_masspm_group')) { - $sql = 'SELECT g.group_id, g.group_name, g.group_type + $sql = 'SELECT g.group_id, g.group_name, g.group_type, g.group_colour FROM ' . GROUPS_TABLE . ' g'; if (!$auth->acl_gets('a_group', 'a_groupadd', 'a_groupdel')) @@ -148,7 +158,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $group_options = ''; while ($row = $db->sql_fetchrow($result)) { - $group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '">' . $group_helper->get_name($row['group_name']) . '</option>'; + $group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '"' . ($row['group_colour'] ? ' style="color: #' . $row['group_colour'] . '"' : '') . '>' . $group_helper->get_name($row['group_name']) . '</option>'; } $db->sql_freeresult($result); } @@ -406,7 +416,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $quote_username = (isset($post['quote_username'])) ? $post['quote_username'] : ''; $icon_id = (isset($post['icon_id'])) ? $post['icon_id'] : 0; - if (($action == 'reply' || $action == 'quote' || $action == 'quotepost') && !sizeof($address_list) && !$refresh && !$submit && !$preview) + if (($action == 'reply' || $action == 'quote' || $action == 'quotepost') && !count($address_list) && !$refresh && !$submit && !$preview) { // Add the original author as the recipient if quoting a post or only replying and not having checked "reply to all" if ($action == 'quotepost' || !$reply_to_all) @@ -428,7 +438,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) } } } - else if ($action == 'edit' && !sizeof($address_list) && !$refresh && !$submit && !$preview) + else if ($action == 'edit' && !count($address_list) && !$refresh && !$submit && !$preview) { // Rebuild TO and BCC Header $address_list = rebuild_header(array('to' => $post['to_address'], 'bcc' => $post['bcc_address'])); @@ -561,7 +571,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) unset($list[$user->data['user_id']]); } - $max_recipients = ($max_recipients < sizeof($list)) ? sizeof($list) : $max_recipients; + $max_recipients = ($max_recipients < count($list)) ? count($list) : $max_recipients; unset($list); } @@ -584,7 +594,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) } // Check for too many recipients - if (!empty($address_list['u']) && $max_recipients && sizeof($address_list['u']) > $max_recipients) + if (!empty($address_list['u']) && $max_recipients && count($address_list['u']) > $max_recipients) { $address_list = get_recipients($address_list, $max_recipients); $error[] = $user->lang('TOO_MANY_RECIPIENTS', $max_recipients); @@ -659,13 +669,16 @@ function compose_pm($id, $mode, $action, $user_folders = array()) { if (confirm_box(true)) { + $message_parser->message = $message; + $message_parser->parse($bbcode_status, $url_status, $smilies_status, $img_status, $flash_status, true, $url_status); + $sql = 'INSERT INTO ' . DRAFTS_TABLE . ' ' . $db->sql_build_array('INSERT', array( 'user_id' => $user->data['user_id'], 'topic_id' => 0, 'forum_id' => 0, 'save_time' => $current_time, 'draft_subject' => $subject, - 'draft_message' => $message + 'draft_message' => $message_parser->message, ) ); $db->sql_query($sql); @@ -788,7 +801,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) // Parse Attachments - before checksum is calculated $message_parser->parse_attachments('fileupload', $action, 0, $submit, $preview, $refresh, true); - if (sizeof($message_parser->warn_msg) && !($remove_u || $remove_g || $add_to || $add_bcc)) + if (count($message_parser->warn_msg) && !($remove_u || $remove_g || $add_to || $add_bcc)) { $error[] = implode('<br />', $message_parser->warn_msg); $message_parser->warn_msg = array(); @@ -798,7 +811,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $message_parser->parse($enable_bbcode, ($config['allow_post_links']) ? $enable_urls : false, $enable_smilies, $img_status, $flash_status, true, $config['allow_post_links']); // On a refresh we do not care about message parsing errors - if (sizeof($message_parser->warn_msg) && !$refresh) + if (count($message_parser->warn_msg) && !$refresh) { $error[] = implode('<br />', $message_parser->warn_msg); } @@ -825,14 +838,14 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $error[] = $user->lang['EMPTY_MESSAGE_SUBJECT']; } - if (!sizeof($address_list)) + if (!count($address_list)) { $error[] = $user->lang['NO_RECIPIENT']; } } // Store message, sync counters - if (!sizeof($error) && $submit) + if (!count($error) && $submit) { $pm_data = array( 'msg_id' => (int) $msg_id, @@ -889,7 +902,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) } // Preview - if (!sizeof($error) && $preview) + if (!count($error) && $preview) { $preview_message = $message_parser->format_display($enable_bbcode, $enable_urls, $enable_smilies, false); @@ -909,7 +922,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) } // Attachment Preview - if (sizeof($message_parser->attachment_data)) + if (count($message_parser->attachment_data)) { $template->assign_var('S_HAS_ATTACHMENTS', true); @@ -929,7 +942,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $preview_subject = censor_text($subject); - if (!sizeof($error)) + if (!count($error)) { $template->assign_vars(array( 'PREVIEW_SUBJECT' => $preview_subject, @@ -943,7 +956,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) } // Decode text for message display - $bbcode_uid = (($action == 'quote' || $action == 'forward') && !$preview && !$refresh && (!sizeof($error) || (sizeof($error) && !$submit))) ? $bbcode_uid : $message_parser->bbcode_uid; + $bbcode_uid = (($action == 'quote' || $action == 'forward') && !$preview && !$refresh && (!count($error) || (count($error) && !$submit))) ? $bbcode_uid : $message_parser->bbcode_uid; $message_parser->decode_message($bbcode_uid); @@ -954,7 +967,16 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $post_id = $request->variable('p', 0); if ($config['allow_post_links']) { - $message_link = "[url=" . generate_board_url() . "/viewtopic.$phpEx?p={$post_id}#p{$post_id}]{$user->lang['SUBJECT']}{$user->lang['COLON']} {$message_subject}[/url]\n\n"; + $message_link = generate_board_url() . "/viewtopic.$phpEx?p={$post_id}#p{$post_id}"; + $message_link_subject = "{$user->lang['SUBJECT']}{$user->lang['COLON']} {$message_subject}"; + if ($bbcode_status) + { + $message_link = "[url=" . $message_link . "]" . $message_link_subject . "[/url]\n\n"; + } + else + { + $message_link = $message_link . " - " . $message_link_subject . "\n\n"; + } } else { @@ -974,16 +996,27 @@ function compose_pm($id, $mode, $action, $user_folders = array()) { $quote_attributes['post_id'] = $post['msg_id']; } - $quote_text = $phpbb_container->get('text_formatter.utils')->generate_quote( - censor_text($message_parser->message), - $quote_attributes - ); - $message_parser->message = $message_link . $quote_text . "\n\n"; + + /** @var \phpbb\language\language $language */ + $language = $phpbb_container->get('language'); + /** @var \phpbb\textformatter\utils_interface $text_formatter_utils */ + $text_formatter_utils = $phpbb_container->get('text_formatter.utils'); + phpbb_format_quote($language, $message_parser, $text_formatter_utils, $bbcode_status, $quote_attributes, $message_link); } if (($action == 'reply' || $action == 'quote' || $action == 'quotepost') && !$preview && !$refresh) { $message_subject = ((!preg_match('/^Re:/', $message_subject)) ? 'Re: ' : '') . censor_text($message_subject); + + /** + * This event allows you to modify the PM subject of the PM being quoted + * + * @event core.pm_modify_message_subject + * @var string message_subject String with the PM subject already censored. + * @since 3.2.8-RC1 + */ + $vars = array('message_subject'); + extract($phpbb_dispatcher->trigger_event('core.pm_modify_message_subject', compact($vars))); } if ($action == 'forward' && !$preview && !$refresh && !$submit) @@ -1035,7 +1068,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) // Build address list for display // array('u' => array($author_id => 'to')); - if (sizeof($address_list)) + if (count($address_list)) { // Get Usernames and Group Names $result = array(); @@ -1174,8 +1207,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) break; } - $s_hidden_fields = '<input type="hidden" name="lastclick" value="' . $current_time . '" />'; - $s_hidden_fields .= (isset($check_value)) ? '<input type="hidden" name="status_switch" value="' . $check_value . '" />' : ''; + $s_hidden_fields = (isset($check_value)) ? '<input type="hidden" name="status_switch" value="' . $check_value . '" />' : ''; $s_hidden_fields .= ($draft_id || isset($_REQUEST['draft_loaded'])) ? '<input type="hidden" name="draft_loaded" value="' . ((isset($_REQUEST['draft_loaded'])) ? $request->variable('draft_loaded', 0) : $draft_id) . '" />' : ''; $form_enctype = (@ini_get('file_uploads') == '0' || strtolower(@ini_get('file_uploads')) == 'off' || !$config['allow_pm_attach'] || !$auth->acl_get('u_pm_attach')) ? '' : ' enctype="multipart/form-data"'; @@ -1184,7 +1216,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $controller_helper = $phpbb_container->get('controller.helper'); // Start assigning vars for main posting page ... - $template->assign_vars(array( + $template_ary = array( 'L_POST_A' => $page_title, 'L_ICON' => $user->lang['PM_ICON'], 'L_MESSAGE_BODY_EXPLAIN' => $user->lang('MESSAGE_BODY_EXPLAIN', (int) $config['max_post_chars']), @@ -1198,7 +1230,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) 'URL_STATUS' => ($url_status) ? $user->lang['URL_IS_ON'] : $user->lang['URL_IS_OFF'], 'MAX_FONT_SIZE' => (int) $config['max_post_font_size'], 'MINI_POST_IMG' => $user->img('icon_post_target', $user->lang['PM']), - 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + 'ERROR' => (count($error)) ? implode('<br />', $error) : '', 'MAX_RECIPIENTS' => ($config['allow_mass_pm'] && ($auth->acl_get('u_masspm') || $auth->acl_get('u_masspm_group'))) ? $max_recipients : 0, 'S_COMPOSE_PM' => true, @@ -1229,7 +1261,19 @@ function compose_pm($id, $mode, $action, $user_folders = array()) 'S_CLOSE_PROGRESS_WINDOW' => isset($_POST['add_file']), 'U_PROGRESS_BAR' => append_sid("{$phpbb_root_path}posting.$phpEx", 'f=0&mode=popup'), 'UA_PROGRESS_BAR' => addslashes(append_sid("{$phpbb_root_path}posting.$phpEx", 'f=0&mode=popup')), - )); + ); + + /** + * Modify the default template vars + * + * @event core.ucp_pm_compose_template + * @var array template_ary Template variables + * @since 3.2.6-RC1 + */ + $vars = array('template_ary'); + extract($phpbb_dispatcher->trigger_event('core.ucp_pm_compose_template', compact($vars))); + + $template->assign_vars($template_ary); // Build custom bbcodes array display_custom_bbcodes(); @@ -1262,7 +1306,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) function handle_message_list_actions(&$address_list, &$error, $remove_u, $remove_g, $add_to, $add_bcc) { global $auth, $db, $user; - global $request; + global $request, $phpbb_dispatcher; // Delete User [TO/BCC] if ($remove_u && $request->variable('remove_u', array(0 => ''))) @@ -1300,7 +1344,7 @@ function handle_message_list_actions(&$address_list, &$error, $remove_u, $remove } // If add to or add bcc not pressed, users could still have usernames listed they want to add... - if (!$add_to && !$add_bcc && (sizeof($group_list) || sizeof($usernames))) + if (!$add_to && !$add_bcc && (count($group_list) || count($usernames))) { $add_to = true; @@ -1321,7 +1365,7 @@ function handle_message_list_actions(&$address_list, &$error, $remove_u, $remove { $type = ($add_to) ? 'to' : 'bcc'; - if (sizeof($group_list)) + if (count($group_list)) { foreach ($group_list as $group_id) { @@ -1333,13 +1377,13 @@ function handle_message_list_actions(&$address_list, &$error, $remove_u, $remove $user_id_ary = array(); // Reveal the correct user_ids - if (sizeof($usernames)) + if (count($usernames)) { $user_id_ary = array(); user_get_id_name($user_id_ary, $usernames, array(USER_NORMAL, USER_FOUNDER, USER_INACTIVE)); // If there are users not existing, we will at least print a notice... - if (!sizeof($user_id_ary)) + if (!count($user_id_ary)) { $error[] = $user->lang['PM_NO_USERS']; } @@ -1408,7 +1452,7 @@ function handle_message_list_actions(&$address_list, &$error, $remove_u, $remove $error[] = $user->lang['PM_USERS_REMOVED_NO_PERMISSION']; } - if (!sizeof(array_keys($address_list['u']))) + if (!count(array_keys($address_list['u']))) { return; } @@ -1439,6 +1483,21 @@ function handle_message_list_actions(&$address_list, &$error, $remove_u, $remove $error[] = $user->lang['PM_USERS_REMOVED_NO_PERMISSION']; } } + + /** + * Event for additional message list actions + * + * @event core.message_list_actions + * @var array address_list The assoc array with the recipient user/group ids + * @var array error The array containing error data + * @var bool remove_u The variable for removing a user + * @var bool remove_g The variable for removing a group + * @var bool add_to The variable for adding a user to the [TO] field + * @var bool add_bcc The variable for adding a user to the [BCC] field + * @since 3.2.4-RC1 + */ + $vars = array('address_list', 'error', 'remove_u', 'remove_g', 'add_to', 'add_bcc'); + extract($phpbb_dispatcher->trigger_event('core.message_list_actions', compact($vars))); } /** @@ -1466,7 +1525,7 @@ function num_recipients($address_list) foreach ($address_list as $field => $adr_ary) { - $num_recipients += sizeof($adr_ary); + $num_recipients += count($adr_ary); } return $num_recipients; diff --git a/phpBB/includes/ucp/ucp_pm_options.php b/phpBB/includes/ucp/ucp_pm_options.php index 2458c4118d..3861962516 100644 --- a/phpBB/includes/ucp/ucp_pm_options.php +++ b/phpBB/includes/ucp/ucp_pm_options.php @@ -521,7 +521,7 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit $action_option = $request->variable('action_option', ''); $back = (isset($_REQUEST['back'])) ? $request->variable('back', array('' => 0)) : array(); - if (sizeof($back)) + if (count($back)) { if ($action_option) { diff --git a/phpBB/includes/ucp/ucp_pm_viewfolder.php b/phpBB/includes/ucp/ucp_pm_viewfolder.php index b5bb406d7d..09e7bf4d7c 100644 --- a/phpBB/includes/ucp/ucp_pm_viewfolder.php +++ b/phpBB/includes/ucp/ucp_pm_viewfolder.php @@ -39,7 +39,7 @@ function view_folder($id, $mode, $folder_id, $folder) // Grab icons $icons = $cache->obtain_icons(); - $color_rows = array('marked', 'replied'); + $color_rows = array('message_reported', 'marked', 'replied'); $_module = new p_master(); $_module->list_modules('ucp'); @@ -114,7 +114,7 @@ function view_folder($id, $mode, $folder_id, $folder) ); // Okay, lets dump out the page ... - if (sizeof($folder_info['pm_list'])) + if (count($folder_info['pm_list'])) { $address_list = array(); @@ -138,9 +138,9 @@ function view_folder($id, $mode, $folder_id, $folder) $row_indicator = ''; foreach ($color_rows as $var) { - if (($var != 'friend' && $var != 'foe' && $row['pm_' . $var]) + if (($var !== 'friend' && $var !== 'foe' && $row[($var === 'message_reported') ? $var : "pm_{$var}"]) || - (($var == 'friend' || $var == 'foe') && isset(${$var}[$row['author_id']]) && ${$var}[$row['author_id']])) + (($var === 'friend' || $var === 'foe') && isset(${$var}[$row['author_id']]) && ${$var}[$row['author_id']])) { $row_indicator = $var; break; @@ -236,7 +236,7 @@ function view_folder($id, $mode, $folder_id, $folder) $_types = array('u', 'g'); foreach ($_types as $ug_type) { - if (isset($address_temp[$message_id][$ug_type]) && sizeof($address_temp[$message_id][$ug_type])) + if (isset($address_temp[$message_id][$ug_type]) && count($address_temp[$message_id][$ug_type])) { if (!isset($address[$message_id][$ug_type])) { @@ -269,8 +269,8 @@ function view_folder($id, $mode, $folder_id, $folder) // There is the chance that all recipients of the message got deleted. To avoid creating // exports without recipients, we add a bogus "undisclosed recipient". - if (!(isset($address[$message_id]['g']) && sizeof($address[$message_id]['g'])) && - !(isset($address[$message_id]['u']) && sizeof($address[$message_id]['u']))) + if (!(isset($address[$message_id]['g']) && count($address[$message_id]['g'])) && + !(isset($address[$message_id]['u']) && count($address[$message_id]['u']))) { $address[$message_id]['u'] = array(); $address[$message_id]['u']['to'] = array(); diff --git a/phpBB/includes/ucp/ucp_pm_viewmessage.php b/phpBB/includes/ucp/ucp_pm_viewmessage.php index 48d14a133c..7c0091ef47 100644 --- a/phpBB/includes/ucp/ucp_pm_viewmessage.php +++ b/phpBB/includes/ucp/ucp_pm_viewmessage.php @@ -113,7 +113,7 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) $db->sql_freeresult($result); // No attachments exist, but message table thinks they do so go ahead and reset attach flags - if (!sizeof($attachments)) + if (!count($attachments)) { $sql = 'UPDATE ' . PRIVMSGS_TABLE . " SET message_attachment = 0 @@ -134,7 +134,7 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) parse_attachments(false, $message, $attachments, $update_count); // Update the attachment download counts - if (sizeof($update_count)) + if (count($update_count)) { $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET download_count = download_count + 1 @@ -240,7 +240,7 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) 'U_PM_ACTION' => $url . '&mode=compose&f=' . $folder_id . '&p=' . $message_row['msg_id'], - 'S_HAS_ATTACHMENTS' => (sizeof($attachments)) ? true : false, + 'S_HAS_ATTACHMENTS' => (count($attachments)) ? true : false, 'S_DISPLAY_NOTICE' => $display_notice && $message_row['message_attachment'], 'S_AUTHOR_DELETED' => ($author_id == ANONYMOUS) ? true : false, 'S_SPECIAL_FOLDER' => in_array($folder_id, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX)), @@ -267,6 +267,8 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) * @var array user_info User data of the sender * @since 3.1.0-a1 * @changed 3.1.6-RC1 Added user_info into event + * @changed 3.2.2-RC1 Deprecated + * @deprecated 4.0.0 Event name is misspelled and is replaced with new event with correct name */ $vars = array( 'id', @@ -281,6 +283,37 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) ); extract($phpbb_dispatcher->trigger_event('core.ucp_pm_view_messsage', compact($vars))); + /** + * Modify pm and sender data before it is assigned to the template + * + * @event core.ucp_pm_view_message + * @var mixed id Active module category (can be int or string) + * @var string mode Active module + * @var int folder_id ID of the folder the message is in + * @var int msg_id ID of the private message + * @var array folder Array with data of user's message folders + * @var array message_row Array with message data + * @var array cp_row Array with senders custom profile field data + * @var array msg_data Template array with message data + * @var array user_info User data of the sender + * @var array attachments Attachments data + * @since 3.2.2-RC1 + * @changed 3.2.5-RC1 Added attachments + */ + $vars = array( + 'id', + 'mode', + 'folder_id', + 'msg_id', + 'folder', + 'message_row', + 'cp_row', + 'msg_data', + 'user_info', + 'attachments', + ); + extract($phpbb_dispatcher->trigger_event('core.ucp_pm_view_message', compact($vars))); + $template->assign_vars($msg_data); $contact_fields = array( @@ -330,7 +363,7 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) } // Display not already displayed Attachments for this post, we already parsed them. ;) - if (isset($attachments) && sizeof($attachments)) + if (isset($attachments) && count($attachments)) { foreach ($attachments as $attachment) { diff --git a/phpBB/includes/ucp/ucp_prefs.php b/phpBB/includes/ucp/ucp_prefs.php index c2aa910ed0..7785aeb07b 100644 --- a/phpBB/includes/ucp/ucp_prefs.php +++ b/phpBB/includes/ucp/ucp_prefs.php @@ -96,7 +96,7 @@ class ucp_prefs $error[] = 'FORM_INVALID'; } - if (!sizeof($error)) + if (!count($error)) { $sql_ary = array( 'user_allow_pm' => $data['allowpm'], @@ -188,7 +188,7 @@ class ucp_prefs $db->sql_freeresult($result); $template->assign_vars(array( - 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + 'ERROR' => (count($error)) ? implode('<br />', $error) : '', 'S_NOTIFY_EMAIL' => ($data['notifymethod'] == NOTIFY_EMAIL) ? true : false, 'S_NOTIFY_IM' => ($data['notifymethod'] == NOTIFY_IM) ? true : false, @@ -277,7 +277,7 @@ class ucp_prefs $error[] = 'FORM_INVALID'; } - if (!sizeof($error)) + if (!count($error)) { $user->optionset('viewimg', $data['images']); $user->optionset('viewflash', $data['flash']); @@ -412,7 +412,7 @@ class ucp_prefs extract($phpbb_dispatcher->trigger_event('core.ucp_prefs_view_after', compact($vars))); $template->assign_vars(array( - 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + 'ERROR' => (count($error)) ? implode('<br />', $error) : '', 'S_IMAGES' => $data['images'], 'S_FLASH' => $data['flash'], diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php index b7f8501fe4..36ab3d0463 100644 --- a/phpBB/includes/ucp/ucp_profile.php +++ b/phpBB/includes/ucp/ucp_profile.php @@ -98,7 +98,7 @@ class ucp_profile $passwords_manager = $phpbb_container->get('passwords.manager'); // Only check the new password against the previous password if there have been no errors - if (!sizeof($error) && $auth->acl_get('u_chgpasswd') && $data['new_password'] && $passwords_manager->check($data['new_password'], $user->data['user_password'])) + if (!count($error) && $auth->acl_get('u_chgpasswd') && $data['new_password'] && $passwords_manager->check($data['new_password'], $user->data['user_password'])) { $error[] = 'SAME_PASSWORD_ERROR'; } @@ -125,7 +125,7 @@ class ucp_profile $vars = array('data', 'submit', 'error'); extract($phpbb_dispatcher->trigger_event('core.ucp_profile_reg_details_validate', compact($vars))); - if (!sizeof($error)) + if (!count($error)) { $sql_ary = array( 'username' => ($auth->acl_get('u_chgname') && $config['allow_namechange']) ? $data['username'] : $user->data['username'], @@ -133,7 +133,6 @@ class ucp_profile 'user_email' => ($auth->acl_get('u_chgemail')) ? $data['email'] : $user->data['user_email'], 'user_email_hash' => ($auth->acl_get('u_chgemail')) ? phpbb_email_hash($data['email']) : $user->data['user_email_hash'], 'user_password' => ($auth->acl_get('u_chgpasswd') && $data['new_password']) ? $passwords_manager->hash($data['new_password']) : $user->data['user_password'], - 'user_passchg' => ($auth->acl_get('u_chgpasswd') && $data['new_password']) ? time() : 0, ); if ($auth->acl_get('u_chgname') && $config['allow_namechange'] && $data['username'] != $user->data['username']) @@ -147,6 +146,8 @@ class ucp_profile if ($auth->acl_get('u_chgpasswd') && $data['new_password'] && !$passwords_manager->check($data['new_password'], $user->data['user_password'])) { + $sql_ary['user_passchg'] = time(); + $user->reset_login_keys(); $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_NEW_PASSWORD', false, array( 'reportee_id' => $user->data['user_id'], @@ -159,7 +160,7 @@ class ucp_profile $phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_UPDATE_EMAIL', false, array( 'reportee_id' => $user->data['user_id'], $user->data['username'], - $data['user_email'], + $user->data['user_email'], $data['email'] )); } @@ -220,7 +221,7 @@ class ucp_profile $vars = array('data', 'sql_ary'); extract($phpbb_dispatcher->trigger_event('core.ucp_profile_reg_details_sql_ary', compact($vars))); - if (sizeof($sql_ary)) + if (count($sql_ary)) { $sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' @@ -257,7 +258,7 @@ class ucp_profile } $template->assign_vars(array( - 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + 'ERROR' => (count($error)) ? implode('<br />', $error) : '', 'USERNAME' => $data['username'], 'EMAIL' => $data['email'], @@ -343,7 +344,7 @@ class ucp_profile // validate custom profile fields $cp->submit_cp_field('profile', $user->get_iso_lang_id(), $cp_data, $cp_error); - if (sizeof($cp_error)) + if (count($cp_error)) { $error = array_merge($error, $cp_error); } @@ -365,7 +366,7 @@ class ucp_profile $vars = array('data', 'submit', 'error'); extract($phpbb_dispatcher->trigger_event('core.ucp_profile_validate_profile_info', compact($vars))); - if (!sizeof($error)) + if (!count($error)) { $data['notify'] = $user->data['user_notify_type']; @@ -449,7 +450,7 @@ class ucp_profile } $template->assign_vars(array( - 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + 'ERROR' => (count($error)) ? implode('<br />', $error) : '', 'S_JABBER_ENABLED' => $config['jab_enable'], 'JABBER' => $data['jabber'], )); @@ -469,8 +470,15 @@ class ucp_profile trigger_error('NO_AUTH_SIGNATURE'); } - include($phpbb_root_path . 'includes/functions_posting.' . $phpEx); - include($phpbb_root_path . 'includes/functions_display.' . $phpEx); + if (!function_exists('generate_smilies')) + { + include($phpbb_root_path . 'includes/functions_posting.' . $phpEx); + } + + if (!function_exists('display_custom_bbcodes')) + { + include($phpbb_root_path . 'includes/functions_display.' . $phpEx); + } $preview = $request->is_set_post('preview'); @@ -537,7 +545,7 @@ class ucp_profile 'sig' ); - if (sizeof($warn_msg)) + if (count($warn_msg)) { $error += $warn_msg; } @@ -549,7 +557,7 @@ class ucp_profile } else { - if (!sizeof($error)) + if (!count($error)) { $user->optionset('sig_bbcode', $enable_bbcode); $user->optionset('sig_smilies', $enable_smilies); @@ -594,7 +602,7 @@ class ucp_profile $controller_helper = $phpbb_container->get('controller.helper'); $template->assign_vars(array( - 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + 'ERROR' => (count($error)) ? implode('<br />', $error) : '', 'SIGNATURE' => $decoded_message['text'], 'SIGNATURE_PREVIEW' => $signature_preview, @@ -753,7 +761,7 @@ class ucp_profile $avatar = phpbb_get_user_avatar($user->data, 'USER_AVATAR', true); $template->assign_vars(array( - 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + 'ERROR' => (count($error)) ? implode('<br />', $error) : '', 'AVATAR' => $avatar, 'S_FORM_ENCTYPE' => ' enctype="multipart/form-data"', @@ -778,7 +786,7 @@ class ucp_profile $error[] = 'FORM_INVALID'; } - if (!sizeof($error)) + if (!count($error)) { if (!empty($keys)) { @@ -825,7 +833,7 @@ class ucp_profile } $template->assign_vars(array( - 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + 'ERROR' => (count($error)) ? implode('<br />', $error) : '', 'L_TITLE' => $user->lang['UCP_PROFILE_' . strtoupper($mode)], diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php index 594100ac65..0e673cb692 100644 --- a/phpBB/includes/ucp/ucp_register.php +++ b/phpBB/includes/ucp/ucp_register.php @@ -166,8 +166,8 @@ class ucp_register ->format($user->lang['DATE_FORMAT'], true); unset($now); - $template->assign_vars(array( - 'S_LANG_OPTIONS' => (sizeof($lang_row) > 1) ? language_select($user_lang) : '', + $template_vars = array( + 'S_LANG_OPTIONS' => (count($lang_row) > 1) ? language_select($user_lang) : '', 'L_COPPA_NO' => sprintf($user->lang['UCP_COPPA_BEFORE'], $coppa_birthday), 'L_COPPA_YES' => sprintf($user->lang['UCP_COPPA_ON_AFTER'], $coppa_birthday), @@ -180,12 +180,12 @@ class ucp_register 'COOKIE_NAME' => $config['cookie_name'], 'COOKIE_PATH' => $config['cookie_path'], - )); + ); } else { - $template->assign_vars(array( - 'S_LANG_OPTIONS' => (sizeof($lang_row) > 1) ? language_select($user_lang) : '', + $template_vars = array( + 'S_LANG_OPTIONS' => (count($lang_row) > 1) ? language_select($user_lang) : '', 'L_TERMS_OF_USE' => sprintf($user->lang['TERMS_OF_USE_CONTENT'], $config['sitename'], generate_board_url()), 'S_SHOW_COPPA' => false, @@ -195,11 +195,32 @@ class ucp_register 'COOKIE_NAME' => $config['cookie_name'], 'COOKIE_PATH' => $config['cookie_path'], - ) ); } + + $tpl_name = 'ucp_agreement'; + + /** + * Allows to modify the agreements. + * + * @event core.ucp_register_agreement_modify_template_data + * @var string tpl_name Template file + * @var array template_vars Array with data about to be assigned to the template + * @var array s_hidden_fields Array with hidden form elements + * @var array lang_row Array with available languages, read only + * @since 3.2.2-RC1 + */ + $vars = array('tpl_name', 'template_vars', 's_hidden_fields', 'lang_row'); + extract($phpbb_dispatcher->trigger_event('core.ucp_register_agreement_modify_template_data', compact($vars))); + unset($lang_row); + $template_vars = array_merge($template_vars, array( + 'S_HIDDEN_FIELDS' => build_hidden_fields($s_hidden_fields), + )); + + $template->assign_vars($template_vars); + /** * Allows to modify the agreements. * @@ -207,10 +228,11 @@ class ucp_register * * @event core.ucp_register_agreement * @since 3.1.6-RC1 + * @deprecated 3.2.2-RC1 Replaced by core.ucp_register_agreement_modify_template_data and to be removed in 3.3.0-RC1 */ $phpbb_dispatcher->dispatch('core.ucp_register_agreement'); - $this->tpl_name = 'ucp_agreement'; + $this->tpl_name = $tpl_name; return; } @@ -297,7 +319,7 @@ class ucp_register // validate custom profile fields $cp->submit_cp_field('register', $user->get_iso_lang_id(), $cp_data, $error); - if (!sizeof($error)) + if (!count($error)) { if ($data['new_password'] != $data['password_confirm']) { @@ -318,7 +340,7 @@ class ucp_register $vars = array('submit', 'data', 'cp_data', 'error'); extract($phpbb_dispatcher->trigger_event('core.ucp_register_data_after', compact($vars))); - if (!sizeof($error)) + if (!count($error)) { $server_url = generate_board_url(); @@ -459,6 +481,32 @@ class ucp_register ); } + /** + * Modify messenger data before welcome mail is sent + * + * @event core.ucp_register_welcome_email_before + * @var array user_row Array with user registration data + * @var array cp_data Array with custom profile fields data + * @var array data Array with current ucp registration data + * @var string message Message to be displayed to the user after registration + * @var string server_url Server URL + * @var int user_id New user ID + * @var string user_actkey User activation key + * @var messenger messenger phpBB Messenger + * @since 3.2.4-RC1 + */ + $vars = array( + 'user_row', + 'cp_data', + 'data', + 'message', + 'server_url', + 'user_id', + 'user_actkey', + 'messenger', + ); + extract($phpbb_dispatcher->trigger_event('core.ucp_register_welcome_email_before', compact($vars))); + $messenger->send(NOTIFY_EMAIL); } @@ -486,6 +534,30 @@ class ucp_register } } + /** + * Perform additional actions after user registration + * + * @event core.ucp_register_register_after + * @var array user_row Array with user registration data + * @var array cp_data Array with custom profile fields data + * @var array data Array with current ucp registration data + * @var string message Message to be displayed to the user after registration + * @var string server_url Server URL + * @var int user_id New user ID + * @var string user_actkey User activation key + * @since 3.2.4-RC1 + */ + $vars = array( + 'user_row', + 'cp_data', + 'data', + 'message', + 'server_url', + 'user_id', + 'user_actkey', + ); + extract($phpbb_dispatcher->trigger_event('core.ucp_register_register_after', compact($vars))); + $message = $message . '<br /><br />' . sprintf($user->lang['RETURN_INDEX'], '<a href="' . append_sid("{$phpbb_root_path}index.$phpEx") . '">', '</a>'); trigger_error($message); } @@ -505,7 +577,6 @@ class ucp_register { $s_hidden_fields = array_merge($s_hidden_fields, $captcha->get_hidden_fields()); } - $s_hidden_fields = build_hidden_fields($s_hidden_fields); // Visual Confirmation - Show images if ($config['enable_confirm']) @@ -531,8 +602,7 @@ class ucp_register // Assign template vars for timezone select phpbb_timezone_select($template, $user, $data['tz'], true); - $template->assign_vars(array( - 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + $template_vars = array( 'USERNAME' => $data['username'], 'PASSWORD' => $data['new_password'], 'PASSWORD_CONFIRM' => $data['password_confirm'], @@ -547,13 +617,41 @@ class ucp_register 'S_CONFIRM_REFRESH' => ($config['enable_confirm'] && $config['confirm_refresh']) ? true : false, 'S_REGISTRATION' => true, 'S_COPPA' => $coppa, - 'S_HIDDEN_FIELDS' => $s_hidden_fields, 'S_UCP_ACTION' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register'), 'COOKIE_NAME' => $config['cookie_name'], 'COOKIE_PATH' => $config['cookie_path'], + ); + + $tpl_name = 'ucp_register'; + + /** + * Modify template data on the registration page + * + * @event core.ucp_register_modify_template_data + * @var array template_vars Array with template data + * @var array data Array with user data, read only + * @var array error Array with errors + * @var array s_hidden_fields Array with hidden field elements + * @var string tpl_name Template name + * @since 3.2.2-RC1 + */ + $vars = array( + 'template_vars', + 'data', + 'error', + 's_hidden_fields', + 'tpl_name', + ); + extract($phpbb_dispatcher->trigger_event('core.ucp_register_modify_template_data', compact($vars))); + + $template_vars = array_merge($template_vars, array( + 'ERROR' => (count($error)) ? implode('<br />', $error) : '', + 'S_HIDDEN_FIELDS' => build_hidden_fields($s_hidden_fields), )); + $template->assign_vars($template_vars); + // $user->profile_fields = array(); @@ -561,8 +659,7 @@ class ucp_register $cp->generate_profile_fields('register', $user->get_iso_lang_id()); // - $this->tpl_name = 'ucp_register'; - $this->page_title = 'UCP_REGISTRATION'; + $this->tpl_name = $tpl_name; } /** diff --git a/phpBB/includes/ucp/ucp_remind.php b/phpBB/includes/ucp/ucp_remind.php index f46df99edb..e50428bfea 100644 --- a/phpBB/includes/ucp/ucp_remind.php +++ b/phpBB/includes/ucp/ucp_remind.php @@ -50,11 +50,16 @@ class ucp_remind trigger_error('FORM_INVALID'); } + if (empty($email)) + { + trigger_error('NO_EMAIL_USER'); + } + $sql_array = array( 'SELECT' => 'user_id, username, user_permissions, user_email, user_jabber, user_notify_type, user_type, user_lang, user_inactive_reason', 'FROM' => array(USERS_TABLE => 'u'), - 'WHERE' => "user_email_hash = '" . $db->sql_escape(phpbb_email_hash($email)) . "' - AND username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'" + 'WHERE' => "user_email_hash = '" . $db->sql_escape(phpbb_email_hash($email)) . "'" . + (!empty($username) ? " AND username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'" : ''), ); /** @@ -74,82 +79,87 @@ class ucp_remind extract($phpbb_dispatcher->trigger_event('core.ucp_remind_modify_select_sql', compact($vars))); $sql = $db->sql_build_query('SELECT', $sql_array); - $result = $db->sql_query($sql); - $user_row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); + $result = $db->sql_query_limit($sql, 2); // don't waste resources on more rows than we need + $rowset = $db->sql_fetchrowset($result); - if (!$user_row) + if (count($rowset) > 1) { - trigger_error('NO_EMAIL_USER'); - } + $db->sql_freeresult($result); - if ($user_row['user_type'] == USER_IGNORE) - { - trigger_error('NO_USER'); + $template->assign_vars(array( + 'USERNAME_REQUIRED' => true, + 'EMAIL' => $email, + )); } - - if ($user_row['user_type'] == USER_INACTIVE) + else { - if ($user_row['user_inactive_reason'] == INACTIVE_MANUAL) + $message = $user->lang['PASSWORD_UPDATED_IF_EXISTED'] . '<br /><br />' . sprintf($user->lang['RETURN_INDEX'], '<a href="' . append_sid("{$phpbb_root_path}index.$phpEx") . '">', '</a>'); + + if (empty($rowset)) { - trigger_error('ACCOUNT_DEACTIVATED'); + trigger_error($message); } - else + + $user_row = $rowset[0]; + $db->sql_freeresult($result); + + if (!$user_row) { - trigger_error('ACCOUNT_NOT_ACTIVATED'); + trigger_error($message); } - } - // Check users permissions - $auth2 = new \phpbb\auth\auth(); - $auth2->acl($user_row); + if ($user_row['user_type'] == USER_IGNORE || $user_row['user_type'] == USER_INACTIVE) + { + trigger_error($message); + } - if (!$auth2->acl_get('u_chgpasswd')) - { - send_status_line(403, 'Forbidden'); - trigger_error('NO_AUTH_PASSWORD_REMINDER'); - } + // Check users permissions + $auth2 = new \phpbb\auth\auth(); + $auth2->acl($user_row); - $server_url = generate_board_url(); + if (!$auth2->acl_get('u_chgpasswd')) + { + trigger_error($message); + } - // Make password at least 8 characters long, make it longer if admin wants to. - // gen_rand_string() however has a limit of 12 or 13. - $user_password = gen_rand_string_friendly(max(8, mt_rand((int) $config['min_pass_chars'], (int) $config['max_pass_chars']))); + $server_url = generate_board_url(); - // For the activation key a random length between 6 and 10 will do. - $user_actkey = gen_rand_string(mt_rand(6, 10)); + // Make password at least 8 characters long, make it longer if admin wants to. + // gen_rand_string() however has a limit of 12 or 13. + $user_password = gen_rand_string_friendly(max(8, mt_rand((int) $config['min_pass_chars'], (int) $config['max_pass_chars']))); - // Instantiate passwords manager - /* @var $manager \phpbb\passwords\manager */ - $passwords_manager = $phpbb_container->get('passwords.manager'); + // For the activation key a random length between 6 and 10 will do. + $user_actkey = gen_rand_string(mt_rand(6, 10)); - $sql = 'UPDATE ' . USERS_TABLE . " - SET user_newpasswd = '" . $db->sql_escape($passwords_manager->hash($user_password)) . "', user_actkey = '" . $db->sql_escape($user_actkey) . "' - WHERE user_id = " . $user_row['user_id']; - $db->sql_query($sql); + // Instantiate passwords manager + /* @var $manager \phpbb\passwords\manager */ + $passwords_manager = $phpbb_container->get('passwords.manager'); - include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_newpasswd = '" . $db->sql_escape($passwords_manager->hash($user_password)) . "', user_actkey = '" . $db->sql_escape($user_actkey) . "' + WHERE user_id = " . $user_row['user_id']; + $db->sql_query($sql); - $messenger = new messenger(false); + include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); - $messenger->template('user_activate_passwd', $user_row['user_lang']); + $messenger = new messenger(false); - $messenger->set_addresses($user_row); + $messenger->template('user_activate_passwd', $user_row['user_lang']); - $messenger->anti_abuse_headers($config, $user); + $messenger->set_addresses($user_row); - $messenger->assign_vars(array( - 'USERNAME' => htmlspecialchars_decode($user_row['username']), - 'PASSWORD' => htmlspecialchars_decode($user_password), - 'U_ACTIVATE' => "$server_url/ucp.$phpEx?mode=activate&u={$user_row['user_id']}&k=$user_actkey") - ); + $messenger->anti_abuse_headers($config, $user); - $messenger->send($user_row['user_notify_type']); + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($user_row['username']), + 'PASSWORD' => htmlspecialchars_decode($user_password), + 'U_ACTIVATE' => "$server_url/ucp.$phpEx?mode=activate&u={$user_row['user_id']}&k=$user_actkey") + ); - meta_refresh(3, append_sid("{$phpbb_root_path}index.$phpEx")); + $messenger->send($user_row['user_notify_type']); - $message = $user->lang['PASSWORD_UPDATED'] . '<br /><br />' . sprintf($user->lang['RETURN_INDEX'], '<a href="' . append_sid("{$phpbb_root_path}index.$phpEx") . '">', '</a>'); - trigger_error($message); + trigger_error($message); + } } $template->assign_vars(array( diff --git a/phpBB/includes/ucp/ucp_zebra.php b/phpBB/includes/ucp/ucp_zebra.php index fa6a03f87c..b4c561fc76 100644 --- a/phpBB/includes/ucp/ucp_zebra.php +++ b/phpBB/includes/ucp/ucp_zebra.php @@ -47,7 +47,7 @@ class ucp_zebra $data[$var] = $request->variable($var, $default, true); } - if (!empty($data['add']) || sizeof($data['usernames'])) + if (!empty($data['add']) || count($data['usernames'])) { if (confirm_box(true)) { @@ -105,35 +105,35 @@ class ucp_zebra $db->sql_freeresult($result); // remove friends from the username array - $n = sizeof($data['add']); + $n = count($data['add']); $data['add'] = array_diff($data['add'], $friends); - if (sizeof($data['add']) < $n && $mode == 'foes') + if (count($data['add']) < $n && $mode == 'foes') { $error[] = $user->lang['NOT_ADDED_FOES_FRIENDS']; } // remove foes from the username array - $n = sizeof($data['add']); + $n = count($data['add']); $data['add'] = array_diff($data['add'], $foes); - if (sizeof($data['add']) < $n && $mode == 'friends') + if (count($data['add']) < $n && $mode == 'friends') { $error[] = $user->lang['NOT_ADDED_FRIENDS_FOES']; } // remove the user himself from the username array - $n = sizeof($data['add']); + $n = count($data['add']); $data['add'] = array_diff($data['add'], array(utf8_clean_string($user->data['username']))); - if (sizeof($data['add']) < $n) + if (count($data['add']) < $n) { $error[] = $user->lang['NOT_ADDED_' . $l_mode . '_SELF']; } unset($friends, $foes, $n); - if (sizeof($data['add'])) + if (count($data['add'])) { $sql = 'SELECT user_id, user_type FROM ' . USERS_TABLE . ' @@ -159,7 +159,7 @@ class ucp_zebra } $db->sql_freeresult($result); - if (sizeof($user_id_ary)) + if (count($user_id_ary)) { // Remove users from foe list if they are admins or moderators if ($mode == 'foes') @@ -175,7 +175,7 @@ class ucp_zebra $perms = array_unique($perms); - if (sizeof($perms)) + if (count($perms)) { $error[] = $user->lang['NOT_ADDED_FOES_MOD_ADMIN']; } @@ -185,7 +185,7 @@ class ucp_zebra unset($perms); } - if (sizeof($user_id_ary)) + if (count($user_id_ary)) { $sql_mode = ($mode == 'friends') ? 'friend' : 'foe'; @@ -218,7 +218,7 @@ class ucp_zebra } unset($user_id_ary); } - else if (!sizeof($error)) + else if (!count($error)) { $error[] = $user->lang['USER_NOT_FOUND_OR_INACTIVE']; } @@ -244,7 +244,7 @@ class ucp_zebra else if ($updated) { meta_refresh(3, $this->u_action); - $message = $user->lang[$l_mode . '_UPDATED'] . '<br />' . implode('<br />', $error) . ((sizeof($error)) ? '<br />' : '') . '<br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); + $message = $user->lang[$l_mode . '_UPDATED'] . '<br />' . implode('<br />', $error) . ((count($error)) ? '<br />' : '') . '<br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); trigger_error($message); } else diff --git a/phpBB/includes/utf/utf_tools.php b/phpBB/includes/utf/utf_tools.php index 01caf47349..89de454427 100644 --- a/phpBB/includes/utf/utf_tools.php +++ b/phpBB/includes/utf/utf_tools.php @@ -1390,7 +1390,7 @@ function utf8_wordwrap($string, $width = 75, $break = "\n", $cut = false) { $words = explode(' ', $line); - for ($i = 0, $size = sizeof($words); $i < $size; $i++) + for ($i = 0, $size = count($words); $i < $size; $i++) { $word = $words[$i]; diff --git a/phpBB/index.php b/phpBB/index.php index 4e37782206..13b914abd3 100644 --- a/phpBB/index.php +++ b/phpBB/index.php @@ -55,6 +55,17 @@ if (($mark_notification = $request->variable('mark_notification', 0))) $notification->mark_read(); + /** + * You can use this event to perform additional tasks or redirect user elsewhere. + * + * @event core.index_mark_notification_after + * @var int mark_notification Notification ID + * @var \phpbb\notification\type\type_interface notification Notification instance + * @since 3.2.6-RC1 + */ + $vars = array('mark_notification', 'notification'); + extract($phpbb_dispatcher->trigger_event('core.index_mark_notification_after', compact($vars))); + if ($request->is_ajax()) { $json_response = new \phpbb\json_response(); diff --git a/phpBB/install/app.php b/phpBB/install/app.php index ef59689a65..710f49570b 100644 --- a/phpBB/install/app.php +++ b/phpBB/install/app.php @@ -20,9 +20,9 @@ define('PHPBB_ENVIRONMENT', 'production'); $phpbb_root_path = '../'; $phpEx = substr(strrchr(__FILE__, '.'), 1); -if (version_compare(PHP_VERSION, '5.4') < 0) +if (version_compare(PHP_VERSION, '5.4.7', '<') || version_compare(PHP_VERSION, '7.3-dev', '>=')) { - die('You are running an unsupported PHP version. Please upgrade to PHP 5.4.0 or higher before trying to install or update to phpBB 3.2'); + die('You are running an unsupported PHP version. Please upgrade to PHP equal to or greater than 5.4.7 but less than 7.3-dev in order to install or update to phpBB 3.2'); } $startup_new_path = $phpbb_root_path . 'install/update/update/new/install/startup.' . $phpEx; diff --git a/phpBB/install/convert/controller/convertor.php b/phpBB/install/convert/controller/convertor.php index 7b2a00d7b9..3639b10dc5 100644 --- a/phpBB/install/convert/controller/convertor.php +++ b/phpBB/install/convert/controller/convertor.php @@ -537,7 +537,7 @@ class convertor foreach ($prefixes as $prefix => $count) { - if ($count >= sizeof($tables)) + if ($count >= count($tables)) { $possible_prefix = $prefix; break; @@ -730,7 +730,7 @@ class convertor include_once($this->phpbb_root_path . 'install/convertors/' . $entry); if (isset($convertor_data)) { - $sort[strtolower($convertor_data['forum_name'])] = sizeof($convertors); + $sort[strtolower($convertor_data['forum_name'])] = count($convertors); $convertors[] = array( 'tag' => $m[1], diff --git a/phpBB/install/convert/convertor.php b/phpBB/install/convert/convertor.php index f7f05ebdae..5118651b71 100644 --- a/phpBB/install/convert/convertor.php +++ b/phpBB/install/convert/convertor.php @@ -312,9 +312,9 @@ class convertor } } - if (sizeof($bad_folders)) + if (count($bad_folders)) { - $msg = (sizeof($bad_folders) == 1) ? $user->lang['MAKE_FOLDER_WRITABLE'] : $user->lang['MAKE_FOLDERS_WRITABLE']; + $msg = (count($bad_folders) == 1) ? $user->lang['MAKE_FOLDER_WRITABLE'] : $user->lang['MAKE_FOLDERS_WRITABLE']; sort($bad_folders); $this->error(sprintf($msg, implode('<br />', $bad_folders)), __LINE__, __FILE__, true); @@ -371,7 +371,7 @@ class convertor $val = array($val); } - for ($j = 0, $size = sizeof($val); $j < $size; ++$j) + for ($j = 0, $size = count($val); $j < $size; ++$j) { if (preg_match('/LEFT JOIN ([a-z0-9_]+) AS ([a-z0-9_]+)/i', $val[$j], $m)) { @@ -412,11 +412,11 @@ class convertor // Throw an error if some tables are missing // We used to do some guessing here, but since we have a suggestion of possible values earlier, I don't see it adding anything here to do it again - if (sizeof($missing_tables) == sizeof($tables_list)) + if (count($missing_tables) == count($tables_list)) { $this->error($user->lang['NO_TABLES_FOUND'] . ' ' . $user->lang['CHECK_TABLE_PREFIX'], __LINE__, __FILE__); } - else if (sizeof($missing_tables)) + else if (count($missing_tables)) { $this->error(sprintf($user->lang['TABLES_MISSING'], implode($user->lang['COMMA_SEPARATOR'], $missing_tables)) . '<br /><br />' . $user->lang['CHECK_TABLE_PREFIX'], __LINE__, __FILE__); } @@ -514,7 +514,7 @@ class convertor )); // This loop takes one target table and processes it - while ($current_table < sizeof($convert->convertor['schema'])) + while ($current_table < count($convert->convertor['schema'])) { $schema = $convert->convertor['schema'][$current_table]; @@ -753,7 +753,7 @@ class convertor case 'mysqli': $waiting_rows[] = '(' . implode(', ', $insert_values) . ')'; - if (sizeof($waiting_rows) >= $convert->num_wait_rows) + if (count($waiting_rows) >= $convert->num_wait_rows) { $errored = false; @@ -809,7 +809,7 @@ class convertor $src_db->sql_freeresult($___result); // We might still have some rows waiting - if (sizeof($waiting_rows)) + if (count($waiting_rows)) { $errored = false; $db->sql_return_on_error(true); @@ -888,7 +888,7 @@ class convertor $current_table++; // $percentage = ($skip_rows == 0) ? 0 : floor(100 / ($total_rows / $skip_rows)); - $msg = sprintf($user->lang['STEP_PERCENT_COMPLETED'], $current_table, sizeof($convert->convertor['schema'])); + $msg = sprintf($user->lang['STEP_PERCENT_COMPLETED'], $current_table, count($convert->convertor['schema'])); $this->template->assign_vars(array( 'BODY' => $msg, @@ -1126,7 +1126,7 @@ class convertor } else { - while ($last_statement < sizeof($convert->convertor['execute_last'])) + while ($last_statement < count($convert->convertor['execute_last'])) { // @codingStandardsIgnoreStart eval($convert->convertor['execute_last'][$last_statement]); @@ -1140,8 +1140,8 @@ class convertor $last_statement++; $url = $this->save_convert_progress($converter, 'jump=1&last=' . $last_statement); - $percentage = ($last_statement == 0) ? 0 : floor(100 / (sizeof($convert->convertor['execute_last']) / $last_statement)); - $msg = sprintf($user->lang['STEP_PERCENT_COMPLETED'], $last_statement, sizeof($convert->convertor['execute_last']), $percentage); + $percentage = ($last_statement == 0) ? 0 : floor(100 / (count($convert->convertor['execute_last']) / $last_statement)); + $msg = sprintf($user->lang['STEP_PERCENT_COMPLETED'], $last_statement, count($convert->convertor['execute_last']), $percentage); $this->template->assign_vars(array( 'L_SUBMIT' => $user->lang['CONTINUE_LAST'], diff --git a/phpBB/install/convertors/convert_phpbb20.php b/phpBB/install/convertors/convert_phpbb20.php index aff9eef55b..654f705967 100644 --- a/phpBB/install/convertors/convert_phpbb20.php +++ b/phpBB/install/convertors/convert_phpbb20.php @@ -38,7 +38,7 @@ $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms); $convertor_data = array( 'forum_name' => 'phpBB 2.0.x', 'version' => '1.0.3', - 'phpbb_version' => '3.2.1', + 'phpbb_version' => '3.2.8', 'author' => '<a href="https://www.phpbb.com/">phpBB Limited</a>', 'dbms' => $dbms, 'dbhost' => $dbhost, diff --git a/phpBB/install/convertors/functions_phpbb20.php b/phpBB/install/convertors/functions_phpbb20.php index 6f43e1915e..2da901d3de 100644 --- a/phpBB/install/convertors/functions_phpbb20.php +++ b/phpBB/install/convertors/functions_phpbb20.php @@ -1071,7 +1071,7 @@ function phpbb_convert_authentication($mode) } } - if (sizeof($forum_ids)) + if (count($forum_ids)) { // Now make sure the user is able to read these forums $hold_ary = $auth->acl_group_raw_data(false, 'f_list', $forum_ids); @@ -1267,7 +1267,7 @@ function phpbb_prepare_message($message) // parse($allow_bbcode, $allow_magic_url, $allow_smilies, $allow_img_bbcode = true, $allow_flash_bbcode = true, $allow_quote_bbcode = true, $allow_url_bbcode = true, $update_this_message = true, $mode = 'post') $message_parser->parse($enable_bbcode, $enable_magic_url, $enable_smilies); - if (sizeof($message_parser->warn_msg)) + if (count($message_parser->warn_msg)) { $msg_id = isset($convert->row['post_id']) ? $convert->row['post_id'] : $convert->row['privmsgs_id']; $convert->p_master->error('<span style="color:red">' . $user->lang['POST_ID'] . ': ' . $msg_id . ' ' . $user->lang['CONV_ERROR_MESSAGE_PARSER'] . ': <br /><br />' . implode('<br />', $message_parser->warn_msg), __LINE__, __FILE__, true); @@ -1495,7 +1495,7 @@ function phpbb_attachment_forum_perms($forum_permissions) $forum_ids[] = (int) $forum_id; } - if (sizeof($forum_ids)) + if (count($forum_ids)) { return attachment_forum_perms($forum_ids); } @@ -1694,7 +1694,6 @@ function phpbb_import_attach_config() $config->set('img_create_thumbnail', $attach_config['img_create_thumbnail']); $config->set('img_max_thumb_width', 400); $config->set('img_min_thumb_filesize', $attach_config['img_min_thumb_filesize']); - $config->set('img_imagick', $attach_config['img_imagick']); } /** @@ -1860,7 +1859,7 @@ function phpbb_check_username_collisions() $db->sql_freeresult($result); // there was at least one collision, the admin will have to solve it before conversion can continue - if (sizeof($colliding_names)) + if (count($colliding_names)) { $sql = 'SELECT user_id, username_clean FROM ' . USERCONV_TABLE . ' diff --git a/phpBB/install/phpbbcli.php b/phpBB/install/phpbbcli.php index afc70f3302..7659b13f56 100755 --- a/phpBB/install/phpbbcli.php +++ b/phpBB/install/phpbbcli.php @@ -23,7 +23,7 @@ if (php_sapi_name() !== 'cli') define('IN_PHPBB', true); define('IN_INSTALL', true); define('PHPBB_ENVIRONMENT', 'production'); -define('PHPBB_VERSION', '3.2.1-RC1'); +define('PHPBB_VERSION', '3.2.8-RC1'); $phpbb_root_path = __DIR__ . '/../'; $phpEx = substr(strrchr(__FILE__, '.'), 1); diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index ca0e8bd614..d614579f3d 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -103,9 +103,10 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('extension_force_un INSERT INTO phpbb_config (config_name, config_value) VALUES ('delete_time', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_check_mx', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_enable', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_function_name', 'mail'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_force_sender', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_max_chunk_size', '50'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_package_size', '20'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('enable_accurate_pm_button', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('enable_confirm', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('enable_mod_rewrite', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('allow_board_notifications', '1'); @@ -148,7 +149,6 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('hot_threshold', '2 INSERT INTO phpbb_config (config_name, config_value) VALUES ('icons_path', 'images/icons'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_create_thumbnail', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_display_inlined', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_imagick', ''); INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_link_height', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_link_width', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('img_max_height', '0'); @@ -269,9 +269,9 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('smilies_per_page', INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_auth_method', 'PLAIN'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_delivery', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_host', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_password', ''); +INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('smtp_password', '', 1); INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_port', '25'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_username', ''); +INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('smtp_username', '', 1); INSERT INTO phpbb_config (config_name, config_value) VALUES ('teampage_memberships', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('teampage_forums', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('topics_per_page', '25'); @@ -279,7 +279,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('tpl_allow_php', '0 INSERT INTO phpbb_config (config_name, config_value) VALUES ('upload_icons_path', 'images/upload_icons'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('upload_path', 'files'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('use_system_cron', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.2.2-dev'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.2.9-dev'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('warnings_expire_days', '90'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('warnings_gc', '14400'); @@ -328,6 +328,7 @@ INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_icons', 1); INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_ignoreflood', 1); INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_img', 1); INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_list', 1); +INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_list_topics', 1); INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_noapprove', 1); INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_poll', 1); INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_post', 1); @@ -477,7 +478,7 @@ INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_NEW_MEMBER', 'ROLE_DESCRIPTION_FORUM_NEW_MEMBER', 'f_', 10); # -- phpbb_styles -INSERT INTO phpbb_styles (style_name, style_copyright, style_active, style_path, bbcode_bitfield, style_parent_id, style_parent_tree) VALUES ('prosilver', '© phpBB Limited', 1, 'prosilver', 'kNg=', 0, ''); +INSERT INTO phpbb_styles (style_name, style_copyright, style_active, style_path, bbcode_bitfield, style_parent_id, style_parent_tree) VALUES ('prosilver', '© phpBB Limited', 1, 'prosilver', '//g=', 0, ''); # -- Forums INSERT INTO phpbb_forums (forum_name, forum_desc, left_id, right_id, parent_id, forum_type, forum_posts_approved, forum_posts_unapproved, forum_posts_softdeleted, forum_topics_approved, forum_topics_unapproved, forum_topics_softdeleted, forum_last_post_id, forum_last_poster_id, forum_last_poster_name, forum_last_poster_colour, 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) VALUES ('{L_FORUMS_FIRST_CATEGORY}', '', 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 'Admin', 'AA0000', 972086460, '', '', '', '', '', '', '', 0, 0, ''); @@ -565,13 +566,13 @@ 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 16, auth_option_id, 0 FROM phpbb_acl_options WHERE auth_option = 'f_'; # Read Only Access (f_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 17, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option IN ('f_', 'f_download', 'f_list', 'f_read', 'f_search', 'f_subscribe', 'f_print'); +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 17, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option IN ('f_', 'f_download', 'f_list', 'f_list_topics', 'f_read', 'f_search', 'f_subscribe', 'f_print'); # Limited Access (f_) INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 18, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_announce_global', 'f_attach', 'f_bump', 'f_delete', 'f_flash', 'f_icons', 'f_ignoreflood', 'f_poll', 'f_sticky', 'f_user_lock', 'f_votechg'); # Bot Access (f_) -INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 19, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option IN ('f_', 'f_download', 'f_list', 'f_read', 'f_print'); +INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 19, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option IN ('f_', 'f_download', 'f_list', 'f_list_topics', 'f_read', 'f_print'); # On Moderation Queue (f_) INSERT INTO phpbb_acl_roles_data (role_id, auth_option_id, auth_setting) SELECT 20, auth_option_id, 1 FROM phpbb_acl_options WHERE auth_option LIKE 'f_%' AND auth_option NOT IN ('f_announce', 'f_announce_global', 'f_bump', 'f_delete', 'f_flash', 'f_icons', 'f_ignoreflood', 'f_poll', 'f_sticky', 'f_user_lock', 'f_votechg', 'f_noapprove'); diff --git a/phpBB/language/en/acp/attachments.php b/phpBB/language/en/acp/attachments.php index 123c35a502..86430f46bd 100644 --- a/phpBB/language/en/acp/attachments.php +++ b/phpBB/language/en/acp/attachments.php @@ -111,8 +111,6 @@ $lang = array_merge($lang, array( 'IMAGE_LINK_SIZE' => 'Image link dimensions', 'IMAGE_LINK_SIZE_EXPLAIN' => 'Display image attachment as an inline text link if image is larger than this. To disable this behaviour, set the values to 0px by 0px.', - 'IMAGICK_PATH' => 'ImageMagick path', - 'IMAGICK_PATH_EXPLAIN' => 'Full path to the imagemagick convert application, e.g. <samp>/usr/bin/</samp>.', 'MAX_ATTACHMENTS' => 'Maximum number of attachments per post', 'MAX_ATTACHMENTS_PM' => 'Maximum number of attachments per private message', @@ -135,7 +133,6 @@ $lang = array_merge($lang, array( 'NO_EXT_GROUP_SPECIFIED' => 'No extension group specified.', 'NO_FILE_CAT' => 'None', 'NO_IMAGE' => 'No image', - 'NO_THUMBNAIL_SUPPORT' => 'Thumbnail support has been disabled. For proper functionality either the GD extension need to be available or imagemagick being installed. Both were not found.', 'NO_UPLOAD_DIR' => 'The upload directory you specified does not exist.', 'NO_WRITE_UPLOAD' => 'The upload directory you specified cannot be written to. Please alter the permissions to allow the webserver to write to it.', @@ -147,7 +144,6 @@ $lang = array_merge($lang, array( 'REMOVE_DISALLOWED_IPS' => 'Remove or un-exclude <em>disallowed</em> IPs/hostnames', 'RESYNC_FILES_STATS_CONFIRM' => 'Are you sure you wish to resynchronise file statistics?', - 'SEARCH_IMAGICK' => 'Search for ImageMagick', 'SECURE_ALLOW_DENY' => 'Allow/Deny list', 'SECURE_ALLOW_DENY_EXPLAIN' => 'Change the default behaviour when secure downloads are enabled of the Allow/Deny list to that of a <strong>whitelist</strong> (Allow) or a <strong>blacklist</strong> (Deny).', 'SECURE_DOWNLOADS' => 'Enable secure downloads', diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php index e6c56a5bbb..651b76625d 100644 --- a/phpBB/language/en/acp/board.php +++ b/phpBB/language/en/acp/board.php @@ -44,7 +44,7 @@ $lang = array_merge($lang, array( 'BOARD_STYLE' => 'Board style', 'CUSTOM_DATEFORMAT' => 'Custom…', 'DEFAULT_DATE_FORMAT' => 'Date format', - 'DEFAULT_DATE_FORMAT_EXPLAIN' => 'The date format is the same as the PHP <code>date</code> function.', + 'DEFAULT_DATE_FORMAT_EXPLAIN' => 'The date format is the same as the PHP <code><a href="https://secure.php.net/manual/function.date.php">date()</a></code> function.', 'DEFAULT_LANGUAGE' => 'Default language', 'DEFAULT_STYLE' => 'Default style', 'DEFAULT_STYLE_EXPLAIN' => 'The default style for new users.', @@ -107,18 +107,18 @@ $lang = array_merge($lang, array( 'ACP_AVATAR_SETTINGS_EXPLAIN' => 'Avatars are generally small, unique images a user can associate with themselves. Depending on the style they are usually displayed below the username when viewing topics. Here you can determine how users can define their avatars. Please note that in order to upload avatars you need to have created the directory you name below and ensure it can be written to by the web server. Please also note that file size limits are only imposed on uploaded avatars, they do not apply to remotely linked images.', 'ALLOW_AVATARS' => 'Enable avatars', - 'ALLOW_AVATARS_EXPLAIN' => 'Allow general usage of avatars;<br />If you disable avatars in general or avatars of a certain mode, the disabled avatars will no longer be shown on the board, but users will still be able to download their own avatars in the User Control Panel.', + 'ALLOW_AVATARS_EXPLAIN' => 'Allow general usage of avatars;<br>If you disable avatars in general or avatars of a certain mode, the disabled avatars will no longer be shown on the board, but users will still be able to download their own avatars in the User Control Panel.', 'ALLOW_GRAVATAR' => 'Enable gravatar avatars', 'ALLOW_LOCAL' => 'Enable gallery avatars', 'ALLOW_REMOTE' => 'Enable remote avatars', - 'ALLOW_REMOTE_EXPLAIN' => 'Avatars linked to from another website.', + 'ALLOW_REMOTE_EXPLAIN' => 'Avatars linked to from another website.<br><em><strong class="error">Warning:</strong> Enabling this feature might allow users to check for the existence of files and services that are only accessible on the local network.</em>', 'ALLOW_REMOTE_UPLOAD' => 'Enable remote avatar uploading', - 'ALLOW_REMOTE_UPLOAD_EXPLAIN' => 'Allow uploading of avatars from another website.', + 'ALLOW_REMOTE_UPLOAD_EXPLAIN' => 'Allow uploading of avatars from another website.<br><em><strong class="error">Warning:</strong> Enabling this feature might allow users to check for the existence of files and services that are only accessible on the local network.</em>', 'ALLOW_UPLOAD' => 'Enable avatar uploading', 'AVATAR_GALLERY_PATH' => 'Avatar gallery path', - 'AVATAR_GALLERY_PATH_EXPLAIN' => 'Path under your phpBB root directory for pre-loaded images, e.g. <samp>images/avatars/gallery</samp>.<br />Double dots like <samp>../</samp> will be stripped from the path for security reasons.', + 'AVATAR_GALLERY_PATH_EXPLAIN' => 'Path under your phpBB root directory for pre-loaded images, e.g. <samp>images/avatars/gallery</samp>.<br>Double dots like <samp>../</samp> will be stripped from the path for security reasons.', 'AVATAR_STORAGE_PATH' => 'Avatar storage path', - 'AVATAR_STORAGE_PATH_EXPLAIN' => 'Path under your phpBB root directory, e.g. <samp>images/avatars/upload</samp>.<br />Avatar uploading <strong>will not be available</strong> if this path is not writable.<br />Double dots like <samp>../</samp> will be stripped from the path for security reasons.', + 'AVATAR_STORAGE_PATH_EXPLAIN' => 'Path under your phpBB root directory, e.g. <samp>images/avatars/upload</samp>.<br>Avatar uploading <strong>will not be available</strong> if this path is not writable.<br>Double dots like <samp>../</samp> will be stripped from the path for security reasons.', 'MAX_AVATAR_SIZE' => 'Maximum avatar dimensions', 'MAX_AVATAR_SIZE_EXPLAIN' => 'Width x Height in pixels.', 'MAX_FILESIZE' => 'Maximum avatar file size', @@ -274,7 +274,7 @@ $lang = array_merge($lang, array( 'ACP_FEED_SETTINGS_OTHER' => 'Other feeds and settings', 'ACP_FEED_ENABLE' => 'Enable feeds', - 'ACP_FEED_ENABLE_EXPLAIN' => 'Turns on or off ATOM feeds for the entire board.<br />Disabling this switches off all feeds, no matter how the options below are set.', + 'ACP_FEED_ENABLE_EXPLAIN' => 'Turns on or off ATOM feeds for the entire board.<br>Disabling this switches off all feeds, no matter how the options below are set.', 'ACP_FEED_LIMIT' => 'Number of items', 'ACP_FEED_LIMIT_EXPLAIN' => 'The maximum number of feed items to display.', @@ -290,7 +290,7 @@ $lang = array_merge($lang, array( 'ACP_FEED_TOPICS_ACTIVE' => 'Enable active topics feed', 'ACP_FEED_TOPICS_ACTIVE_EXPLAIN' => 'Enables the “Active Topics” feed, which displays the last active topics including the last post.', 'ACP_FEED_NEWS' => 'News feed', - 'ACP_FEED_NEWS_EXPLAIN' => 'Pull the first post from these forums. Select no forums to disable news feed.<br />Select multiple forums by holding <samp>CTRL</samp> and clicking.', + 'ACP_FEED_NEWS_EXPLAIN' => 'Pull the first post from these forums. Select no forums to disable news feed.<br>Select multiple forums by holding <samp>CTRL</samp> and clicking.', 'ACP_FEED_OVERALL_FORUMS' => 'Enable forums feed', 'ACP_FEED_OVERALL_FORUMS_EXPLAIN' => 'Enables the “All forums” feed, which displays a list of forums.', @@ -298,9 +298,9 @@ $lang = array_merge($lang, array( 'ACP_FEED_HTTP_AUTH' => 'Allow HTTP Authentication', 'ACP_FEED_HTTP_AUTH_EXPLAIN' => 'Enables HTTP authentication, which allows users to receive content that is hidden to guest users by adding the <samp>auth=http</samp> parameter to the feed URL. Please note that some PHP setups require additional changes to the .htaccess file. Instructions can be found in that file.', 'ACP_FEED_ITEM_STATISTICS' => 'Item statistics', - 'ACP_FEED_ITEM_STATISTICS_EXPLAIN' => 'Display individual statistics underneath feed items<br />(e.g. posted by, date and time, replies, views)', + 'ACP_FEED_ITEM_STATISTICS_EXPLAIN' => 'Display individual statistics underneath feed items<br>(e.g. posted by, date and time, replies, views)', 'ACP_FEED_EXCLUDE_ID' => 'Exclude these forums', - 'ACP_FEED_EXCLUDE_ID_EXPLAIN' => 'Content from these will be <strong>not included in feeds</strong>. Select no forum to pull data from all forums.<br />Select/Deselect multiple forums by holding <samp>CTRL</samp> and clicking.', + 'ACP_FEED_EXCLUDE_ID_EXPLAIN' => 'Content from these will be <strong>not included in feeds</strong>. Select no forum to pull data from all forums.<br>Select/Deselect multiple forums by holding <samp>CTRL</samp> and clicking.', )); // Visual Confirmation Settings @@ -348,16 +348,16 @@ $lang = array_merge($lang, array( // Cookie Settings $lang = array_merge($lang, array( - 'ACP_COOKIE_SETTINGS_EXPLAIN' => 'These details define the data used to send cookies to your users browsers. In most cases the default values for the cookie settings should be sufficient. If you do need to change any do so with care, incorrect settings can prevent users logging in. If you have problems with users staying logging in to your board, visit the <b><a href="https://www.phpbb.com/support/go/cookie-settings/">phpBB.com Knowledge Base - Fixing incorrect cookie settings</a></b>.', + 'ACP_COOKIE_SETTINGS_EXPLAIN' => 'These details define the data used to send cookies to your users browsers. In most cases the default values for the cookie settings should be sufficient. If you do need to change any do so with care, incorrect settings can prevent users logging in. If you have problems with users staying logging in to your board, visit the <strong><a href="https://www.phpbb.com/support/go/cookie-settings">phpBB.com Knowledge Base - Fixing incorrect cookie settings</a></strong>.', 'COOKIE_DOMAIN' => 'Cookie domain', - 'COOKIE_DOMAIN_EXPLAIN' => 'In most cases the cookie domain is optional. Leave it blank if you are unsure.<br /><br /> In the case where you have a board integrated with other software or have multiple domains, then to determine the cookie domain you need to do the following. If you have something like <i>example.com</i> and <i>forums.example.com</i>, or perhaps <i>forums.example.com</i> and <i>blog.example.com</i>. Remove the subdomains until you find the common domain, <i>example.com</i>. Now add a dot in front of the common domain and you would enter .example.com (note the dot at the beginning).', + 'COOKIE_DOMAIN_EXPLAIN' => 'In most cases the cookie domain is optional. Leave it blank if you are unsure.<br><br> In the case where you have a board integrated with other software or have multiple domains, then to determine the cookie domain you need to do the following. If you have something like <i>example.com</i> and <i>forums.example.com</i>, or perhaps <i>forums.example.com</i> and <i>blog.example.com</i>. Remove the subdomains until you find the common domain, <i>example.com</i>. Now add a dot in front of the common domain and you would enter .example.com (note the dot at the beginning).', 'COOKIE_NAME' => 'Cookie name', 'COOKIE_NAME_EXPLAIN' => 'This can be anything what you want, make it original. Whenever the cookie settings are changed the name of the cookie should be changed.', 'COOKIE_NOTICE' => 'Cookie notice', 'COOKIE_NOTICE_EXPLAIN' => 'If enabled a cookie notice will be displayed to users when visiting your board. This might be required by law depending on the content of your board and enabled extensions.', 'COOKIE_PATH' => 'Cookie path', - 'COOKIE_PATH_EXPLAIN' => 'Note that this is always a slash, it does not matter what your board URL is.', + 'COOKIE_PATH_EXPLAIN' => 'This will usually be the same as your script path or simply a slash to make the cookie accessible across the site domain.', 'COOKIE_SECURE' => 'Cookie secure', 'COOKIE_SECURE_EXPLAIN' => 'If your server is running via SSL set this to enabled else leave as disabled. Having this enabled and not running via SSL will result in server errors during redirects.', 'ONLINE_LENGTH' => 'View online time span', @@ -371,7 +371,7 @@ $lang = array_merge($lang, array( 'ACP_CONTACT_SETTINGS_EXPLAIN' => 'Here you can enable and disable the contact page and also add a text that is displayed on the page.', 'CONTACT_US_ENABLE' => 'Enable contact page', - 'CONTACT_US_ENABLE_EXPLAIN' => 'This page allows users to send emails to board administrators', + 'CONTACT_US_ENABLE_EXPLAIN' => 'This page allows users to send emails to board administrators. Please note that board-wide emails option must be enabled as well. You can find this option in General > Client Communication > Email settings.', 'CONTACT_US_INFO' => 'Contact information', 'CONTACT_US_INFO_EXPLAIN' => 'The message is displayed on the contact page', @@ -404,6 +404,8 @@ $lang = array_merge($lang, array( 'READ_NOTIFICATION_EXPIRE_DAYS_EXPLAIN' => 'Number of days that will elapse before a read notification will automatically be deleted. Set this value to 0 to make notifications permanent.', 'RECOMPILE_STYLES' => 'Recompile stale style components', 'RECOMPILE_STYLES_EXPLAIN' => 'Check for updated style components on filesystem and recompile.', + 'YES_ACCURATE_PM_BUTTON' => 'Enable permission specific PM button in topic pages', + 'YES_ACCURATE_PM_BUTTON_EXPLAIN' => 'If this setting is enabled, only post profiles of users who are permitted to read private messages will have a private message button.', 'YES_ANON_READ_MARKING' => 'Enable topic marking for guests', 'YES_ANON_READ_MARKING_EXPLAIN' => 'Stores read/unread status information for guests. If disabled, posts are always marked read for guests.', 'YES_BIRTHDAYS' => 'Enable birthday listing', @@ -430,7 +432,7 @@ $lang = array_merge($lang, array( 'AUTH_METHOD' => 'Select an authentication method', 'AUTH_PROVIDER_OAUTH_ERROR_ELEMENT_MISSING' => 'Both the key and secret of each enabled OAuth service provider must be provided. Only one was provided for an OAuth service provider.', - 'AUTH_PROVIDER_OAUTH_EXPLAIN' => 'Each OAuth provider requires a unique secret and key in order to authenticate with the external server. These should be supplied by the OAuth service when you register your website with them and should be entered exactly as provided to you.<br />Any service that does not have both a key and a secret entered here will not be available for use by the forum users. Also note, that user can still register and login using the DB authentication plug-in.', + 'AUTH_PROVIDER_OAUTH_EXPLAIN' => 'Each OAuth provider requires a unique secret and key in order to authenticate with the external server. These should be supplied by the OAuth service when you register your website with them and should be entered exactly as provided to you.<br>Any service that does not have both a key and a secret entered here will not be available for use by the forum users. Also note, that user can still register and login using the DB authentication plug-in.', 'AUTH_PROVIDER_OAUTH_KEY' => 'Key', 'AUTH_PROVIDER_OAUTH_TITLE' => 'OAuth', 'AUTH_PROVIDER_OAUTH_SECRET' => 'Secret', @@ -446,7 +448,7 @@ $lang = array_merge($lang, array( 'LDAP_NO_EMAIL' => 'The specified email attribute does not exist.', 'LDAP_NO_IDENTITY' => 'Could not find a login identity for %s.', 'LDAP_PASSWORD' => 'LDAP password', - 'LDAP_PASSWORD_EXPLAIN' => 'Leave blank to use anonymous binding, otherwise fill in the password for the above user. Required for Active Directory Servers.<br /><em><strong>Warning:</strong> This password will be stored as plain text in the database, visible to everybody who can access your database or who can view this configuration page.</em>', + 'LDAP_PASSWORD_EXPLAIN' => 'Leave blank to use anonymous binding, otherwise fill in the password for the above user. Required for Active Directory Servers.<br><em><strong>Warning:</strong> This password will be stored as plain text in the database, visible to everybody who can access your database or who can view this configuration page.</em>', 'LDAP_PORT' => 'LDAP server port', 'LDAP_PORT_EXPLAIN' => 'Optionally you can specify a port which should be used to connect to the LDAP server instead of the default port 389.', 'LDAP_SERVER' => 'LDAP server name', @@ -527,7 +529,7 @@ $lang = array_merge($lang, array( 'IP_LOGIN_LIMIT_TIME' => 'IP address login attempt expiration time', 'IP_LOGIN_LIMIT_TIME_EXPLAIN' => 'Login attempts expire after this period.', 'IP_LOGIN_LIMIT_USE_FORWARDED' => 'Limit login attempts by <var>X_FORWARDED_FOR</var> header', - 'IP_LOGIN_LIMIT_USE_FORWARDED_EXPLAIN' => 'Instead of limiting login attempts by IP address they are limited by <var>X_FORWARDED_FOR</var> values. <br /><em><strong>Warning:</strong> Only enable this if you are operating a proxy server that sets <var>X_FORWARDED_FOR</var> to trustworthy values.</em>', + 'IP_LOGIN_LIMIT_USE_FORWARDED_EXPLAIN' => 'Instead of limiting login attempts by IP address they are limited by <var>X_FORWARDED_FOR</var> values. <br><em><strong>Warning:</strong> Only enable this if you are operating a proxy server that sets <var>X_FORWARDED_FOR</var> to trustworthy values.</em>', 'MAX_LOGIN_ATTEMPTS' => 'Maximum number of login attempts per username', 'MAX_LOGIN_ATTEMPTS_EXPLAIN' => 'The number of login attempts allowed for a single account before the anti-spambot task is triggered. Enter 0 to prevent the anti-spambot task from being triggered for distinct user accounts.', 'NO_IP_VALIDATION' => 'None', @@ -552,8 +554,8 @@ $lang = array_merge($lang, array( $lang = array_merge($lang, array( 'ACP_EMAIL_SETTINGS_EXPLAIN' => 'This information is used when the board sends emails to your users. Please ensure the email address you specify is valid, any bounced or undeliverable messages will likely be sent to that address. If your host does not provide a native (PHP based) email service you can instead send messages directly using SMTP. This requires the address of an appropriate server (ask your provider if necessary). If the server requires authentication (and only if it does) enter the necessary username, password and authentication method.', - 'ADMIN_EMAIL' => 'Return email address', - 'ADMIN_EMAIL_EXPLAIN' => 'This will be used as the return address on all emails, the technical contact email address. It will always be used as the <samp>Return-Path</samp> and <samp>Sender</samp> address in emails.', + 'ADMIN_EMAIL' => 'From email address', + 'ADMIN_EMAIL_EXPLAIN' => 'This will be used as the from address on all emails, the technical contact email address. It will always be used as the <samp>Sender</samp> address in emails.', 'BOARD_EMAIL_FORM' => 'Users send email via board', 'BOARD_EMAIL_FORM_EXPLAIN' => 'Instead of showing the users email address users are able to send emails via the board.', 'BOARD_HIDE_EMAILS' => 'Hide email addresses', @@ -562,10 +564,12 @@ $lang = array_merge($lang, array( 'CONTACT_EMAIL_EXPLAIN' => 'This address will be used whenever a specific contact point is needed, e.g. spam, error output, etc. It will always be used as the <samp>From</samp> and <samp>Reply-To</samp> address in emails.', 'CONTACT_EMAIL_NAME' => 'Contact name', 'CONTACT_EMAIL_NAME_EXPLAIN' => 'This is the contact name that e-mail recipients will see. If you don’t want to have a contact name, leave this field empty.', - 'EMAIL_FUNCTION_NAME' => 'Email function name', - 'EMAIL_FUNCTION_NAME_EXPLAIN' => 'The email function used to send mails through PHP.', + 'EMAIL_FORCE_SENDER' => 'Force from email address', + 'EMAIL_FORCE_SENDER_EXPLAIN' => 'This will set the <samp>Return-Path</samp> to the from email address instead of using the local user and hostname of the server. This setting does not apply when using SMTP.<br><em><strong>Warning:</strong> Requires the user that the webserver runs as to be added as trusted user to the sendmail configuration.</em>', 'EMAIL_PACKAGE_SIZE' => 'Email package size', 'EMAIL_PACKAGE_SIZE_EXPLAIN' => 'This is the number of maximum emails sent out in one package. This setting is applied to the internal message queue; set this value to 0 if you have problems with non-delivered notification emails.', + 'EMAIL_MAX_CHUNK_SIZE' => 'Maximum allowed email recipients', + 'EMAIL_MAX_CHUNK_SIZE_EXPLAIN' => 'If necessary, set this to not exceed the maximum number of recipients that your email server will allow in one email message.', 'EMAIL_SIG' => 'Email signature', 'EMAIL_SIG_EXPLAIN' => 'This text will be attached to all emails the board sends.', 'ENABLE_EMAIL' => 'Enable board-wide emails', @@ -573,28 +577,28 @@ $lang = array_merge($lang, array( 'SEND_TEST_EMAIL' => 'Send a test email', 'SEND_TEST_EMAIL_EXPLAIN' => 'This will send a test email to the address defined in your account.', 'SMTP_ALLOW_SELF_SIGNED' => 'Allow self-signed SSL certificates', - 'SMTP_ALLOW_SELF_SIGNED_EXPLAIN'=> 'Allow connections to SMTP server with self-signed SSL certificate.<em><strong>Warning:</strong> Allowing self-signed SSL certificates may cause security implications.</em>', + 'SMTP_ALLOW_SELF_SIGNED_EXPLAIN'=> 'Allow connections to SMTP server with self-signed SSL certificate. <br><em><strong>Warning:</strong> Allowing self-signed SSL certificates may cause security implications.</em>', 'SMTP_AUTH_METHOD' => 'Authentication method for SMTP', 'SMTP_AUTH_METHOD_EXPLAIN' => 'Only used if a username/password is set, ask your provider if you are unsure which method to use.', 'SMTP_CRAM_MD5' => 'CRAM-MD5', 'SMTP_DIGEST_MD5' => 'DIGEST-MD5', 'SMTP_LOGIN' => 'LOGIN', 'SMTP_PASSWORD' => 'SMTP password', - 'SMTP_PASSWORD_EXPLAIN' => 'Only enter a password if your SMTP server requires it.<br /><em><strong>Warning:</strong> This password will be stored as plain text in the database, visible to everybody who can access your database or who can view this configuration page.</em>', + 'SMTP_PASSWORD_EXPLAIN' => 'Only enter a password if your SMTP server requires it.<br><em><strong>Warning:</strong> This password will be stored as plain text in the database, visible to everybody who can access your database or who can view this configuration page.</em>', 'SMTP_PLAIN' => 'PLAIN', 'SMTP_POP_BEFORE_SMTP' => 'POP-BEFORE-SMTP', 'SMTP_PORT' => 'SMTP server port', 'SMTP_PORT_EXPLAIN' => 'Only change this if you know your SMTP server is on a different port.', 'SMTP_SERVER' => 'SMTP server address', - 'SMTP_SERVER_EXPLAIN' => 'Note that you have to provide the protocol that your server uses. If you are using SSL, this has to be "ssl://your.mailserver.com"', + 'SMTP_SERVER_EXPLAIN' => 'Do not provide a protocol (<samp>ssl://</samp> or <samp>tsl://</samp>) unless your mail host tells you to do so.', 'SMTP_SETTINGS' => 'SMTP settings', 'SMTP_USERNAME' => 'SMTP username', 'SMTP_USERNAME_EXPLAIN' => 'Only enter a username if your SMTP server requires it.', 'SMTP_VERIFY_PEER' => 'Verify SSL certificate', - 'SMTP_VERIFY_PEER_EXPLAIN' => 'Require verification of SSL certificate used by SMTP server.<em><strong>Warning:</strong> Connecting peers with unverified SSL certificates may cause security implications.</em>', + 'SMTP_VERIFY_PEER_EXPLAIN' => 'Require verification of SSL certificate used by SMTP server. <br><em><strong>Warning:</strong> Connecting peers with unverified SSL certificates may cause security implications.</em>', 'SMTP_VERIFY_PEER_NAME' => 'Verify SMTP peer name', - 'SMTP_VERIFY_PEER_NAME_EXPLAIN' => 'Require verification of peer name for SMTP servers using SSL / TLS connections.<em><strong>Warning:</strong> Connecting to unverified peers may cause security implications.</em>', - 'TEST_EMAIL_SENT' => 'The test email has been sent.<br />If you don’t receive it, please check your emails configuration.<br /><br />If you require assistance, please visit the <a href="https://www.phpbb.com/community/">phpBB support forums</a>.', + 'SMTP_VERIFY_PEER_NAME_EXPLAIN' => 'Require verification of peer name for SMTP servers using SSL / TLS connections. <br><em><strong>Warning:</strong> Connecting to unverified peers may cause security implications.</em>', + 'TEST_EMAIL_SENT' => 'The test email has been sent.<br>If you don’t receive it, please check your emails configuration.<br><br>If you require assistance, please visit the <a href="https://www.phpbb.com/community/">phpBB support forums</a>.', 'USE_SMTP' => 'Use SMTP server for email', 'USE_SMTP_EXPLAIN' => 'Select “Yes” if you want or have to send email via a named server instead of the local mail function.', @@ -605,7 +609,7 @@ $lang = array_merge($lang, array( 'ACP_JABBER_SETTINGS_EXPLAIN' => 'Here you can enable and control the use of Jabber for instant messaging and board notifications. Jabber is an open source protocol and therefore available for use by anyone. Some Jabber servers include gateways or transports which allow you to contact users on other networks. Not all servers offer all transports and changes in protocols can prevent transports from operating. Please be sure to enter already registered account details - phpBB will use the details you enter here as is.', 'JAB_ALLOW_SELF_SIGNED' => 'Allow self-signed SSL certificates', - 'JAB_ALLOW_SELF_SIGNED_EXPLAIN' => 'Allow connections to Jabber server with self-signed SSL certificate.<em><strong>Warning:</strong> Allowing self-signed SSL certificates may cause security implications.</em>', + 'JAB_ALLOW_SELF_SIGNED_EXPLAIN' => 'Allow connections to Jabber server with self-signed SSL certificate. <br><em><strong>Warning:</strong> Allowing self-signed SSL certificates may cause security implications.</em>', 'JAB_ENABLE' => 'Enable Jabber', 'JAB_ENABLE_EXPLAIN' => 'Enables use of Jabber messaging and notifications.', 'JAB_GTALK_NOTE' => 'Please note that GTalk will not work because the <samp>dns_get_record</samp> function could not be found. This function is not available in PHP4, and is not implemented on Windows platforms. It currently does not work on BSD-based systems, including Mac OS.', @@ -623,7 +627,7 @@ $lang = array_merge($lang, array( 'JAB_USERNAME' => 'Jabber username or JID', 'JAB_USERNAME_EXPLAIN' => 'Specify a registered username or a valid JID. The username will not be checked for validity. If you only specify a username, then your JID will be the username and the server you specified above. Else, specify a valid JID, for example user@jabber.org.', 'JAB_VERIFY_PEER' => 'Verify SSL certificate', - 'JAB_VERIFY_PEER_EXPLAIN' => 'Require verification of SSL certificate used by Jabber server.<em><strong>Warning:</strong> Connecting peers with unverified SSL certificates may cause security implications.</em>', + 'JAB_VERIFY_PEER_EXPLAIN' => 'Require verification of SSL certificate used by Jabber server. <br><em><strong>Warning:</strong> Connecting peers with unverified SSL certificates may cause security implications.</em>', 'JAB_VERIFY_PEER_NAME' => 'Verify Jabber peer name', - 'JAB_VERIFY_PEER_NAME_EXPLAIN' => 'Require verification of peer name for Jabber servers using SSL / TLS connections.<em><strong>Warning:</strong> Connecting to unverified peers may cause security implications.</em>', + 'JAB_VERIFY_PEER_NAME_EXPLAIN' => 'Require verification of peer name for Jabber servers using SSL / TLS connections. <br><em><strong>Warning:</strong> Connecting to unverified peers may cause security implications.</em>', )); diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php index de5039f047..1c2253542c 100644 --- a/phpBB/language/en/acp/common.php +++ b/phpBB/language/en/acp/common.php @@ -325,6 +325,7 @@ $lang = array_merge($lang, array( 'TOTAL_SIZE' => 'Total size', 'UCP' => 'User Control Panel', + 'URL_INVALID' => 'The provided URL for the setting “%1$s” is invalid.', 'USERNAMES_EXPLAIN' => 'Place each username on a separate line.', 'USER_CONTROL_PANEL' => 'User Control Panel', @@ -552,6 +553,7 @@ $lang = array_merge($lang, array( 'LOG_BBCODE_ADD' => '<strong>Added new BBCode</strong><br />» %s', 'LOG_BBCODE_EDIT' => '<strong>Edited BBCode</strong><br />» %s', 'LOG_BBCODE_DELETE' => '<strong>Deleted BBCode</strong><br />» %s', + 'LOG_BBCODE_CONFIGURATION_ERROR' => '<strong>Error while configuring BBCode</strong>: %1$s<br />» %2$s', 'LOG_BOT_ADDED' => '<strong>New bot added</strong><br />» %s', 'LOG_BOT_DELETE' => '<strong>Deleted bot</strong><br />» %s', diff --git a/phpBB/language/en/acp/database.php b/phpBB/language/en/acp/database.php index ab85701eaa..302aaee570 100644 --- a/phpBB/language/en/acp/database.php +++ b/phpBB/language/en/acp/database.php @@ -38,14 +38,15 @@ if (empty($lang) || !is_array($lang)) // Database Backup/Restore $lang = array_merge($lang, array( - 'ACP_BACKUP_EXPLAIN' => 'Here you can backup all your phpBB related data. You may store the resulting archive in your <samp>store/</samp> folder or download it directly. Depending on your server configuration you may be able to compress the file in a number of formats.', + 'ACP_BACKUP_EXPLAIN' => 'Here you can backup all your phpBB related data. The resulting archive will be stored in your <samp>store/</samp> folder. Depending on your server configuration you may be able to compress the file in a number of formats.', 'ACP_RESTORE_EXPLAIN' => 'This will perform a full restore of all phpBB tables from a saved file. If your server supports it you may use a gzip or bzip2 compressed text file and it will automatically be decompressed. <strong>WARNING</strong> This will overwrite any existing data. The restore may take a long time to process please do not move from this page till it is complete. Backups are stored in the <samp>store/</samp> folder and are assumed to be generated by phpBB’s backup functionality. Restoring backups that were not created by the built in system may or may not work.', - 'BACKUP_DELETE' => 'The backup file has been deleted successfully.', - 'BACKUP_INVALID' => 'The selected file to backup is invalid.', - 'BACKUP_OPTIONS' => 'Backup options', - 'BACKUP_SUCCESS' => 'The backup file has been created successfully.', - 'BACKUP_TYPE' => 'Backup type', + 'BACKUP_DELETE' => 'The backup file has been deleted successfully.', + 'BACKUP_INVALID' => 'The selected file to backup is invalid.', + 'BACKUP_NOT_SUPPORTED' => 'The selected backup is not supported', + 'BACKUP_OPTIONS' => 'Backup options', + 'BACKUP_SUCCESS' => 'The backup file has been created successfully.', + 'BACKUP_TYPE' => 'Backup type', 'DATABASE' => 'Database utilities', 'DATA_ONLY' => 'Data only', diff --git a/phpBB/language/en/acp/forums.php b/phpBB/language/en/acp/forums.php index 7a7176369f..d92d3f8c9e 100644 --- a/phpBB/language/en/acp/forums.php +++ b/phpBB/language/en/acp/forums.php @@ -97,6 +97,7 @@ $lang = array_merge($lang, array( 'FORUM_LINK_TRACK_EXPLAIN' => 'Records the number of times a forum link was clicked.', 'FORUM_NAME' => 'Forum name', 'FORUM_NAME_EMPTY' => 'You must enter a name for this forum.', + 'FORUM_NAME_EMOJI' => 'The forum name you entered is invalid.<br>It contains the following unsupported characters:<br>%s', 'FORUM_PARENT' => 'Parent forum', 'FORUM_PASSWORD' => 'Forum password', 'FORUM_PASSWORD_CONFIRM' => 'Confirm forum password', diff --git a/phpBB/language/en/acp/groups.php b/phpBB/language/en/acp/groups.php index 9d0bb5f8b9..5d68132a34 100644 --- a/phpBB/language/en/acp/groups.php +++ b/phpBB/language/en/acp/groups.php @@ -92,7 +92,7 @@ $lang = array_merge($lang, array( 'GROUP_OPEN' => 'Open', 'GROUP_PENDING' => 'Pending members', 'GROUP_MAX_RECIPIENTS' => 'Maximum number of allowed recipients per private message', - 'GROUP_MAX_RECIPIENTS_EXPLAIN' => 'The maximum number of allowed recipients in a private message. The maximum for all groups of the user is used to determine the actual value.<br />Set this value to 0 to overwrite the setting for all users of this group with the board-wide setting.', + 'GROUP_MAX_RECIPIENTS_EXPLAIN' => 'The maximum number of allowed recipients in a private message. The maximum for all groups of the user is used to determine the actual value.<br />Set this value to 0 to overwrite the setting for all users of this group with the board-wide setting.', 'GROUP_OPTIONS_SAVE' => 'Group wide options', 'GROUP_PROMOTE' => 'Promote to group leader', 'GROUP_RANK' => 'Group rank', @@ -111,6 +111,7 @@ $lang = array_merge($lang, array( 'GROUP_USERS_ADDED' => 'New users added to group successfully.', 'GROUP_USERS_EXIST' => 'The selected users are already members.', 'GROUP_USERS_REMOVE' => 'Users removed from group and new defaults set successfully.', + 'GROUP_USERS_INVALID' => 'No users were added to the group as the following usernames do not exist: %s', 'LEGEND_EXPLAIN' => 'These are the groups which are displayed in the group legend:', 'LEGEND_SETTINGS' => 'Legend settings', diff --git a/phpBB/language/en/acp/permissions.php b/phpBB/language/en/acp/permissions.php index 1ade2d6eb8..54d968cdaa 100644 --- a/phpBB/language/en/acp/permissions.php +++ b/phpBB/language/en/acp/permissions.php @@ -54,7 +54,7 @@ $lang = array_merge($lang, array( <br /> - <p>For further information on setting up and managing permissions on your phpBB3 board, please see the section on <a href="https://www.phpbb.com/support/docs/en/3.1/ug/quickstart/permissions/">Setting permissions of our Quick Start Guide</a>.</p> + <p>For further information on setting up and managing permissions on your phpBB3 board, please see the section on <a href="https://www.phpbb.com/support/docs/en/3.2/ug/quickstart/permissions/">Setting permissions of our Quick Start Guide</a>.</p> ', 'ACL_NEVER' => 'Never', diff --git a/phpBB/language/en/acp/permissions_phpbb.php b/phpBB/language/en/acp/permissions_phpbb.php index f986eced38..2c7b3d3aee 100644 --- a/phpBB/language/en/acp/permissions_phpbb.php +++ b/phpBB/language/en/acp/permissions_phpbb.php @@ -81,8 +81,8 @@ $lang = array_merge($lang, array( 'ACL_U_SIG' => 'Can use signature', 'ACL_U_SENDPM' => 'Can send private messages', - 'ACL_U_MASSPM' => 'Can send messages to multiple users', - 'ACL_U_MASSPM_GROUP'=> 'Can send messages to groups', + 'ACL_U_MASSPM' => 'Can send private messages to multiple users', + 'ACL_U_MASSPM_GROUP'=> 'Can send private messages to groups', 'ACL_U_READPM' => 'Can read private messages', 'ACL_U_PM_EDIT' => 'Can edit own private messages', 'ACL_U_PM_DELETE' => 'Can remove private messages from own folder', @@ -107,6 +107,7 @@ $lang = array_merge($lang, array( // Forum Permissions $lang = array_merge($lang, array( 'ACL_F_LIST' => 'Can see forum', + 'ACL_F_LIST_TOPICS' => 'Can see topics', 'ACL_F_READ' => 'Can read forum', 'ACL_F_SEARCH' => 'Can search the forum', 'ACL_F_SUBSCRIBE' => 'Can subscribe forum', diff --git a/phpBB/language/en/acp/profile.php b/phpBB/language/en/acp/profile.php index d365aeb183..87c950581e 100644 --- a/phpBB/language/en/acp/profile.php +++ b/phpBB/language/en/acp/profile.php @@ -111,7 +111,7 @@ $lang = array_merge($lang, array( 'FIRST_OPTION' => 'First option', 'HIDE_PROFILE_FIELD' => 'Hide profile field', - 'HIDE_PROFILE_FIELD_EXPLAIN' => 'Hide the profile field from all other users except the user, administrators and moderators who are still able to see this field. If the Display in user control panel option is disabled, the user will not be able to see or change this field and the field can only be changed by administrators.', + 'HIDE_PROFILE_FIELD_EXPLAIN' => 'Hide the profile field from all users except administrators and moderators, who are still able to see this field. If the Display in user control panel option is disabled, the user will not be able to see or change this field and the field can only be changed by administrators.', 'INVALID_CHARS_FIELD_IDENT' => 'Field identification can only contain lowercase a-z and _', 'INVALID_FIELD_IDENT_LEN' => 'Field identification can only be 17 characters long', @@ -161,8 +161,8 @@ $lang = array_merge($lang, array( 'STEP_2_EXPLAIN_EDIT' => 'Here you are able to change some common options.<br /><strong>Please note that changes to profile fields will not affect existing profile fields entered by your users.</strong>', 'STEP_2_TITLE_CREATE' => 'Profile type specific options', 'STEP_2_TITLE_EDIT' => 'Profile type specific options', - 'STEP_3_EXPLAIN_CREATE' => 'Since you have more than one board language installed, you have to fill out the remaining language items too. The profile field will work with the default language enabled, you are able to fill out the remaining language items later too.', - 'STEP_3_EXPLAIN_EDIT' => 'Since you have more than one board language installed, you now can change or add the remaining language items too. The profile field will work with the default language enabled.', + 'STEP_3_EXPLAIN_CREATE' => 'Since you have more than one board language installed, you have to fill out the remaining language items too. If you don’t, then default language setting for this custom profile field will be used, you are able to fill out the remaining language items later too.', + 'STEP_3_EXPLAIN_EDIT' => 'Since you have more than one board language installed, you now can change or add the remaining language items too. If you don’t, then default language setting for this custom profile field will be used.', 'STEP_3_TITLE_CREATE' => 'Remaining language definitions', 'STEP_3_TITLE_EDIT' => 'Language definitions', 'STRING_DEFAULT_VALUE_EXPLAIN' => 'Enter a default phrase to be displayed, a default value. Leave empty if you want to show it empty at the first place.', diff --git a/phpBB/language/en/acp/search.php b/phpBB/language/en/acp/search.php index c52b71c121..443dbb7fb7 100644 --- a/phpBB/language/en/acp/search.php +++ b/phpBB/language/en/acp/search.php @@ -116,7 +116,10 @@ $lang = array_merge($lang, array( 2 => 'The current rate of indexing is approximately %1$.1f posts per second.<br />Indexing in progress…', ), 'SEARCH_INDEX_DELETE_REDIRECT' => array( - 2 => 'All posts up to post id %2$d have been removed from the search index.<br />Deleting in progress…', + 2 => 'All posts up to post id %2$d have been removed from the search index, of which %1$d posts were within this step.<br />', + ), + 'SEARCH_INDEX_DELETE_REDIRECT_RATE' => array( + 2 => 'The current rate of deleting is approximately %1$.1f posts per second.<br />Deleting in progress…', ), 'SEARCH_INDEX_CREATED' => 'Successfully indexed all posts in the board database.', 'SEARCH_INDEX_REMOVED' => 'Successfully deleted the search index for this backend.', diff --git a/phpBB/language/en/acp/styles.php b/phpBB/language/en/acp/styles.php index 9293d67ecc..44be3c11cd 100644 --- a/phpBB/language/en/acp/styles.php +++ b/phpBB/language/en/acp/styles.php @@ -21,7 +21,7 @@ if (!defined('IN_PHPBB')) if (empty($lang) || !is_array($lang)) { - $lang = array(); + $lang = []; } // DEVELOPERS PLEASE NOTE @@ -36,54 +36,56 @@ if (empty($lang) || !is_array($lang)) // 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 -$lang = array_merge($lang, array( - 'ACP_STYLES_EXPLAIN' => 'Here you can manage the available styles on your board. You may alter existing styles, delete, deactivate, reactivate, install new ones. You can also see what a style will look like using the preview function. Also listed is the total user count for each style, note that overriding user styles will not be reflected here.', +$lang = array_merge($lang, [ + 'ACP_STYLES_EXPLAIN' => 'Here you can manage the styles available on your board.<br>Please note you cannot uninstall the “<strong>prosilver</strong>” style as it is phpBB’s default and primary parent style.', - 'CANNOT_BE_INSTALLED' => 'Cannot be installed', - 'CONFIRM_UNINSTALL_STYLES' => 'Are you sure you wish to uninstall selected styles?', - 'COPYRIGHT' => 'Copyright', + 'CANNOT_BE_INSTALLED' => 'Cannot be installed', + 'CONFIRM_UNINSTALL_STYLES' => 'Are you sure you wish to uninstall selected styles?', + 'COPYRIGHT' => 'Copyright', - 'DEACTIVATE_DEFAULT' => 'You cannot deactivate the default style.', - 'DELETE_FROM_FS' => 'Delete from filesystem', - 'DELETE_STYLE_FILES_FAILED' => 'Error deleting files for style "%s".', - 'DELETE_STYLE_FILES_SUCCESS' => 'Files for style "%s" have been deleted.', - 'DETAILS' => 'Details', + 'DEACTIVATE_DEFAULT' => 'You cannot deactivate the default style.', + 'DELETE_FROM_FS' => 'Delete from filesystem', + 'DELETE_STYLE_FILES_FAILED' => 'Error deleting files for style "%s".', + 'DELETE_STYLE_FILES_SUCCESS' => 'Files for style "%s" have been deleted.', + 'DETAILS' => 'Details', - 'INHERITING_FROM' => 'Inherits from', - 'INSTALL_STYLE' => 'Install style', - 'INSTALL_STYLES' => 'Install styles', - 'INSTALL_STYLES_EXPLAIN' => 'Here you can install new styles.<br />If you cannot find a specific style in list below, check to make sure style is already installed. If it is not installed, check if it was uploaded correctly.', - 'INVALID_STYLE_ID' => 'Invalid style ID.', + 'INHERITING_FROM' => 'Inherits from', + 'INSTALL_STYLE' => 'Install style', + 'INSTALL_STYLES' => 'Install styles', + 'INSTALL_STYLES_EXPLAIN' => 'Here you can install new styles.<br>If you cannot find a specific style in list below, check to make sure style is already installed. If it is not installed, check if it was uploaded correctly.', + 'INVALID_STYLE_ID' => 'Invalid style ID.', - 'NO_MATCHING_STYLES_FOUND' => 'No styles match your query.', - 'NO_UNINSTALLED_STYLE' => 'No uninstalled styles detected.', + 'NO_MATCHING_STYLES_FOUND' => 'No styles match your query.', + 'NO_UNINSTALLED_STYLE' => 'No uninstalled styles detected.', - 'PURGED_CACHE' => 'Cache was purged.', + 'PURGED_CACHE' => 'Cache was purged.', - 'REQUIRES_STYLE' => 'This style requires the style "%s" to be installed.', + 'REQUIRES_STYLE' => 'This style requires the style "%s" to be installed.', - 'STYLE_ACTIVATE' => 'Activate', - 'STYLE_ACTIVE' => 'Active', - 'STYLE_DEACTIVATE' => 'Deactivate', - 'STYLE_DEFAULT' => 'Make default style', - 'STYLE_DEFAULT_CHANGE_INACTIVE' => 'You must activate style before making it default style.', - 'STYLE_ERR_INVALID_PARENT' => 'Invalid parent style.', - 'STYLE_ERR_NAME_EXIST' => 'A style with that name already exists.', - 'STYLE_ERR_STYLE_NAME' => 'You must supply a name for this style.', - 'STYLE_INSTALLED' => 'Style "%s" has been installed.', + 'STYLE_ACTIVATE' => 'Activate', + 'STYLE_ACTIVE' => 'Active', + 'STYLE_DEACTIVATE' => 'Deactivate', + 'STYLE_DEFAULT' => 'Make default style', + 'STYLE_DEFAULT_CHANGE_INACTIVE' => 'You must activate style before making it default style.', + 'STYLE_ERR_INVALID_PARENT' => 'Invalid parent style.', + 'STYLE_ERR_NAME_EXIST' => 'A style with that name already exists.', + 'STYLE_ERR_STYLE_NAME' => 'You must supply a name for this style.', + 'STYLE_INSTALLED' => 'Style "%s" has been installed.', 'STYLE_INSTALLED_RETURN_INSTALLED_STYLES' => 'Return to installed styles list', 'STYLE_INSTALLED_RETURN_UNINSTALLED_STYLES' => 'Install more styles', - 'STYLE_NAME' => 'Style name', - 'STYLE_NAME_RESERVED' => 'Style "%s" can not be installed, because the name is reserved.', - 'STYLE_NOT_INSTALLED' => 'Style "%s" was not installed.', - 'STYLE_PATH' => 'Style path', - 'STYLE_UNINSTALL' => 'Uninstall', - 'STYLE_UNINSTALL_DEPENDENT' => 'Style "%s" cannot be uninstalled because it has one or more child styles.', - 'STYLE_UNINSTALLED' => 'Style "%s" uninstalled successfully.', - 'STYLE_USED_BY' => 'Used by (including robots)', - 'STYLE_VERSION' => 'Style version', + 'STYLE_NAME' => 'Style name', + 'STYLE_NAME_RESERVED' => 'Style "%s" can not be installed, because the name is reserved.', + 'STYLE_NOT_INSTALLED' => 'Style "%s" was not installed.', + 'STYLE_PATH' => 'Style path', + 'STYLE_UNINSTALL' => 'Uninstall', + 'STYLE_UNINSTALL_DEPENDENT' => 'Style "%s" cannot be uninstalled because it has one or more child styles.', + 'STYLE_UNINSTALLED' => 'Style "%s" uninstalled successfully.', + 'STYLE_PHPBB_VERSION' => 'phpBB Version', + 'STYLE_USED_BY' => 'Used by (including robots)', + 'STYLE_VERSION' => 'Style version', - 'UNINSTALL_DEFAULT' => 'You cannot uninstall the default style.', + 'UNINSTALL_PROSILVER' => 'You cannot uninstall the style “prosilver”.', + 'UNINSTALL_DEFAULT' => 'You cannot uninstall the default style.', - 'BROWSE_STYLES_DATABASE' => 'Browse styles database', -)); + 'BROWSE_STYLES_DATABASE' => 'Browse styles database', +]); diff --git a/phpBB/language/en/captcha_qa.php b/phpBB/language/en/captcha_qa.php index 28011eb636..637c4e035e 100644 --- a/phpBB/language/en/captcha_qa.php +++ b/phpBB/language/en/captcha_qa.php @@ -49,7 +49,7 @@ $lang = array_merge($lang, array( 'ANSWER' => 'Answer', 'EDIT_QUESTION' => 'Edit Question', 'QUESTIONS' => 'Questions', - 'QUESTIONS_EXPLAIN' => 'For every form submission where you have enabled the Q&A plugin, users will be asked one of the questions specified here. To use this plugin at least one question must be set in the default language. These questions should be easy for your target audience to answer but beyond the ability of a bot capable of running a Google™ search. Using a large and regularly changed set of questions will yield the best results. Enable the strict setting if your question relies on mixed case, punctuation or whitespace.', + 'QUESTIONS_EXPLAIN' => 'For every form submission where you have enabled the Q&A plugin, users will be asked one of the questions specified here. To use this plugin at least one question must be set in the default language. These questions should be easy for your target audience to answer but beyond the ability of a bot capable of running a Google™ search. Only a single proper question is necessary. If you start receiving spam registrations, the question should be changed. Enable the strict setting if your question relies on mixed case, punctuation or whitespace.', 'QUESTION_DELETED' => 'Question deleted', 'QUESTION_LANG' => 'Language', 'QUESTION_LANG_EXPLAIN' => 'The language this question and its answers are written in.', diff --git a/phpBB/language/en/captcha_recaptcha.php b/phpBB/language/en/captcha_recaptcha.php index 0acf850043..dde2a4ba08 100644 --- a/phpBB/language/en/captcha_recaptcha.php +++ b/phpBB/language/en/captcha_recaptcha.php @@ -37,7 +37,7 @@ if (empty($lang) || !is_array($lang)) // in a url you again do not need to specify an order e.g., 'Click %sHERE%s' is fine $lang = array_merge($lang, array( - 'RECAPTCHA_LANG' => 'en', + 'RECAPTCHA_LANG' => 'en-GB', // Find the language/country code on https://developers.google.com/recaptcha/docs/language - If no code exists for your language you can use "en" or leave the string empty 'RECAPTCHA_NOT_AVAILABLE' => 'In order to use reCaptcha, you must create an account on <a href="http://www.google.com/recaptcha">www.google.com/recaptcha</a>.', 'CAPTCHA_RECAPTCHA' => 'reCaptcha', 'RECAPTCHA_INCORRECT' => 'The solution you provided was incorrect', diff --git a/phpBB/language/en/cli.php b/phpBB/language/en/cli.php index 1655855edb..505d12e8ff 100644 --- a/phpBB/language/en/cli.php +++ b/phpBB/language/en/cli.php @@ -117,6 +117,7 @@ $lang = array_merge($lang, array( 'CLI_EXTENSION_ENABLE_FAILURE' => 'Could not enable extension %s', 'CLI_EXTENSION_ENABLE_SUCCESS' => 'Successfully enabled extension %s', 'CLI_EXTENSION_ENABLED' => 'Extension %s is already enabled', + 'CLI_EXTENSION_NOT_EXIST' => 'Extension %s does not exist', 'CLI_EXTENSION_NAME' => 'Name of the extension', 'CLI_EXTENSION_PURGE_FAILURE' => 'Could not purge extension %s', 'CLI_EXTENSION_PURGE_SUCCESS' => 'Successfully purged extension %s', diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php index d7a1ce8e71..8df8fc630b 100644 --- a/phpBB/language/en/common.php +++ b/phpBB/language/en/common.php @@ -62,7 +62,6 @@ $lang = array_merge($lang, array( 'ACCOUNT_ALREADY_ACTIVATED' => 'Your account has already been activated.', 'ACCOUNT_DEACTIVATED' => 'Your account has been manually deactivated and is only able to be reactivated by an administrator.', - 'ACCOUNT_NOT_ACTIVATED' => 'Your account has not been activated yet.', 'ACP' => 'Administration Control Panel', 'ACP_SHORT' => 'ACP', 'ACTIVE' => 'active', @@ -92,6 +91,7 @@ $lang = array_merge($lang, array( 'ATTACHED_IMAGE_NOT_IMAGE' => 'The image file you tried to attach is invalid.', 'AUTHOR' => 'Author', 'AUTH_NO_PROFILE_CREATED' => 'The creation of a user profile was unsuccessful.', + 'AUTH_PROVIDER_OAUTH_ERROR_ALREADY_LINKED' => 'The account is already linked with other user.', 'AUTH_PROVIDER_OAUTH_ERROR_INVALID_ENTRY' => 'Invalid database entry.', 'AUTH_PROVIDER_OAUTH_ERROR_INVALID_SERVICE_TYPE' => 'Invalid service type provided to OAuth service handler.', 'AUTH_PROVIDER_OAUTH_ERROR_SERVICE_NOT_CREATED' => 'OAuth service not created', @@ -138,8 +138,10 @@ $lang = array_merge($lang, array( 1 => 'Users browsing this forum: %2$s and %1$d guest', 2 => 'Users browsing this forum: %2$s and %1$d guests', ), + 'BUTTON_DELETE' => 'Delete', 'BUTTON_EDIT' => 'Edit', 'BUTTON_FORUM_LOCKED' => 'Locked', + 'BUTTON_INFORMATION' => 'Information', 'BUTTON_NEW_TOPIC' => 'New Topic', 'BUTTON_PM' => 'PM', 'BUTTON_PM_FORWARD' => 'Forward', @@ -148,7 +150,9 @@ $lang = array_merge($lang, array( 'BUTTON_PM_REPLY_ALL' => 'Reply All', 'BUTTON_POST_REPLY' => 'Post Reply', 'BUTTON_QUOTE' => 'Quote', + 'BUTTON_REPORT' => 'Report', 'BUTTON_TOPIC_LOCKED' => 'Locked', + 'BUTTON_WARN' => 'Warn', 'BYTES' => 'Bytes', 'BYTES_SHORT' => 'B', @@ -189,7 +193,7 @@ $lang = array_merge($lang, array( 'DAYS' => 'Days', 'DELETE' => 'Delete', 'DELETE_ALL' => 'Delete all', - 'DELETE_COOKIES' => 'Delete all board cookies', + 'DELETE_COOKIES' => 'Delete cookies', 'DELETE_MARKED' => 'Delete marked', 'DELETE_POST' => 'Delete post', 'DELIMITER' => 'Delimiter', @@ -516,6 +520,7 @@ $lang = array_merge($lang, array( 'NO_FEED_ENABLED' => 'Feeds are not available on this board.', 'NO_FEED' => 'The requested feed is not available.', 'NO_STYLE_DATA' => 'Could not get style data', + 'NO_STYLE_CFG' => 'Could not get the style configuration file for: %s', 'NO_SUBJECT' => 'No subject specified', // Used for posts having no subject defined but displayed within management pages. 'NO_SUCH_SEARCH_MODULE' => 'The specified search backend doesn’t exist.', 'NO_SUPPORTED_AUTH_METHODS' => 'No supported authentication methods.', @@ -604,6 +609,7 @@ $lang = array_merge($lang, array( 'PREVIOUS' => 'Previous', // Used in pagination 'PREVIOUS_STEP' => 'Previous', 'PRIVACY' => 'Privacy policy', + 'PRIVACY_LINK' => 'Privacy', 'PRIVATE_MESSAGE' => 'Private message', 'PRIVATE_MESSAGES' => 'Private messages', 'PRIVATE_MESSAGING' => 'Private messaging', @@ -728,6 +734,7 @@ $lang = array_merge($lang, array( 'SUBMIT' => 'Submit', 'TB' => 'TB', + 'TERMS_LINK' => 'Terms', 'TERMS_USE' => 'Terms of use', 'TEST_CONNECTION' => 'Test connection', 'THE_TEAM' => 'The team', @@ -775,6 +782,10 @@ $lang = array_merge($lang, array( 'TOPIC_REVIEW' => 'Topic review', 'TOPIC_TITLE' => 'Topic title', 'TOPIC_UNAPPROVED' => 'This topic has not been approved.', + 'TOPIC_UNAPPROVED_FORUM' => array( + 1 => 'Topic awaiting approval', + 2 => 'Topics awaiting approval', + ), 'TOPIC_DELETED' => 'This topic has been deleted.', 'TOTAL_ATTACHMENTS' => 'Attachment(s)', 'TOTAL_LOGS' => array( diff --git a/phpBB/language/en/email/admin_activate.txt b/phpBB/language/en/email/admin_activate.txt index a53ab1269e..71faca70b2 100644 --- a/phpBB/language/en/email/admin_activate.txt +++ b/phpBB/language/en/email/admin_activate.txt @@ -7,7 +7,7 @@ The account owned by "{USERNAME}" has been deactivated or newly created, you sho Use this link to view the user's profile: {U_USER_DETAILS} -Use this link to activate the account: +You may activate the account immediately by clicking on this link: {U_ACTIVATE} {EMAIL_SIG} diff --git a/phpBB/language/en/email/forum_notify.txt b/phpBB/language/en/email/forum_notify.txt index ccae82c862..1dfe8c652d 100644 --- a/phpBB/language/en/email/forum_notify.txt +++ b/phpBB/language/en/email/forum_notify.txt @@ -1,4 +1,5 @@ Subject: Forum post notification - "{FORUM_NAME}" +List-Unsubscribe: <{U_STOP_WATCHING_FORUM}> Hello {USERNAME}, diff --git a/phpBB/language/en/email/newtopic_notify.txt b/phpBB/language/en/email/newtopic_notify.txt index b9416d8e40..0dfc9e43b4 100644 --- a/phpBB/language/en/email/newtopic_notify.txt +++ b/phpBB/language/en/email/newtopic_notify.txt @@ -1,4 +1,5 @@ Subject: New topic notification - "{FORUM_NAME}" +List-Unsubscribe: <{U_STOP_WATCHING_FORUM}> Hello {USERNAME}, @@ -6,6 +7,10 @@ You are receiving this notification because you are watching the forum "{FORUM_N {U_FORUM} +To see new topic directly, visit the following link: + +{U_TOPIC} + If you no longer wish to watch this forum you can either click the "Unsubscribe forum" link found in the forum above, or by clicking the following link: {U_STOP_WATCHING_FORUM} diff --git a/phpBB/language/en/email/report_pm.txt b/phpBB/language/en/email/report_pm.txt index a101a014ff..a6b8086a9a 100644 --- a/phpBB/language/en/email/report_pm.txt +++ b/phpBB/language/en/email/report_pm.txt @@ -1,4 +1,4 @@ -Subject: Private Message report - "{TOPIC_TITLE}" +Subject: Private Message report - "{SUBJECT}" Hello {USERNAME}, diff --git a/phpBB/language/en/email/topic_notify.txt b/phpBB/language/en/email/topic_notify.txt index 20b86ee729..92bf85806e 100644 --- a/phpBB/language/en/email/topic_notify.txt +++ b/phpBB/language/en/email/topic_notify.txt @@ -1,4 +1,5 @@ Subject: Topic reply notification - "{TOPIC_TITLE}" +List-Unsubscribe: <{U_STOP_WATCHING_TOPIC}> Hello {USERNAME}, diff --git a/phpBB/language/en/help/faq.php b/phpBB/language/en/help/faq.php index e59d950948..6b165da0f8 100644 --- a/phpBB/language/en/help/faq.php +++ b/phpBB/language/en/help/faq.php @@ -111,8 +111,8 @@ $lang = array_merge($lang, array( 'HELP_FAQ_LOGIN_CANNOT_REGISTER_QUESTION' => 'Why can’t I register?', 'HELP_FAQ_LOGIN_COPPA_ANSWER' => 'COPPA, or the Children’s Online Privacy Protection Act of 1998, is a law in the United States requiring websites which can potentially collect information from minors under the age of 13 to have written parental consent or some other method of legal guardian acknowledgment, allowing the collection of personally identifiable information from a minor under the age of 13. If you are unsure if this applies to you as someone trying to register or to the website you are trying to register on, contact legal counsel for assistance. Please note that phpBB Limited and the owners of this board cannot provide legal advice and is not a point of contact for legal concerns of any kind, except as outlined in question “Who do I contact about abusive and/or legal matters related to this board?”.', 'HELP_FAQ_LOGIN_COPPA_QUESTION' => 'What is COPPA?', - 'HELP_FAQ_LOGIN_DELETE_COOKIES_ANSWER' => '“Delete all board cookies” deletes the cookies created by phpBB which keep you authenticated and logged into the board. Cookies also provide functions such as read tracking if they have been enabled by a board administrator. If you are having login or logout problems, deleting board cookies may help.', - 'HELP_FAQ_LOGIN_DELETE_COOKIES_QUESTION' => 'What does the “Delete all board cookies” do?', + 'HELP_FAQ_LOGIN_DELETE_COOKIES_ANSWER' => '“Delete cookies” deletes the cookies created by phpBB which keep you authenticated and logged into the board. Cookies also provide functions such as read tracking if they have been enabled by a board administrator. If you are having login or logout problems, deleting board cookies may help.', + 'HELP_FAQ_LOGIN_DELETE_COOKIES_QUESTION' => 'What does the “Delete cookies” do?', 'HELP_FAQ_LOGIN_LOST_PASSWORD_ANSWER' => 'Don’t panic! While your password cannot be retrieved, it can easily be reset. Visit the login page and click <em>I forgot my password</em>. Follow the instructions and you should be able to log in again shortly.<br />However, if you are not able to reset your password, contact a board administrator.', 'HELP_FAQ_LOGIN_LOST_PASSWORD_QUESTION' => 'I’ve lost my password!', 'HELP_FAQ_LOGIN_REGISTER_ANSWER' => 'You may not have to, it is up to the administrator of the board as to whether you need to register in order to post messages. However; registration will give you access to additional features not available to guest users such as definable avatar images, private messaging, emailing of fellow users, usergroup subscription, etc. It only takes a few moments to register so it is recommended you do so.', diff --git a/phpBB/language/en/install.php b/phpBB/language/en/install.php index f7d9f58d43..9bceeccde7 100644 --- a/phpBB/language/en/install.php +++ b/phpBB/language/en/install.php @@ -49,7 +49,7 @@ $lang = array_merge($lang, array( // Support page 'SUPPORT_TITLE' => 'Support', - 'SUPPORT_BODY' => 'Full support will be provided for the current stable release of phpBB3, free of charge. This includes:</p><ul><li>installation</li><li>configuration</li><li>technical questions</li><li>problems relating to potential bugs in the software</li><li>updating from Release Candidate (RC) versions to the latest stable version</li><li>converting from phpBB 2.0.x to phpBB3</li><li>converting from other discussion board software to phpBB3 (please see the <a href="https://www.phpbb.com/community/viewforum.php?f=486">Convertors Forum</a>)</li></ul><p>We encourage users still running beta versions of phpBB3 to replace their installation with a fresh copy of the latest version.</p><h2>Extensions / Styles</h2><p>For issues relating to Extensions, please post in the appropriate <a href="https://www.phpbb.com/community/viewforum.php?f=451">Extensions Forum</a>.<br />For issues relating to styles, templates and themes, please post in the appropriate <a href="https://www.phpbb.com/community/viewforum.php?f=471">Styles Forum</a>.<br /><br />If your question relates to a specific package, please post directly in the topic dedicated to the package.</p><h2>Obtaining Support</h2><p><a href="https://www.phpbb.com/community/viewtopic.php?f=14&t=571070">The phpBB Welcome Package</a><br /><a href="https://www.phpbb.com/support/">Support Section</a><br /><a href="https://www.phpbb.com/support/docs/en/3.1/ug/quickstart/">Quick Start Guide</a><br /><br />To ensure you stay up to date with the latest news and releases, why not <a href="https://www.phpbb.com/support/">subscribe to our mailing list</a>?<br /><br />', + 'SUPPORT_BODY' => 'Full support will be provided for the current stable release of phpBB3, free of charge. This includes:</p><ul><li>installation</li><li>configuration</li><li>technical questions</li><li>problems relating to potential bugs in the software</li><li>updating from Release Candidate (RC) versions to the latest stable version</li><li>converting from phpBB 2.0.x to phpBB3</li><li>converting from other discussion board software to phpBB3 (please see the <a href="https://www.phpbb.com/community/viewforum.php?f=486">Convertors Forum</a>)</li></ul><p>We encourage users still running beta versions of phpBB3 to replace their installation with a fresh copy of the latest version.</p><h2>Extensions / Styles</h2><p>For issues relating to Extensions, please post in the appropriate <a href="https://www.phpbb.com/community/viewforum.php?f=451">Extensions Forum</a>.<br />For issues relating to styles, templates and themes, please post in the appropriate <a href="https://www.phpbb.com/community/viewforum.php?f=471">Styles Forum</a>.<br /><br />If your question relates to a specific package, please post directly in the topic dedicated to the package.</p><h2>Obtaining Support</h2><p><a href="https://www.phpbb.com/support/">Support Section</a><br /><a href="https://www.phpbb.com/support/docs/en/3.2/ug/quickstart/">Quick Start Guide</a><br /><br />To ensure you stay up to date with the latest news and releases, follow us on <a href="https://www.twitter.com/phpbb/">Twitter</a> and <a href="https://www.facebook.com/phpbb/">Facebook</a><br /><br />', // License 'LICENSE_TITLE' => 'General Public License', @@ -193,6 +193,7 @@ $lang = array_merge($lang, array( 'DB_OPTION_SQLITE3' => 'SQLite 3', // Errors + 'INST_ERR_DB' => 'Database installation error', 'INST_ERR_NO_DB' => 'Cannot load the PHP module for the selected database type.', 'INST_ERR_DB_INVALID_PREFIX' => 'The prefix you entered is invalid. It must start with a letter and must only contain letters, numbers and underscores.', 'INST_ERR_PREFIX_TOO_LONG' => 'The table prefix you have specified is too long. The maximum length is %d characters.', @@ -354,17 +355,40 @@ $lang = array_merge($lang, array( <br /> + <h1>How to update your installation with the Full Package</h1> + + <p>The recommended way of updating your installation is using the full package. If core phpBB files have been modified in your installation you may wish to use the automatic update package in order to not lose these changes. You are also able to update your installation using the other methods listed within the INSTALL.html document. The steps for updating phpBB3 using the full package are:</p> + + <ol style="margin-left: 20px; font-size: 1.1em;"> + <li><strong class="error">Backup all board files and the database.</strong></li> + <li>Go to the <a href="https://www.phpbb.com/downloads/" title="https://www.phpbb.com/downloads/">phpBB.com downloads page</a> and download the latest "Full Package" archive.</li> + <li>Unpack the archive.</li> + <li>Remove (delete) the <code class="inline">config.php</code> file, and the <code class="inline">/images</code>, <code class="inline">/store</code> and <code class="inline">/files</code> folders <em>from the package</em> (not your site).</li> + <li>Go to the ACP, Board settings, and make sure prosilver is set as the default style. If not, set it to prosilver.</li> + <li>Delete the <code class="inline">/vendor</code> and <code class="inline">/cache</code> folders from the board’s root folder on the host.</li> + <li>Via FTP or SSH upload the remaining files and folders (that is, the remaining CONTENTS of the phpBB3 folder) to the root folder of your board installation on the server, overwriting the existing files. (Note: take care not to delete any extensions in your <code class="inline">/ext</code> folder when uploading the new phpBB3 contents.)</li> + <li><strong><a href="%1$s" title="%1$s">Now start the update process by pointing your browser to the install folder</a>.</strong></li> + <li>Follow the steps to update the database and let that run to completion.</li> + <li>Via FTP or SSH delete the <code class="inline">/install</code> folder from the root of your board installation.<br><br></li> + </ol> + + <p>You now have a new up to date board containing all your users and posts. Follow up tasks:</p> + <ul style="margin-left: 20px; font-size: 1.1em;"> + <li>Update your language pack</li> + <li>Update your style<br><br></li> + </ul> + <h1>How to update your installation with the Automatic Update Package</h1> - <p>The recommended way of updating your installation listed here is only valid for the automatic update package. You are also able to update your installation using the methods listed within the INSTALL.html document. The steps for updating phpBB3 automatically are:</p> + <p>The automatic update package is only recommended in case core phpBB files have been modified in your installation. You are also able to update your installation using the methods listed within the INSTALL.html document. The steps for updating phpBB3 using the automatic update package are:</p> - <ul style="margin-left: 20px; font-size: 1.1em;"> - <li>Go to the <a href="https://www.phpbb.com/downloads/" title="https://www.phpbb.com/downloads/">phpBB.com downloads page</a> and download the "Automatic Update Package" archive.<br /><br /></li> - <li>Unpack the archive.<br /><br /></li> - <li>Upload the complete uncompressed "install" and "vendor" folders to your phpBB root directory (where your config.php file is).<br /><br /></li> - </ul> + <ol style="margin-left: 20px; font-size: 1.1em;"> + <li>Go to the <a href="https://www.phpbb.com/downloads/" title="https://www.phpbb.com/downloads/">phpBB.com downloads page</a> and download the "Automatic Update Package" archive.</li> + <li>Unpack the archive.</li> + <li>Upload the complete uncompressed "install" and "vendor" folders to your phpBB root directory (where your config.php file is).<br><br></li> + </ol> - <p>Once uploaded your board will be offline for normal users due to the install directory you uploaded now present.<br /><br /> + <p>Once uploaded your board will be offline for normal users due to the install directory you uploaded now being present.<br /><br /> <strong><a href="%1$s" title="%1$s">Now start the update process by pointing your browser to the install folder</a>.</strong><br /> <br /> You will then be guided through the update process. You will be notified once the update is complete. diff --git a/phpBB/language/en/posting.php b/phpBB/language/en/posting.php index 7c415b3457..426475e77a 100644 --- a/phpBB/language/en/posting.php +++ b/phpBB/language/en/posting.php @@ -43,6 +43,7 @@ $lang = array_merge($lang, array( 'ADD_POLL' => 'Poll creation', 'ADD_POLL_EXPLAIN' => 'If you do not want to add a poll to your topic leave the fields blank.', 'ALREADY_DELETED' => 'Sorry but this message is already deleted.', + 'ATTACH_COMMENT_NO_EMOJIS' => 'The attachment comment contains forbidden characters (Emoji).', 'ATTACH_DISK_FULL' => 'There is not enough free disk space to post this attachment.', 'ATTACH_QUOTA_REACHED' => 'Sorry, the board attachment quota has been reached.', 'ATTACH_SIG' => 'Attach a signature (signatures can be altered via the UCP)', @@ -145,6 +146,7 @@ $lang = array_merge($lang, array( 'LOAD_DRAFT_EXPLAIN' => 'Here you are able to select the draft you want to continue writing. Your current post will be cancelled, all current post contents will be deleted. View, edit and delete drafts within your User Control Panel.', 'LOGIN_EXPLAIN_BUMP' => 'You need to login in order to bump topics within this forum.', 'LOGIN_EXPLAIN_DELETE' => 'You need to login in order to delete posts within this forum.', + 'LOGIN_EXPLAIN_SOFT_DELETE' => 'You need to login in order to soft-delete posts within this forum.', 'LOGIN_EXPLAIN_POST' => 'You need to login in order to post within this forum.', 'LOGIN_EXPLAIN_QUOTE' => 'You need to login in order to quote posts within this forum.', 'LOGIN_EXPLAIN_REPLY' => 'You need to login in order to reply to topics within this forum.', diff --git a/phpBB/language/en/ucp.php b/phpBB/language/en/ucp.php index 5056e23d24..8549230b9f 100644 --- a/phpBB/language/en/ucp.php +++ b/phpBB/language/en/ucp.php @@ -89,6 +89,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.', + 'ATTACHMENT_LOCKED' => 'This topic is locked, you cannot delete the attachment.', 'AUTOLOGIN_SESSION_KEYS_DELETED'=> 'The selected "Remember Me" login keys were successfully deleted.', 'AVATAR_CATEGORY' => 'Category', 'AVATAR_DRIVER_GRAVATAR_TITLE' => 'Gravatar', @@ -115,7 +116,7 @@ $lang = array_merge($lang, array( 'BIRTHDAY' => 'Birthday', 'BIRTHDAY_EXPLAIN' => 'Setting a year will list your age when it is your birthday.', 'BOARD_DATE_FORMAT' => 'My date format', - 'BOARD_DATE_FORMAT_EXPLAIN' => 'The syntax used is identical to the PHP <a href="http://www.php.net/date">date()</a> function.', + 'BOARD_DATE_FORMAT_EXPLAIN' => 'The syntax used is identical to the PHP <a href="https://secure.php.net/manual/function.date.php">date()</a> function.', 'BOARD_LANGUAGE' => 'My language', 'BOARD_STYLE' => 'My board style', 'BOARD_TIMEZONE' => 'My timezone', @@ -272,6 +273,7 @@ $lang = array_merge($lang, array( 'IMPORTANT_NEWS' => 'Important announcements', 'INVALID_USER_BIRTHDAY' => 'The entered birthday is not a valid date.', 'INVALID_CHARS_USERNAME' => 'The username contains forbidden characters.', + 'INVALID_EMOJIS_USERNAME' => 'The username contains forbidden characters (Emoji).', 'INVALID_CHARS_NEW_PASSWORD'=> 'The password does not contain the required characters.', 'ITEMS_REQUIRED' => 'The items marked with * are required profile fields and need to be filled out.', @@ -302,6 +304,7 @@ $lang = array_merge($lang, array( 'MESSAGE_EDITED' => 'Message successfully edited.', 'MESSAGE_HISTORY' => 'Message history', 'MESSAGE_REMOVED_FROM_OUTBOX' => 'This message was deleted by its author.', + 'MESSAGE_REPORTED_MESSAGE' => 'Reported message', 'MESSAGE_SENT_ON' => 'on', 'MESSAGE_STORED' => 'This message has been sent successfully.', 'MESSAGE_TO' => 'To', @@ -373,10 +376,10 @@ $lang = array_merge($lang, array( 'NO_AUTH_EDIT_MESSAGE' => 'You are not authorised to edit private messages.', '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_PRINT_MESSAGE' => 'You are not authorised to print private messages.', 'NO_AUTH_READ_REMOVED_MESSAGE' => 'You are not able to read this message because it was removed by the author.', 'NO_AUTH_SEND_MESSAGE' => 'You are not authorised to send private messages.', 'NO_AUTH_SIGNATURE' => 'You are not authorised to define a signature.', @@ -386,6 +389,7 @@ $lang = array_merge($lang, array( 'NO_BOOKMARKS_SELECTED' => 'You have selected no bookmarks.', 'NO_EDIT_READ_MESSAGE' => 'Private message cannot be edited because it has already been read.', 'NO_EMAIL_USER' => 'The email/username information submitted could not be found.', + 'EMAIL_NOT_UNIQUE' => 'Email you specified is used by multiple users. You must specify username as well.', 'NO_FOES' => 'No foes currently defined', 'NO_FRIENDS' => 'No friends currently defined', 'NO_FRIENDS_OFFLINE' => 'No friends offline', @@ -411,7 +415,7 @@ $lang = array_merge($lang, array( 'PASS_TYPE_SYMBOL_EXPLAIN' => 'Password must be between %1$s and %2$s long, must contain letters in mixed case, must contain numbers and must contain symbols.', 'PASSWORD' => 'Password', 'PASSWORD_ACTIVATED' => 'Your new password has been activated.', - 'PASSWORD_UPDATED' => 'A new password was sent to your registered email address.', + 'PASSWORD_UPDATED_IF_EXISTED' => 'If your account exists, a new password was sent to your registered email address. If you do not receive an email, it may be because you are banned, your account is not activated, or you are not allowed to change your password. Contact admin if any of those reasons apply. Also, check your spam filter.', 'PERMISSIONS_RESTORED' => 'Successfully restored original permissions.', 'PERMISSIONS_TRANSFERRED' => 'Successfully transferred permissions from <strong>%s</strong>, you are now able to browse the board with this user’s permissions.<br />Please note that admin permissions were not transferred. You are able to revert to your permission set at any time.', 'PM_DISABLED' => 'Private messaging has been disabled on this board.', diff --git a/phpBB/language/en/viewforum.php b/phpBB/language/en/viewforum.php index 9946a3eda4..e2a6e2a718 100644 --- a/phpBB/language/en/viewforum.php +++ b/phpBB/language/en/viewforum.php @@ -53,7 +53,8 @@ $lang = array_merge($lang, array( 'NEW_POSTS_LOCKED' => 'New posts [ Locked ]', // Not used anymore 'NO_NEW_POSTS_HOT' => 'No new posts [ Popular ]', // Not used anymore 'NO_NEW_POSTS_LOCKED' => 'No new posts [ Locked ]', // Not used anymore - 'NO_READ_ACCESS' => 'You do not have the required permissions to read topics within this forum.', + 'NO_READ_ACCESS' => 'You do not have the required permissions to view or read topics within this forum.', + 'NO_FORUMS_IN_CATEGORY' => 'This category has no forums.', 'NO_UNREAD_POSTS_HOT' => 'No unread posts [ Popular ]', 'NO_UNREAD_POSTS_LOCKED' => 'No unread posts [ Locked ]', diff --git a/phpBB/language/en/viewtopic.php b/phpBB/language/en/viewtopic.php index 5890eecdb6..5d127acb3d 100644 --- a/phpBB/language/en/viewtopic.php +++ b/phpBB/language/en/viewtopic.php @@ -88,6 +88,7 @@ $lang = array_merge($lang, array( 'NO_UNREAD_POSTS' => 'There are no new unread posts for this topic.', 'NO_VOTE_OPTION' => 'You must specify an option when voting.', 'NO_VOTES' => 'No votes', + 'NO_AUTH_PRINT_TOPIC' => 'You are not authorised to print topics.', 'POLL_ENDED_AT' => 'Poll ended at %s', 'POLL_RUN_TILL' => 'Poll runs till %s', diff --git a/phpBB/mcp.php b/phpBB/mcp.php index a5464f4a73..c4a8a66c18 100644 --- a/phpBB/mcp.php +++ b/phpBB/mcp.php @@ -36,7 +36,7 @@ $template->assign_var('S_IN_MCP', true); $id = $request->variable('i', ''); $mode = $request->variable('mode', array('')); -$mode = sizeof($mode) ? array_shift($mode) : $request->variable('mode', ''); +$mode = count($mode) ? array_shift($mode) : $request->variable('mode', ''); // Only Moderators can go beyond this point if (!$user->data['is_registered']) @@ -59,7 +59,7 @@ if ($forum_action !== '' && $request->variable('sort', false, false, \phpbb\requ $action = $forum_action; } -if (sizeof($action_ary)) +if (count($action_ary)) { list($action, ) = each($action_ary); } diff --git a/phpBB/memberlist.php b/phpBB/memberlist.php index 985b45acf7..ce7159c150 100644 --- a/phpBB/memberlist.php +++ b/phpBB/memberlist.php @@ -173,7 +173,7 @@ switch ($mode) 'LEFT_JOIN' => array( array( 'FROM' => array(USERS_TABLE => 'u'), - 'ON' => 'ug.user_id = u.user_id AND ug.user_pending = 0', + 'ON' => 'ug.user_id = u.user_id', ), array( 'FROM' => array(GROUPS_TABLE => 'g'), @@ -181,7 +181,7 @@ switch ($mode) ), ), - 'WHERE' => $db->sql_in_set('g.group_id', $group_ids, false, true), + 'WHERE' => $db->sql_in_set('g.group_id', $group_ids, false, true) . ' AND ug.user_pending = 0', 'ORDER_BY' => 'u.username_clean ASC', ); @@ -489,9 +489,31 @@ switch ($mode) } // Get user... - $sql = 'SELECT * - FROM ' . USERS_TABLE . ' - WHERE ' . (($username) ? "username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'" : "user_id = $user_id"); + $sql_array = array( + 'SELECT' => 'u.*', + 'FROM' => array( + USERS_TABLE => 'u' + ), + 'WHERE' => (($username) ? "u.username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'" : "u.user_id = $user_id"), + ); + + /** + * Modify user data SQL before member profile row is created + * + * @event core.memberlist_modify_viewprofile_sql + * @var int user_id The user ID + * @var string username The username + * @var array sql_array Array containing the main query + * @since 3.2.6-RC1 + */ + $vars = array( + 'user_id', + 'username', + 'sql_array', + ); + extract($phpbb_dispatcher->trigger_event('core.memberlist_modify_viewprofile_sql', compact($vars))); + + $sql = $db->sql_build_query('SELECT', $sql_array); $result = $db->sql_query($sql); $member = $db->sql_fetchrow($result); $db->sql_freeresult($result); @@ -523,12 +545,37 @@ switch ($mode) $sql_uid_ary = ($auth_hidden_groups) ? array($user_id) : array($user_id, (int) $user->data['user_id']); // Do the SQL thang - $sql = 'SELECT g.group_id, g.group_name, g.group_type, ug.user_id - FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . ' ug - WHERE ' . $db->sql_in_set('ug.user_id', $sql_uid_ary) . ' - AND g.group_id = ug.group_id - AND ug.user_pending = 0'; - $result = $db->sql_query($sql); + $sql_ary = [ + 'SELECT' => 'g.group_id, g.group_name, g.group_type, ug.user_id', + + 'FROM' => [ + GROUPS_TABLE => 'g', + ], + + 'LEFT_JOIN' => [ + [ + 'FROM' => [USER_GROUP_TABLE => 'ug'], + 'ON' => 'g.group_id = ug.group_id', + ], + ], + + 'WHERE' => $db->sql_in_set('ug.user_id', $sql_uid_ary) . ' + AND ug.user_pending = 0', + ]; + + /** + * Modify the query used to get the group data + * + * @event core.modify_memberlist_viewprofile_group_sql + * @var array sql_ary Array containing the query + * @since 3.2.6-RC1 + */ + $vars = array( + 'sql_ary', + ); + extract($phpbb_dispatcher->trigger_event('core.modify_memberlist_viewprofile_group_sql', compact($vars))); + + $result = $db->sql_query($db->sql_build_query('SELECT', $sql_ary)); // Divide data into profile data and current user data $profile_groups = $user_groups = array(); @@ -567,6 +614,20 @@ switch ($mode) unset($user_groups); asort($group_sort); + /** + * Modify group data before options is created and data is unset + * + * @event core.modify_memberlist_viewprofile_group_data + * @var array group_data Array containing the group data + * @var array group_sort Array containing the sorted group data + * @since 3.2.6-RC1 + */ + $vars = array( + 'group_data', + 'group_sort', + ); + extract($phpbb_dispatcher->trigger_event('core.modify_memberlist_viewprofile_group_data', compact($vars))); + $group_options = ''; foreach ($group_sort as $group_id => $null) { @@ -702,42 +763,58 @@ switch ($mode) $member['posts_in_queue'] = 0; } - $template->assign_vars(array( - 'L_POSTS_IN_QUEUE' => $user->lang('NUM_POSTS_IN_QUEUE', $member['posts_in_queue']), + // Define the main array of vars to assign to memberlist_view.html + $template_ary = array( + 'L_POSTS_IN_QUEUE' => $user->lang('NUM_POSTS_IN_QUEUE', $member['posts_in_queue']), - 'POSTS_DAY' => $user->lang('POST_DAY', $posts_per_day), - 'POSTS_PCT' => $user->lang('POST_PCT', $percentage), + 'POSTS_DAY' => $user->lang('POST_DAY', $posts_per_day), + 'POSTS_PCT' => $user->lang('POST_PCT', $percentage), - 'SIGNATURE' => $member['user_sig'], - 'POSTS_IN_QUEUE'=> $member['posts_in_queue'], + 'SIGNATURE' => $member['user_sig'], + 'POSTS_IN_QUEUE' => $member['posts_in_queue'], - 'PM_IMG' => $user->img('icon_contact_pm', $user->lang['SEND_PRIVATE_MESSAGE']), - 'L_SEND_EMAIL_USER' => $user->lang('SEND_EMAIL_USER', $member['username']), - 'EMAIL_IMG' => $user->img('icon_contact_email', $user->lang['EMAIL']), - 'JABBER_IMG' => $user->img('icon_contact_jabber', $user->lang['JABBER']), - 'SEARCH_IMG' => $user->img('icon_user_search', $user->lang['SEARCH']), + 'PM_IMG' => $user->img('icon_contact_pm', $user->lang['SEND_PRIVATE_MESSAGE']), + 'L_SEND_EMAIL_USER' => $user->lang('SEND_EMAIL_USER', $member['username']), + 'EMAIL_IMG' => $user->img('icon_contact_email', $user->lang['EMAIL']), + 'JABBER_IMG' => $user->img('icon_contact_jabber', $user->lang['JABBER']), + 'SEARCH_IMG' => $user->img('icon_user_search', $user->lang['SEARCH']), - 'S_PROFILE_ACTION' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group'), - 'S_GROUP_OPTIONS' => $group_options, - 'S_CUSTOM_FIELDS' => (isset($profile_fields['row']) && sizeof($profile_fields['row'])) ? true : false, + 'S_PROFILE_ACTION' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group'), + 'S_GROUP_OPTIONS' => $group_options, + 'S_CUSTOM_FIELDS' => (isset($profile_fields['row']) && count($profile_fields['row'])) ? true : false, - '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) : '', + '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) : '', - 'U_SWITCH_PERMISSIONS' => ($auth->acl_get('a_switchperm') && $user->data['user_id'] != $user_id) ? append_sid("{$phpbb_root_path}ucp.$phpEx", "mode=switch_perm&u={$user_id}&hash=" . generate_link_hash('switchperm')) : '', - 'U_EDIT_SELF' => ($user_id == $user->data['user_id'] && $auth->acl_get('u_chgprofileinfo')) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=ucp_profile&mode=profile_info') : '', + 'U_SWITCH_PERMISSIONS' => ($auth->acl_get('a_switchperm') && $user->data['user_id'] != $user_id) ? append_sid("{$phpbb_root_path}ucp.$phpEx", "mode=switch_perm&u={$user_id}&hash=" . generate_link_hash('switchperm')) : '', + 'U_EDIT_SELF' => ($user_id == $user->data['user_id'] && $auth->acl_get('u_chgprofileinfo')) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=ucp_profile&mode=profile_info') : '', - 'S_USER_NOTES' => ($user_notes_enabled) ? true : false, - 'S_WARN_USER' => ($warn_user_enabled) ? true : false, - 'S_ZEBRA' => ($user->data['user_id'] != $user_id && $user->data['is_registered'] && $zebra_enabled) ? true : false, - 'U_ADD_FRIEND' => (!$friend && !$foe && $friends_enabled) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=zebra&add=' . urlencode(htmlspecialchars_decode($member['username']))) : '', - 'U_ADD_FOE' => (!$friend && !$foe && $foes_enabled) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=zebra&mode=foes&add=' . urlencode(htmlspecialchars_decode($member['username']))) : '', - 'U_REMOVE_FRIEND' => ($friend && $friends_enabled) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=zebra&remove=1&usernames[]=' . $user_id) : '', - 'U_REMOVE_FOE' => ($foe && $foes_enabled) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=zebra&remove=1&mode=foes&usernames[]=' . $user_id) : '', + 'S_USER_NOTES' => ($user_notes_enabled) ? true : false, + 'S_WARN_USER' => ($warn_user_enabled) ? true : false, + 'S_ZEBRA' => ($user->data['user_id'] != $user_id && $user->data['is_registered'] && $zebra_enabled) ? true : false, + 'U_ADD_FRIEND' => (!$friend && !$foe && $friends_enabled) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=zebra&add=' . urlencode(htmlspecialchars_decode($member['username']))) : '', + 'U_ADD_FOE' => (!$friend && !$foe && $foes_enabled) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=zebra&mode=foes&add=' . urlencode(htmlspecialchars_decode($member['username']))) : '', + 'U_REMOVE_FRIEND' => ($friend && $friends_enabled) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=zebra&remove=1&usernames[]=' . $user_id) : '', + 'U_REMOVE_FOE' => ($foe && $foes_enabled) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=zebra&remove=1&mode=foes&usernames[]=' . $user_id) : '', - 'U_CANONICAL' => generate_board_url() . '/' . append_sid("memberlist.$phpEx", 'mode=viewprofile&u=' . $user_id, true, ''), - )); + 'U_CANONICAL' => generate_board_url() . '/' . append_sid("memberlist.$phpEx", 'mode=viewprofile&u=' . $user_id, true, ''), + ); + + /** + * Modify user's template vars before we display the profile + * + * @event core.memberlist_modify_view_profile_template_vars + * @var array template_ary Array with user's template vars + * @since 3.2.6-RC1 + */ + $vars = array( + 'template_ary', + ); + extract($phpbb_dispatcher->trigger_event('core.memberlist_modify_view_profile_template_vars', compact($vars))); + + // Assign vars to memberlist_view.html + $template->assign_vars($template_ary); if (!empty($profile_fields['row'])) { @@ -933,7 +1010,7 @@ switch ($mode) // We validate form and field here, only id/class allowed $form = (!preg_match('/^[a-z0-9_-]+$/i', $form)) ? '' : $form; $field = (!preg_match('/^[a-z0-9_-]+$/i', $field)) ? '' : $field; - if ((($mode == '' || $mode == 'searchuser') || sizeof(array_intersect($request->variable_names(\phpbb\request\request_interface::GET), $search_params)) > 0) && ($config['load_search'] || $auth->acl_get('a_'))) + if ((($mode == '' || $mode == 'searchuser') || count(array_intersect($request->variable_names(\phpbb\request\request_interface::GET), $search_params)) > 0) && ($config['load_search'] || $auth->acl_get('a_'))) { $username = $request->variable('username', '', true); $email = strtolower($request->variable('email', '')); @@ -980,7 +1057,7 @@ switch ($mode) $sql_where .= ($jabber) ? ' AND u.user_jabber ' . $db->sql_like_expression(str_replace('*', $db->get_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 . ' ' : ''; - if (isset($find_key_match[$joined_select]) && sizeof($joined) == 3) + if (isset($find_key_match[$joined_select]) && count($joined) == 3) { $joined_time = gmmktime(0, 0, 0, (int) $joined[1], (int) $joined[2], (int) $joined[0]); @@ -990,13 +1067,24 @@ switch ($mode) } } - if (isset($find_key_match[$active_select]) && sizeof($active) == 3 && $auth->acl_get('u_viewonline')) + if (isset($find_key_match[$active_select]) && count($active) == 3 && $auth->acl_get('u_viewonline')) { $active_time = gmmktime(0, 0, 0, (int) $active[1], (int) $active[2], (int) $active[0]); if ($active_time !== false) { - $sql_where .= " AND u.user_lastvisit " . $find_key_match[$active_select] . ' ' . $active_time; + if ($active_select === 'lt' && (int) $active[0] == 0 && (int) $active[1] == 0 && (int) $active[2] == 0) + { + $sql_where .= ' AND u.user_lastvisit = 0'; + } + else if ($active_select === 'gt') + { + $sql_where .= ' AND u.user_lastvisit ' . $find_key_match[$active_select] . ' ' . $active_time; + } + else + { + $sql_where .= ' AND (u.user_lastvisit > 0 AND u.user_lastvisit < ' . $active_time . ')'; + } } } @@ -1146,18 +1234,18 @@ switch ($mode) $avatar_img = phpbb_get_group_avatar($group_row); // ... same for group rank - $user_rank_data = array( + $group_rank_data = array( 'title' => null, 'img' => null, 'img_src' => null, ); if ($group_row['group_rank']) { - $user_rank_data = phpbb_get_user_rank($group_row, false); + $group_rank_data = $group_helper->get_rank($group_row); - if ($user_rank_data['img']) + if ($group_rank_data['img']) { - $user_rank_data['img'] .= '<br />'; + $group_rank_data['img'] .= '<br />'; } } // include modules for manage groups link display or not @@ -1184,11 +1272,11 @@ switch ($mode) 'GROUP_NAME' => $group_helper->get_name($group_row['group_name']), 'GROUP_COLOR' => $group_row['group_colour'], 'GROUP_TYPE' => $user->lang['GROUP_IS_' . $group_row['l_group_type']], - 'GROUP_RANK' => $user_rank_data['title'], + 'GROUP_RANK' => $group_rank_data['title'], 'AVATAR_IMG' => $avatar_img, - 'RANK_IMG' => $user_rank_data['img'], - 'RANK_IMG_SRC' => $user_rank_data['img_src'], + 'RANK_IMG' => $group_rank_data['img'], + 'RANK_IMG_SRC' => $group_rank_data['img_src'], 'U_PM' => ($auth->acl_get('u_sendpm') && $auth->acl_get('u_masspm_group') && $group_row['group_receive_pm'] && $config['allow_privmsg'] && $config['allow_mass_pm']) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&mode=compose&g=' . $group_id) : '', 'U_MANAGE' => ($can_manage_group) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=ucp_groups&mode=manage') : false,) @@ -1308,11 +1396,6 @@ switch ($mode) } $sort_params[] = "mode=$mode"; - $pagination_url = append_sid("{$phpbb_root_path}memberlist.$phpEx", implode('&', $params)); - $sort_url = append_sid("{$phpbb_root_path}memberlist.$phpEx", implode('&', $sort_params)); - - unset($search_params, $sort_params); - $u_first_char_params = implode('&', $u_first_char_params); $u_first_char_params .= ($u_first_char_params) ? '&' : ''; @@ -1324,16 +1407,47 @@ switch ($mode) } $first_characters['other'] = $user->lang['OTHER']; + $first_char_block_vars = []; + foreach ($first_characters as $char => $desc) { - $template->assign_block_vars('first_char', array( + $first_char_block_vars[] = [ 'DESC' => $desc, 'VALUE' => $char, 'S_SELECTED' => ($first_char == $char) ? true : false, 'U_SORT' => append_sid("{$phpbb_root_path}memberlist.$phpEx", $u_first_char_params . 'first_char=' . $char) . '#memberlist', - )); + ]; } + /** + * Modify memberlist sort and pagination parameters + * + * @event core.memberlist_modify_sort_pagination_params + * @var array sort_params Array with URL parameters for sorting + * @var array params Array with URL parameters for pagination + * @var array first_characters Array that maps each letter in a-z, 'other' and the empty string to their display representation + * @var string u_first_char_params Concatenated URL parameters for first character search links + * @var array first_char_block_vars Template block variables for each first character + * @var int total_users Total number of users found in this search + * @since 3.2.6-RC1 + */ + $vars = [ + 'sort_params', + 'params', + 'first_characters', + 'u_first_char_params', + 'first_char_block_vars', + 'total_users', + ]; + extract($phpbb_dispatcher->trigger_event('core.memberlist_modify_sort_pagination_params', compact($vars))); + + $template->assign_block_vars_array('first_char', $first_char_block_vars); + + $pagination_url = append_sid("{$phpbb_root_path}memberlist.$phpEx", implode('&', $params)); + $sort_url = append_sid("{$phpbb_root_path}memberlist.$phpEx", implode('&', $sort_params)); + + unset($search_params, $sort_params); + // Some search user specific data if (($mode == '' || $mode == 'searchuser') && ($config['load_search'] || $auth->acl_get('a_'))) { @@ -1449,7 +1563,7 @@ switch ($mode) $leaders_set = false; // So, did we get any users? - if (sizeof($user_list)) + if (count($user_list)) { // Session time?! Session time... $sql = 'SELECT session_user_id, MAX(session_time) AS session_time @@ -1469,19 +1583,58 @@ switch ($mode) // Do the SQL thang if ($mode == 'group') { - $sql = "SELECT u.* - $sql_select - FROM " . USERS_TABLE . " u - $sql_from - WHERE " . $db->sql_in_set('u.user_id', $user_list) . " - $sql_where_data"; + $sql_from_ary = explode(',', $sql_from); + $extra_tables = []; + foreach ($sql_from_ary as $entry) + { + $table_data = explode(' ', trim($entry)); + + if (empty($table_data[0]) || empty($table_data[1])) + { + continue; + } + + $extra_tables[$table_data[0]] = $table_data[1]; + } + + $sql_array = array( + 'SELECT' => 'u.*' . $sql_select, + 'FROM' => array_merge([USERS_TABLE => 'u'], $extra_tables), + 'WHERE' => $db->sql_in_set('u.user_id', $user_list) . $sql_where_data . '', + ); } else { - $sql = 'SELECT * - FROM ' . USERS_TABLE . ' - WHERE ' . $db->sql_in_set('user_id', $user_list); + $sql_array = array( + 'SELECT' => 'u.*', + 'FROM' => array( + USERS_TABLE => 'u' + ), + 'WHERE' => $db->sql_in_set('u.user_id', $user_list), + ); } + + /** + * Modify user data SQL before member row is created + * + * @event core.memberlist_modify_memberrow_sql + * @var string mode Memberlist mode + * @var string sql_select Additional select statement + * @var string sql_from Additional from statement + * @var array sql_array Array containing the main query + * @var array user_list Array containing list of users + * @since 3.2.6-RC1 + */ + $vars = array( + 'mode', + 'sql_select', + 'sql_from', + 'sql_array', + 'user_list', + ); + extract($phpbb_dispatcher->trigger_event('core.memberlist_modify_memberrow_sql', compact($vars))); + + $sql = $db->sql_build_query('SELECT', $sql_array); $result = $db->sql_query($sql); $id_cache = array(); @@ -1492,9 +1645,10 @@ switch ($mode) $id_cache[$row['user_id']] = $row; } + $db->sql_freeresult($result); - // Load custom profile fields + // Load custom profile fields if required if ($config['load_cpf_memberlist']) { // Grab all profile fields from users in id cache for later use - similar to the poster cache @@ -1534,7 +1688,7 @@ switch ($mode) $vars = array('user_list', 'use_contact_fields'); extract($phpbb_dispatcher->trigger_event('core.memberlist_memberrow_before', compact($vars))); - for ($i = 0, $end = sizeof($user_list); $i < $end; ++$i) + for ($i = 0, $end = count($user_list); $i < $end; ++$i) { $user_id = $user_list[$i]; $row = $id_cache[$user_id]; @@ -1550,21 +1704,21 @@ switch ($mode) $memberrow = array_merge(phpbb_show_profile($row, false, false, false), array( 'ROW_NUMBER' => $i + ($start + 1), - 'S_CUSTOM_PROFILE' => (isset($cp_row['row']) && sizeof($cp_row['row'])) ? true : false, + 'S_CUSTOM_PROFILE' => (isset($cp_row['row']) && count($cp_row['row'])) ? true : false, 'S_GROUP_LEADER' => $is_leader, 'S_INACTIVE' => $row['user_type'] == USER_INACTIVE, 'U_VIEW_PROFILE' => get_username_string('profile', $user_id, $row['username']), )); - if (isset($cp_row['row']) && sizeof($cp_row['row'])) + if (isset($cp_row['row']) && count($cp_row['row'])) { $memberrow = array_merge($memberrow, $cp_row['row']); } $template->assign_block_vars('memberrow', $memberrow); - if (isset($cp_row['blockrow']) && sizeof($cp_row['blockrow'])) + if (isset($cp_row['blockrow']) && count($cp_row['blockrow'])) { foreach ($cp_row['blockrow'] as $field_data) { diff --git a/phpBB/phpbb/attachment/delete.php b/phpBB/phpbb/attachment/delete.php index 922f24b5dc..3c98e21587 100644 --- a/phpBB/phpbb/attachment/delete.php +++ b/phpBB/phpbb/attachment/delete.php @@ -104,6 +104,8 @@ class delete $this->set_sql_constraints($mode); + $sql_id = $this->sql_id; + /** * Perform additional actions before collecting data for attachment(s) deletion * @@ -122,11 +124,21 @@ class delete ); extract($this->dispatcher->trigger_event('core.delete_attachments_collect_data_before', compact($vars))); + $this->sql_id = $sql_id; + unset($sql_id); + // Collect post and topic ids for later use if we need to touch remaining entries (if resync is enabled) $this->collect_attachment_info($resync); // Delete attachments from database - $this->delete_attachments_from_db(); + $this->delete_attachments_from_db($mode, $ids, $resync); + + $sql_id = $this->sql_id; + $post_ids = $this->post_ids; + $topic_ids = $this->topic_ids; + $message_ids = $this->message_ids; + $physical = $this->physical; + $num_deleted = $this->num_deleted; /** * Perform additional actions after attachment(s) deletion from the database @@ -156,13 +168,21 @@ class delete ); extract($this->dispatcher->trigger_event('core.delete_attachments_from_database_after', compact($vars))); + $this->sql_id = $sql_id; + $this->post_ids = $post_ids; + $this->topic_ids = $topic_ids; + $this->message_ids = $message_ids; + $this->physical = $physical; + $this->num_deleted = $num_deleted; + unset($sql_id, $post_ids, $topic_ids, $message_ids, $physical, $num_deleted); + if (!$this->num_deleted) { return 0; } // Delete attachments from filesystem - $this->remove_from_filesystem(); + $this->remove_from_filesystem($mode, $ids, $resync); // If we do not resync, we do not need to adjust any message, post, topic or user entries if (!$resync) @@ -288,8 +308,14 @@ class delete /** * Delete attachments from database table */ - protected function delete_attachments_from_db() + protected function delete_attachments_from_db($mode, $ids, $resync) { + $sql_id = $this->sql_id; + $post_ids = $this->post_ids; + $topic_ids = $this->topic_ids; + $message_ids = $this->message_ids; + $physical = $this->physical; + /** * Perform additional actions before attachment(s) deletion * @@ -316,6 +342,13 @@ class delete ); extract($this->dispatcher->trigger_event('core.delete_attachments_before', compact($vars))); + $this->sql_id = $sql_id; + $this->post_ids = $post_ids; + $this->topic_ids = $topic_ids; + $this->message_ids = $message_ids; + $this->physical = $physical; + unset($sql_id, $post_ids, $topic_ids, $message_ids, $physical); + // Delete attachments $sql = 'DELETE FROM ' . ATTACHMENTS_TABLE . ' WHERE ' . $this->db->sql_in_set($this->sql_id, $this->ids); @@ -329,7 +362,7 @@ class delete /** * Delete attachments from filesystem */ - protected function remove_from_filesystem() + protected function remove_from_filesystem($mode, $ids, $resync) { $space_removed = $files_removed = 0; @@ -348,6 +381,13 @@ class delete } } + $sql_id = $this->sql_id; + $post_ids = $this->post_ids; + $topic_ids = $this->topic_ids; + $message_ids = $this->message_ids; + $physical = $this->physical; + $num_deleted = $this->num_deleted; + /** * Perform additional actions after attachment(s) deletion from the filesystem * @@ -380,6 +420,14 @@ class delete ); extract($this->dispatcher->trigger_event('core.delete_attachments_from_filesystem_after', compact($vars))); + $this->sql_id = $sql_id; + $this->post_ids = $post_ids; + $this->topic_ids = $topic_ids; + $this->message_ids = $message_ids; + $this->physical = $physical; + $this->num_deleted = $num_deleted; + unset($sql_id, $post_ids, $topic_ids, $message_ids, $physical, $num_deleted); + if ($space_removed || $files_removed) { $this->config->increment('upload_dir_size', $space_removed * (-1), false); diff --git a/phpBB/phpbb/attachment/resync.php b/phpBB/phpbb/attachment/resync.php index 6c2e0a8b0d..aeacf82511 100644 --- a/phpBB/phpbb/attachment/resync.php +++ b/phpBB/phpbb/attachment/resync.php @@ -87,7 +87,7 @@ class resync */ public function resync($type, $ids) { - if (empty($type) || !is_array($ids) || !sizeof($ids) || !in_array($type, array('post', 'topic', 'message'))) + if (empty($type) || !is_array($ids) || !count($ids) || !in_array($type, array('post', 'topic', 'message'))) { return; } @@ -112,7 +112,7 @@ class resync // Now only unset those ids remaining $ids = array_diff($ids, $remaining_ids); - if (sizeof($ids)) + if (count($ids)) { $sql = 'UPDATE ' . $this->resync_table . ' SET ' . $type . '_attachment = 0 diff --git a/phpBB/phpbb/attachment/upload.php b/phpBB/phpbb/attachment/upload.php index f9863b372c..b9d32058db 100644 --- a/phpBB/phpbb/attachment/upload.php +++ b/phpBB/phpbb/attachment/upload.php @@ -162,7 +162,7 @@ class upload // Make sure the image category only holds valid images... $this->check_image($is_image); - if (sizeof($this->file->error)) + if (count($this->file->error)) { $this->file->remove(); $this->file_data['error'] = array_merge($this->file_data['error'], $this->file->error); diff --git a/phpBB/phpbb/auth/auth.php b/phpBB/phpbb/auth/auth.php index dbd83f1eb0..f46a21a8ae 100644 --- a/phpBB/phpbb/auth/auth.php +++ b/phpBB/phpbb/auth/auth.php @@ -72,8 +72,8 @@ class auth // Verify bitstring length with options provided... $renew = false; - $global_length = sizeof($this->acl_options['global']); - $local_length = sizeof($this->acl_options['local']); + $global_length = count($this->acl_options['global']); + $local_length = count($this->acl_options['local']); // Specify comparing length (bitstring is padded to 31 bits) $global_length = ($global_length % 31) ? ($global_length - ($global_length % 31) + 31) : $global_length; @@ -236,7 +236,7 @@ class auth $sql = 'SELECT forum_id FROM ' . FORUMS_TABLE; - if (sizeof($this->acl)) + if (count($this->acl)) { $sql .= ' WHERE ' . $db->sql_in_set('forum_id', array_keys($this->acl), true); } @@ -278,7 +278,7 @@ class auth } // If we get forum_ids not having this permission, we need to fill the remaining parts - if ($negate && sizeof($this->acl_forum_ids)) + if ($negate && count($this->acl_forum_ids)) { foreach ($this->acl_forum_ids as $f) { @@ -455,7 +455,7 @@ class auth { $hold_str = ''; - if (sizeof($hold_ary)) + if (count($hold_ary)) { ksort($hold_ary); diff --git a/phpBB/phpbb/auth/provider/ldap.php b/phpBB/phpbb/auth/provider/ldap.php index c48b771ab0..0789a6234d 100644 --- a/phpBB/phpbb/auth/provider/ldap.php +++ b/phpBB/phpbb/auth/provider/ldap.php @@ -99,7 +99,7 @@ class ldap extends \phpbb\auth\provider\base @ldap_close($ldap); - if (!is_array($result) || sizeof($result) < 2) + if (!is_array($result) || count($result) < 2) { return sprintf($this->user->lang['LDAP_NO_IDENTITY'], $this->user->data['username']); } @@ -192,7 +192,7 @@ class ldap extends \phpbb\auth\provider\base $ldap_result = @ldap_get_entries($ldap, $search); - if (is_array($ldap_result) && sizeof($ldap_result) > 1) + if (is_array($ldap_result) && count($ldap_result) > 1) { if (@ldap_bind($ldap, $ldap_result[0]['dn'], htmlspecialchars_decode($password))) { diff --git a/phpBB/phpbb/auth/provider/oauth/oauth.php b/phpBB/phpbb/auth/provider/oauth/oauth.php index fdc5f57df0..0d94acfbca 100644 --- a/phpBB/phpbb/auth/provider/oauth/oauth.php +++ b/phpBB/phpbb/auth/provider/oauth/oauth.php @@ -191,7 +191,7 @@ class oauth extends \phpbb\auth\provider\base return $provider->login($username, $password); } - // Requst the name of the OAuth service + // Request the name of the OAuth service $service_name_original = $this->request->variable('oauth_service', '', false); $service_name = 'auth.provider.oauth.service.' . strtolower($service_name_original); if ($service_name_original === '' || !array_key_exists($service_name, $this->service_providers)) @@ -221,12 +221,37 @@ class oauth extends \phpbb\auth\provider\base 'provider' => $service_name_original, 'oauth_provider_id' => $unique_id ); + $sql = 'SELECT user_id FROM ' . $this->auth_provider_oauth_token_account_assoc . ' WHERE ' . $this->db->sql_build_array('SELECT', $data); $result = $this->db->sql_query($sql); $row = $this->db->sql_fetchrow($result); $this->db->sql_freeresult($result); + $redirect_data = array( + 'auth_provider' => 'oauth', + 'login_link_oauth_service' => $service_name_original, + ); + + /** + * Event is triggered before check if provider is already associated with an account + * + * @event core.oauth_login_after_check_if_provider_id_has_match + * @var array row User row + * @var array data Provider data + * @var array redirect_data Data to be appended to the redirect url + * @var \OAuth\Common\Service\ServiceInterface service OAuth service + * @since 3.2.3-RC1 + * @changed 3.2.6-RC1 Added redirect_data + */ + $vars = array( + 'row', + 'data', + 'redirect_data', + 'service', + ); + extract($this->dispatcher->trigger_event('core.oauth_login_after_check_if_provider_id_has_match', compact($vars))); + if (!$row) { // The user does not yet exist, ask to link or create profile @@ -234,15 +259,12 @@ class oauth extends \phpbb\auth\provider\base 'status' => LOGIN_SUCCESS_LINK_PROFILE, 'error_msg' => 'LOGIN_OAUTH_ACCOUNT_NOT_LINKED', 'user_row' => array(), - 'redirect_data' => array( - 'auth_provider' => 'oauth', - 'login_link_oauth_service' => $service_name_original, - ), + 'redirect_data' => $redirect_data, ); } // Retrieve the user's account - $sql = 'SELECT user_id, username, user_password, user_passchg, user_email, user_type, user_login_attempts + $sql = 'SELECT user_id, username, user_password, user_passchg, user_email, user_ip, user_type, user_login_attempts FROM ' . $this->users_table . ' WHERE user_id = ' . (int) $row['user_id']; $result = $this->db->sql_query($sql); @@ -254,11 +276,36 @@ class oauth extends \phpbb\auth\provider\base throw new \Exception('AUTH_PROVIDER_OAUTH_ERROR_INVALID_ENTRY'); } + /** + * Check if the user is banned. + * The fourth parameter, return, has to be true, + * otherwise the OAuth login is still called and + * an uncaught exception is thrown as there is no + * token stored in the database. + */ + $ban = $this->user->check_ban($row['user_id'], $row['user_ip'], $row['user_email'], true); + if (!empty($ban)) + { + $till_date = !empty($ban['ban_end']) ? $this->user->format_date($ban['ban_end']) : ''; + $message = !empty($ban['ban_end']) ? 'BOARD_BAN_TIME' : 'BOARD_BAN_PERM'; + + $contact_link = phpbb_get_board_contact_link($this->config, $this->phpbb_root_path, $this->php_ext); + $message = $this->user->lang($message, $till_date, '<a href="' . $contact_link . '">', '</a>'); + $message .= !empty($ban['ban_give_reason']) ? '<br /><br />' . $this->user->lang('BOARD_BAN_REASON', $ban['ban_give_reason']) : ''; + $message .= !empty($ban['ban_triggered_by']) ? '<br /><br /><em>' . $this->user->lang('BAN_TRIGGERED_BY_' . strtoupper($ban['ban_triggered_by'])) . '</em>' : ''; + + return array( + 'status' => LOGIN_BREAK, + 'error_msg' => $message, + 'user_row' => $row, + ); + } + // Update token storage to store the user_id $storage->set_user_id($row['user_id']); /** - * Event is triggered after user is successfuly logged in via OAuth. + * Event is triggered after user is successfully logged in via OAuth. * * @event core.auth_oauth_login_after * @var array row User row @@ -376,7 +423,7 @@ class oauth extends \phpbb\auth\provider\base if ($credentials['key'] && $credentials['secret']) { $actual_name = str_replace('auth.provider.oauth.service.', '', $service_name); - $redirect_url = build_url(false) . '&login=external&oauth_service=' . $actual_name; + $redirect_url = generate_board_url() . '/ucp.' . $this->php_ext . '?mode=login&login=external&oauth_service=' . $actual_name; $login_data['BLOCK_VARS'][$service_name] = array( 'REDIRECT_URL' => redirect($redirect_url, true), 'SERVICE_NAME' => $this->user->lang['AUTH_PROVIDER_OAUTH_SERVICE_' . strtoupper($actual_name)], @@ -587,6 +634,21 @@ class oauth extends \phpbb\auth\provider\base */ protected function link_account_perform_link(array $data) { + // Check if the external account is already associated with other user + $sql = 'SELECT user_id + FROM ' . $this->auth_provider_oauth_token_account_assoc . " + WHERE provider = '" . $this->db->sql_escape($data['provider']) . "' + AND oauth_provider_id = '" . $this->db->sql_escape($data['oauth_provider_id']) . "'"; + $result = $this->db->sql_query($sql); + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + if ($row) + { + trigger_error('AUTH_PROVIDER_OAUTH_ERROR_ALREADY_LINKED'); + } + + // Link account $sql = 'INSERT INTO ' . $this->auth_provider_oauth_token_account_assoc . ' ' . $this->db->sql_build_array('INSERT', $data); $this->db->sql_query($sql); @@ -635,7 +697,7 @@ class oauth extends \phpbb\auth\provider\base $oauth_user_ids = array(); - if ($rows !== false && sizeof($rows)) + if ($rows !== false && count($rows)) { foreach ($rows as $row) { @@ -658,6 +720,7 @@ class oauth extends \phpbb\auth\provider\base 'oauth_service' => $actual_name, ), + 'SERVICE_ID' => $actual_name, 'SERVICE_NAME' => $this->user->lang['AUTH_PROVIDER_OAUTH_SERVICE_' . strtoupper($actual_name)], 'UNIQUE_ID' => (isset($oauth_user_ids[$actual_name])) ? $oauth_user_ids[$actual_name] : null, ); @@ -691,7 +754,7 @@ class oauth extends \phpbb\auth\provider\base AND user_id = " . (int) $user_id; $this->db->sql_query($sql); - // Clear all tokens belonging to the user on this servce + // Clear all tokens belonging to the user on this service $service_name = 'auth.provider.oauth.service.' . strtolower($link_data['oauth_service']); $storage = new \phpbb\auth\provider\oauth\token_storage($this->db, $this->user, $this->auth_provider_oauth_token_storage_table, $this->auth_provider_oauth_state_table); $storage->clearToken($service_name); diff --git a/phpBB/phpbb/auth/provider/provider_interface.php b/phpBB/phpbb/auth/provider/provider_interface.php index 35e0f559a1..463324ff46 100644 --- a/phpBB/phpbb/auth/provider/provider_interface.php +++ b/phpBB/phpbb/auth/provider/provider_interface.php @@ -71,9 +71,10 @@ interface provider_interface * options with whatever configuraton values are passed to it as an array. * It then returns the name of the acp file related to this authentication * provider. - * @param array $new_config Contains the new configuration values that - * have been set in acp_board. - * @return array|null Returns null if not implemented or an array with + * + * @param \phpbb\config\config $new_config Contains the new configuration values + * that have been set in acp_board. + * @return array|null Returns null if not implemented or an array with * the template file name and an array of the vars * that the template needs that must conform to the * following example: diff --git a/phpBB/phpbb/avatar/driver/local.php b/phpBB/phpbb/avatar/driver/local.php index f5547c4bc6..4b84e4201c 100644 --- a/phpBB/phpbb/avatar/driver/local.php +++ b/phpBB/phpbb/avatar/driver/local.php @@ -64,7 +64,7 @@ class local extends \phpbb\avatar\driver\driver $table_cols = isset($row['avatar_gallery_cols']) ? $row['avatar_gallery_cols'] : 4; $row_count = $col_count = $avatar_pos = 0; - $avatar_count = sizeof($avatar_list[$category]); + $avatar_count = count($avatar_list[$category]); reset($avatar_list[$category]); @@ -158,7 +158,7 @@ class local extends \phpbb\avatar\driver\driver */ protected function get_avatar_list($user) { - $avatar_list = ($this->cache == null) ? false : $this->cache->get('_avatar_local_list'); + $avatar_list = ($this->cache == null) ? false : $this->cache->get('_avatar_local_list_' . $user->data['user_lang']); if ($avatar_list === false) { @@ -198,7 +198,7 @@ class local extends \phpbb\avatar\driver\driver if ($this->cache != null) { - $this->cache->put('_avatar_local_list', $avatar_list, 86400); + $this->cache->put('_avatar_local_list_' . $user->data['user_lang'], $avatar_list, 86400); } } diff --git a/phpBB/phpbb/avatar/driver/upload.php b/phpBB/phpbb/avatar/driver/upload.php index 887a0ff258..a012bb15b6 100644 --- a/phpBB/phpbb/avatar/driver/upload.php +++ b/phpBB/phpbb/avatar/driver/upload.php @@ -148,7 +148,8 @@ class upload extends \phpbb\avatar\driver\driver // Do not allow specifying the port (see RFC 3986) or IP addresses // remote_upload() will do its own check for allowed filetypes - if (preg_match('@^(http|https|ftp)://[^/:?#]+:[0-9]+[/:?#]@i', $url) || + if (!preg_match('#^(http|https|ftp)://(?:(.*?\.)*?[a-z0-9\-]+?\.[a-z]{2,4}|(?:\d{1,3}\.){3,5}\d{1,3}):?([0-9]*?).*?\.('. implode('|', $this->allowed_extensions) . ')$#i', $url) || + preg_match('@^(http|https|ftp)://[^/:?#]+:[0-9]+[/:?#]@i', $url) || preg_match('#^(http|https|ftp)://(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])#i', $url) || preg_match('#^(http|https|ftp)://(?:(?:(?:[\dA-F]{1,4}:){6}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:::(?:[\dA-F]{1,4}:){0,5}(?:[\dA-F]{1,4}(?::[\dA-F]{1,4})?|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:):(?:[\dA-F]{1,4}:){4}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,2}:(?:[\dA-F]{1,4}:){3}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,3}:(?:[\dA-F]{1,4}:){2}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,4}:(?:[\dA-F]{1,4}:)(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,5}:(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,6}:[\dA-F]{1,4})|(?:(?:[\dA-F]{1,4}:){1,7}:)|(?:::))#i', $url)) { @@ -167,7 +168,7 @@ class upload extends \phpbb\avatar\driver\driver $file->clean_filename('avatar', $prefix, $row['id']); // If there was an error during upload, then abort operation - if (sizeof($file->error)) + if (count($file->error)) { $file->remove(); $error = $file->error; @@ -203,15 +204,18 @@ class upload extends \phpbb\avatar\driver\driver * * @event core.avatar_driver_upload_move_file_before * @var array filedata Array containing uploaded file data + * @var \phpbb\files\filespec file Instance of filespec class * @var string destination Destination directory where the file is going to be moved * @var string prefix Prefix for the avatar filename * @var array row Array with avatar row data * @var array error Array of errors, if filled in by this event file will not be moved * @since 3.1.6-RC1 * @changed 3.1.9-RC1 Added filedata + * @changed 3.2.3-RC1 Added file */ $vars = array( 'filedata', + 'file', 'destination', 'prefix', 'row', @@ -221,7 +225,7 @@ class upload extends \phpbb\avatar\driver\driver unset($filedata); - if (!sizeof($error)) + if (!count($error)) { // Move file and overwrite any existing image $file->move_file($destination, true); @@ -229,7 +233,7 @@ class upload extends \phpbb\avatar\driver\driver // If there was an error during move, then clean up leftovers $error = array_merge($error, $file->error); - if (sizeof($error)) + if (count($error)) { $file->remove(); return false; @@ -291,7 +295,7 @@ class upload extends \phpbb\avatar\driver\driver ); extract($this->dispatcher->trigger_event('core.avatar_driver_upload_delete_before', compact($vars))); - if (!sizeof($error) && $this->filesystem->exists($filename)) + if (!count($error) && $this->filesystem->exists($filename)) { try { diff --git a/phpBB/phpbb/avatar/manager.php b/phpBB/phpbb/avatar/manager.php index 26eb17c265..a909a91042 100644 --- a/phpBB/phpbb/avatar/manager.php +++ b/phpBB/phpbb/avatar/manager.php @@ -22,6 +22,12 @@ class manager protected $config; /** + * phpBB event dispatcher + * @var \phpbb\event\dispatcher_interface + */ + protected $phpbb_dispatcher; + + /** * Array that contains a list of enabled drivers * @var array */ @@ -49,11 +55,13 @@ class manager * Construct an avatar manager object * * @param \phpbb\config\config $config phpBB configuration + * @param \phpbb\event\dispatcher_interface $phpbb_dispatcher phpBB event dispatcher * @param array $avatar_drivers Avatar drivers passed via the service container */ - public function __construct(\phpbb\config\config $config, $avatar_drivers) + public function __construct(\phpbb\config\config $config, \phpbb\event\dispatcher_interface $phpbb_dispatcher, $avatar_drivers) { $this->config = $config; + $this->phpbb_dispatcher = $phpbb_dispatcher; $this->register_avatar_drivers($avatar_drivers); } @@ -263,7 +271,7 @@ class manager $config_name = $driver->get_config_name(); return array( - 'allow_avatar_' . $config_name => array('lang' => 'ALLOW_' . strtoupper(str_replace('\\', '_', $config_name)), 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_avatar_' . $config_name => array('lang' => 'ALLOW_' . strtoupper(str_replace('\\', '_', $config_name)), 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), ); } @@ -331,6 +339,19 @@ class manager WHERE user_avatar = '" . $db->sql_escape($avatar_data['avatar']) . "'"; $db->sql_query($sql); } + + /** + * Event is triggered after user avatar has been deleted + * + * @event core.avatar_manager_avatar_delete_after + * @var \phpbb\user user phpBB user object + * @var array avatar_data Normalised avatar-related user data + * @var string table Table to delete avatar from + * @var string prefix Column prefix to delete avatar from + * @since 3.2.4-RC1 + */ + $vars = array('user', 'avatar_data', 'table', 'prefix'); + extract($this->phpbb_dispatcher->trigger_event('core.avatar_manager_avatar_delete_after', compact($vars))); } /** diff --git a/phpBB/phpbb/cache/driver/apcu.php b/phpBB/phpbb/cache/driver/apcu.php index 40192e4026..c96cf0de57 100644 --- a/phpBB/phpbb/cache/driver/apcu.php +++ b/phpBB/phpbb/cache/driver/apcu.php @@ -25,7 +25,11 @@ class apcu extends \phpbb\cache\driver\memory */ function purge() { - apcu_clear_cache(); + /* + * Use an iterator to selectively delete our cache entries without disturbing + * any other cache users (e.g. other phpBB boards hosted on this server) + */ + apcu_delete(new \APCUIterator('#^' . $this->key_prefix . '#')); parent::purge(); } diff --git a/phpBB/phpbb/cache/driver/base.php b/phpBB/phpbb/cache/driver/base.php index f4b3dc278d..3eca521148 100644 --- a/phpBB/phpbb/cache/driver/base.php +++ b/phpBB/phpbb/cache/driver/base.php @@ -123,7 +123,7 @@ abstract class base implements \phpbb\cache\driver\driver_interface */ function sql_fetchrow($query_id) { - if ($this->sql_row_pointer[$query_id] < sizeof($this->sql_rowset[$query_id])) + if ($this->sql_row_pointer[$query_id] < count($this->sql_rowset[$query_id])) { return $this->sql_rowset[$query_id][$this->sql_row_pointer[$query_id]++]; } @@ -136,7 +136,7 @@ abstract class base implements \phpbb\cache\driver\driver_interface */ function sql_fetchfield($query_id, $field) { - if ($this->sql_row_pointer[$query_id] < sizeof($this->sql_rowset[$query_id])) + if ($this->sql_row_pointer[$query_id] < count($this->sql_rowset[$query_id])) { return (isset($this->sql_rowset[$query_id][$this->sql_row_pointer[$query_id]][$field])) ? $this->sql_rowset[$query_id][$this->sql_row_pointer[$query_id]++][$field] : false; } @@ -149,7 +149,7 @@ abstract class base implements \phpbb\cache\driver\driver_interface */ function sql_rowseek($rownum, $query_id) { - if ($rownum >= sizeof($this->sql_rowset[$query_id])) + if ($rownum >= count($this->sql_rowset[$query_id])) { return false; } diff --git a/phpBB/phpbb/cache/driver/file.php b/phpBB/phpbb/cache/driver/file.php index e9d2ba8e04..de6f444251 100644 --- a/phpBB/phpbb/cache/driver/file.php +++ b/phpBB/phpbb/cache/driver/file.php @@ -135,7 +135,7 @@ class file extends \phpbb\cache\driver\base if (file_exists($this->cache_dir . 'data_global.' . $phpEx)) { - if (!sizeof($this->vars)) + if (!count($this->vars)) { $this->load(); } @@ -290,7 +290,7 @@ class file extends \phpbb\cache\driver\base } else { - if (!sizeof($this->vars)) + if (!count($this->vars)) { $this->load(); } diff --git a/phpBB/phpbb/cache/driver/memory.php b/phpBB/phpbb/cache/driver/memory.php index cc03804705..eba9549877 100644 --- a/phpBB/phpbb/cache/driver/memory.php +++ b/phpBB/phpbb/cache/driver/memory.php @@ -51,10 +51,11 @@ abstract class memory extends \phpbb\cache\driver\base function load() { // grab the global cache - $this->vars = $this->_read('global'); + $data = $this->_read('global'); - if ($this->vars !== false) + if ($data !== false) { + $this->vars = $data; return true; } @@ -188,7 +189,7 @@ abstract class memory extends \phpbb\cache\driver\base } else { - if (!sizeof($this->vars)) + if (!count($this->vars)) { $this->load(); } diff --git a/phpBB/phpbb/cache/service.php b/phpBB/phpbb/cache/service.php index 8a4366fed1..502ae27625 100644 --- a/phpBB/phpbb/cache/service.php +++ b/phpBB/phpbb/cache/service.php @@ -227,7 +227,7 @@ class service // Store allowed extensions forum wise if ($row['allow_group']) { - $extensions['_allowed_post'][$extension] = (!sizeof($allowed_forums)) ? 0 : $allowed_forums; + $extensions['_allowed_post'][$extension] = (!count($allowed_forums)) ? 0 : $allowed_forums; } if ($row['allow_in_pm']) diff --git a/phpBB/phpbb/captcha/char_cube3d.php b/phpBB/phpbb/captcha/char_cube3d.php index a712b16dce..0255259ac4 100644 --- a/phpBB/phpbb/captcha/char_cube3d.php +++ b/phpBB/phpbb/captcha/char_cube3d.php @@ -220,7 +220,7 @@ class char_cube3d */ function scale($vector, $length) { - if (sizeof($vector) == 2) + if (count($vector) == 2) { return array($vector[0] * $length, $vector[1] * $length); } diff --git a/phpBB/phpbb/captcha/colour_manager.php b/phpBB/phpbb/captcha/colour_manager.php index 6ca3c3fd2c..82332da810 100644 --- a/phpBB/phpbb/captcha/colour_manager.php +++ b/phpBB/phpbb/captcha/colour_manager.php @@ -256,7 +256,7 @@ class colour_manager if (is_array($resource)) { $results = array(); - for ($i = 0, $size = sizeof($resource); $i < $size; ++$i) + for ($i = 0, $size = count($resource); $i < $size; ++$i) { $results = array_merge($results, $this->mono_range($resource[$i], $count, $include_original)); } diff --git a/phpBB/phpbb/captcha/gd.php b/phpBB/phpbb/captcha/gd.php index e9538439c6..91b2f89d81 100644 --- a/phpBB/phpbb/captcha/gd.php +++ b/phpBB/phpbb/captcha/gd.php @@ -100,7 +100,7 @@ class gd $noise_bitmaps = $this->captcha_noise_bg_bitmaps(); for ($i = 0; $i < $code_len; ++$i) { - $noise[$i] = new char_cube3d($noise_bitmaps, mt_rand(1, sizeof($noise_bitmaps['data']))); + $noise[$i] = new char_cube3d($noise_bitmaps, mt_rand(1, count($noise_bitmaps['data']))); $noise[$i]->range(); //$box = $noise[$i]->dimensions($sizes[$i]); @@ -1658,32 +1658,32 @@ class gd 'height' => 15, 'data' => array( - 'A' => $chars['A'][mt_rand(0, min(sizeof($chars['A']), $config['captcha_gd_fonts']) -1)], - 'B' => $chars['B'][mt_rand(0, min(sizeof($chars['B']), $config['captcha_gd_fonts']) -1)], - 'C' => $chars['C'][mt_rand(0, min(sizeof($chars['C']), $config['captcha_gd_fonts']) -1)], - 'D' => $chars['D'][mt_rand(0, min(sizeof($chars['D']), $config['captcha_gd_fonts']) -1)], - 'E' => $chars['E'][mt_rand(0, min(sizeof($chars['E']), $config['captcha_gd_fonts']) -1)], - 'F' => $chars['F'][mt_rand(0, min(sizeof($chars['F']), $config['captcha_gd_fonts']) -1)], - 'G' => $chars['G'][mt_rand(0, min(sizeof($chars['G']), $config['captcha_gd_fonts']) -1)], - 'H' => $chars['H'][mt_rand(0, min(sizeof($chars['H']), $config['captcha_gd_fonts']) -1)], - 'I' => $chars['I'][mt_rand(0, min(sizeof($chars['I']), $config['captcha_gd_fonts']) -1)], - 'J' => $chars['J'][mt_rand(0, min(sizeof($chars['J']), $config['captcha_gd_fonts']) -1)], - 'K' => $chars['K'][mt_rand(0, min(sizeof($chars['K']), $config['captcha_gd_fonts']) -1)], - 'L' => $chars['L'][mt_rand(0, min(sizeof($chars['L']), $config['captcha_gd_fonts']) -1)], - 'M' => $chars['M'][mt_rand(0, min(sizeof($chars['M']), $config['captcha_gd_fonts']) -1)], - 'N' => $chars['N'][mt_rand(0, min(sizeof($chars['N']), $config['captcha_gd_fonts']) -1)], - 'O' => $chars['O'][mt_rand(0, min(sizeof($chars['O']), $config['captcha_gd_fonts']) -1)], - 'P' => $chars['P'][mt_rand(0, min(sizeof($chars['P']), $config['captcha_gd_fonts']) -1)], - 'Q' => $chars['Q'][mt_rand(0, min(sizeof($chars['Q']), $config['captcha_gd_fonts']) -1)], - 'R' => $chars['R'][mt_rand(0, min(sizeof($chars['R']), $config['captcha_gd_fonts']) -1)], - 'S' => $chars['S'][mt_rand(0, min(sizeof($chars['S']), $config['captcha_gd_fonts']) -1)], - 'T' => $chars['T'][mt_rand(0, min(sizeof($chars['T']), $config['captcha_gd_fonts']) -1)], - 'U' => $chars['U'][mt_rand(0, min(sizeof($chars['U']), $config['captcha_gd_fonts']) -1)], - 'V' => $chars['V'][mt_rand(0, min(sizeof($chars['V']), $config['captcha_gd_fonts']) -1)], - 'W' => $chars['W'][mt_rand(0, min(sizeof($chars['W']), $config['captcha_gd_fonts']) -1)], - 'X' => $chars['X'][mt_rand(0, min(sizeof($chars['X']), $config['captcha_gd_fonts']) -1)], - 'Y' => $chars['Y'][mt_rand(0, min(sizeof($chars['Y']), $config['captcha_gd_fonts']) -1)], - 'Z' => $chars['Z'][mt_rand(0, min(sizeof($chars['Z']), $config['captcha_gd_fonts']) -1)], + 'A' => $chars['A'][mt_rand(0, min(count($chars['A']), $config['captcha_gd_fonts']) -1)], + 'B' => $chars['B'][mt_rand(0, min(count($chars['B']), $config['captcha_gd_fonts']) -1)], + 'C' => $chars['C'][mt_rand(0, min(count($chars['C']), $config['captcha_gd_fonts']) -1)], + 'D' => $chars['D'][mt_rand(0, min(count($chars['D']), $config['captcha_gd_fonts']) -1)], + 'E' => $chars['E'][mt_rand(0, min(count($chars['E']), $config['captcha_gd_fonts']) -1)], + 'F' => $chars['F'][mt_rand(0, min(count($chars['F']), $config['captcha_gd_fonts']) -1)], + 'G' => $chars['G'][mt_rand(0, min(count($chars['G']), $config['captcha_gd_fonts']) -1)], + 'H' => $chars['H'][mt_rand(0, min(count($chars['H']), $config['captcha_gd_fonts']) -1)], + 'I' => $chars['I'][mt_rand(0, min(count($chars['I']), $config['captcha_gd_fonts']) -1)], + 'J' => $chars['J'][mt_rand(0, min(count($chars['J']), $config['captcha_gd_fonts']) -1)], + 'K' => $chars['K'][mt_rand(0, min(count($chars['K']), $config['captcha_gd_fonts']) -1)], + 'L' => $chars['L'][mt_rand(0, min(count($chars['L']), $config['captcha_gd_fonts']) -1)], + 'M' => $chars['M'][mt_rand(0, min(count($chars['M']), $config['captcha_gd_fonts']) -1)], + 'N' => $chars['N'][mt_rand(0, min(count($chars['N']), $config['captcha_gd_fonts']) -1)], + 'O' => $chars['O'][mt_rand(0, min(count($chars['O']), $config['captcha_gd_fonts']) -1)], + 'P' => $chars['P'][mt_rand(0, min(count($chars['P']), $config['captcha_gd_fonts']) -1)], + 'Q' => $chars['Q'][mt_rand(0, min(count($chars['Q']), $config['captcha_gd_fonts']) -1)], + 'R' => $chars['R'][mt_rand(0, min(count($chars['R']), $config['captcha_gd_fonts']) -1)], + 'S' => $chars['S'][mt_rand(0, min(count($chars['S']), $config['captcha_gd_fonts']) -1)], + 'T' => $chars['T'][mt_rand(0, min(count($chars['T']), $config['captcha_gd_fonts']) -1)], + 'U' => $chars['U'][mt_rand(0, min(count($chars['U']), $config['captcha_gd_fonts']) -1)], + 'V' => $chars['V'][mt_rand(0, min(count($chars['V']), $config['captcha_gd_fonts']) -1)], + 'W' => $chars['W'][mt_rand(0, min(count($chars['W']), $config['captcha_gd_fonts']) -1)], + 'X' => $chars['X'][mt_rand(0, min(count($chars['X']), $config['captcha_gd_fonts']) -1)], + 'Y' => $chars['Y'][mt_rand(0, min(count($chars['Y']), $config['captcha_gd_fonts']) -1)], + 'Z' => $chars['Z'][mt_rand(0, min(count($chars['Z']), $config['captcha_gd_fonts']) -1)], '1' => array( array(0,0,0,1,1,0,0,0,0), diff --git a/phpBB/phpbb/captcha/plugins/captcha_abstract.php b/phpBB/phpbb/captcha/plugins/captcha_abstract.php index 82b08704ff..b508767d17 100644 --- a/phpBB/phpbb/captcha/plugins/captcha_abstract.php +++ b/phpBB/phpbb/captcha/plugins/captcha_abstract.php @@ -169,7 +169,7 @@ abstract class captcha_abstract } while ($row = $db->sql_fetchrow($result)); - if (sizeof($sql_in)) + if (count($sql_in)) { $sql = 'DELETE FROM ' . CONFIRM_TABLE . ' WHERE ' . $db->sql_in_set('session_id', $sql_in); diff --git a/phpBB/phpbb/captcha/plugins/gd.php b/phpBB/phpbb/captcha/plugins/gd.php index 831e5bcfdf..6d3c9bb3d2 100644 --- a/phpBB/phpbb/captcha/plugins/gd.php +++ b/phpBB/phpbb/captcha/plugins/gd.php @@ -51,7 +51,7 @@ class gd extends captcha_abstract return 'CAPTCHA_GD'; } - function acp_page($id, &$module) + function acp_page($id, $module) { global $user, $template, $phpbb_log, $request; global $config; diff --git a/phpBB/phpbb/captcha/plugins/gd_wave.php b/phpBB/phpbb/captcha/plugins/gd_wave.php index bde46f8815..4ac26ed2b7 100644 --- a/phpBB/phpbb/captcha/plugins/gd_wave.php +++ b/phpBB/phpbb/captcha/plugins/gd_wave.php @@ -33,7 +33,7 @@ class gd_wave extends captcha_abstract return '\\phpbb\\captcha\\gd_wave'; } - function acp_page($id, &$module) + function acp_page($id, $module) { global $user; diff --git a/phpBB/phpbb/captcha/plugins/nogd.php b/phpBB/phpbb/captcha/plugins/nogd.php index 6845e5935c..da67cd2bf4 100644 --- a/phpBB/phpbb/captcha/plugins/nogd.php +++ b/phpBB/phpbb/captcha/plugins/nogd.php @@ -33,7 +33,7 @@ class nogd extends captcha_abstract return '\\phpbb\\captcha\\non_gd'; } - function acp_page($id, &$module) + function acp_page($id, $module) { global $user; diff --git a/phpBB/phpbb/captcha/plugins/qa.php b/phpBB/phpbb/captcha/plugins/qa.php index 9d481acc5d..966b8d32f2 100644 --- a/phpBB/phpbb/captcha/plugins/qa.php +++ b/phpBB/phpbb/captcha/plugins/qa.php @@ -21,7 +21,7 @@ class qa { var $confirm_id; var $answer; - var $question_ids; + var $question_ids = []; var $question_text; var $question_lang; var $question_strict; @@ -84,7 +84,7 @@ class qa $db->sql_freeresult($result); // fallback to the board default lang - if (!sizeof($this->question_ids)) + if (!count($this->question_ids)) { $this->question_lang = $config['default_lang']; @@ -101,14 +101,13 @@ class qa } // final fallback to any language - if (!sizeof($this->question_ids)) + if (!count($this->question_ids)) { $this->question_lang = ''; $sql = 'SELECT q.question_id, q.lang_iso FROM ' . $this->table_captcha_questions . ' q, ' . $this->table_captcha_answers . ' a - WHERE q.question_id = a.question_id - GROUP BY lang_iso'; + WHERE q.question_id = a.question_id'; $result = $db->sql_query($sql, 7200); while ($row = $db->sql_fetchrow($result)) @@ -311,7 +310,7 @@ class qa } while ($row = $db->sql_fetchrow($result)); - if (sizeof($sql_in)) + if (count($sql_in)) { $sql = 'DELETE FROM ' . $this->table_qa_confirm . ' WHERE ' . $db->sql_in_set('confirm_id', $sql_in); @@ -395,7 +394,7 @@ class qa $error = ''; - if (!sizeof($this->question_ids)) + if (!count($this->question_ids)) { /** @var \phpbb\log\log_interface $phpbb_log */ $phpbb_log->add('critical', $user->data['user_id'], $user->ip, 'LOG_ERROR_CAPTCHA', time(), array($user->lang('CONFIRM_QUESTION_MISSING'))); @@ -439,7 +438,7 @@ class qa { global $db, $user; - if (!sizeof($this->question_ids)) + if (!count($this->question_ids)) { return; } @@ -465,7 +464,7 @@ class qa { global $db, $user; - if (!sizeof($this->question_ids)) + if (!count($this->question_ids)) { return; } @@ -536,7 +535,7 @@ class qa { global $db, $user; - if (!strlen($this->confirm_id) || !sizeof($this->question_ids)) + if (!strlen($this->confirm_id) || !count($this->question_ids)) { return false; } @@ -638,7 +637,7 @@ class qa /** * API function - The ACP backend, this marks the end of the easy methods */ - function acp_page($id, &$module) + function acp_page($id, $module) { global $config, $request, $phpbb_log, $template, $user; @@ -776,7 +775,7 @@ class qa /** * This handles the list overview */ - function acp_question_list(&$module) + function acp_question_list($module) { global $db, $template; @@ -979,7 +978,7 @@ class qa if (!isset($langs[$question_data['lang_iso']]) || !strlen($question_data['question_text']) || - !sizeof($question_data['answers']) || + !count($question_data['answers']) || !is_array($question_data['answers'])) { return false; diff --git a/phpBB/phpbb/captcha/plugins/recaptcha.php b/phpBB/phpbb/captcha/plugins/recaptcha.php index 152709a9ea..b7c0b5f5e2 100644 --- a/phpBB/phpbb/captcha/plugins/recaptcha.php +++ b/phpBB/phpbb/captcha/plugins/recaptcha.php @@ -66,7 +66,7 @@ class recaptcha extends captcha_abstract throw new \Exception('No generator class given.'); } - function acp_page($id, &$module) + function acp_page($id, $module) { global $config, $template, $user, $phpbb_log, $request; diff --git a/phpBB/phpbb/console/command/extension/enable.php b/phpBB/phpbb/console/command/extension/enable.php index f92de0069c..a6f5b10e86 100644 --- a/phpBB/phpbb/console/command/extension/enable.php +++ b/phpBB/phpbb/console/command/extension/enable.php @@ -37,6 +37,13 @@ class enable extends command $io = new SymfonyStyle($input, $output); $name = $input->getArgument('extension-name'); + + if (!$this->manager->is_available($name)) + { + $io->error($this->user->lang('CLI_EXTENSION_NOT_EXIST', $name)); + return 1; + } + $extension = $this->manager->get_extension($name); if (!$extension->is_enableable()) diff --git a/phpBB/phpbb/console/command/thumbnail/delete.php b/phpBB/phpbb/console/command/thumbnail/delete.php index cfa9891fbc..7b95c20cf2 100644 --- a/phpBB/phpbb/console/command/thumbnail/delete.php +++ b/phpBB/phpbb/console/command/thumbnail/delete.php @@ -19,6 +19,11 @@ use Symfony\Component\Console\Style\SymfonyStyle; class delete extends \phpbb\console\command\command { /** + * @var \phpbb\config\config + */ + protected $config; + + /** * @var \phpbb\db\driver\driver_interface */ protected $db; @@ -32,12 +37,14 @@ class delete extends \phpbb\console\command\command /** * Constructor * + * @param \config\config $config The config * @param \phpbb\user $user The user object (used to get language information) * @param \phpbb\db\driver\driver_interface $db Database connection * @param string $phpbb_root_path Root path */ - public function __construct(\phpbb\user $user, \phpbb\db\driver\driver_interface $db, $phpbb_root_path) + public function __construct(\phpbb\config\config $config, \phpbb\user $user, \phpbb\db\driver\driver_interface $db, $phpbb_root_path) { + $this->config = $config; $this->db = $db; $this->phpbb_root_path = $phpbb_root_path; @@ -101,13 +108,13 @@ class delete extends \phpbb\console\command\command $return = 0; while ($row = $this->db->sql_fetchrow($result)) { - $thumbnail_path = $this->phpbb_root_path . 'files/thumb_' . $row['physical_filename']; + $thumbnail_path = $this->phpbb_root_path . $this->config['upload_path'] . '/thumb_' . $row['physical_filename']; if (@unlink($thumbnail_path)) { $thumbnail_deleted[] = $row['attach_id']; - if (sizeof($thumbnail_deleted) === 250) + if (count($thumbnail_deleted) === 250) { $this->commit_changes($thumbnail_deleted); $thumbnail_deleted = array(); diff --git a/phpBB/phpbb/console/command/thumbnail/generate.php b/phpBB/phpbb/console/command/thumbnail/generate.php index 64f7555336..1f6582b17b 100644 --- a/phpBB/phpbb/console/command/thumbnail/generate.php +++ b/phpBB/phpbb/console/command/thumbnail/generate.php @@ -20,6 +20,11 @@ use Symfony\Component\Console\Style\SymfonyStyle; class generate extends \phpbb\console\command\command { /** + * @var \phpbb\config\config + */ + protected $config; + + /** * @var \phpbb\db\driver\driver_interface */ protected $db; @@ -45,14 +50,16 @@ class generate extends \phpbb\console\command\command /** * Constructor * + * @param \config\config $config The config * @param \phpbb\user $user The user object (used to get language information) * @param \phpbb\db\driver\driver_interface $db Database connection * @param \phpbb\cache\service $cache The cache service * @param string $phpbb_root_path Root path * @param string $php_ext PHP extension */ - public function __construct(\phpbb\user $user, \phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, $phpbb_root_path, $php_ext) + public function __construct(\phpbb\config\config $config, \phpbb\user $user, \phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, $phpbb_root_path, $php_ext) { + $this->config = $config; $this->db = $db; $this->cache = $cache; $this->phpbb_root_path = $phpbb_root_path; @@ -126,8 +133,8 @@ class generate extends \phpbb\console\command\command { if (isset($extensions[$row['extension']]['display_cat']) && $extensions[$row['extension']]['display_cat'] == ATTACHMENT_CATEGORY_IMAGE) { - $source = $this->phpbb_root_path . 'files/' . $row['physical_filename']; - $destination = $this->phpbb_root_path . 'files/thumb_' . $row['physical_filename']; + $source = $this->phpbb_root_path . $this->config['upload_path'] . '/' . $row['physical_filename']; + $destination = $this->phpbb_root_path . $this->config['upload_path'] . '/thumb_' . $row['physical_filename']; if (create_thumbnail($source, $destination, $row['mimetype'])) { diff --git a/phpBB/phpbb/console/exception_subscriber.php b/phpBB/phpbb/console/exception_subscriber.php index b920d4abae..b240993203 100644 --- a/phpBB/phpbb/console/exception_subscriber.php +++ b/phpBB/phpbb/console/exception_subscriber.php @@ -29,12 +29,10 @@ class exception_subscriber implements EventSubscriberInterface * Construct method * * @param \phpbb\language\language $language Language object - * @param bool $debug Debug mode */ - public function __construct(\phpbb\language\language $language, $debug = false) + public function __construct(\phpbb\language\language $language) { $this->language = $language; - $this->debug = $debug; } /** @@ -52,14 +50,7 @@ class exception_subscriber implements EventSubscriberInterface $parameters = array_merge(array($original_exception->getMessage()), $original_exception->get_parameters()); $message = call_user_func_array(array($this->language, 'lang'), $parameters); - if ($this->debug) - { - $exception = new \RuntimeException($message , $original_exception->getCode(), $original_exception); - } - else - { - $exception = new \RuntimeException($message , $original_exception->getCode()); - } + $exception = new \RuntimeException($message , $original_exception->getCode(), $original_exception); $event->setException($exception); } diff --git a/phpBB/phpbb/content_visibility.php b/phpBB/phpbb/content_visibility.php index bf7dc2c703..f023e0742c 100644 --- a/phpBB/phpbb/content_visibility.php +++ b/phpBB/phpbb/content_visibility.php @@ -131,6 +131,42 @@ class content_visibility return (int) $data[$mode . '_approved'] + (int) $data[$mode . '_unapproved'] + (int) $data[$mode . '_softdeleted']; } + + /** + * Check topic/post visibility for a given forum ID + * + * Note: Read permissions are not checked. + * + * @param $mode string Either "topic" or "post" + * @param $forum_id int The forum id is used for permission checks + * @param $data array Array with item information to check visibility + * @return bool True if the item is visible, false if not + */ + public function is_visible($mode, $forum_id, $data) + { + $is_visible = $this->auth->acl_get('m_approve', $forum_id) || $data[$mode . '_visibility'] == ITEM_APPROVED; + + /** + * Allow changing the result of calling is_visible + * + * @event core.phpbb_content_visibility_is_visible + * @var bool is_visible Default visibility condition, to be modified by extensions if needed. + * @var string mode Either "topic" or "post" + * @var int forum_id Forum id of the current item + * @var array data Array of item information + * @since 3.2.2-RC1 + */ + $vars = array( + 'is_visible', + 'mode', + 'forum_id', + 'data', + ); + extract($this->phpbb_dispatcher->trigger_event('core.phpbb_content_visibility_is_visible', compact($vars))); + + return $is_visible; + } + /** * Create topic/post visibility SQL for a given forum ID * @@ -176,10 +212,14 @@ class content_visibility if ($this->auth->acl_get('m_approve', $forum_id)) { - return $where_sql . '1 = 1'; + $where_sql .= '1 = 1'; + } + else + { + $where_sql .= $table_alias . $mode . '_visibility = ' . ITEM_APPROVED; } - return $where_sql . $table_alias . $mode . '_visibility = ' . ITEM_APPROVED; + return '(' . $where_sql . ')'; } /** @@ -195,16 +235,21 @@ class content_visibility */ public function get_forums_visibility_sql($mode, $forum_ids = array(), $table_alias = '') { - $where_sql = '('; + $where_sql = ''; - $approve_forums = array_intersect($forum_ids, array_keys($this->auth->acl_getf('m_approve', true))); + $approve_forums = array_keys($this->auth->acl_getf('m_approve', true)); + if (!empty($forum_ids) && !empty($approve_forums)) + { + $approve_forums = array_intersect($forum_ids, $approve_forums); + $forum_ids = array_diff($forum_ids, $approve_forums); + } $get_forums_visibility_sql_overwrite = false; /** * Allow changing the result of calling get_forums_visibility_sql * * @event core.phpbb_content_visibility_get_forums_visibility_before - * @var string where_sql The action the user tried to execute + * @var string where_sql Extra visibility conditions. It must end with either an SQL "AND" or an "OR" * @var string mode Either "topic" or "post" depending on the query this is being used in * @var array forum_ids Array of forum ids which the posts/topics are limited to * @var string table_alias Table alias to prefix in SQL queries @@ -229,33 +274,13 @@ class content_visibility return $get_forums_visibility_sql_overwrite; } - if (sizeof($approve_forums)) - { - // Remove moderator forums from the rest - $forum_ids = array_diff($forum_ids, $approve_forums); - - if (!sizeof($forum_ids)) - { - // The user can see all posts/topics in all specified forums - return $where_sql . $this->db->sql_in_set($table_alias . 'forum_id', $approve_forums) . ')'; - } - else - { - // Moderator can view all posts/topics in some forums - $where_sql .= $this->db->sql_in_set($table_alias . 'forum_id', $approve_forums) . ' OR '; - } - } - else - { - // The user is just a normal user - return $where_sql . $table_alias . $mode . '_visibility = ' . ITEM_APPROVED . ' - AND ' . $this->db->sql_in_set($table_alias . 'forum_id', $forum_ids, false, true) . ')'; - } - + // Moderator can view all posts/topics in the moderated forums + $where_sql .= '(' . $this->db->sql_in_set($table_alias . 'forum_id', $approve_forums, false, true) . ' OR '; + // Normal user can view approved items only $where_sql .= '(' . $table_alias . $mode . '_visibility = ' . ITEM_APPROVED . ' - AND ' . $this->db->sql_in_set($table_alias . 'forum_id', $forum_ids) . '))'; + AND ' . $this->db->sql_in_set($table_alias . 'forum_id', $forum_ids, false, true) . '))'; - return $where_sql; + return '(' . $where_sql . ')'; } /** @@ -281,12 +306,12 @@ class content_visibility * Allow changing the result of calling get_global_visibility_sql * * @event core.phpbb_content_visibility_get_global_visibility_before - * @var array where_sqls The action the user tried to execute + * @var array where_sqls Array of extra visibility conditions. Will be joined by imploding with "OR". * @var string mode Either "topic" or "post" depending on the query this is being used in * @var array exclude_forum_ids Array of forum ids the current user doesn't have access to * @var string table_alias Table alias to prefix in SQL queries * @var array approve_forums Array of forums where the user has m_approve permissions - * @var string visibility_sql_overwrite Forces the function to return an implosion of where_sqls (joined by "OR") + * @var string visibility_sql_overwrite If not empty, forces the function to return visibility_sql_overwrite after executing the event * @since 3.1.3-RC1 */ $vars = array( @@ -304,24 +329,17 @@ class content_visibility return $visibility_sql_overwrite; } - if (sizeof($exclude_forum_ids)) - { - $where_sqls[] = '(' . $this->db->sql_in_set($table_alias . 'forum_id', $exclude_forum_ids, true) . ' - AND ' . $table_alias . $mode . '_visibility = ' . ITEM_APPROVED . ')'; - } - else - { - $where_sqls[] = $table_alias . $mode . '_visibility = ' . ITEM_APPROVED; - } + // Include approved items in all forums but the excluded + $where_sqls[] = '(' . $this->db->sql_in_set($table_alias . 'forum_id', $exclude_forum_ids, true, true) . ' + AND ' . $table_alias . $mode . '_visibility = ' . ITEM_APPROVED . ')'; - if (sizeof($approve_forums)) + // If user has moderator permissions, add everything in the moderated forums + if (count($approve_forums)) { $where_sqls[] = $this->db->sql_in_set($table_alias . 'forum_id', $approve_forums); - return '(' . implode(' OR ', $where_sqls) . ')'; } - // There is only one element, so we just return that one - return $where_sqls[0]; + return '(' . implode(' OR ', $where_sqls) . ')'; } /** @@ -437,12 +455,13 @@ class content_visibility * @var int topic_id Topic of the post IDs to be modified. * @var int forum_id Forum ID that the topic_id resides in. * @var int user_id User ID doing this action. - * @var int timestamp Timestamp of this action. + * @var int time Timestamp of this action. * @var string reason Reason specified by the user for this change. * @var bool is_starter Are we changing the topic's starter? * @var bool is_latest Are we changing the topic's latest post? * @var array data The data array for this action. * @since 3.1.10-RC1 + * @changed 3.2.2-RC1 Use time instead of non-existent timestamp */ $vars = array( 'visibility', @@ -450,7 +469,7 @@ class content_visibility 'topic_id', 'forum_id', 'user_id', - 'timestamp', + 'time', 'reason', 'is_starter', 'is_latest', @@ -565,7 +584,7 @@ class content_visibility $sql_ary[$recipient_field] = " + $count_increase"; } - if (sizeof($sql_ary)) + if (count($sql_ary)) { $forum_sql = array(); @@ -622,12 +641,13 @@ class content_visibility * @var int topic_id Topic of the post IDs to be modified. * @var int forum_id Forum ID that the topic_id resides in. * @var int user_id User ID doing this action. - * @var int timestamp Timestamp of this action. + * @var int time Timestamp of this action. * @var string reason Reason specified by the user for this change. * @var bool is_starter Are we changing the topic's starter? * @var bool is_latest Are we changing the topic's latest post? * @var array data The data array for this action. * @since 3.1.10-RC1 + * @changed 3.2.2-RC1 Use time instead of non-existent timestamp */ $vars = array( 'visibility', @@ -635,7 +655,7 @@ class content_visibility 'topic_id', 'forum_id', 'user_id', - 'timestamp', + 'time', 'reason', 'is_starter', 'is_latest', @@ -709,18 +729,19 @@ class content_visibility * @var int topic_id Topic of the post IDs to be modified. * @var int forum_id Forum ID that the topic_id resides in. * @var int user_id User ID doing this action. - * @var int timestamp Timestamp of this action. + * @var int time Timestamp of this action. * @var string reason Reason specified by the user for this change. * @var bool force_update_all Force an update on all posts within the topic, regardless of their current approval state. * @var array data The data array for this action. * @since 3.1.10-RC1 + * @changed 3.2.2-RC1 Use time instead of non-existent timestamp */ $vars = array( 'visibility', 'topic_id', 'forum_id', 'user_id', - 'timestamp', + 'time', 'reason', 'force_update_all', 'data', @@ -758,18 +779,19 @@ class content_visibility * @var int topic_id Topic of the post IDs to be modified. * @var int forum_id Forum ID that the topic_id resides in. * @var int user_id User ID doing this action. - * @var int timestamp Timestamp of this action. + * @var int time Timestamp of this action. * @var string reason Reason specified by the user for this change. * @var bool force_update_all Force an update on all posts within the topic, regardless of their current approval state. * @var array data The data array for this action. * @since 3.1.10-RC1 + * @changed 3.2.2-RC1 Use time instead of non-existent timestamp */ $vars = array( 'visibility', 'topic_id', 'forum_id', 'user_id', - 'timestamp', + 'time', 'reason', 'force_update_all', 'data', diff --git a/phpBB/phpbb/cron/task/core/prune_all_forums.php b/phpBB/phpbb/cron/task/core/prune_all_forums.php index b47939ccbe..5005f5b894 100644 --- a/phpBB/phpbb/cron/task/core/prune_all_forums.php +++ b/phpBB/phpbb/cron/task/core/prune_all_forums.php @@ -55,21 +55,26 @@ class prune_all_forums extends \phpbb\cron\task\base include($this->phpbb_root_path . 'includes/functions_admin.' . $this->php_ext); } - $sql = 'SELECT forum_id, prune_next, enable_prune, prune_days, prune_viewed, forum_flags, prune_freq - FROM ' . FORUMS_TABLE . " - WHERE enable_prune = 1 - AND prune_next < " . time(); + $sql = 'SELECT forum_id, prune_next, enable_prune, prune_days, prune_viewed, enable_shadow_prune, prune_shadow_days, prune_shadow_freq, prune_shadow_next, forum_flags, prune_freq + FROM ' . FORUMS_TABLE; $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { - if ($row['prune_days']) + if ($row['enable_prune'] && $row['prune_next'] < time()) { - auto_prune($row['forum_id'], 'posted', $row['forum_flags'], $row['prune_days'], $row['prune_freq']); - } + if ($row['prune_days']) + { + auto_prune($row['forum_id'], 'posted', $row['forum_flags'], $row['prune_days'], $row['prune_freq']); + } - if ($row['prune_viewed']) + if ($row['prune_viewed']) + { + auto_prune($row['forum_id'], 'viewed', $row['forum_flags'], $row['prune_viewed'], $row['prune_freq']); + } + } + if ($row['enable_shadow_prune'] && $row['prune_shadow_next'] < time() && $row['prune_shadow_days']) { - auto_prune($row['forum_id'], 'viewed', $row['forum_flags'], $row['prune_viewed'], $row['prune_freq']); + auto_prune($row['forum_id'], 'shadow', $row['forum_flags'], $row['prune_shadow_days'], $row['prune_shadow_freq']); } } $this->db->sql_freeresult($result); diff --git a/phpBB/phpbb/datetime.php b/phpBB/phpbb/datetime.php index 63cdba90fd..4b799b6219 100644 --- a/phpBB/phpbb/datetime.php +++ b/phpBB/phpbb/datetime.php @@ -60,6 +60,12 @@ class datetime extends \DateTime public function format($format = '', $force_absolute = false) { $format = $format ? $format : $this->user->date_format; + + if (substr($this->user->lang_name, 0,2) != 'en') + { + $format = preg_replace('/([^\\\])S/','$1', $format); + } + $format = self::format_cache($format, $this->user); $relative = ($format['is_short'] && !$force_absolute); $now = new self($this->user, 'now', $this->user->timezone); diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php index 214c5590e7..a36ce8c0d7 100644 --- a/phpBB/phpbb/db/driver/driver.php +++ b/phpBB/phpbb/db/driver/driver.php @@ -537,7 +537,9 @@ abstract class driver implements driver_interface */ function sql_in_set($field, $array, $negate = false, $allow_empty_set = false) { - if (!sizeof($array)) + $array = (array) $array; + + if (!count($array)) { if (!$allow_empty_set) { @@ -559,12 +561,7 @@ abstract class driver implements driver_interface } } - if (!is_array($array)) - { - $array = array($array); - } - - if (sizeof($array) == 1) + if (count($array) == 1) { @reset($array); $var = current($array); @@ -632,7 +629,7 @@ abstract class driver implements driver_interface */ function sql_multi_insert($table, $sql_ary) { - if (!sizeof($sql_ary)) + if (!count($sql_ary)) { return false; } @@ -738,7 +735,7 @@ abstract class driver implements driver_interface // We run the following code to determine if we need to re-order the table array. ;) // The reason for this is that for multi-aliased tables (two equal tables) in the FROM statement the last table need to match the first comparison. // DBMS who rely on this: Oracle, PostgreSQL and MSSQL. For all other DBMS it makes absolutely no difference in which order the table is. - if (!empty($array['LEFT_JOIN']) && sizeof($array['FROM']) > 1 && $used_multi_alias !== false) + if (!empty($array['LEFT_JOIN']) && count($array['FROM']) > 1 && $used_multi_alias !== false) { // Take first LEFT JOIN $join = current($array['LEFT_JOIN']); @@ -848,7 +845,7 @@ abstract class driver implements driver_interface default: - switch (sizeof($condition)) + switch (count($condition)) { case 3: @@ -906,9 +903,10 @@ abstract class driver implements driver_interface // Subquery with {left hand} {operator} {compare kind} {SELECT Kind } {Sub Query} - $condition = $condition[self::LEFT_STMT] . ' ' . $condition[self::COMPARE_OP] . ' ' . $condition[self::SUBQUERY_OP] . ' ( '; - $condition .= $this->sql_build_query($condition[self::SUBQUERY_SELECT_TYPE], $condition[self::SUBQUERY_BUILD]); - $condition .= ' )'; + $result = $condition[self::LEFT_STMT] . ' ' . $condition[self::COMPARE_OP] . ' ' . $condition[self::SUBQUERY_OP] . ' ( '; + $result .= $this->sql_build_query($condition[self::SUBQUERY_SELECT_TYPE], $condition[self::SUBQUERY_BUILD]); + $result .= ' )'; + $condition = $result; break; @@ -1138,7 +1136,7 @@ abstract class driver implements driver_interface $html_table = func_get_arg(2); $row = func_get_arg(3); - if (!$html_table && sizeof($row)) + if (!$html_table && count($row)) { $html_table = true; $this->html_hold .= '<table cellspacing="1"><tr>'; diff --git a/phpBB/phpbb/db/driver/mssql_base.php b/phpBB/phpbb/db/driver/mssql_base.php index 514df9eaca..98d16ca7fc 100644 --- a/phpBB/phpbb/db/driver/mssql_base.php +++ b/phpBB/phpbb/db/driver/mssql_base.php @@ -61,6 +61,14 @@ abstract class mssql_base extends \phpbb\db\driver\driver } /** + * {@inheritDoc} + */ + function cast_expr_to_bigint($expression) + { + return 'CONVERT(BIGINT, ' . $expression . ')'; + } + + /** * Build db-specific query data * @access private */ diff --git a/phpBB/phpbb/db/driver/mssqlnative.php b/phpBB/phpbb/db/driver/mssqlnative.php index 50dce35baa..a4dcac5966 100644 --- a/phpBB/phpbb/db/driver/mssqlnative.php +++ b/phpBB/phpbb/db/driver/mssqlnative.php @@ -50,7 +50,8 @@ class mssqlnative extends \phpbb\db\driver\mssql_base $this->db_connect_id = sqlsrv_connect($this->server, array( 'Database' => $this->dbname, 'UID' => $this->user, - 'PWD' => $sqlpassword + 'PWD' => $sqlpassword, + 'CharacterSet' => 'UTF-8' )); return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error(''); @@ -267,7 +268,7 @@ class mssqlnative extends \phpbb\db\driver\mssql_base unset($row['line2'], $row['line3']); } } - return (sizeof($row)) ? $row : false; + return ($row !== null) ? $row : false; } /** diff --git a/phpBB/phpbb/db/driver/oracle.php b/phpBB/phpbb/db/driver/oracle.php index 54238a15ef..5fd14709f8 100644 --- a/phpBB/phpbb/db/driver/oracle.php +++ b/phpBB/phpbb/db/driver/oracle.php @@ -136,7 +136,7 @@ class oracle extends \phpbb\db\driver\driver */ function _rewrite_col_compare($args) { - if (sizeof($args) == 4) + if (count($args) == 4) { if ($args[2] == '=') { @@ -290,7 +290,7 @@ class oracle extends \phpbb\db\driver\driver and/or need the db restore script, uncomment this. - if (sizeof($cols) !== sizeof($vals)) + if (count($cols) !== count($vals)) { // Try to replace some common data we know is from our restore script or from other sources $regs[3] = str_replace("'||chr(47)||'", '/', $regs[3]); @@ -332,7 +332,7 @@ class oracle extends \phpbb\db\driver\driver if ($string) { // New value if cols != value - $vals[(sizeof($cols) !== sizeof($vals)) ? $i : $i - 1] .= $string; + $vals[(count($cols) !== count($vals)) ? $i : $i - 1] .= $string; } $vals = array(0 => $vals); diff --git a/phpBB/phpbb/db/extractor/mssql_extractor.php b/phpBB/phpbb/db/extractor/mssql_extractor.php index 2817d3ebcc..4eeab4780e 100644 --- a/phpBB/phpbb/db/extractor/mssql_extractor.php +++ b/phpBB/phpbb/db/extractor/mssql_extractor.php @@ -132,14 +132,14 @@ class mssql_extractor extends base_extractor $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) { - if (!sizeof($rows)) + if (!count($rows)) { $sql_data .= "ALTER TABLE [$table_name] WITH NOCHECK ADD\n"; $sql_data .= "\tCONSTRAINT [{$row['CONSTRAINT_NAME']}] PRIMARY KEY CLUSTERED \n\t(\n"; } $rows[] = "\t\t[{$row['COLUMN_NAME']}]"; } - if (sizeof($rows)) + if (count($rows)) { $sql_data .= implode(",\n", $rows); $sql_data .= "\n\t) ON [PRIMARY] \nGO\n"; diff --git a/phpBB/phpbb/db/extractor/oracle_extractor.php b/phpBB/phpbb/db/extractor/oracle_extractor.php index 79a991889b..bc43a37b10 100644 --- a/phpBB/phpbb/db/extractor/oracle_extractor.php +++ b/phpBB/phpbb/db/extractor/oracle_extractor.php @@ -82,7 +82,7 @@ class oracle_extractor extends base_extractor } $this->db->sql_freeresult($result); - if (sizeof($primary_key)) + if (count($primary_key)) { $rows[] = " CONSTRAINT {$constraint_name} PRIMARY KEY (" . implode(', ', $primary_key) . ')'; } @@ -103,7 +103,7 @@ class oracle_extractor extends base_extractor } $this->db->sql_freeresult($result); - if (sizeof($unique)) + if (count($unique)) { $rows[] = " CONSTRAINT {$constraint_name} UNIQUE (" . implode(', ', $unique) . ')'; } diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc1.php index faef68121d..40bb58c10d 100644 --- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc1.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_6_rc1.php @@ -153,7 +153,10 @@ class release_3_0_6_rc1 extends \phpbb\db\migration\migration 'ACP_BOARD_CONFIGURATION', array( 'module_basename' => 'acp_board', - 'modes' => array('feed'), + 'module_langname' => 'ACP_FEED_SETTINGS', + 'module_mode' => 'feed', + 'module_auth' => 'acl_a_board', + 'after' => array('signature', 'ACP_SIGNATURE_SETTINGS'), ), )), array('module.add', array( @@ -161,7 +164,11 @@ class release_3_0_6_rc1 extends \phpbb\db\migration\migration 'ACP_CAT_USERS', array( 'module_basename' => 'acp_users', - 'modes' => array('warnings'), + 'module_langname' => 'ACP_USER_WARNINGS', + 'module_mode' => 'warnings', + 'module_auth' => 'acl_a_user', + 'module_display' => false, + 'after' => array('feedback', 'ACP_USER_FEEDBACK'), ), )), array('module.add', array( @@ -169,7 +176,9 @@ class release_3_0_6_rc1 extends \phpbb\db\migration\migration 'ACP_SERVER_CONFIGURATION', array( 'module_basename' => 'acp_send_statistics', - 'modes' => array('send_statistics'), + 'module_langname' => 'ACP_SEND_STATISTICS', + 'module_mode' => 'send_statistics', + 'module_auth' => 'acl_a_server', ), )), array('module.add', array( @@ -177,7 +186,10 @@ class release_3_0_6_rc1 extends \phpbb\db\migration\migration 'ACP_FORUM_BASED_PERMISSIONS', array( 'module_basename' => 'acp_permissions', - 'modes' => array('setting_forum_copy'), + 'module_langname' => 'ACP_FORUM_PERMISSIONS_COPY', + 'module_mode' => 'setting_forum_copy', + 'module_auth' => 'acl_a_fauth && acl_a_authusers && acl_a_authgroups && acl_a_mauth', + 'after' => array('setting_forum_local', 'ACP_FORUM_PERMISSIONS'), ), )), array('module.add', array( @@ -185,7 +197,29 @@ class release_3_0_6_rc1 extends \phpbb\db\migration\migration 'MCP_REPORTS', array( 'module_basename' => 'mcp_pm_reports', - 'modes' => array('pm_reports','pm_reports_closed','pm_report_details'), + 'module_langname' => 'MCP_PM_REPORTS_OPEN', + 'module_mode' => 'pm_reports', + 'module_auth' => 'acl_m_pm_report', + ), + )), + array('module.add', array( + 'mcp', + 'MCP_REPORTS', + array( + 'module_basename' => 'mcp_pm_reports', + 'module_langname' => 'MCP_PM_REPORTS_CLOSED', + 'module_mode' => 'pm_reports_closed', + 'module_auth' => 'acl_m_pm_report', + ), + )), + array('module.add', array( + 'mcp', + 'MCP_REPORTS', + array( + 'module_basename' => 'mcp_pm_reports', + 'module_langname' => 'MCP_PM_REPORT_DETAILS', + 'module_mode' => 'pm_report_details', + 'module_auth' => 'acl_m_pm_report', ), )), array('custom', array(array(&$this, 'add_newly_registered_group'))), diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_8_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_8_rc1.php index 22fd51543b..836cb4577a 100644 --- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_8_rc1.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_8_rc1.php @@ -36,7 +36,10 @@ class release_3_0_8_rc1 extends \phpbb\db\migration\migration 'ACP_MESSAGES', array( 'module_basename' => 'acp_board', - 'modes' => array('post'), + 'module_langname' => 'ACP_POST_SETTINGS', + 'module_mode' => 'post', + 'module_auth' => 'acl_a_board', + 'after' => array('message', 'ACP_MESSAGE_SETTINGS'), ), )), array('config.add', array('load_unreads_search', 1)), @@ -55,9 +58,14 @@ class release_3_0_8_rc1 extends \phpbb\db\migration\migration $result = $this->db->sql_query($sql); $extension_groups_updated = array(); - while ($lang_dir = $this->db->sql_fetchfield('lang_dir')) + while ($row = $this->db->sql_fetchrow($result)) { - $lang_dir = basename($lang_dir); + if (empty($row['lang_dir'])) + { + continue; + } + + $lang_dir = basename($row['lang_dir']); // The language strings we need are either in language/.../acp/attachments.php // in the update package if we're updating to 3.0.8-RC1 or later, diff --git a/phpBB/phpbb/db/migration/data/v310/auth_provider_oauth.php b/phpBB/phpbb/db/migration/data/v310/auth_provider_oauth.php index 2d51bd53e4..1e2024a071 100644 --- a/phpBB/phpbb/db/migration/data/v310/auth_provider_oauth.php +++ b/phpBB/phpbb/db/migration/data/v310/auth_provider_oauth.php @@ -17,7 +17,12 @@ class auth_provider_oauth extends \phpbb\db\migration\migration { public function effectively_installed() { - return $this->db_tools->sql_table_exists($this->table_prefix . 'auth_provider_oauth'); + return $this->db_tools->sql_table_exists($this->table_prefix . 'oauth_tokens'); + } + + static public function depends_on() + { + return array('\phpbb\db\migration\data\v30x\release_3_0_0'); } public function update_schema() @@ -69,7 +74,9 @@ class auth_provider_oauth extends \phpbb\db\migration\migration 'UCP_PROFILE', array( 'module_basename' => 'ucp_auth_link', - 'modes' => array('auth_link'), + 'module_langname' => 'UCP_AUTH_LINK_MANAGE', + 'module_mode' => 'auth_link', + 'module_auth' => 'authmethod_oauth', ), )), ); diff --git a/phpBB/phpbb/db/migration/data/v310/contact_admin_acp_module.php b/phpBB/phpbb/db/migration/data/v310/contact_admin_acp_module.php index 20bd547ac3..e48a9a1d3d 100644 --- a/phpBB/phpbb/db/migration/data/v310/contact_admin_acp_module.php +++ b/phpBB/phpbb/db/migration/data/v310/contact_admin_acp_module.php @@ -23,7 +23,9 @@ class contact_admin_acp_module extends \phpbb\db\migration\migration 'ACP_BOARD_CONFIGURATION', array( 'module_basename' => 'acp_contact', - 'modes' => array('contact'), + 'module_langname' => 'ACP_CONTACT_SETTINGS', + 'module_mode' => 'contact', + 'module_auth' => 'acl_a_board', ), )), ); diff --git a/phpBB/phpbb/db/migration/data/v310/dev.php b/phpBB/phpbb/db/migration/data/v310/dev.php index 250258eea7..9cc953ad8d 100644 --- a/phpBB/phpbb/db/migration/data/v310/dev.php +++ b/phpBB/phpbb/db/migration/data/v310/dev.php @@ -125,7 +125,9 @@ class dev extends \phpbb\db\migration\container_aware_migration 'ACP_GROUPS', array( 'module_basename' => 'acp_groups', - 'modes' => array('position'), + 'module_langname' => 'ACP_GROUPS_POSITION', + 'module_mode' => 'position', + 'module_auth' => 'acl_a_group', ), )), array('module.add', array( @@ -133,7 +135,9 @@ class dev extends \phpbb\db\migration\container_aware_migration 'ACP_ATTACHMENTS', array( 'module_basename' => 'acp_attachments', - 'modes' => array('manage'), + 'module_langname' => 'ACP_MANAGE_ATTACHMENTS', + 'module_mode' => 'manage', + 'module_auth' => 'acl_a_attach', ), )), array('module.add', array( @@ -141,7 +145,19 @@ class dev extends \phpbb\db\migration\container_aware_migration 'ACP_STYLE_MANAGEMENT', array( 'module_basename' => 'acp_styles', - 'modes' => array('install', 'cache'), + 'module_langname' => 'ACP_STYLES_INSTALL', + 'module_mode' => 'install', + 'module_auth' => 'acl_a_styles', + ), + )), + array('module.add', array( + 'acp', + 'ACP_STYLE_MANAGEMENT', + array( + 'module_basename' => 'acp_styles', + 'module_langname' => 'ACP_STYLES_CACHE', + 'module_mode' => 'cache', + 'module_auth' => 'acl_a_styles', ), )), array('module.add', array( @@ -149,7 +165,8 @@ class dev extends \phpbb\db\migration\container_aware_migration 'UCP_PROFILE', array( 'module_basename' => 'ucp_profile', - 'modes' => array('autologin_keys'), + 'module_langname' => 'UCP_PROFILE_AUTOLOGIN_KEYS', + 'module_mode' => 'autologin_keys', ), )), // Module will be renamed later diff --git a/phpBB/phpbb/db/migration/data/v310/extensions.php b/phpBB/phpbb/db/migration/data/v310/extensions.php index 3171435482..2e7c5c5316 100644 --- a/phpBB/phpbb/db/migration/data/v310/extensions.php +++ b/phpBB/phpbb/db/migration/data/v310/extensions.php @@ -66,7 +66,9 @@ class extensions extends \phpbb\db\migration\migration 'ACP_EXTENSION_MANAGEMENT', array( 'module_basename' => 'acp_extensions', - 'modes' => array('main'), + 'module_langname' => 'ACP_EXTENSIONS', + 'module_mode' => 'main', + 'module_auth' => 'acl_a_extensions', ), )), array('permission.add', array('a_extensions', true, 'a_styles')), diff --git a/phpBB/phpbb/db/migration/data/v310/notifications.php b/phpBB/phpbb/db/migration/data/v310/notifications.php index f4d012b5ac..789aaa3ba9 100644 --- a/phpBB/phpbb/db/migration/data/v310/notifications.php +++ b/phpBB/phpbb/db/migration/data/v310/notifications.php @@ -85,7 +85,9 @@ class notifications extends \phpbb\db\migration\migration 'UCP_MAIN', array( 'module_basename' => 'ucp_notifications', - 'modes' => array('notification_list'), + 'module_langname' => 'UCP_NOTIFICATION_LIST', + 'module_mode' => 'notification_list', + 'module_auth' => 'cfg_allow_board_notifications', ), )), array('module.add', array( @@ -93,7 +95,8 @@ class notifications extends \phpbb\db\migration\migration 'UCP_PREFS', array( 'module_basename' => 'ucp_notifications', - 'modes' => array('notification_options'), + 'module_langname' => 'UCP_NOTIFICATION_OPTIONS', + 'module_mode' => 'notification_options', ), )), array('config.add', array('load_notifications', 1)), diff --git a/phpBB/phpbb/db/migration/data/v310/softdelete_mcp_modules.php b/phpBB/phpbb/db/migration/data/v310/softdelete_mcp_modules.php index 5e68db5889..90dab991e1 100644 --- a/phpBB/phpbb/db/migration/data/v310/softdelete_mcp_modules.php +++ b/phpBB/phpbb/db/migration/data/v310/softdelete_mcp_modules.php @@ -45,7 +45,9 @@ class softdelete_mcp_modules extends \phpbb\db\migration\migration 'MCP_QUEUE', array( 'module_basename' => 'mcp_queue', - 'modes' => array('deleted_topics'), + 'module_langname' => 'MCP_QUEUE_DELETED_TOPICS', + 'module_mode' => 'deleted_topics', + 'module_auth' => 'aclf_m_approve', ), )), array('module.add', array( @@ -53,7 +55,9 @@ class softdelete_mcp_modules extends \phpbb\db\migration\migration 'MCP_QUEUE', array( 'module_basename' => 'mcp_queue', - 'modes' => array('deleted_posts'), + 'module_langname' => 'MCP_QUEUE_DELETED_POSTS', + 'module_mode' => 'deleted_posts', + 'module_auth' => 'aclf_m_approve', ), )), ); diff --git a/phpBB/phpbb/db/migration/data/v310/style_update_p1.php b/phpBB/phpbb/db/migration/data/v310/style_update_p1.php index 2c7b7edf2e..a7e30a9cb7 100644 --- a/phpBB/phpbb/db/migration/data/v310/style_update_p1.php +++ b/phpBB/phpbb/db/migration/data/v310/style_update_p1.php @@ -133,7 +133,7 @@ class style_update_p1 extends \phpbb\db\migration\migration } // Remove old entries from styles table - if (!sizeof($valid_styles)) + if (!count($valid_styles)) { // No valid styles: remove everything and add prosilver $this->sql_query('DELETE FROM ' . STYLES_TABLE); @@ -160,12 +160,12 @@ class style_update_p1 extends \phpbb\db\migration\migration FROM ' . STYLES_TABLE . " WHERE style_name = 'prosilver'"; $result = $this->sql_query($sql); - $default_style = $this->db->sql_fetchfield('style_id'); + $default_style = (int) $this->db->sql_fetchfield('style_id'); $this->db->sql_freeresult($result); $this->config->set('default_style', $default_style); - $sql = 'UPDATE ' . USERS_TABLE . ' SET user_style = 0'; + $sql = 'UPDATE ' . USERS_TABLE . ' SET user_style = ' . (int) $default_style; $this->sql_query($sql); } else @@ -183,9 +183,9 @@ class style_update_p1 extends \phpbb\db\migration\migration } // Reset styles for users - $this->sql_query('UPDATE ' . USERS_TABLE . ' - SET user_style = 0 - WHERE ' . $this->db->sql_in_set('user_style', $valid_styles, true)); + $this->sql_query('UPDATE ' . USERS_TABLE . " + SET user_style = '" . (int) $valid_styles[0] . "' + WHERE " . $this->db->sql_in_set('user_style', $valid_styles, true)); } } } diff --git a/phpBB/phpbb/db/migration/data/v310/teampage.php b/phpBB/phpbb/db/migration/data/v310/teampage.php index f8edbc3492..3a37b17e97 100644 --- a/phpBB/phpbb/db/migration/data/v310/teampage.php +++ b/phpBB/phpbb/db/migration/data/v310/teampage.php @@ -93,13 +93,13 @@ class teampage extends \phpbb\db\migration\migration $teampage_entries[] = array( 'group_id' => (int) $row['group_id'], 'teampage_name' => '', - 'teampage_position' => sizeof($teampage_entries) + 1, + 'teampage_position' => count($teampage_entries) + 1, 'teampage_parent' => 0, ); } $this->db->sql_freeresult($result); - if (sizeof($teampage_entries)) + if (count($teampage_entries)) { $this->db->sql_multi_insert(TEAMPAGE_TABLE, $teampage_entries); } diff --git a/phpBB/phpbb/db/migration/data/v31x/v3112.php b/phpBB/phpbb/db/migration/data/v31x/v3112.php new file mode 100644 index 0000000000..0d75d35184 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v31x/v3112.php @@ -0,0 +1,36 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v31x; + +class v3112 extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return phpbb_version_compare($this->config['version'], '3.1.12', '>='); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v31x\v3111', + ); + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.1.12')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v320/add_help_phpbb.php b/phpBB/phpbb/db/migration/data/v320/add_help_phpbb.php index 8fadb4bde4..804adc4490 100644 --- a/phpBB/phpbb/db/migration/data/v320/add_help_phpbb.php +++ b/phpBB/phpbb/db/migration/data/v320/add_help_phpbb.php @@ -32,16 +32,15 @@ class add_help_phpbb extends \phpbb\db\migration\migration return array( array('config.add', array('help_send_statistics', true)), array('config.add', array('help_send_statistics_time', 0)), - array('if', array( - array('module.exists', array('acp', false, 'ACP_SEND_STATISTICS')), - array('module.remove', array('acp', false, 'ACP_SEND_STATISTICS')), - )), + array('module.remove', array('acp', false, 'ACP_SEND_STATISTICS')), array('module.add', array( 'acp', 'ACP_SERVER_CONFIGURATION', array( 'module_basename' => 'acp_help_phpbb', - 'modes' => array('help_phpbb'), + 'module_langname' => 'ACP_HELP_PHPBB', + 'module_mode' => 'help_phpbb', + 'module_auth' => 'acl_a_server', ), )), ); diff --git a/phpBB/phpbb/db/migration/data/v320/remove_outdated_media.php b/phpBB/phpbb/db/migration/data/v320/remove_outdated_media.php index c14d31f1c0..88fe59ccc9 100644 --- a/phpBB/phpbb/db/migration/data/v320/remove_outdated_media.php +++ b/phpBB/phpbb/db/migration/data/v320/remove_outdated_media.php @@ -15,10 +15,17 @@ namespace phpbb\db\migration\data\v320; class remove_outdated_media extends \phpbb\db\migration\migration { + // Following constants were deprecated in 3.2 + // and moved from constants.php to compatibility_globals.php, + // thus define them as class constants + const ATTACHMENT_CATEGORY_WM = 2; + const ATTACHMENT_CATEGORY_RM = 3; + const ATTACHMENT_CATEGORY_QUICKTIME = 6; + protected $cat_id = array( - ATTACHMENT_CATEGORY_WM, - ATTACHMENT_CATEGORY_RM, - ATTACHMENT_CATEGORY_QUICKTIME, + self::ATTACHMENT_CATEGORY_WM, + self::ATTACHMENT_CATEGORY_RM, + self::ATTACHMENT_CATEGORY_QUICKTIME, ); static public function depends_on() @@ -78,13 +85,11 @@ class remove_outdated_media extends \phpbb\db\migration\migration WHERE ' . $this->db->sql_in_set('group_id', $group_ids); } - $result = $this->db->sql_query($sql); - $this->db->sql_freeresult($result); + $this->db->sql_query($sql); // delete the now empty, outdated media extension groups $sql = 'DELETE FROM ' . EXTENSION_GROUPS_TABLE . ' WHERE ' . $this->db->sql_in_set('group_id', $group_ids); - $result = $this->db->sql_query($sql); - $this->db->sql_freeresult($result); + $this->db->sql_query($sql); } } diff --git a/phpBB/phpbb/db/migration/data/v32x/disable_remote_avatar.php b/phpBB/phpbb/db/migration/data/v32x/disable_remote_avatar.php new file mode 100644 index 0000000000..b08833fad4 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/disable_remote_avatar.php @@ -0,0 +1,34 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\db\migration\data\v32x; + +use phpbb\db\migration\migration; + +class disable_remote_avatar extends migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\v325', + ); + } + + public function update_data() + { + return array( + array('config.update', array('allow_avatar_remote', '0')), + array('config.update', array('allow_avatar_remote_upload', '0')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/email_force_sender.php b/phpBB/phpbb/db/migration/data/v32x/email_force_sender.php new file mode 100644 index 0000000000..5319b7f76e --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/email_force_sender.php @@ -0,0 +1,37 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v32x; + +class email_force_sender extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\v321', + ); + } + + public function effectively_installed() + { + return isset($this->config['email_force_sender']); + } + + public function update_data() + { + return array( + array('config.add', array('email_force_sender', '0')), + array('config.remove', array('email_function_name')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/enable_accurate_pm_button.php b/phpBB/phpbb/db/migration/data/v32x/enable_accurate_pm_button.php new file mode 100644 index 0000000000..a7b99606f7 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/enable_accurate_pm_button.php @@ -0,0 +1,36 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v32x; + +class enable_accurate_pm_button extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\v322', + ); + } + + public function effectively_installed() + { + return isset($this->config['enable_accurate_pm_button']); + } + + public function update_data() + { + return array( + array('config.add', array('enable_accurate_pm_button', '1')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/f_list_topics_permission_add.php b/phpBB/phpbb/db/migration/data/v32x/f_list_topics_permission_add.php new file mode 100644 index 0000000000..49727e5a62 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/f_list_topics_permission_add.php @@ -0,0 +1,31 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\db\migration\data\v32x; + +class f_list_topics_permission_add extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\v321', + ); + } + + public function update_data() + { + return array( + array('permission.add', array('f_list_topics', false, 'f_read')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/fix_user_styles.php b/phpBB/phpbb/db/migration/data/v32x/fix_user_styles.php new file mode 100644 index 0000000000..16fbdbc77b --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/fix_user_styles.php @@ -0,0 +1,54 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v32x; + +class fix_user_styles extends \phpbb\db\migration\migration +{ + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v320\v320', + ); + } + + public function update_data() + { + return array( + array('custom', array(array($this, 'styles_fix'))), + ); + } + + public function styles_fix() + { + $default_style = (int) $this->config['default_style']; + $enabled_styles = array(); + + // Get enabled styles + $sql = 'SELECT style_id + FROM ' . STYLES_TABLE . ' + WHERE style_active = 1'; + $result = $this->db->sql_query($sql); + while ($row = $this->db->sql_fetchrow($result)) + { + $enabled_styles[] = (int) $row['style_id']; + } + $this->db->sql_freeresult($result); + + // Set the default style to users who have an invalid style + $this->sql_query('UPDATE ' . USERS_TABLE . ' + SET user_style = ' . (int) $default_style . ' + WHERE ' . $this->db->sql_in_set('user_style', $enabled_styles, true)); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/forum_topics_per_page_type.php b/phpBB/phpbb/db/migration/data/v32x/forum_topics_per_page_type.php new file mode 100644 index 0000000000..afcecf2ef0 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/forum_topics_per_page_type.php @@ -0,0 +1,37 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v32x; + +class forum_topics_per_page_type extends \phpbb\db\migration\migration +{ + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\v323', + ); + } + + public function update_schema() + { + return array( + 'change_columns' => array( + $this->table_prefix . 'forums' => array( + 'forum_topics_per_page' => array('USINT', 0), + ), + ), + ); + } + +} diff --git a/phpBB/phpbb/db/migration/data/v32x/jquery_update.php b/phpBB/phpbb/db/migration/data/v32x/jquery_update.php new file mode 100644 index 0000000000..6dc58ec638 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/jquery_update.php @@ -0,0 +1,37 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\db\migration\data\v32x; + +class jquery_update extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return $this->config['load_jquery_url'] === '//ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js'; + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\v325rc1', + ); + } + + public function update_data() + { + return array( + array('config.update', array('load_jquery_url', '//ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js')), + ); + } + +} diff --git a/phpBB/phpbb/db/migration/data/v32x/merge_duplicate_bbcodes.php b/phpBB/phpbb/db/migration/data/v32x/merge_duplicate_bbcodes.php new file mode 100644 index 0000000000..71ee19e3dd --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/merge_duplicate_bbcodes.php @@ -0,0 +1,84 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v32x; + +class merge_duplicate_bbcodes extends \phpbb\db\migration\container_aware_migration +{ + public function update_data() + { + return [ + ['custom', [[$this, 'update_bbcodes_table']]], + ]; + } + + public function update_bbcodes_table() + { + $sql = 'SELECT bbcode_id, bbcode_tag, bbcode_helpline, bbcode_match, bbcode_tpl FROM ' . BBCODES_TABLE; + $result = $this->sql_query($sql); + $bbcodes = []; + while ($row = $this->db->sql_fetchrow($result)) + { + $variant = (substr($row['bbcode_tag'], -1) === '=') ? 'with': 'without'; + $bbcode_name = strtolower(rtrim($row['bbcode_tag'], '=')); + $bbcodes[$bbcode_name][$variant] = $row; + } + $this->db->sql_freeresult($result); + + foreach ($bbcodes as $bbcode_name => $variants) + { + if (count($variants) === 2) + { + $this->merge_bbcodes($variants['without'], $variants['with']); + } + } + } + + protected function merge_bbcodes(array $without, array $with) + { + try + { + $merged = $this->container->get('text_formatter.s9e.bbcode_merger')->merge_bbcodes( + [ + 'usage' => $without['bbcode_match'], + 'template' => $without['bbcode_tpl'] + ], + [ + 'usage' => $with['bbcode_match'], + 'template' => $with['bbcode_tpl'] + ] + ); + } + catch (\Exception $e) + { + // Ignore the pair and move on. The BBCodes would have to be fixed manually + return; + } + + $bbcode_data = [ + 'bbcode_tag' => $without['bbcode_tag'], + 'bbcode_helpline' => $without['bbcode_helpline'] . ' | ' . $with['bbcode_helpline'], + 'bbcode_match' => $merged['usage'], + 'bbcode_tpl' => $merged['template'] + ]; + + $sql = 'UPDATE ' . BBCODES_TABLE . ' + SET ' . $this->db->sql_build_array('UPDATE', $bbcode_data) . ' + WHERE bbcode_id = ' . (int) $without['bbcode_id']; + $this->sql_query($sql); + + $sql = 'DELETE FROM ' . BBCODES_TABLE . ' + WHERE bbcode_id = ' . (int) $with['bbcode_id']; + $this->sql_query($sql); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/remove_imagick.php b/phpBB/phpbb/db/migration/data/v32x/remove_imagick.php new file mode 100644 index 0000000000..7ad396f8e8 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/remove_imagick.php @@ -0,0 +1,31 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v32x; + +class remove_imagick extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\v324rc1', + ); + } + + public function update_data() + { + return array( + array('config.remove', array('img_imagick')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/smtp_dynamic_data.php b/phpBB/phpbb/db/migration/data/v32x/smtp_dynamic_data.php new file mode 100644 index 0000000000..aeaa3e8979 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/smtp_dynamic_data.php @@ -0,0 +1,42 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\db\migration\data\v32x; + +class smtp_dynamic_data extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\v326rc1', + ); + } + + public function update_data() + { + return array( + array('custom', array(array($this, 'set_smtp_dynamic'))), + ); + } + + public function set_smtp_dynamic() + { + $smtp_auth_entries = [ + 'smtp_password', + 'smtp_username', + ]; + $this->sql_query('UPDATE ' . CONFIG_TABLE . ' + SET is_dynamic = 1 + WHERE ' . $this->db->sql_in_set('config_name', $smtp_auth_entries)); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/timezone_p3.php b/phpBB/phpbb/db/migration/data/v32x/timezone_p3.php new file mode 100644 index 0000000000..433f62ace9 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/timezone_p3.php @@ -0,0 +1,29 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v32x; + +class timezone_p3 extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array('\phpbb\db\migration\data\v310\timezone'); + } + + public function update_data() + { + return array( + array('config.remove', array('board_dst')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/update_prosilver_bitfield.php b/phpBB/phpbb/db/migration/data/v32x/update_prosilver_bitfield.php new file mode 100644 index 0000000000..6e51a01834 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/update_prosilver_bitfield.php @@ -0,0 +1,39 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v32x; + +class update_prosilver_bitfield extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\v321', + ); + } + + public function update_data() + { + return array( + array('custom', array(array($this, 'update_bbcode_bitfield'))), + ); + } + + public function update_bbcode_bitfield() + { + $sql = 'UPDATE ' . STYLES_TABLE . " + SET bbcode_bitfield = '//g=' + WHERE style_path = 'prosilver'"; + $this->sql_query($sql); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/v321.php b/phpBB/phpbb/db/migration/data/v32x/v321.php index 268f978b4b..fdbb5cff19 100644 --- a/phpBB/phpbb/db/migration/data/v32x/v321.php +++ b/phpBB/phpbb/db/migration/data/v32x/v321.php @@ -23,6 +23,7 @@ class v321 extends \phpbb\db\migration\migration static public function depends_on() { return array( + '\phpbb\db\migration\data\v31x\v3111', '\phpbb\db\migration\data\v32x\v321rc1', ); diff --git a/phpBB/phpbb/db/migration/data/v32x/v322.php b/phpBB/phpbb/db/migration/data/v32x/v322.php new file mode 100644 index 0000000000..7ecbbb3e79 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/v322.php @@ -0,0 +1,37 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v32x; + +class v322 extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return phpbb_version_compare($this->config['version'], '3.2.2', '>='); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v31x\v3112', + '\phpbb\db\migration\data\v32x\v322rc1', + ); + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.2.2')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/v322rc1.php b/phpBB/phpbb/db/migration/data/v32x/v322rc1.php new file mode 100644 index 0000000000..4fd6270132 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/v322rc1.php @@ -0,0 +1,41 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v32x; + +class v322rc1 extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return phpbb_version_compare($this->config['version'], '3.2.2-RC1', '>='); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\v321', + '\phpbb\db\migration\data\v32x\fix_user_styles', + '\phpbb\db\migration\data\v32x\update_prosilver_bitfield', + '\phpbb\db\migration\data\v32x\email_force_sender', + '\phpbb\db\migration\data\v32x\f_list_topics_permission_add', + '\phpbb\db\migration\data\v32x\merge_duplicate_bbcodes', + ); + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.2.2-RC1')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/v323.php b/phpBB/phpbb/db/migration/data/v32x/v323.php new file mode 100644 index 0000000000..1ec28ceb37 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/v323.php @@ -0,0 +1,37 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v32x; + +class v323 extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return phpbb_version_compare($this->config['version'], '3.2.3', '>='); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\v323rc2', + ); + + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.2.3')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/v323rc1.php b/phpBB/phpbb/db/migration/data/v32x/v323rc1.php new file mode 100644 index 0000000000..c3fcd1ab0b --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/v323rc1.php @@ -0,0 +1,37 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v32x; + +class v323rc1 extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return phpbb_version_compare($this->config['version'], '3.2.3-RC1', '>='); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\v322', + '\phpbb\db\migration\data\v32x\enable_accurate_pm_button', + ); + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.2.3-RC1')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/v323rc2.php b/phpBB/phpbb/db/migration/data/v32x/v323rc2.php new file mode 100644 index 0000000000..32235ee067 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/v323rc2.php @@ -0,0 +1,36 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v32x; + +class v323rc2 extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return phpbb_version_compare($this->config['version'], '3.2.3-RC2', '>='); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\v323rc1', + ); + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.2.3-RC2')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/v324.php b/phpBB/phpbb/db/migration/data/v32x/v324.php new file mode 100644 index 0000000000..cd7783fdee --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/v324.php @@ -0,0 +1,38 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v32x; + +class v324 extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return phpbb_version_compare($this->config['version'], '3.2.4', '>='); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\v324rc1', + '\phpbb\db\migration\data\v32x\remove_imagick', + ); + + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.2.4')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/v324rc1.php b/phpBB/phpbb/db/migration/data/v32x/v324rc1.php new file mode 100644 index 0000000000..0221e2621a --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/v324rc1.php @@ -0,0 +1,37 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v32x; + +class v324rc1 extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return phpbb_version_compare($this->config['version'], '3.2.4-RC1', '>='); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\v323', + '\phpbb\db\migration\data\v32x\forum_topics_per_page_type', + ); + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.2.4-RC1')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/v325.php b/phpBB/phpbb/db/migration/data/v32x/v325.php new file mode 100644 index 0000000000..59de4916df --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/v325.php @@ -0,0 +1,38 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v32x; + +class v325 extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return phpbb_version_compare($this->config['version'], '3.2.5', '>='); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\v325rc1', + '\phpbb\db\migration\data\v32x\jquery_update', + ); + + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.2.5')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/v325rc1.php b/phpBB/phpbb/db/migration/data/v32x/v325rc1.php new file mode 100644 index 0000000000..2d0de0a432 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/v325rc1.php @@ -0,0 +1,36 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v32x; + +class v325rc1 extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return phpbb_version_compare($this->config['version'], '3.2.5-RC1', '>='); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\v324', + ); + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.2.5-RC1')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/v326.php b/phpBB/phpbb/db/migration/data/v32x/v326.php new file mode 100644 index 0000000000..2d511b9ed8 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/v326.php @@ -0,0 +1,39 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v32x; + +class v326 extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return phpbb_version_compare($this->config['version'], '3.2.6', '>='); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\v326rc1', + '\phpbb\db\migration\data\v32x\disable_remote_avatar', + '\phpbb\db\migration\data\v32x\smtp_dynamic_data', + ); + + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.2.6')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/v326rc1.php b/phpBB/phpbb/db/migration/data/v32x/v326rc1.php new file mode 100644 index 0000000000..092700d3db --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/v326rc1.php @@ -0,0 +1,37 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v32x; + +class v326rc1 extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return phpbb_version_compare($this->config['version'], '3.2.6-RC1', '>='); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\v325', + ); + + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.2.6-RC1')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/v327.php b/phpBB/phpbb/db/migration/data/v32x/v327.php new file mode 100644 index 0000000000..f9ea11f4b9 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/v327.php @@ -0,0 +1,37 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v32x; + +class v327 extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return phpbb_version_compare($this->config['version'], '3.2.7', '>='); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\v327rc1', + ); + + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.2.7')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/v327rc1.php b/phpBB/phpbb/db/migration/data/v32x/v327rc1.php new file mode 100644 index 0000000000..c8169105af --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/v327rc1.php @@ -0,0 +1,36 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v32x; + +class v327rc1 extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return phpbb_version_compare($this->config['version'], '3.2.7-RC1', '>='); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\v326', + ); + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.2.7-RC1')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v32x/v328rc1.php b/phpBB/phpbb/db/migration/data/v32x/v328rc1.php new file mode 100644 index 0000000000..fa43cf33a7 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/v328rc1.php @@ -0,0 +1,37 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v32x; + +class v328rc1 extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return phpbb_version_compare($this->config['version'], '3.2.8-RC1', '>='); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\timezone_p3', + '\phpbb\db\migration\data\v32x\v327', + ); + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.2.8-RC1')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/tool/config.php b/phpBB/phpbb/db/migration/tool/config.php index 33aa8ff026..a351c4858e 100644 --- a/phpBB/phpbb/db/migration/tool/config.php +++ b/phpBB/phpbb/db/migration/tool/config.php @@ -134,7 +134,7 @@ class config implements \phpbb\db\migration\tool\tool_interface case 'remove': $call = 'add'; - if (sizeof($arguments) == 1) + if (count($arguments) == 1) { $arguments[] = ''; } diff --git a/phpBB/phpbb/db/migration/tool/config_text.php b/phpBB/phpbb/db/migration/tool/config_text.php index 54b45f6f6d..5fe9a25b70 100644 --- a/phpBB/phpbb/db/migration/tool/config_text.php +++ b/phpBB/phpbb/db/migration/tool/config_text.php @@ -110,7 +110,7 @@ class config_text implements \phpbb\db\migration\tool\tool_interface case 'remove': $call = 'add'; - if (sizeof($arguments) == 1) + if (count($arguments) == 1) { $arguments[] = ''; } diff --git a/phpBB/phpbb/db/migration/tool/module.php b/phpBB/phpbb/db/migration/tool/module.php index b47c426110..e5133c8152 100644 --- a/phpBB/phpbb/db/migration/tool/module.php +++ b/phpBB/phpbb/db/migration/tool/module.php @@ -84,9 +84,12 @@ class module implements \phpbb\db\migration\tool\tool_interface * Use false to ignore the parent check and check class wide. * @param int|string $module The module_id|module_langname you would like to * check for to see if it exists - * @return bool true/false if module exists + * @param bool $lazy Checks lazily if the module exists. Returns true if it exists in at + * least one given parent. + * @return bool true if module exists in *all* given parents, false if not in any given parent; + * true if ignoring parent check and module exists class wide, false if not found at all. */ - public function exists($class, $parent, $module) + public function exists($class, $parent, $module, $lazy = false) { // the main root directory should return true if (!$module) @@ -94,33 +97,48 @@ class module implements \phpbb\db\migration\tool\tool_interface return true; } - $parent_sql = ''; + $parent_sqls = []; if ($parent !== false) { - $parent = $this->get_parent_module_id($parent, $module, false); - if ($parent === false) + $parents = $this->get_parent_module_id($parent, $module, false); + if ($parents === false) { return false; } - $parent_sql = 'AND parent_id = ' . (int) $parent; + foreach ((array) $parents as $parent_id) + { + $parent_sqls[] = 'AND parent_id = ' . (int) $parent_id; + } + } + else + { + $parent_sqls[] = ''; } - $sql = 'SELECT module_id - FROM ' . $this->modules_table . " - WHERE module_class = '" . $this->db->sql_escape($class) . "' - $parent_sql - AND " . ((is_numeric($module)) ? 'module_id = ' . (int) $module : "module_langname = '" . $this->db->sql_escape($module) . "'"); - $result = $this->db->sql_query($sql); - $module_id = $this->db->sql_fetchfield('module_id'); - $this->db->sql_freeresult($result); - - if ($module_id) + foreach ($parent_sqls as $parent_sql) { - return true; + $sql = 'SELECT module_id + FROM ' . $this->modules_table . " + WHERE module_class = '" . $this->db->sql_escape($class) . "' + $parent_sql + AND " . ((is_numeric($module)) ? 'module_id = ' . (int) $module : "module_langname = '" . $this->db->sql_escape($module) . "'"); + $result = $this->db->sql_query($sql); + $module_id = $this->db->sql_fetchfield('module_id'); + $this->db->sql_freeresult($result); + + if (!$lazy && !$module_id) + { + return false; + } + if ($lazy && $module_id) + { + return true; + } } - return false; + // Returns true, if modules exist in all parents and false otherwise + return !$lazy; } /** @@ -172,7 +190,7 @@ class module implements \phpbb\db\migration\tool\tool_interface $data = array('module_langname' => $data); } - $parent = $data['parent_id'] = $this->get_parent_module_id($parent, $data); + $parents = (array) $this->get_parent_module_id($parent, $data); if (!isset($data['module_langname'])) { @@ -195,99 +213,135 @@ class module implements \phpbb\db\migration\tool\tool_interface ); // Run the "manual" way with the data we've collected. - $this->add($class, $parent, $new_module); + foreach ($parents as $parent) + { + $this->add($class, $parent, $new_module); + } } } return; } - // The "manual" way - if (!$this->exists($class, false, $parent)) - { - throw new \phpbb\db\migration\exception('MODULE_NOT_EXIST', $parent); - } - - if ($this->exists($class, $parent, $data['module_langname'])) + foreach ($parents as $parent) { - throw new \phpbb\db\migration\exception('MODULE_EXISTS', $data['module_langname']); - } + $data['parent_id'] = $parent; - $module_data = array( - 'module_enabled' => (isset($data['module_enabled'])) ? $data['module_enabled'] : 1, - 'module_display' => (isset($data['module_display'])) ? $data['module_display'] : 1, - 'module_basename' => (isset($data['module_basename'])) ? $data['module_basename'] : '', - 'module_class' => $class, - 'parent_id' => (int) $parent, - 'module_langname' => (isset($data['module_langname'])) ? $data['module_langname'] : '', - 'module_mode' => (isset($data['module_mode'])) ? $data['module_mode'] : '', - 'module_auth' => (isset($data['module_auth'])) ? $data['module_auth'] : '', - ); - - try - { - $this->module_manager->update_module_data($module_data); + // The "manual" way + if (!$this->exists($class, false, $parent)) + { + throw new \phpbb\db\migration\exception('MODULE_NOT_EXIST', $parent); + } - // Success - $module_log_name = ((isset($this->user->lang[$data['module_langname']])) ? $this->user->lang[$data['module_langname']] : $data['module_langname']); - $phpbb_log->add('admin', (isset($user->data['user_id'])) ? $user->data['user_id'] : ANONYMOUS, $user->ip, 'LOG_MODULE_ADD', false, array($module_log_name)); + if ($this->exists($class, $parent, $data['module_langname'])) + { + throw new \phpbb\db\migration\exception('MODULE_EXISTS', $data['module_langname']); + } - // Move the module if requested above/below an existing one - if (isset($data['before']) && $data['before']) + $module_data = array( + 'module_enabled' => (isset($data['module_enabled'])) ? $data['module_enabled'] : 1, + 'module_display' => (isset($data['module_display'])) ? $data['module_display'] : 1, + 'module_basename' => (isset($data['module_basename'])) ? $data['module_basename'] : '', + 'module_class' => $class, + 'parent_id' => (int) $parent, + 'module_langname' => (isset($data['module_langname'])) ? $data['module_langname'] : '', + 'module_mode' => (isset($data['module_mode'])) ? $data['module_mode'] : '', + 'module_auth' => (isset($data['module_auth'])) ? $data['module_auth'] : '', + ); + + try { - $sql = 'SELECT left_id + $this->module_manager->update_module_data($module_data); + + // Success + $module_log_name = ((isset($this->user->lang[$data['module_langname']])) ? $this->user->lang[$data['module_langname']] : $data['module_langname']); + $phpbb_log->add('admin', (isset($user->data['user_id'])) ? $user->data['user_id'] : ANONYMOUS, $user->ip, 'LOG_MODULE_ADD', false, array($module_log_name)); + + // Move the module if requested above/below an existing one + if (isset($data['before']) && $data['before']) + { + $before_mode = $before_langname = ''; + if (is_array($data['before'])) + { + // Restore legacy-legacy behaviour from phpBB 3.0 + list($before_mode, $before_langname) = $data['before']; + } + else + { + // Legacy behaviour from phpBB 3.1+ + $before_langname = $data['before']; + } + + $sql = 'SELECT left_id FROM ' . $this->modules_table . " WHERE module_class = '" . $this->db->sql_escape($class) . "' AND parent_id = " . (int) $parent . " - AND module_langname = '" . $this->db->sql_escape($data['before']) . "'"; - $this->db->sql_query($sql); - $to_left = (int) $this->db->sql_fetchfield('left_id'); + AND module_langname = '" . $this->db->sql_escape($before_langname) . "'" + . (($before_mode) ? " AND module_mode = '" . $this->db->sql_escape($before_mode) . "'" : ''); + $result = $this->db->sql_query($sql); + $to_left = (int) $this->db->sql_fetchfield('left_id'); + $this->db->sql_freeresult($result); - $sql = 'UPDATE ' . $this->modules_table . " + $sql = 'UPDATE ' . $this->modules_table . " SET left_id = left_id + 2, right_id = right_id + 2 WHERE module_class = '" . $this->db->sql_escape($class) . "' AND left_id >= $to_left AND left_id < {$module_data['left_id']}"; - $this->db->sql_query($sql); + $this->db->sql_query($sql); - $sql = 'UPDATE ' . $this->modules_table . " + $sql = 'UPDATE ' . $this->modules_table . " SET left_id = $to_left, right_id = " . ($to_left + 1) . " WHERE module_class = '" . $this->db->sql_escape($class) . "' AND module_id = {$module_data['module_id']}"; - $this->db->sql_query($sql); - } - else if (isset($data['after']) && $data['after']) - { - $sql = 'SELECT right_id + $this->db->sql_query($sql); + } + else if (isset($data['after']) && $data['after']) + { + $after_mode = $after_langname = ''; + if (is_array($data['after'])) + { + // Restore legacy-legacy behaviour from phpBB 3.0 + list($after_mode, $after_langname) = $data['after']; + } + else + { + // Legacy behaviour from phpBB 3.1+ + $after_langname = $data['after']; + } + + $sql = 'SELECT right_id FROM ' . $this->modules_table . " WHERE module_class = '" . $this->db->sql_escape($class) . "' AND parent_id = " . (int) $parent . " - AND module_langname = '" . $this->db->sql_escape($data['after']) . "'"; - $this->db->sql_query($sql); - $to_right = (int) $this->db->sql_fetchfield('right_id'); + AND module_langname = '" . $this->db->sql_escape($after_langname) . "'" + . (($after_mode) ? " AND module_mode = '" . $this->db->sql_escape($after_mode) . "'" : ''); + $result = $this->db->sql_query($sql); + $to_right = (int) $this->db->sql_fetchfield('right_id'); + $this->db->sql_freeresult($result); - $sql = 'UPDATE ' . $this->modules_table . " + $sql = 'UPDATE ' . $this->modules_table . " SET left_id = left_id + 2, right_id = right_id + 2 WHERE module_class = '" . $this->db->sql_escape($class) . "' AND left_id >= $to_right AND left_id < {$module_data['left_id']}"; - $this->db->sql_query($sql); + $this->db->sql_query($sql); - $sql = 'UPDATE ' . $this->modules_table . ' + $sql = 'UPDATE ' . $this->modules_table . ' SET left_id = ' . ($to_right + 1) . ', right_id = ' . ($to_right + 2) . " WHERE module_class = '" . $this->db->sql_escape($class) . "' AND module_id = {$module_data['module_id']}"; - $this->db->sql_query($sql); + $this->db->sql_query($sql); + } + } + catch (module_exception $e) + { + // Error + throw new \phpbb\db\migration\exception('MODULE_ERROR', $e->getMessage()); } - } - catch (module_exception $e) - { - // Error - throw new \phpbb\db\migration\exception('MODULE_ERROR', $e->getMessage()); } // Clear the Modules Cache - $this->cache->destroy("_modules_$class"); + $this->module_manager->remove_cache_file($class); } /** @@ -334,7 +388,7 @@ class module implements \phpbb\db\migration\tool\tool_interface } else { - if (!$this->exists($class, $parent, $module)) + if (!$this->exists($class, $parent, $module, true)) { return; } @@ -342,8 +396,8 @@ class module implements \phpbb\db\migration\tool\tool_interface $parent_sql = ''; if ($parent !== false) { - $parent = $this->get_parent_module_id($parent, $module); - $parent_sql = 'AND parent_id = ' . (int) $parent; + $parents = (array) $this->get_parent_module_id($parent, $module); + $parent_sql = 'AND ' . $this->db->sql_in_set('parent_id', $parents); } $module_ids = array(); @@ -371,7 +425,7 @@ class module implements \phpbb\db\migration\tool\tool_interface $this->module_manager->delete_module($module_id, $class); } - $this->cache->destroy("_modules_$class"); + $this->module_manager->remove_cache_file($class); } } @@ -457,23 +511,14 @@ class module implements \phpbb\db\migration\tool\tool_interface * @param string|int $parent_id The parent module_id|module_langname * @param int|string|array $data The module_id, module_langname for existance checking or module data array for adding * @param bool $throw_exception The flag indicating if exception should be thrown on error - * @return mixed The int parent module_id or false + * @return mixed The int parent module_id, an array of int parent module_id values or false * @throws \phpbb\db\migration\exception */ public function get_parent_module_id($parent_id, $data = '', $throw_exception = true) { - // Initialize exception object placeholder - $exception = false; - // Allow '' to be sent as 0 $parent_id = $parent_id ?: 0; - // If automatic adding is in action, convert array back to string to simplify things - if (is_array($data) && sizeof($data) == 1) - { - $data = $data['module_langname']; - } - if (!is_numeric($parent_id)) { // Refresh the $module_categories array @@ -482,65 +527,30 @@ class module implements \phpbb\db\migration\tool\tool_interface // Search for the parent module_langname $ids = array_keys($this->module_categories, $parent_id); - switch (sizeof($ids)) + switch (count($ids)) { // No parent with the given module_langname exist case 0: - $exception = new \phpbb\db\migration\exception('MODULE_NOT_EXIST', $parent_id); + if ($throw_exception) + { + throw new \phpbb\db\migration\exception('MODULE_NOT_EXIST', $parent_id); + } + + return false; break; // Return the module id case 1: - $parent_id = (int) $ids[0]; + return (int) $ids[0]; break; - // Several modules with the given module_langname were found - // Try to determine the parent_id by the neighbour module parent default: - if (is_array($data) && (isset($data['before']) || isset($data['after']))) - { - $neighbour_module_langname = isset($data['before']) ? $data['before'] : $data['after']; - $sql = 'SELECT parent_id - FROM ' . $this->modules_table . " - WHERE module_langname = '" . $this->db->sql_escape($neighbour_module_langname) . "' - AND " . $this->db->sql_in_set('parent_id', $ids); - $result = $this->db->sql_query($sql); - $parent_id = (int) $this->db->sql_fetchfield('parent_id'); - if (!$parent_id) - { - $exception = new \phpbb\db\migration\exception('PARENT_MODULE_FIND_ERROR', $data['parent_id']); - } - } - else if (!empty($data) && !is_array($data)) - { - // The module_langname is set, checking for the module existance - // As more than 1 parents were found already, there's no way for null parent_id here - $sql = 'SELECT m2.module_id as module_parent_id - FROM ' . $this->modules_table . ' m1, ' . $this->modules_table . " m2 - WHERE " . ((is_numeric($data)) ? 'm1.module_id = ' . (int) $data : "m1.module_langname = '" . $this->db->sql_escape($data)) . "' - AND m2.module_id = m1.parent_id - AND " . $this->db->sql_in_set('m2.module_id', $ids); - $result = $this->db->sql_query($sql); - $parent_id = (int) $this->db->sql_fetchfield('module_parent_id'); - } - else - { - //Unable to get the parent module id, throwing an exception - $exception = new \phpbb\db\migration\exception('MODULE_EXIST_MULTIPLE', $parent_id); - } + // This represents the old behaviour of phpBB 3.0 + return $ids; break; } } - if ($exception !== false) - { - if ($throw_exception) - { - throw $exception; - } - return false; - } - return $parent_id; } } diff --git a/phpBB/phpbb/db/migration/tool/permission.php b/phpBB/phpbb/db/migration/tool/permission.php index 9688420025..4b53aa32a7 100644 --- a/phpBB/phpbb/db/migration/tool/permission.php +++ b/phpBB/phpbb/db/migration/tool/permission.php @@ -442,7 +442,7 @@ class permission implements \phpbb\db\migration\tool\tool_interface } ); - if (sizeof($auth_option)) + if (count($auth_option)) { return $this->permission_set($role_name, $auth_option, 'role', $has_permission); } diff --git a/phpBB/phpbb/db/migrator.php b/phpBB/phpbb/db/migrator.php index 6c026c3ae1..2b0c66fc58 100644 --- a/phpBB/phpbb/db/migrator.php +++ b/phpBB/phpbb/db/migrator.php @@ -632,7 +632,7 @@ class migrator */ protected function process_data_step($steps, $state, $revert = false) { - if (sizeof($steps) === 0) + if (count($steps) === 0) { return true; } @@ -659,7 +659,7 @@ class migrator // Result will be null or true if everything completed correctly // Stop after each update step, to let the updater control the script runtime $result = $this->run_step($steps[$step], $last_result, $revert); - if (($result !== null && $result !== true) || $step + 1 < sizeof($steps)) + if (($result !== null && $result !== true) || $step + 1 < count($steps)) { return array( 'result' => $result, @@ -760,7 +760,7 @@ class migrator $condition = $parameters[0]; - if (!$condition) + if (!$condition || (is_array($condition) && !$this->run_step($condition, $last_result, $reverse))) { return false; } diff --git a/phpBB/phpbb/db/sql_insert_buffer.php b/phpBB/phpbb/db/sql_insert_buffer.php index 18e4814a77..30e807b154 100644 --- a/phpBB/phpbb/db/sql_insert_buffer.php +++ b/phpBB/phpbb/db/sql_insert_buffer.php @@ -92,7 +92,7 @@ class sql_insert_buffer // Flush buffer if it is full or when DB does not support multi inserts. // In the later case, the buffer will always only contain one row. - if (!$this->db->get_multi_insert() || sizeof($this->buffer) >= $this->max_buffered_rows) + if (!$this->db->get_multi_insert() || count($this->buffer) >= $this->max_buffered_rows) { return $this->flush(); } @@ -104,7 +104,7 @@ class sql_insert_buffer * Inserts a row set, i.e. an array of rows, by calling insert(). * * Please note that it is in most cases better to use insert() instead of - * first building a huge rowset. Or at least sizeof($rows) should be kept + * first building a huge rowset. Or at least count($rows) should be kept * small. * * @param array $rows diff --git a/phpBB/phpbb/db/tools/mssql.php b/phpBB/phpbb/db/tools/mssql.php index 23b49aab44..cbedf9a5c4 100644 --- a/phpBB/phpbb/db/tools/mssql.php +++ b/phpBB/phpbb/db/tools/mssql.php @@ -49,18 +49,18 @@ class mssql extends tools 'STEXT' => '[varchar] (3000)', 'TEXT' => '[varchar] (8000)', 'MTEXT' => '[text]', - 'XSTEXT_UNI'=> '[varchar] (100)', - 'STEXT_UNI' => '[varchar] (255)', - 'TEXT_UNI' => '[varchar] (4000)', - 'MTEXT_UNI' => '[text]', + 'XSTEXT_UNI'=> '[nvarchar] (100)', + 'STEXT_UNI' => '[nvarchar] (255)', + 'TEXT_UNI' => '[nvarchar] (4000)', + 'MTEXT_UNI' => '[ntext]', 'TIMESTAMP' => '[int]', 'DECIMAL' => '[float]', 'DECIMAL:' => '[float]', 'PDECIMAL' => '[float]', 'PDECIMAL:' => '[float]', - 'VCHAR_UNI' => '[varchar] (255)', - 'VCHAR_UNI:'=> '[varchar] (%d)', - 'VCHAR_CI' => '[varchar] (255)', + 'VCHAR_UNI' => '[nvarchar] (255)', + 'VCHAR_UNI:'=> '[nvarchar] (%d)', + 'VCHAR_CI' => '[nvarchar] (255)', 'VARBINARY' => '[varchar] (255)', ), @@ -80,18 +80,18 @@ class mssql extends tools 'STEXT' => '[varchar] (3000)', 'TEXT' => '[varchar] (8000)', 'MTEXT' => '[text]', - 'XSTEXT_UNI'=> '[varchar] (100)', - 'STEXT_UNI' => '[varchar] (255)', - 'TEXT_UNI' => '[varchar] (4000)', - 'MTEXT_UNI' => '[text]', + 'XSTEXT_UNI'=> '[nvarchar] (100)', + 'STEXT_UNI' => '[nvarchar] (255)', + 'TEXT_UNI' => '[nvarchar] (4000)', + 'MTEXT_UNI' => '[ntext]', 'TIMESTAMP' => '[int]', 'DECIMAL' => '[float]', 'DECIMAL:' => '[float]', 'PDECIMAL' => '[float]', 'PDECIMAL:' => '[float]', - 'VCHAR_UNI' => '[varchar] (255)', - 'VCHAR_UNI:'=> '[varchar] (%d)', - 'VCHAR_CI' => '[varchar] (255)', + 'VCHAR_UNI' => '[nvarchar] (255)', + 'VCHAR_UNI:'=> '[nvarchar] (%d)', + 'VCHAR_CI' => '[nvarchar] (255)', 'VARBINARY' => '[varchar] (255)', ), ); @@ -440,7 +440,7 @@ class mssql extends tools { $result = $this->sql_index_drop($table_name, $index_name); $statements = array_merge($statements, $result); - if (sizeof($index_data) > 1) + if (count($index_data) > 1) { // Remove this column from the index and recreate it $recreate_indexes[$index_name] = array_diff($index_data, array($column_name)); @@ -448,6 +448,10 @@ class mssql extends tools } } + // Drop primary keys depending on this column + $result = $this->mssql_get_drop_default_primary_key_queries($table_name, $column_name); + $statements = array_merge($statements, $result); + // Drop default value constraint $result = $this->mssql_get_drop_default_constraints_queries($table_name, $column_name); $statements = array_merge($statements, $result); @@ -541,10 +545,7 @@ class mssql extends tools { $statements = array(); - if ($this->mssql_is_sql_server_2000()) - { - $this->check_index_name_length($table_name, $index_name); - } + $this->check_index_name_length($table_name, $index_name); // remove index length $column = preg_replace('#:.*$#', '', $column); @@ -555,6 +556,21 @@ class mssql extends tools } /** + * {@inheritdoc} + */ + protected function get_max_index_name_length() + { + if ($this->mssql_is_sql_server_2000()) + { + return parent::get_max_index_name_length(); + } + else + { + return 128; + } + } + + /** * {@inheritDoc} */ function sql_list_index($table_name) @@ -685,6 +701,38 @@ class mssql extends tools } /** + * Get queries to drop the primary keys depending on the specified column + * + * We need to drop primary keys depending on this column before being able + * to delete them. + * + * @param string $table_name + * @param string $column_name + * @return array Array with SQL statements + */ + protected function mssql_get_drop_default_primary_key_queries($table_name, $column_name) + { + $statements = array(); + + $sql = "SELECT ccu.CONSTRAINT_NAME, ccu.COLUMN_NAME + FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc + JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE ccu ON tc.CONSTRAINT_NAME = ccu.Constraint_name + WHERE tc.TABLE_NAME = '{$table_name}' + AND tc.CONSTRAINT_TYPE = 'Primary Key' + AND ccu.COLUMN_NAME = '{$column_name}'"; + + $result = $this->db->sql_query($sql); + + while ($primary_key = $this->db->sql_fetchrow($result)) + { + $statements[] = 'ALTER TABLE [' . $table_name . '] DROP CONSTRAINT [' . $primary_key['CONSTRAINT_NAME'] . ']'; + } + $this->db->sql_freeresult($result); + + return $statements; + } + + /** * Checks to see if column is an identity column * * Identity columns cannot have defaults set for them. diff --git a/phpBB/phpbb/db/tools/tools.php b/phpBB/phpbb/db/tools/tools.php index 2f891e43d5..c3352a1f66 100644 --- a/phpBB/phpbb/db/tools/tools.php +++ b/phpBB/phpbb/db/tools/tools.php @@ -576,7 +576,7 @@ class tools implements tools_interface { foreach ($indexes as $index_name) { - if (!$this->sql_index_exists($table, $index_name)) + if (!$this->sql_index_exists($table, $index_name) && !$this->sql_unique_index_exists($table, $index_name)) { continue; } @@ -1561,7 +1561,8 @@ class tools implements tools_interface */ protected function check_index_name_length($table_name, $index_name, $throw_error = true) { - if (strlen($index_name) > 30) + $max_index_name_length = $this->get_max_index_name_length(); + if (strlen($index_name) > $max_index_name_length) { // Try removing the table prefix if it's at the beginning $table_prefix = substr(CONFIG_TABLE, 0, -6); // strlen(config) @@ -1582,7 +1583,7 @@ class tools implements tools_interface if ($throw_error) { - trigger_error("Index name '$index_name' on table '$table_name' is too long. The maximum is 30 characters.", E_USER_ERROR); + trigger_error("Index name '$index_name' on table '$table_name' is too long. The maximum is $max_index_name_length characters.", E_USER_ERROR); } } @@ -1590,6 +1591,16 @@ class tools implements tools_interface } /** + * Get maximum index name length. Might vary depending on db type + * + * @return int Maximum index name length + */ + protected function get_max_index_name_length() + { + return 30; + } + + /** * {@inheritDoc} */ function sql_list_index($table_name) diff --git a/phpBB/phpbb/debug/error_handler.php b/phpBB/phpbb/debug/error_handler.php index 246e724f56..ebd828b97f 100644 --- a/phpBB/phpbb/debug/error_handler.php +++ b/phpBB/phpbb/debug/error_handler.php @@ -17,7 +17,7 @@ use Symfony\Component\Debug\ErrorHandler; class error_handler extends ErrorHandler { - public function handleError($type, $message, $file, $line, array $context, array $backtrace = null) + public function handleError($type, $message, $file, $line) { if ($type === E_USER_WARNING || $type === E_USER_NOTICE) { @@ -26,6 +26,6 @@ class error_handler extends ErrorHandler $handler($type, $message, $file, $line); } - return parent::handleError($type, $message, $file, $line, $context, $backtrace); + return parent::handleError($type, $message, $file, $line); } } diff --git a/phpBB/phpbb/di/container_builder.php b/phpBB/phpbb/di/container_builder.php index ac1a1a1733..8c1ce8bde2 100644 --- a/phpBB/phpbb/di/container_builder.php +++ b/phpBB/phpbb/di/container_builder.php @@ -143,6 +143,13 @@ class container_builder { if ($this->use_extensions) { + $autoload_cache = new ConfigCache($this->get_autoload_filename(), defined('DEBUG')); + if (!$autoload_cache->isFresh()) + { + // autoload cache should be refreshed + $this->load_extensions(); + } + require($this->get_autoload_filename()); } diff --git a/phpBB/phpbb/event/dispatcher.php b/phpBB/phpbb/event/dispatcher.php index 1c4abeb108..1ba2ab8987 100644 --- a/phpBB/phpbb/event/dispatcher.php +++ b/phpBB/phpbb/event/dispatcher.php @@ -57,7 +57,12 @@ class dispatcher extends ContainerAwareEventDispatcher implements dispatcher_int return $event; } - return parent::dispatch($eventName, $event); + foreach ((array) $eventName as $name) + { + $event = parent::dispatch($name, $event); + } + + return $event; } /** diff --git a/phpBB/phpbb/event/md_exporter.php b/phpBB/phpbb/event/md_exporter.php index e042d0a5d1..1a2d7c989e 100644 --- a/phpBB/phpbb/event/md_exporter.php +++ b/phpBB/phpbb/event/md_exporter.php @@ -87,7 +87,7 @@ class md_exporter $this->validate_events_from_file($file_name, $this->crawl_file_for_events($file_name)); } - return sizeof($this->events); + return count($this->events); } /** @@ -113,7 +113,7 @@ class md_exporter } } - return sizeof($this->events); + return count($this->events); } /** @@ -143,6 +143,8 @@ class md_exporter list($event_name, $details) = explode("\n===\n", $event, 2); $this->validate_event_name($event_name); + $sorted_events = [$this->current_event, $event_name]; + natsort($sorted_events); $this->current_event = $event_name; if (isset($this->events[$this->current_event])) @@ -150,6 +152,12 @@ class md_exporter throw new \LogicException("The event '{$this->current_event}' is defined multiple times"); } + // Use array_values() to get actual first element and check against natural order + if (array_values($sorted_events)[0] === $event_name) + { + throw new \LogicException("The event '{$sorted_events[1]}' should be defined before '{$sorted_events[0]}'"); + } + if (($this->filter == 'adm' && strpos($this->current_event, 'acp_') !== 0) || ($this->filter == 'styles' && strpos($this->current_event, 'acp_') === 0)) { @@ -219,7 +227,7 @@ class md_exporter ); } - return sizeof($this->events); + return count($this->events); } /** @@ -381,9 +389,16 @@ class md_exporter $files = explode("\n + ", $file_details); foreach ($files as $file) { + if (!preg_match('#^([^ ]+)( \([0-9]+\))?$#', $file)) + { + throw new \LogicException("Invalid event instances for file '{$file}' found for event '{$this->current_event}'", 1); + } + + list($file) = explode(" ", $file); + if (!file_exists($this->path . $file) || substr($file, -5) !== '.html') { - throw new \LogicException("Invalid file '{$file}' not found for event '{$this->current_event}'", 1); + throw new \LogicException("Invalid file '{$file}' not found for event '{$this->current_event}'", 2); } if (($this->filter !== 'adm') && strpos($file, 'styles/prosilver/template/') === 0) @@ -396,7 +411,7 @@ class md_exporter } else { - throw new \LogicException("Invalid file '{$file}' not found for event '{$this->current_event}'", 2); + throw new \LogicException("Invalid file '{$file}' not found for event '{$this->current_event}'", 3); } $this->events_by_file[$file][] = $this->current_event; @@ -416,7 +431,7 @@ class md_exporter } else { - throw new \LogicException("Invalid file list found for event '{$this->current_event}'", 2); + throw new \LogicException("Invalid file list found for event '{$this->current_event}'", 1); } return $files_list; @@ -439,16 +454,9 @@ class md_exporter $event_list = array(); $file_content = file_get_contents($this->path . $file); - $events = explode('<!-- EVENT ', $file_content); - // Remove the code before the first event - array_shift($events); - foreach ($events as $event) - { - $event = explode(' -->', $event, 2); - $event_list[] = array_shift($event); - } + preg_match_all('/(?:{%|<!--) EVENT (.*) (?:%}|-->)/U', $file_content, $event_list); - return $event_list; + return $event_list[1]; } /** diff --git a/phpBB/phpbb/event/php_exporter.php b/phpBB/phpbb/event/php_exporter.php index 26d7e2b426..71c94a681d 100644 --- a/phpBB/phpbb/event/php_exporter.php +++ b/phpBB/phpbb/event/php_exporter.php @@ -117,7 +117,7 @@ class php_exporter } ksort($this->events); - return sizeof($this->events); + return count($this->events); } /** @@ -196,13 +196,13 @@ class php_exporter $content = file_get_contents($this->path . $this->current_file); $num_events_found = 0; - if (strpos($content, "dispatcher->trigger_event('") || strpos($content, "dispatcher->dispatch('")) + if (strpos($content, 'dispatcher->trigger_event(') || strpos($content, 'dispatcher->dispatch(')) { $this->set_content(explode("\n", $content)); - for ($i = 0, $num_lines = sizeof($this->file_lines); $i < $num_lines; $i++) + for ($i = 0, $num_lines = count($this->file_lines); $i < $num_lines; $i++) { $event_line = false; - $found_trigger_event = strpos($this->file_lines[$i], "dispatcher->trigger_event('"); + $found_trigger_event = strpos($this->file_lines[$i], 'dispatcher->trigger_event('); $arguments = array(); if ($found_trigger_event !== false) { @@ -216,7 +216,7 @@ class php_exporter } else { - $found_dispatch = strpos($this->file_lines[$i], "dispatcher->dispatch('"); + $found_dispatch = strpos($this->file_lines[$i], 'dispatcher->dispatch('); if ($found_dispatch !== false) { $event_line = $i; @@ -264,7 +264,30 @@ class php_exporter // Find event description line $description_line_num = $this->find_description(); - $description = substr(trim($this->file_lines[$description_line_num]), strlen('* ')); + $description_lines = array(); + + while (true) + { + $description_line = substr(trim($this->file_lines[$description_line_num]), strlen('*')); + $description_line = trim(str_replace("\t", " ", $description_line)); + + // Reached end of description if line is a tag + if (strlen($description_line) && $description_line[0] == '@') + { + break; + } + + $description_lines[] = $description_line; + $description_line_num++; + } + + // If there is an empty line between description and first tag, remove it + if (!strlen(end($description_lines))) + { + array_pop($description_lines); + } + + $description = trim(implode('<br/>', $description_lines)); if (isset($this->events[$this->current_event])) { @@ -316,17 +339,17 @@ class php_exporter if ($is_dispatch) { - $regex = '#\$([a-z](?:[a-z0-9_]|->)*)'; - $regex .= '->dispatch\('; - $regex .= '\'' . $this->preg_match_event_name() . '\''; - $regex .= '\);#'; + $regex = '#\$[a-z](?:[a-z0-9_]|->)*'; + $regex .= '->dispatch\((\[)?'; + $regex .= '\'' . $this->preg_match_event_name() . '(?(1)\', \'(?2))+\''; + $regex .= '(?(1)\])\);#'; } else { - $regex = '#extract\(\$([a-z](?:[a-z0-9_]|->)*)'; - $regex .= '->trigger_event\('; - $regex .= '\'' . $this->preg_match_event_name() . '\''; - $regex .= ', compact\(\$vars\)\)\);#'; + $regex = '#extract\(\$[a-z](?:[a-z0-9_]|->)*'; + $regex .= '->trigger_event\((\[)?'; + $regex .= '\'' . $this->preg_match_event_name() . '(?(1)\', \'(?2))+\''; + $regex .= '(?(1)\]), compact\(\$vars\)\)\);#'; } $match = array(); @@ -359,7 +382,7 @@ class php_exporter public function get_vars_from_array() { $line = ltrim($this->file_lines[$this->current_event_line - 1], "\t"); - if ($line === ');') + if ($line === ');' || $line === '];') { $vars_array = $this->get_vars_from_multi_line_array(); } @@ -370,7 +393,7 @@ class php_exporter foreach ($vars_array as $var) { - if (!preg_match('#^([a-zA-Z_][a-zA-Z0-9_]*)$#', $var)) + if (!preg_match('#^[a-z_][a-z0-9_]*$#i', $var)) { throw new \LogicException("Found invalid var '{$var}' in array for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 3); } @@ -392,12 +415,12 @@ class php_exporter public function get_vars_from_single_line_array($line, $throw_multiline = true) { $match = array(); - preg_match('#^\$vars = (?:\[|array\()\'([a-zA-Z0-9_\' ,]+)\'[\)\]];$#', $line, $match); + preg_match('#^\$vars = (?:(\[)|array\()\'([a-z0-9_\' ,]+)\'(?(1)\]|\));$#i', $line, $match); - if (isset($match[1])) + if (isset($match[2])) { - $vars_array = explode("', '", $match[1]); - if ($throw_multiline && sizeof($vars_array) > 6) + $vars_array = explode("', '", $match[2]); + if ($throw_multiline && count($vars_array) > 6) { throw new \LogicException('Should use multiple lines for $vars definition ' . "for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 2); @@ -420,7 +443,7 @@ class php_exporter { $current_vars_line = 2; $var_lines = array(); - while (ltrim($this->file_lines[$this->current_event_line - $current_vars_line], "\t") !== '$vars = array(') + while (!in_array(ltrim($this->file_lines[$this->current_event_line - $current_vars_line], "\t"), ['$vars = array(', '$vars = ['])) { $var_lines[] = substr(trim($this->file_lines[$this->current_event_line - $current_vars_line]), 0, -1); @@ -460,7 +483,7 @@ class php_exporter if (strpos($var_line, '* @var ') === 0) { $doc_line = explode(' ', $var_line, 5); - if (sizeof($doc_line) !== 5) + if (count($doc_line) !== 5) { throw new \LogicException("Found invalid line '{$this->file_lines[$this->current_event_line - $current_doc_line]}' " . "for event '{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 1); @@ -485,7 +508,7 @@ class php_exporter foreach ($doc_vars as $var) { - if (!preg_match('#^([a-zA-Z_][a-zA-Z0-9_]*)$#', $var)) + if (!preg_match('#^[a-z_][a-z0-9_]*$#i', $var)) { throw new \LogicException("Found invalid @var '{$var}' in docblock for event " . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'", 4); @@ -707,9 +730,9 @@ class php_exporter { $vars_array = array_unique($vars_array); $vars_docblock = array_unique($vars_docblock); - $sizeof_vars_array = sizeof($vars_array); + $sizeof_vars_array = count($vars_array); - if ($sizeof_vars_array !== sizeof($vars_docblock) || $sizeof_vars_array !== sizeof(array_intersect($vars_array, $vars_docblock))) + if ($sizeof_vars_array !== count($vars_docblock) || $sizeof_vars_array !== count(array_intersect($vars_array, $vars_docblock))) { throw new \LogicException("\$vars array does not match the list of '@var' tags for event " . "'{$this->current_event}' in file '{$this->current_file}:{$this->current_event_line}'"); diff --git a/phpBB/phpbb/feed/helper.php b/phpBB/phpbb/feed/helper.php index e15d1e131e..7d50b7ce7d 100644 --- a/phpBB/phpbb/feed/helper.php +++ b/phpBB/phpbb/feed/helper.php @@ -13,41 +13,52 @@ namespace phpbb\feed; +use phpbb\config\config; +use phpbb\path_helper; +use phpbb\textformatter\s9e\renderer; +use phpbb\user; +use Symfony\Component\DependencyInjection\ContainerInterface; + /** * Class with some helpful functions used in feeds */ class helper { - /** @var \phpbb\config\config */ + /** @var config */ protected $config; - /** @var \phpbb\user */ - protected $user; + /** @var ContainerInterface */ + protected $container; - /** @var string */ - protected $phpbb_root_path; + /** @var path_helper */ + protected $path_helper; - /** @var string */ - protected $phpEx; + /** @var renderer */ + protected $renderer; + + /** @var user */ + protected $user; /** * Constructor * - * @param \phpbb\config\config $config Config object - * @param \phpbb\user $user User object - * @param string $phpbb_root_path Root path - * @param string $phpEx PHP file extension + * @param config $config Config object + * @param ContainerInterface $container Service container object + * @param path_helper $path_helper Path helper object + * @param renderer $renderer TextFormatter renderer object + * @param user $user User object */ - public function __construct(\phpbb\config\config $config, \phpbb\user $user, $phpbb_root_path, $phpEx) + public function __construct(config $config, ContainerInterface $container, path_helper $path_helper, renderer $renderer, user $user) { $this->config = $config; + $this->container = $container; + $this->path_helper = $path_helper; + $this->renderer = $renderer; $this->user = $user; - $this->phpbb_root_path = $phpbb_root_path; - $this->phpEx = $phpEx; } /** - * Run links through append_sid(), prepend generate_board_url() and remove session id + * Returns the board url (and caches it in the function) */ public function get_board_url() { @@ -104,16 +115,12 @@ class helper return ''; } - // Prepare some bbcodes for better parsing - $content = preg_replace("#\[quote(=".*?")?:$uid\]\s*(.*?)\s*\[/quote:$uid\]#si", "[quote$1:$uid]<br />$2<br />[/quote:$uid]", $content); - - $content = generate_text_for_display($content, $uid, $bitfield, $options); + // Setup our own quote_helper to remove all attributes from quotes + $this->renderer->configure_quote_helper($this->container->get('feed.quote_helper')); - // Add newlines - $content = str_replace('<br />', '<br />' . "\n", $content); + $this->renderer->set_smilies_path($this->get_board_url() . '/' . $this->config['smilies_path']); - // Convert smiley Relative paths to Absolute path, Windows style - $content = str_replace($this->phpbb_root_path . $this->config['smilies_path'], $this->get_board_url() . '/' . $this->config['smilies_path'], $content); + $content = generate_text_for_display($content, $uid, $bitfield, $options); // Remove "Select all" link and mouse events $content = str_replace('<a href="#" onclick="selectCode(this); return false;">' . $this->user->lang['SELECT_ALL_CODE'] . '</a>', '', $content); @@ -152,7 +159,7 @@ class helper $content .= implode('<br />', $post_attachments); // Convert attachments' relative path to absolute path - $content = str_replace($this->phpbb_root_path . 'download/file.' . $this->phpEx, $this->get_board_url() . '/download/file.' . $this->phpEx, $content); + $content = str_replace($this->path_helper->get_web_root_path() . 'download/file.' . $this->path_helper->get_php_ext(), $this->get_board_url() . '/download/file.' . $this->path_helper->get_php_ext(), $content); } // Remove Comments from inline attachments [ia] diff --git a/phpBB/phpbb/feed/quote_helper.php b/phpBB/phpbb/feed/quote_helper.php new file mode 100644 index 0000000000..843d075028 --- /dev/null +++ b/phpBB/phpbb/feed/quote_helper.php @@ -0,0 +1,36 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\feed; + +/** + * Modified quote_helper for feeds (basically just removing all attributes) + */ +class quote_helper extends \phpbb\textformatter\s9e\quote_helper +{ + /** + * {@inheritdoc} + */ + public function inject_metadata($xml) + { + // In feeds we don't want any attributes, so delete all of them + return \s9e\TextFormatter\Utils::replaceAttributes( + $xml, + 'QUOTE', + function () + { + return []; + } + ); + } +} diff --git a/phpBB/phpbb/file_downloader.php b/phpBB/phpbb/file_downloader.php index ab9505a14c..403ca5bc83 100644 --- a/phpBB/phpbb/file_downloader.php +++ b/phpBB/phpbb/file_downloader.php @@ -42,7 +42,7 @@ class file_downloader $this->error_number = 0; $this->error_string = ''; - if ($socket = @fsockopen(($port == 443 ? 'tls://' : '') . $host, $port, $this->error_number, $this->error_string, $timeout)) + if ($socket = @fsockopen(($port == 443 ? 'ssl://' : '') . $host, $port, $this->error_number, $this->error_string, $timeout)) { @fputs($socket, "GET $directory/$filename HTTP/1.0\r\n"); @fputs($socket, "HOST: $host\r\n"); diff --git a/phpBB/phpbb/files/filespec.php b/phpBB/phpbb/files/filespec.php index f1a32ef4a8..6847bca4cb 100644 --- a/phpBB/phpbb/files/filespec.php +++ b/phpBB/phpbb/files/filespec.php @@ -121,7 +121,7 @@ class filespec */ public function set_upload_ary($upload_ary) { - if (!isset($upload_ary) || !sizeof($upload_ary)) + if (!isset($upload_ary) || !count($upload_ary)) { return $this; } @@ -403,7 +403,7 @@ class filespec */ public function move_file($destination, $overwrite = false, $skip_image_check = false, $chmod = false) { - if (sizeof($this->error)) + if (count($this->error)) { return false; } @@ -478,7 +478,7 @@ class filespec // Remove temporary filename @unlink($this->filename); - if (sizeof($this->error)) + if (count($this->error)) { return false; } diff --git a/phpBB/phpbb/files/types/form.php b/phpBB/phpbb/files/types/form.php index 832f090c47..2c3beb6e02 100644 --- a/phpBB/phpbb/files/types/form.php +++ b/phpBB/phpbb/files/types/form.php @@ -119,7 +119,7 @@ class form extends base // PHP Upload file size check $file = $this->check_upload_size($file); - if (sizeof($file->error)) + if (count($file->error)) { return $file; } diff --git a/phpBB/phpbb/files/types/local.php b/phpBB/phpbb/files/types/local.php index 7e9210b196..4dfe4f7506 100644 --- a/phpBB/phpbb/files/types/local.php +++ b/phpBB/phpbb/files/types/local.php @@ -86,7 +86,7 @@ class local extends base // PHP Upload file size check $file = $this->check_upload_size($file); - if (sizeof($file->error)) + if (count($file->error)) { return $file; } diff --git a/phpBB/phpbb/files/upload.php b/phpBB/phpbb/files/upload.php index a9bf74094d..50e15c9844 100644 --- a/phpBB/phpbb/files/upload.php +++ b/phpBB/phpbb/files/upload.php @@ -261,7 +261,7 @@ class upload * * @param filespec $file Instance of filespec class */ - public function common_checks(&$file) + public function common_checks($file) { // Filesize is too big or it's 0 if it was larger than the maxsize in the upload form if ($this->max_filesize && ($file->get('filesize') > $this->max_filesize || $file->get('filesize') == 0)) @@ -297,7 +297,7 @@ class upload * * @return bool True if extension is allowed, false if not */ - public function valid_extension(&$file) + public function valid_extension($file) { return (in_array($file->get('extension'), $this->allowed_extensions)) ? true : false; } @@ -310,7 +310,7 @@ class upload * @return bool True if dimensions are valid or no constraints set, false * if not */ - public function valid_dimensions(&$file) + public function valid_dimensions($file) { if (!$this->max_width && !$this->max_height && !$this->min_width && !$this->min_height) { @@ -350,7 +350,7 @@ class upload * * @return bool True if content is valid, false if not */ - public function valid_content(&$file) + public function valid_content($file) { return ($file->check_content($this->disallowed_content)); } diff --git a/phpBB/phpbb/filesystem/filesystem.php b/phpBB/phpbb/filesystem/filesystem.php index 2112882d1d..bfafdf5ddd 100644 --- a/phpBB/phpbb/filesystem/filesystem.php +++ b/phpBB/phpbb/filesystem/filesystem.php @@ -171,7 +171,7 @@ class filesystem implements filesystem_interface continue; } - if ($part === '..' && !empty($filtered) && $filtered[sizeof($filtered) - 1] !== '.' && $filtered[sizeof($filtered) - 1] !== '..') + if ($part === '..' && !empty($filtered) && $filtered[count($filtered) - 1] !== '.' && $filtered[count($filtered) - 1] !== '..') { array_pop($filtered); } @@ -367,7 +367,7 @@ class filesystem implements filesystem_interface $common_php_group = @filegroup(__FILE__); // And the owner and the groups PHP is running under. - $php_uid = (function_exists('posic_getuid')) ? @posix_getuid() : false; + $php_uid = (function_exists('posix_getuid')) ? @posix_getuid() : false; $php_gids = (function_exists('posix_getgroups')) ? @posix_getgroups() : false; // If we are unable to get owner/group, then do not try to set them by guessing @@ -671,7 +671,7 @@ class filesystem implements filesystem_interface else if (function_exists('debug_backtrace')) { $call_stack = debug_backtrace(0); - $this->working_directory = str_replace(DIRECTORY_SEPARATOR, '/', dirname($call_stack[sizeof($call_stack) - 1]['file'])); + $this->working_directory = str_replace(DIRECTORY_SEPARATOR, '/', dirname($call_stack[count($call_stack) - 1]['file'])); } else { @@ -683,7 +683,7 @@ class filesystem implements filesystem_interface //$dir_parts = explode(DIRECTORY_SEPARATOR, __DIR__); //$namespace_parts = explode('\\', trim(__NAMESPACE__, '\\')); - //$namespace_part_count = sizeof($namespace_parts); + //$namespace_part_count = count($namespace_parts); // Check if we still loading from root //if (array_slice($dir_parts, -$namespace_part_count) === $namespace_parts) @@ -807,7 +807,7 @@ class filesystem implements filesystem_interface array_pop($resolved); $resolved_path = false; } - else if ($path_part === '..' && !empty($resolved) && !in_array($resolved[sizeof($resolved) - 1], array('.', '..'))) + else if ($path_part === '..' && !empty($resolved) && !in_array($resolved[count($resolved) - 1], array('.', '..'))) { array_pop($resolved); $resolved_path = false; diff --git a/phpBB/phpbb/group/helper.php b/phpBB/phpbb/group/helper.php index 5befddfc53..aa3876b325 100644 --- a/phpBB/phpbb/group/helper.php +++ b/phpBB/phpbb/group/helper.php @@ -13,19 +13,74 @@ namespace phpbb\group; +use phpbb\auth\auth; +use phpbb\cache\service as cache; +use phpbb\config\config; +use phpbb\language\language; +use phpbb\event\dispatcher_interface; +use phpbb\path_helper; +use phpbb\user; + class helper { - /** @var \phpbb\language\language */ + /** @var auth */ + protected $auth; + + /** @var cache */ + protected $cache; + + /** @var config */ + protected $config; + + /** @var language */ protected $language; + /** @var dispatcher_interface */ + protected $dispatcher; + + /** @var path_helper */ + protected $path_helper; + + /** @var user */ + protected $user; + + /** @var string phpBB root path */ + protected $phpbb_root_path; + + /** @var array Return templates for a group name string */ + protected $name_strings; + /** * Constructor * - * @param \phpbb\language\language $language Language object + * @param auth $auth Authentication object + * @param cache $cache Cache service object + * @param config $config Configuration object + * @param language $language Language object + * @param dispatcher_interface $dispatcher Event dispatcher object + * @param path_helper $path_helper Path helper object + * @param user $user User object */ - public function __construct(\phpbb\language\language $language) + public function __construct(auth $auth, cache $cache, config $config, language $language, dispatcher_interface $dispatcher, path_helper $path_helper, user $user) { + $this->auth = $auth; + $this->cache = $cache; + $this->config = $config; $this->language = $language; + $this->dispatcher = $dispatcher; + $this->path_helper = $path_helper; + $this->user = $user; + + $this->phpbb_root_path = $path_helper->get_phpbb_root_path(); + + /** @html Group name spans and links for usage in the template */ + $this->name_strings = array( + 'base_url' => "{$path_helper->get_phpbb_root_path()}memberlist.{$path_helper->get_php_ext()}?mode=group&g={GROUP_ID}", + 'tpl_noprofile' => '<span class="username">{GROUP_NAME}</span>', + 'tpl_noprofile_colour' => '<span class="username-coloured" style="color: {GROUP_COLOUR};">{GROUP_NAME}</span>', + 'tpl_profile' => '<a class="username" href="{PROFILE_URL}">{GROUP_NAME}</a>', + 'tpl_profile_colour' => '<a class="username-coloured" href="{PROFILE_URL}" style="color: {GROUP_COLOUR};">{GROUP_NAME}</a>', + ); } /** @@ -37,4 +92,203 @@ class helper { return $this->language->is_set('G_' . utf8_strtoupper($group_name)) ? $this->language->lang('G_' . utf8_strtoupper($group_name)) : $group_name; } + + /** + * Get group name details for placing into templates. + * + * @html Group name spans and links + * + * @param string $mode Profile (for getting an url to the profile), + * group_name (for obtaining the group name), + * colour (for obtaining the group colour), + * full (for obtaining a coloured group name link to the group's profile), + * no_profile (the same as full but forcing no profile link) + * @param int $group_id The group id + * @param string $group_name The group name + * @param string $group_colour The group colour + * @param mixed $custom_profile_url optional parameter to specify a profile url. The group id gets appended to this url as &g={group_id} + * + * @return string A string consisting of what is wanted based on $mode. + */ + public function get_name_string($mode, $group_id, $group_name, $group_colour = '', $custom_profile_url = false) + { + $s_is_bots = ($group_name === 'BOTS'); + + // This switch makes sure we only run code required for the mode + switch ($mode) + { + case 'full': + case 'no_profile': + case 'colour': + + // Build correct group colour + $group_colour = $group_colour ? '#' . $group_colour : ''; + + // Return colour + if ($mode === 'colour') + { + $group_name_string = $group_colour; + break; + } + + // no break; + + case 'group_name': + + // Build correct group name + $group_name = $this->get_name($group_name); + + // Return group name + if ($mode === 'group_name') + { + $group_name_string = $group_name; + break; + } + + // no break; + + case 'profile': + + // Build correct profile url - only show if not anonymous and permission to view profile if registered user + // For anonymous the link leads to a login page. + if ($group_id && !$s_is_bots && ($this->user->data['user_id'] == ANONYMOUS || $this->auth->acl_get('u_viewprofile'))) + { + $profile_url = ($custom_profile_url !== false) ? $custom_profile_url . '&g=' . (int) $group_id : str_replace(array('={GROUP_ID}', '=%7BGROUP_ID%7D'), '=' . (int) $group_id, append_sid($this->name_strings['base_url'])); + } + else + { + $profile_url = ''; + } + + // Return profile + if ($mode === 'profile') + { + $group_name_string = $profile_url; + break; + } + + // no break; + } + + if (!isset($group_name_string)) + { + if (($mode === 'full' && empty($profile_url)) || $mode === 'no_profile' || $s_is_bots) + { + $group_name_string = str_replace(array('{GROUP_COLOUR}', '{GROUP_NAME}'), array($group_colour, $group_name), (!$group_colour) ? $this->name_strings['tpl_noprofile'] : $this->name_strings['tpl_noprofile_colour']); + } + else + { + $group_name_string = str_replace(array('{PROFILE_URL}', '{GROUP_COLOUR}', '{GROUP_NAME}'), array($profile_url, $group_colour, $group_name), (!$group_colour) ? $this->name_strings['tpl_profile'] : $this->name_strings['tpl_profile_colour']); + } + } + + $name_strings = $this->name_strings; + + /** + * Use this event to change the output of the group name + * + * @event core.modify_group_name_string + * @var string mode profile|group_name|colour|full|no_profile + * @var int group_id The group identifier + * @var string group_name The group name + * @var string group_colour The group colour + * @var string custom_profile_url Optional parameter to specify a profile url. + * @var string group_name_string The string that has been generated + * @var array name_strings Array of original return templates + * @since 3.2.8-RC1 + */ + $vars = array( + 'mode', + 'group_id', + 'group_name', + 'group_colour', + 'custom_profile_url', + 'group_name_string', + 'name_strings', + ); + extract($this->dispatcher->trigger_event('core.modify_group_name_string', compact($vars))); + + return $group_name_string; + } + + /** + * Get group rank title and image + * + * @html Group rank image element + * + * @param array $group_data The current stored group data + * + * @return array An associative array containing the rank title (title), + * the rank image as full img tag (img) and the rank image source (img_src) + */ + public function get_rank($group_data) + { + $group_rank_data = array( + 'title' => null, + 'img' => null, + 'img_src' => null, + ); + + /** + * Preparing a group's rank before displaying + * + * @event core.get_group_rank_before + * @var array group_data Array with group's data + * @since 3.2.8-RC1 + */ + + $vars = array('group_data'); + extract($this->dispatcher->trigger_event('core.get_group_rank_before', compact($vars))); + + if (!empty($group_data['group_rank'])) + { + // Only obtain ranks if group rank is set + $ranks = $this->cache->obtain_ranks(); + + if (isset($ranks['special'][$group_data['group_rank']])) + { + $rank = $ranks['special'][$group_data['group_rank']]; + + $group_rank_data['title'] = $rank['rank_title']; + + $group_rank_data['img_src'] = (!empty($rank['rank_image'])) ? $this->path_helper->update_web_root_path($this->phpbb_root_path . $this->config['ranks_path'] . '/' . $rank['rank_image']) : ''; + + /** @html Group rank image element for usage in the template */ + $group_rank_data['img'] = (!empty($rank['rank_image'])) ? '<img src="' . $group_rank_data['img_src'] . '" alt="' . $rank['rank_title'] . '" title="' . $rank['rank_title'] . '" />' : ''; + } + } + + /** + * Modify a group's rank before displaying + * + * @event core.get_group_rank_after + * @var array group_data Array with group's data + * @var array group_rank_data Group rank data + * @since 3.2.8-RC1 + */ + + $vars = array( + 'group_data', + 'group_rank_data', + ); + extract($this->dispatcher->trigger_event('core.get_group_rank_after', compact($vars))); + + return $group_rank_data; + } + + /** + * Get group avatar. + * Wrapper function for phpbb_get_group_avatar() + * + * @param array $group_row Row from the groups table + * @param string $alt Optional language string for alt tag within image, can be a language key or text + * @param bool $ignore_config Ignores the config-setting, to be still able to view the avatar in the UCP + * @param bool $lazy If true, will be lazy loaded (requires JS) + * + * @return string Avatar html + */ + function get_avatar($group_row, $alt = 'GROUP_AVATAR', $ignore_config = false, $lazy = false) + { + return phpbb_get_group_avatar($group_row, $alt, $ignore_config, $lazy); + } } diff --git a/phpBB/phpbb/install/helper/config.php b/phpBB/phpbb/install/helper/config.php index fad6749019..7eb0ae3b05 100644 --- a/phpBB/phpbb/install/helper/config.php +++ b/phpBB/phpbb/install/helper/config.php @@ -330,6 +330,8 @@ class config fwrite($fp, $file_content); fclose($fp); + // Enforce 0600 permission for install config + $this->filesystem->chmod([$this->install_config_file], 0600); } /** diff --git a/phpBB/phpbb/install/helper/database.php b/phpBB/phpbb/install/helper/database.php index 59b86a8ca7..fa5a10c6fc 100644 --- a/phpBB/phpbb/install/helper/database.php +++ b/phpBB/phpbb/install/helper/database.php @@ -76,7 +76,7 @@ class database 'LABEL' => 'Oracle', 'SCHEMA' => 'oracle', 'MODULE' => 'oci8', - 'DELIM' => '/', + 'DELIM' => ';', 'DRIVER' => 'phpbb\db\driver\oracle', 'AVAILABLE' => true, '2.0.x' => false, @@ -338,7 +338,7 @@ class database // Check if SQLite database is writable if ($dbms_info['SCHEMA'] === 'sqlite' - && (!$this->filesystem->is_writable($dbhost) || !$this->filesystem->is_writable(pathinfo($dbhost, PATHINFO_DIRNAME)))) + && (($this->filesystem->exists($dbhost) && !$this->filesystem->is_writable($dbhost)) || !$this->filesystem->is_writable(pathinfo($dbhost, PATHINFO_DIRNAME)))) { $errors[] = array( 'title' =>'INST_ERR_DB_NO_WRITABLE', @@ -372,7 +372,7 @@ class database $tables = array_map('strtolower', $tables); $table_intersect = array_intersect($tables, $table_ary); - if (sizeof($table_intersect)) + if (count($table_intersect)) { $errors[] = array( 'title' => 'INST_ERR_PREFIX', diff --git a/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php b/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php index bce0149890..2a608f504e 100644 --- a/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php +++ b/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php @@ -187,6 +187,7 @@ class ajax_iohandler extends iohandler_base $tpl_ary['KEY'] = $input_name; $tpl_ary['S_EXPLAIN'] = false; $tpl_ary['DISABLED'] = isset($input_options['disabled']) ? $input_options['disabled'] : false; + $tpl_ary['IS_SECONDARY'] = isset($input_options['is_secondary']) ? $input_options['is_secondary'] : false; if (isset($input_options['default'])) { @@ -203,7 +204,7 @@ class ajax_iohandler extends iohandler_base if (in_array($input_options['type'], array('select', 'radio'), true)) { - for ($i = 0, $total = sizeof($input_options['options']); $i < $total; $i++) + for ($i = 0, $total = count($input_options['options']); $i < $total; $i++) { if (isset($input_options['options'][$i]['label'])) { @@ -218,6 +219,11 @@ class ajax_iohandler extends iohandler_base $this->template->assign_block_vars($block_name, $tpl_ary); } + if (isset($form['database_update_submit']) && !$form['database_update_submit']['disabled']) + { + $this->template->assign_var('FORM_TITLE', $this->language->lang('UPDATE_CONTINUE_UPDATE_PROCESS')); + } + $this->template->assign_var('S_NOT_ONLY_BUTTON_FORM', $not_button_form); if (!$not_button_form) @@ -375,7 +381,7 @@ class ajax_iohandler extends iohandler_base */ public function set_active_stage_menu($menu_path) { - $this->nav_data['active'] = $menu_path[sizeof($menu_path) - 1]; + $this->nav_data['active'] = $menu_path[count($menu_path) - 1]; $this->send_response(); } @@ -384,7 +390,7 @@ class ajax_iohandler extends iohandler_base */ public function set_finished_stage_menu($menu_path) { - $this->nav_data['finished'][] = $menu_path[sizeof($menu_path) - 1]; + $this->nav_data['finished'][] = $menu_path[count($menu_path) - 1]; $this->send_response(); } diff --git a/phpBB/phpbb/install/module/install_data/task/add_bots.php b/phpBB/phpbb/install/module/install_data/task/add_bots.php index 1f1cecceb2..07f8e025cf 100644 --- a/phpBB/phpbb/install/module/install_data/task/add_bots.php +++ b/phpBB/phpbb/install/module/install_data/task/add_bots.php @@ -239,7 +239,7 @@ class add_bots extends \phpbb\install\task_base $this->install_config->set('add_bot_index', $i); - if ($i < sizeof($this->bot_list)) + if ($i < count($this->bot_list)) { throw new resource_limit_reached_exception(); } diff --git a/phpBB/phpbb/install/module/install_data/task/add_modules.php b/phpBB/phpbb/install/module/install_data/task/add_modules.php index d21a5be823..b64f4c31db 100644 --- a/phpBB/phpbb/install/module/install_data/task/add_modules.php +++ b/phpBB/phpbb/install/module/install_data/task/add_modules.php @@ -169,7 +169,7 @@ class add_modules extends \phpbb\install\task_base $this->db->sql_return_on_error(true); $module_classes = array('acp', 'mcp', 'ucp'); - $total = sizeof($module_classes); + $total = count($module_classes); $i = $this->config->get('module_class_index', 0); $module_classes = array_slice($module_classes, $i); diff --git a/phpBB/phpbb/install/module/install_database/task/add_config_settings.php b/phpBB/phpbb/install/module/install_database/task/add_config_settings.php index 8002e3ed97..ba439609ff 100644 --- a/phpBB/phpbb/install/module/install_database/task/add_config_settings.php +++ b/phpBB/phpbb/install/module/install_database/task/add_config_settings.php @@ -151,10 +151,6 @@ class add_config_settings extends \phpbb\install\task_base VALUES ('default_lang', '" . $this->db->sql_escape($this->install_config->get('default_lang')) . "')", 'UPDATE ' . $this->config_table . " - SET config_value = '" . $this->db->sql_escape($this->install_config->get('img_imagick')) . "' - WHERE config_name = 'img_imagick'", - - 'UPDATE ' . $this->config_table . " SET config_value = '" . $this->db->sql_escape($this->install_config->get('server_name')) . "' WHERE config_name = 'server_name'", @@ -327,7 +323,7 @@ class add_config_settings extends \phpbb\install\task_base } $i = $this->install_config->get('add_config_settings_index', 0); - $total = sizeof($sql_ary); + $total = count($sql_ary); $sql_ary = array_slice($sql_ary, $i); foreach ($sql_ary as $sql) diff --git a/phpBB/phpbb/install/module/install_database/task/add_default_data.php b/phpBB/phpbb/install/module/install_database/task/add_default_data.php index e32101a3f7..c05e5321fb 100644 --- a/phpBB/phpbb/install/module/install_database/task/add_default_data.php +++ b/phpBB/phpbb/install/module/install_database/task/add_default_data.php @@ -99,7 +99,7 @@ class add_default_data extends \phpbb\install\task_base $sql_query = $this->database_helper->split_sql_file($sql_query, $dbms_info[$dbms]['DELIM']); $i = $this->config->get('add_default_data_index', 0); - $total = sizeof($sql_query); + $total = count($sql_query); $sql_query = array_slice($sql_query, $i); foreach ($sql_query as $sql) diff --git a/phpBB/phpbb/install/module/install_database/task/add_tables.php b/phpBB/phpbb/install/module/install_database/task/add_tables.php index f344f91582..dc814f36ef 100644 --- a/phpBB/phpbb/install/module/install_database/task/add_tables.php +++ b/phpBB/phpbb/install/module/install_database/task/add_tables.php @@ -101,7 +101,7 @@ class add_tables extends \phpbb\install\task_base $db_table_schema = @file_get_contents($this->schema_file_path); $db_table_schema = json_decode($db_table_schema, true); - $total = sizeof($db_table_schema); + $total = count($db_table_schema); $i = $this->config->get('add_table_index', 0); $db_table_schema = array_slice($db_table_schema, $i); diff --git a/phpBB/phpbb/install/module/install_finish/task/install_extensions.php b/phpBB/phpbb/install/module/install_finish/task/install_extensions.php index eee13a6581..47ea156c66 100644 --- a/phpBB/phpbb/install/module/install_finish/task/install_extensions.php +++ b/phpBB/phpbb/install/module/install_finish/task/install_extensions.php @@ -157,7 +157,7 @@ class install_extensions extends \phpbb\install\task_base $this->install_config->set('install_extensions_index', $i); - if ($i < sizeof($all_available_extensions)) + if ($i < count($all_available_extensions)) { throw new resource_limit_reached_exception(); } diff --git a/phpBB/phpbb/install/module/obtain_data/task/obtain_database_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_database_data.php index dc7b060746..6ec1e612b9 100644 --- a/phpBB/phpbb/install/module/obtain_data/task/obtain_database_data.php +++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_database_data.php @@ -78,10 +78,10 @@ class obtain_database_data extends \phpbb\install\task_base implements \phpbb\in $dbms = $this->io_handler->get_input('dbms', ''); $dbhost = $this->io_handler->get_input('dbhost', '', true); $dbport = $this->io_handler->get_input('dbport', ''); - $dbuser = $this->io_handler->get_input('dbuser', ''); - $dbpasswd = $this->io_handler->get_raw_input('dbpasswd', ''); - $dbname = $this->io_handler->get_input('dbname', ''); - $table_prefix = $this->io_handler->get_input('table_prefix', ''); + $dbuser = $this->io_handler->get_input('dbuser', '', true); + $dbpasswd = $this->io_handler->get_raw_input('dbpasswd', '', true); + $dbname = $this->io_handler->get_input('dbname', '', true); + $table_prefix = $this->io_handler->get_input('table_prefix', '', true); // Check database data $user_data_vaild = $this->check_database_data($dbms, $dbhost, $dbport, $dbuser, $dbpasswd, $dbname, $table_prefix); diff --git a/phpBB/phpbb/install/module/obtain_data/task/obtain_email_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_email_data.php index e8a9c971b7..7cd0d7bf23 100644 --- a/phpBB/phpbb/install/module/obtain_data/task/obtain_email_data.php +++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_email_data.php @@ -50,11 +50,11 @@ class obtain_email_data extends \phpbb\install\task_base implements \phpbb\insta // E-mail data $email_enable = $this->io_handler->get_input('email_enable', true); $smtp_delivery = $this->io_handler->get_input('smtp_delivery', ''); - $smtp_host = $this->io_handler->get_input('smtp_host', ''); + $smtp_host = $this->io_handler->get_input('smtp_host', '', true); $smtp_port = $this->io_handler->get_input('smtp_port', ''); $smtp_auth = $this->io_handler->get_input('smtp_auth', ''); - $smtp_user = $this->io_handler->get_input('smtp_user', ''); - $smtp_passwd = $this->io_handler->get_input('smtp_pass', ''); + $smtp_user = $this->io_handler->get_input('smtp_user', '', true); + $smtp_passwd = $this->io_handler->get_input('smtp_pass', '', true); $auth_methods = array('PLAIN', 'LOGIN', 'CRAM-MD5', 'DIGEST-MD5', 'POP-BEFORE-SMTP'); diff --git a/phpBB/phpbb/install/module/obtain_data/task/obtain_imagick_path.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_imagick_path.php deleted file mode 100644 index 377d96ed1a..0000000000 --- a/phpBB/phpbb/install/module/obtain_data/task/obtain_imagick_path.php +++ /dev/null @@ -1,89 +0,0 @@ -<?php -/** - * - * This file is part of the phpBB Forum Software package. - * - * @copyright (c) phpBB Limited <https://www.phpbb.com> - * @license GNU General Public License, version 2 (GPL-2.0) - * - * For full copyright and license information, please see - * the docs/CREDITS.txt file. - * - */ - -namespace phpbb\install\module\obtain_data\task; - -class obtain_imagick_path extends \phpbb\install\task_base implements \phpbb\install\task_interface -{ - /** - * @var \phpbb\install\helper\config - */ - protected $config; - - /** - * Constructor - * - * @param \phpbb\install\helper\config $config Installer's config - */ - public function __construct(\phpbb\install\helper\config $config) - { - $this->config = $config; - - parent::__construct(true); - } - - /** - * {@inheritdoc} - */ - public function run() - { - // Can we find ImageMagick anywhere on the system? - $exe = (DIRECTORY_SEPARATOR == '\\') ? '.exe' : ''; - - $magic_home = getenv('MAGICK_HOME'); - $img_imagick = ''; - if (empty($magic_home)) - { - $locations = array('C:/WINDOWS/', 'C:/WINNT/', 'C:/WINDOWS/SYSTEM/', 'C:/WINNT/SYSTEM/', 'C:/WINDOWS/SYSTEM32/', 'C:/WINNT/SYSTEM32/', '/usr/bin/', '/usr/sbin/', '/usr/local/bin/', '/usr/local/sbin/', '/opt/', '/usr/imagemagick/', '/usr/bin/imagemagick/'); - $path_locations = str_replace('\\', '/', (explode(($exe) ? ';' : ':', getenv('PATH')))); - - $locations = array_merge($path_locations, $locations); - foreach ($locations as $location) - { - // The path might not end properly, fudge it - if (substr($location, -1, 1) !== '/') - { - $location .= '/'; - } - - if (@file_exists($location) && @is_readable($location . 'mogrify' . $exe) && @filesize($location . 'mogrify' . $exe) > 3000) - { - $img_imagick = str_replace('\\', '/', $location); - continue; - } - } - } - else - { - $img_imagick = str_replace('\\', '/', $magic_home); - } - - $this->config->set('img_imagick', $img_imagick); - } - - /** - * {@inheritdoc} - */ - static public function get_step_count() - { - return 0; - } - - /** - * {@inheritdoc} - */ - public function get_task_lang_name() - { - return ''; - } -} diff --git a/phpBB/phpbb/install/module/obtain_data/task/obtain_server_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_server_data.php index 1ef70eae08..5096ce284e 100644 --- a/phpBB/phpbb/install/module/obtain_data/task/obtain_server_data.php +++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_server_data.php @@ -79,9 +79,9 @@ class obtain_server_data extends \phpbb\install\task_base implements \phpbb\inst $cookie_secure = $this->io_handler->get_input('cookie_secure', $cookie_secure); $server_protocol = $this->io_handler->get_input('server_protocol', $server_protocol); $force_server_vars = $this->io_handler->get_input('force_server_vars', 0); - $server_name = $this->io_handler->get_input('server_name', $server_name); + $server_name = $this->io_handler->get_input('server_name', $server_name, true); $server_port = $this->io_handler->get_input('server_port', $server_port); - $script_path = $this->io_handler->get_input('script_path', $script_path); + $script_path = $this->io_handler->get_input('script_path', $script_path, true); // Clean up script path if ($script_path !== '/') diff --git a/phpBB/phpbb/install/module/obtain_data/task/obtain_update_ftp_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_update_ftp_data.php index f31472fc58..3c17576c13 100644 --- a/phpBB/phpbb/install/module/obtain_data/task/obtain_update_ftp_data.php +++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_update_ftp_data.php @@ -85,10 +85,10 @@ class obtain_update_ftp_data extends task_base $method = $methods[0]; } - $ftp_host = $this->iohandler->get_input('ftp_host', ''); - $ftp_user = $this->iohandler->get_input('ftp_user', ''); - $ftp_pass = htmlspecialchars_decode($this->iohandler->get_input('ftp_pass', '')); - $ftp_path = $this->iohandler->get_input('ftp_path', ''); + $ftp_host = $this->iohandler->get_input('ftp_host', '', true); + $ftp_user = $this->iohandler->get_input('ftp_user', '', true); + $ftp_pass = htmlspecialchars_decode($this->iohandler->get_input('ftp_pass', '', true)); + $ftp_path = $this->iohandler->get_input('ftp_path', '', true); $ftp_port = $this->iohandler->get_input('ftp_port', 21); $ftp_time = $this->iohandler->get_input('ftp_timeout', 10); diff --git a/phpBB/phpbb/install/module/requirements/task/check_update.php b/phpBB/phpbb/install/module/requirements/task/check_update.php index cd66ffc8f9..4eb2c6d75e 100644 --- a/phpBB/phpbb/install/module/requirements/task/check_update.php +++ b/phpBB/phpbb/install/module/requirements/task/check_update.php @@ -122,8 +122,11 @@ class check_update extends task_base // Check for a valid update directory if (!$this->filesystem->exists($update_files) || !$this->filesystem->is_readable($update_files)) { - $this->iohandler->add_warning_message('UPDATE_FILES_NOT_FOUND'); - $this->set_test_passed(false); + if ($this->iohandler->get_input('update_type', 'all') === 'all') + { + $this->iohandler->add_warning_message('UPDATE_FILES_NOT_FOUND'); + $this->set_test_passed(false); + } // If there are no update files, we can't check the version etc // However, we can let the users run migrations if they really want to... diff --git a/phpBB/phpbb/install/module/update_database/task/update_extensions.php b/phpBB/phpbb/install/module/update_database/task/update_extensions.php index b66847b243..0195b9c661 100644 --- a/phpBB/phpbb/install/module/update_database/task/update_extensions.php +++ b/phpBB/phpbb/install/module/update_database/task/update_extensions.php @@ -206,7 +206,7 @@ class update_extensions extends task_base $this->install_config->set('update_extensions_index', $i); - if ($i < sizeof($all_available_extensions)) + if ($i < count($all_available_extensions)) { throw new resource_limit_reached_exception(); } diff --git a/phpBB/phpbb/install/module/update_filesystem/task/diff_files.php b/phpBB/phpbb/install/module/update_filesystem/task/diff_files.php index 1792a3b723..2f6048b4fd 100644 --- a/phpBB/phpbb/install/module/update_filesystem/task/diff_files.php +++ b/phpBB/phpbb/install/module/update_filesystem/task/diff_files.php @@ -103,8 +103,8 @@ class diff_files extends task_base $old_path = $this->update_helper->get_path_to_old_update_files(); $new_path = $this->update_helper->get_path_to_new_update_files(); - $files_to_diff = $this->installer_config->get('update_files', array()); - $files_to_diff = $files_to_diff['update_with_diff']; + $update_files = $this->installer_config->get('update_files', array()); + $files_to_diff = $update_files['update_with_diff']; // Set progress bar $this->iohandler->set_task_count(count($files_to_diff), true); @@ -145,7 +145,7 @@ class diff_files extends task_base { $file_contents[] = file_get_contents($file_to_diff); - if ($file_contents[sizeof($file_contents) - 1] === false) + if ($file_contents[count($file_contents) - 1] === false) { $this->iohandler->add_error_message(array('FILE_DIFFER_ERROR_FILE_CANNOT_BE_READ', $files_to_diff)); unset($file_contents); @@ -154,7 +154,6 @@ class diff_files extends task_base } $diff = new \diff3($file_contents[0], $file_contents[1], $file_contents[2]); - unset($file_contents); // Handle conflicts if ($diff->get_num_conflicts() !== 0) @@ -162,12 +161,20 @@ class diff_files extends task_base $merge_conflicts[] = $filename; } - // Save merged output - $this->cache->put( - '_file_' . md5($filename), - base64_encode(implode("\n", $diff->merged_output())) - ); + if ($diff->merged_output() !== $file_contents[1]) + { + // Save merged output + $this->cache->put( + '_file_' . md5($filename), + base64_encode(implode("\n", $diff->merged_output())) + ); + } + else + { + unset($update_files['update_with_diff'][$key]); + } + unset($file_contents); unset($diff); } else @@ -199,6 +206,16 @@ class diff_files extends task_base $this->installer_config->set('merge_conflict_list', $merge_conflicts); $this->installer_config->set('file_diff_update_count', $progress_count); + foreach ($update_files as $type => $files) + { + if (empty($files)) + { + unset($update_files[$type]); + } + } + + $this->installer_config->set('update_files', $update_files); + // Request refresh throw new resource_limit_reached_exception(); } @@ -206,6 +223,16 @@ class diff_files extends task_base $this->iohandler->finish_progress('ALL_FILES_DIFFED'); $this->installer_config->set('merge_conflict_list', $merge_conflicts); + + foreach ($update_files as $type => $files) + { + if (empty($files)) + { + unset($update_files[$type]); + } + } + + $this->installer_config->set('update_files', $update_files); } /** diff --git a/phpBB/phpbb/install/module/update_filesystem/task/download_updated_files.php b/phpBB/phpbb/install/module/update_filesystem/task/download_updated_files.php index 21aa93b7ea..4d7f0e0cdf 100644 --- a/phpBB/phpbb/install/module/update_filesystem/task/download_updated_files.php +++ b/phpBB/phpbb/install/module/update_filesystem/task/download_updated_files.php @@ -86,7 +86,8 @@ class download_updated_files extends task_base { $file_update_info = $this->installer_config->get('update_files', array()); - if (count($file_update_info) > 0) + // Display download box only if the archive won't be empty + if (!empty($file_update_info) && !(isset($file_update_info['delete']) && count($file_update_info) == 1)) { // Render download box $this->iohandler->add_download_link( @@ -99,13 +100,14 @@ class download_updated_files extends task_base // Add form to continue update $this->iohandler->add_user_form_group('UPDATE_CONTINUE_UPDATE_PROCESS', array( 'update_recheck_files_submit' => array( - 'label' => 'UPDATE_RECHECK_UPDATE_FILES', - 'type' => 'submit', + 'label' => 'UPDATE_RECHECK_UPDATE_FILES', + 'type' => 'submit', + 'is_secondary' => empty($file_update_info), ), 'database_update_submit' => array( 'label' => 'UPDATE_CONTINUE_UPDATE_PROCESS', 'type' => 'submit', - 'disabled' => count($file_update_info) > 0, + 'disabled' => !empty($file_update_info), ), )); diff --git a/phpBB/phpbb/language/language.php b/phpBB/phpbb/language/language.php index 42429c2c07..51e6d0b185 100644 --- a/phpBB/phpbb/language/language.php +++ b/phpBB/phpbb/language/language.php @@ -312,7 +312,7 @@ class language // Replace key with language entry and simply pass along... return vsprintf($lang, $args); } - else if (sizeof($lang) == 0) + else if (count($lang) == 0) { // If the language entry is an empty array, we just return the language key return $key; @@ -322,7 +322,7 @@ class language $key_found = false; // We now get the first number passed and will select the key based upon this number - for ($i = 0, $num_args = sizeof($args); $i < $num_args; $i++) + for ($i = 0, $num_args = count($args); $i < $num_args; $i++) { if (is_int($args[$i]) || is_float($args[$i])) { diff --git a/phpBB/phpbb/language/language_file_loader.php b/phpBB/phpbb/language/language_file_loader.php index 359202fd63..b6816afd16 100644 --- a/phpBB/phpbb/language/language_file_loader.php +++ b/phpBB/phpbb/language/language_file_loader.php @@ -127,7 +127,7 @@ class language_file_loader // the first directory from the path (that should be the language directory) $path_diff_parts = explode('/', $path_diff); - if (sizeof($path_diff_parts) > 1) + if (count($path_diff_parts) > 1) { array_shift($path_diff_parts); $component = implode('/', $path_diff_parts) . '/'; diff --git a/phpBB/phpbb/log/log.php b/phpBB/phpbb/log/log.php index 5aad7ee326..5333fe2bdf 100644 --- a/phpBB/phpbb/log/log.php +++ b/phpBB/phpbb/log/log.php @@ -391,7 +391,7 @@ class log implements \phpbb\log\log_interface { $sql_where .= ' AND '; - if (is_array($field_value) && sizeof($field_value) == 2 && !is_array($field_value[1])) + if (is_array($field_value) && count($field_value) == 2 && !is_array($field_value[1])) { $sql_where .= $field . ' ' . $field_value[0] . ' ' . $field_value[1]; } @@ -689,9 +689,9 @@ class log implements \phpbb\log\log_interface } } - if (($num_args - sizeof($log_data_ary)) > 0) + if (($num_args - count($log_data_ary)) > 0) { - $log_data_ary = array_merge($log_data_ary, array_fill(0, $num_args - sizeof($log_data_ary), '')); + $log_data_ary = array_merge($log_data_ary, array_fill(0, $num_args - count($log_data_ary), '')); } $lang_arguments = array_merge(array($log[$i]['action']), $log_data_ary); @@ -740,7 +740,7 @@ class log implements \phpbb\log\log_interface $vars = array('log', 'topic_id_list', 'reportee_id_list'); extract($this->dispatcher->trigger_event('core.get_logs_get_additional_data', compact($vars))); - if (sizeof($topic_id_list)) + if (count($topic_id_list)) { $topic_auth = $this->get_topic_auth($topic_id_list); @@ -752,7 +752,7 @@ class log implements \phpbb\log\log_interface } } - if (sizeof($reportee_id_list)) + if (count($reportee_id_list)) { $reportee_data_list = $this->get_reportee_data($reportee_id_list); @@ -838,7 +838,7 @@ class log implements \phpbb\log\log_interface $keywords_pattern = array(); // Build pattern and keywords... - for ($i = 0, $num_keywords = sizeof($keywords); $i < $num_keywords; $i++) + for ($i = 0, $num_keywords = count($keywords); $i < $num_keywords; $i++) { $keywords_pattern[] = preg_quote($keywords[$i], '#'); $keywords[$i] = $this->db->sql_like_expression($this->db->get_any_char() . $keywords[$i] . $this->db->get_any_char()); @@ -933,6 +933,20 @@ class log implements \phpbb\log\log_interface $forum_auth['f_read'][$row['topic_id']] = $row['forum_id']; } + /** + * Allow modifying SQL query after topic data is retrieved (inside loop). + * + * @event core.phpbb_log_get_topic_auth_sql_after + * @var array forum_auth Forum permissions + * @var array row One row of data from SQL query + * @since 3.2.2-RC1 + */ + $vars = array( + 'forum_auth', + 'row', + ); + extract($this->dispatcher->trigger_event('core.phpbb_log_get_topic_auth_sql_after', compact($vars))); + if ($this->auth->acl_gets('a_', 'm_', $row['forum_id'])) { $forum_auth['m_'][$row['topic_id']] = $row['forum_id']; diff --git a/phpBB/phpbb/message/admin_form.php b/phpBB/phpbb/message/admin_form.php index 96b8d3499e..ae1c1d8614 100644 --- a/phpBB/phpbb/message/admin_form.php +++ b/phpBB/phpbb/message/admin_form.php @@ -22,6 +22,9 @@ class admin_form extends form /** @var \phpbb\config\db_text */ protected $config_text; + /** @var \phpbb\event\dispatcher_interface */ + protected $dispatcher; + /** @var string */ protected $subject; /** @var string */ @@ -37,13 +40,15 @@ class admin_form extends form * @param \phpbb\config\db_text $config_text * @param \phpbb\db\driver\driver_interface $db * @param \phpbb\user $user + * @param \phpbb\event\dispatcher_interface $dispatcher * @param string $phpbb_root_path * @param string $phpEx */ - public function __construct(\phpbb\auth\auth $auth, \phpbb\config\config $config, \phpbb\config\db_text $config_text, \phpbb\db\driver\driver_interface $db, \phpbb\user $user, $phpbb_root_path, $phpEx) + public function __construct(\phpbb\auth\auth $auth, \phpbb\config\config $config, \phpbb\config\db_text $config_text, \phpbb\db\driver\driver_interface $db, \phpbb\user $user, \phpbb\event\dispatcher_interface $dispatcher, $phpbb_root_path, $phpEx) { parent::__construct($auth, $config, $db, $user, $phpbb_root_path, $phpEx); $this->config_text = $config_text; + $this->dispatcher = $dispatcher; } /** @@ -91,6 +96,29 @@ class admin_form extends form $this->errors[] = $this->user->lang['EMPTY_MESSAGE_EMAIL']; } + $subject = $this->subject; + $body = $this->body; + $errors = $this->errors; + + /** + * You can use this event to modify subject and/or body and add new errors. + * + * @event core.message_admin_form_submit_before + * @var string subject Message subject + * @var string body Message body + * @var array errors Form errors + * @since 3.2.6-RC1 + */ + $vars = [ + 'subject', + 'body', + 'errors', + ]; + extract($this->dispatcher->trigger_event('core.message_admin_form_submit_before', compact($vars))); + $this->subject = $subject; + $this->body = $body; + $this->errors = $errors; + if ($this->user->data['is_registered']) { $this->message->set_sender_from_user($this->user); diff --git a/phpBB/phpbb/message/form.php b/phpBB/phpbb/message/form.php index 21d4de0b4d..63bada91ff 100644 --- a/phpBB/phpbb/message/form.php +++ b/phpBB/phpbb/message/form.php @@ -139,7 +139,7 @@ abstract class form $this->errors[] = 'FORM_INVALID'; } - if (!sizeof($this->errors)) + if (!count($this->errors)) { $sql = 'UPDATE ' . USERS_TABLE . ' SET user_emailtime = ' . time() . ' @@ -169,7 +169,7 @@ abstract class form add_form_key('memberlist_email'); $template->assign_vars(array( - 'ERROR_MESSAGE' => (sizeof($this->errors)) ? implode('<br />', $this->errors) : '', + 'ERROR_MESSAGE' => (count($this->errors)) ? implode('<br />', $this->errors) : '', )); } } diff --git a/phpBB/phpbb/message/message.php b/phpBB/phpbb/message/message.php index 5fd24b542e..fa701d1c77 100644 --- a/phpBB/phpbb/message/message.php +++ b/phpBB/phpbb/message/message.php @@ -209,7 +209,7 @@ class message */ public function cc_sender() { - if (!sizeof($this->recipients)) + if (!count($this->recipients)) { trigger_error('No email recipients specified'); } @@ -238,7 +238,7 @@ class message */ public function send(\messenger $messenger, $contact) { - if (!sizeof($this->recipients)) + if (!count($this->recipients)) { return; } @@ -271,7 +271,7 @@ class message 'MESSAGE' => htmlspecialchars_decode($this->body)) ); - if (sizeof($this->template_vars)) + if (count($this->template_vars)) { $messenger->assign_vars($this->template_vars); } diff --git a/phpBB/phpbb/module/module_manager.php b/phpBB/phpbb/module/module_manager.php index 67bac5b33e..00df33f62f 100644 --- a/phpBB/phpbb/module/module_manager.php +++ b/phpBB/phpbb/module/module_manager.php @@ -311,7 +311,7 @@ class module_manager // we're turning a category into a module $branch = $this->get_module_branch($module_data['module_id'], $module_data['module_class'], 'children', false); - if (sizeof($branch)) + if (count($branch)) { throw new module_not_found_exception('NO_CATEGORY_TO_MODULE'); } @@ -353,10 +353,10 @@ class module_manager } $from_data = $moved_modules[0]; - $diff = sizeof($moved_modules) * 2; + $diff = count($moved_modules) * 2; $moved_ids = array(); - for ($i = 0, $size = sizeof($moved_modules); $i < $size; ++$i) + for ($i = 0, $size = count($moved_modules); $i < $size; ++$i) { $moved_ids[] = $moved_modules[$i]['module_id']; } @@ -443,7 +443,7 @@ class module_manager $branch = $this->get_module_branch($module_id, $module_class, 'children', false); - if (sizeof($branch)) + if (count($branch)) { throw new module_exception('CANNOT_REMOVE_MODULE'); } @@ -506,7 +506,7 @@ class module_manager } $this->db->sql_freeresult($result); - if (!sizeof($target)) + if (!count($target)) { // The module is already on top or bottom throw new module_not_found_exception(); diff --git a/phpBB/phpbb/notification/manager.php b/phpBB/phpbb/notification/manager.php index 1cd7e5bc9a..52c650df5d 100644 --- a/phpBB/phpbb/notification/manager.php +++ b/phpBB/phpbb/notification/manager.php @@ -339,7 +339,7 @@ class manager } } - if (!sizeof($notify_users)) + if (!count($notify_users)) { return; } @@ -899,32 +899,19 @@ class manager */ public function get_notification_type_id($notification_type_name) { - $notification_type_ids = $this->cache->get('notification_type_ids'); - - $this->db->sql_transaction('begin'); - - if ($notification_type_ids === false) + $sql = 'SELECT notification_type_id, notification_type_name + FROM ' . $this->notification_types_table; + $result = $this->db->sql_query($sql, 604800); // cache for one week + while ($row = $this->db->sql_fetchrow($result)) { - $notification_type_ids = array(); - - $sql = 'SELECT notification_type_id, notification_type_name - FROM ' . $this->notification_types_table; - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - $notification_type_ids[$row['notification_type_name']] = (int) $row['notification_type_id']; - } - $this->db->sql_freeresult($result); - - $this->cache->put('notification_type_ids', $notification_type_ids); + $notification_type_ids[$row['notification_type_name']] = (int) $row['notification_type_id']; } + $this->db->sql_freeresult($result); if (!isset($notification_type_ids[$notification_type_name])) { if (!isset($this->notification_types[$notification_type_name]) && !isset($this->notification_types['notification.type.' . $notification_type_name])) { - $this->db->sql_transaction('rollback'); - throw new \phpbb\notification\exception('NOTIFICATION_TYPE_NOT_EXIST', array($notification_type_name)); } @@ -934,13 +921,13 @@ class manager )); $this->db->sql_query($sql); + // expose new notification type ID for this request $notification_type_ids[$notification_type_name] = (int) $this->db->sql_nextid(); - $this->cache->put('notification_type_ids', $notification_type_ids); + // destroy cache, we have a new addition which we have to to load next time + $this->cache->destroy('sql', $this->notification_types_table); } - $this->db->sql_transaction('commit'); - return $notification_type_ids[$notification_type_name]; } diff --git a/phpBB/phpbb/notification/method/board.php b/phpBB/phpbb/notification/method/board.php index 931b252daa..faa53576e0 100644 --- a/phpBB/phpbb/notification/method/board.php +++ b/phpBB/phpbb/notification/method/board.php @@ -394,6 +394,6 @@ class board extends \phpbb\notification\method\base WHERE notification_type_id = ' . (int) $notification_type_id; $this->db->sql_query($sql); - $this->cache->destroy('notification_type_ids'); + $this->cache->destroy('sql', $this->notification_types_table); } } diff --git a/phpBB/phpbb/notification/method/email.php b/phpBB/phpbb/notification/method/email.php index 56dd1e9367..6376d13dc7 100644 --- a/phpBB/phpbb/notification/method/email.php +++ b/phpBB/phpbb/notification/method/email.php @@ -65,7 +65,7 @@ class email extends \phpbb\notification\method\messenger_base */ public function is_available(type_interface $notification_type = null) { - return parent::is_available($notification_type) && $this->config['email_enable'] && $this->user->data['user_email']; + return parent::is_available($notification_type) && $this->config['email_enable'] && !empty($this->user->data['user_email']); } /** diff --git a/phpBB/phpbb/notification/method/messenger_base.php b/phpBB/phpbb/notification/method/messenger_base.php index 32e79aa936..f82017b70e 100644 --- a/phpBB/phpbb/notification/method/messenger_base.php +++ b/phpBB/phpbb/notification/method/messenger_base.php @@ -87,7 +87,7 @@ abstract class messenger_base extends \phpbb\notification\method\base $banned_users = phpbb_get_banned_user_ids($user_ids); // Load all the users we need - $this->user_loader->load_users($user_ids); + $this->user_loader->load_users(array_diff($user_ids, $banned_users), array(USER_IGNORE)); // Load the messenger if (!class_exists('messenger')) @@ -107,7 +107,7 @@ abstract class messenger_base extends \phpbb\notification\method\base $user = $this->user_loader->get_user($notification->user_id); - if ($user['user_type'] == USER_IGNORE || ($user['user_type'] == USER_INACTIVE && $user['user_inactive_reason'] == INACTIVE_MANUAL) || in_array($notification->user_id, $banned_users)) + if ($user['user_type'] == USER_INACTIVE && $user['user_inactive_reason'] == INACTIVE_MANUAL) { continue; } diff --git a/phpBB/phpbb/notification/type/admin_activate_user.php b/phpBB/phpbb/notification/type/admin_activate_user.php index 9f2ae857ef..78c10ac36a 100644 --- a/phpBB/phpbb/notification/type/admin_activate_user.php +++ b/phpBB/phpbb/notification/type/admin_activate_user.php @@ -175,7 +175,7 @@ class admin_activate_user extends \phpbb\notification\type\base /** * {@inheritdoc} */ - public function create_insert_array($user, $pre_create_data) + public function create_insert_array($user, $pre_create_data = array()) { $this->set_data('user_actkey', $user['user_actkey']); $this->notification_time = $user['user_regdate']; diff --git a/phpBB/phpbb/notification/type/pm.php b/phpBB/phpbb/notification/type/pm.php index 8fb9172911..c51586afb9 100644 --- a/phpBB/phpbb/notification/type/pm.php +++ b/phpBB/phpbb/notification/type/pm.php @@ -99,7 +99,7 @@ class pm extends \phpbb\notification\type\base 'ignore_users' => array(), ), $options); - if (!sizeof($pm['recipients'])) + if (!count($pm['recipients'])) { return array(); } diff --git a/phpBB/phpbb/notification/type/post.php b/phpBB/phpbb/notification/type/post.php index 03221e7c7a..254f4c07b3 100644 --- a/phpBB/phpbb/notification/type/post.php +++ b/phpBB/phpbb/notification/type/post.php @@ -202,9 +202,9 @@ class post extends \phpbb\notification\type\base 'username' => $this->get_data('post_username'), )), $responders); - $responders_cnt = sizeof($responders); + $responders_cnt = count($responders); $responders = $this->trim_user_ary($responders); - $trimmed_responders_cnt = $responders_cnt - sizeof($responders); + $trimmed_responders_cnt = $responders_cnt - count($responders); foreach ($responders as $responder) { @@ -337,7 +337,7 @@ class post extends \phpbb\notification\type\base */ public function trim_user_ary($users) { - if (sizeof($users) > 4) + if (count($users) > 4) { array_splice($users, 3); } @@ -357,7 +357,7 @@ class post extends \phpbb\notification\type\base */ public function pre_create_insert_array($post, $notify_users) { - if (!sizeof($notify_users) || !$this->inherit_read_status) + if (!count($notify_users) || !$this->inherit_read_status) { return array(); } @@ -426,7 +426,7 @@ class post extends \phpbb\notification\type\base // Do not add more than 25 responders, // we trim the username list to "a, b, c and x others" anyway // so there is no use to add all of them anyway. - if (sizeof($responders) > 25) + if (count($responders) > 25) { return array(); } diff --git a/phpBB/phpbb/notification/type/report_pm.php b/phpBB/phpbb/notification/type/report_pm.php index 7e53ffb3ca..444f98270d 100644 --- a/phpBB/phpbb/notification/type/report_pm.php +++ b/phpBB/phpbb/notification/type/report_pm.php @@ -142,13 +142,16 @@ class report_pm extends \phpbb\notification\type\pm */ public function get_email_template_variables() { - $user_data = $this->user_loader->get_user($this->get_data('reporter_id')); + $user_data = $this->user_loader->get_user($this->get_data('from_user_id')); return array( 'AUTHOR_NAME' => htmlspecialchars_decode($user_data['username']), 'SUBJECT' => htmlspecialchars_decode(censor_text($this->get_data('message_subject'))), - 'U_VIEW_REPORT' => generate_board_url() . "mcp.{$this->php_ext}?r={$this->item_parent_id}&i=pm_reports&mode=pm_report_details", + /** @deprecated 3.2.6-RC1 (to be removed in 4.0.0) use {SUBJECT} instead in report_pm.txt */ + 'TOPIC_TITLE' => htmlspecialchars_decode(censor_text($this->get_data('message_subject'))), + + 'U_VIEW_REPORT' => generate_board_url() . "/mcp.{$this->php_ext}?r={$this->item_parent_id}&i=pm_reports&mode=pm_report_details", ); } @@ -236,8 +239,10 @@ class report_pm extends \phpbb\notification\type\pm */ public function users_to_query() { - return array($this->get_data('reporter_id')); - } + return array( + $this->get_data('from_user_id'), + $this->get_data('reporter_id'), + ); } /** * {@inheritdoc} diff --git a/phpBB/phpbb/notification/type/topic.php b/phpBB/phpbb/notification/type/topic.php index 671c34fe96..5c42afa8c8 100644 --- a/phpBB/phpbb/notification/type/topic.php +++ b/phpBB/phpbb/notification/type/topic.php @@ -261,7 +261,7 @@ class topic extends \phpbb\notification\type\base */ public function pre_create_insert_array($post, $notify_users) { - if (!sizeof($notify_users) || !$this->inherit_read_status) + if (!count($notify_users) || !$this->inherit_read_status) { return array(); } diff --git a/phpBB/phpbb/pagination.php b/phpBB/phpbb/pagination.php index a5a95b096d..a7086f6691 100644 --- a/phpBB/phpbb/pagination.php +++ b/phpBB/phpbb/pagination.php @@ -46,7 +46,7 @@ class pagination /** * Generate a pagination link based on the url and the page information * - * @param string $base_url is url prepended to all links generated within the function + * @param string|array $base_url is url prepended to all links generated within the function * If you use page numbers inside your controller route, base_url should contains a placeholder (%d) * for the page. Also be sure to specify the pagination path information into the start_name argument * @param string $on_page is the page for which we want to generate the link @@ -69,7 +69,7 @@ class pagination * set $generate_page_link_override to the new URL value * * @event core.pagination_generate_page_link - * @var string base_url is url prepended to all links generated within the function + * @var string|array base_url is url prepended to all links generated within the function * If you use page numbers inside your controller route, base_url should contains a placeholder (%d) * for the page. Also be sure to specify the pagination path information into the start_name argument * @var string on_page is the page for which we want to generate the link @@ -120,7 +120,7 @@ class pagination * Generate template rendered pagination * Allows full control of rendering of pagination with the template * - * @param string $base_url is url prepended to all links generated within the function + * @param string|array $base_url is url prepended to all links generated within the function * If you use page numbers inside your controller route, base_url should contains a placeholder (%d) * for the page. Also be sure to specify the pagination path information into the start_name argument * @param string $block_var_name is the name assigned to the pagination data block within the template (example: <!-- BEGIN pagination -->) @@ -132,10 +132,15 @@ class pagination * @param int $start the item which should be considered currently active, used to determine the page we're on * @param bool $reverse_count determines whether we weight display of the list towards the start (false) or end (true) of the list * @param bool $ignore_on_page decides whether we enable an active (unlinked) item, used primarily for embedded lists - * @return null + * @return void */ public function generate_template_pagination($base_url, $block_var_name, $start_name, $num_items, $per_page, $start = 1, $reverse_count = false, $ignore_on_page = false) { + if (empty($base_url)) + { + return; + } + $total_pages = ceil($num_items / $per_page); $on_page = $this->get_on_page($per_page, $start); $u_previous_page = $u_next_page = ''; diff --git a/phpBB/phpbb/permissions.php b/phpBB/phpbb/permissions.php index c9181e6202..7697884b6a 100644 --- a/phpBB/phpbb/permissions.php +++ b/phpBB/phpbb/permissions.php @@ -260,6 +260,7 @@ class permissions // Forum Permissions 'f_list' => array('lang' => 'ACL_F_LIST', 'cat' => 'actions'), + 'f_list_topics' => array('lang' => 'ACL_F_LIST_TOPICS', 'cat' => 'actions'), 'f_read' => array('lang' => 'ACL_F_READ', 'cat' => 'actions'), 'f_search' => array('lang' => 'ACL_F_SEARCH', 'cat' => 'actions'), 'f_subscribe' => array('lang' => 'ACL_F_SUBSCRIBE', 'cat' => 'actions'), diff --git a/phpBB/phpbb/profilefields/manager.php b/phpBB/phpbb/profilefields/manager.php index ea4b24af56..35b18ddf07 100644 --- a/phpBB/phpbb/profilefields/manager.php +++ b/phpBB/phpbb/profilefields/manager.php @@ -230,7 +230,7 @@ class manager */ public function update_profile_field_data($user_id, $cp_data) { - if (!sizeof($cp_data)) + if (!count($cp_data)) { return; } @@ -258,7 +258,7 @@ class manager */ public function generate_profile_fields_template_headlines($restrict_option = '') { - if (!sizeof($this->profile_cache)) + if (!count($this->profile_cache)) { $this->build_cache(); } @@ -318,12 +318,12 @@ class manager $user_ids = array($user_ids); } - if (!sizeof($this->profile_cache)) + if (!count($this->profile_cache)) { $this->build_cache(); } - if (!sizeof($user_ids)) + if (!count($user_ids)) { return array(); } @@ -486,7 +486,7 @@ class manager $sql = 'SELECT f.field_type, f.field_ident, f.field_default_value, l.lang_default_value FROM ' . $this->fields_language_table . ' l, ' . $this->fields_table . ' f WHERE l.lang_id = ' . $this->user->get_iso_lang_id() . ' - ' . ((sizeof($sql_not_in)) ? ' AND ' . $this->db->sql_in_set('f.field_ident', $sql_not_in, true) : '') . ' + ' . ((count($sql_not_in)) ? ' AND ' . $this->db->sql_in_set('f.field_ident', $sql_not_in, true) : '') . ' AND l.field_id = f.field_id'; $result = $this->db->sql_query($sql); diff --git a/phpBB/phpbb/profilefields/type/type_bool.php b/phpBB/phpbb/profilefields/type/type_bool.php index f6f3f17a6c..9c09e27bc4 100644 --- a/phpBB/phpbb/profilefields/type/type_bool.php +++ b/phpBB/phpbb/profilefields/type/type_bool.php @@ -398,7 +398,7 @@ class type_bool extends type_base public function display_options(&$template_vars, &$field_data) { // Initialize these array elements if we are creating a new field - if (!sizeof($field_data['lang_options'])) + if (!count($field_data['lang_options'])) { // No options have been defined for a boolean field. $field_data['lang_options'][0] = ''; diff --git a/phpBB/phpbb/profilefields/type/type_dropdown.php b/phpBB/phpbb/profilefields/type/type_dropdown.php index 17ae89e1b2..d54404bbb4 100644 --- a/phpBB/phpbb/profilefields/type/type_dropdown.php +++ b/phpBB/phpbb/profilefields/type/type_dropdown.php @@ -282,7 +282,7 @@ class type_dropdown extends type_base */ public function validate_options_on_submit($error, $field_data) { - if (!sizeof($field_data['lang_options'])) + if (!count($field_data['lang_options'])) { $error[] = $this->user->lang['NO_FIELD_ENTRIES']; } @@ -298,7 +298,7 @@ class type_dropdown extends type_base if ($step == 2 && $key == 'field_maxlen') { // Get the number of options if this key is 'field_maxlen' - return sizeof(explode("\n", $this->request->variable('lang_options', '', true))); + return count(explode("\n", $this->request->variable('lang_options', '', true))); } return parent::get_excluded_options($key, $action, $current_value, $field_data, $step); @@ -310,7 +310,7 @@ class type_dropdown extends type_base public function display_options(&$template_vars, &$field_data) { // Initialize these array elements if we are creating a new field - if (!sizeof($field_data['lang_options'])) + if (!count($field_data['lang_options'])) { // No options have been defined for the dropdown menu $field_data['lang_options'] = array(); diff --git a/phpBB/phpbb/profilefields/type/type_url.php b/phpBB/phpbb/profilefields/type/type_url.php index 375cf5b19a..37815b66a5 100644 --- a/phpBB/phpbb/profilefields/type/type_url.php +++ b/phpBB/phpbb/profilefields/type/type_url.php @@ -64,11 +64,24 @@ class type_url extends type_string return false; } - if (!preg_match('#^' . get_preg_expression('url') . '$#iu', $field_value)) + if (!preg_match('#^' . get_preg_expression('url_http') . '$#iu', $field_value)) { return $this->user->lang('FIELD_INVALID_URL', $this->get_field_name($field_data['lang_name'])); } return false; } + + /** + * {@inheritDoc} + */ + public function get_profile_value($field_value, $field_data) + { + if (!preg_match('#^' . get_preg_expression('url_http') . '$#iu', $field_value)) + { + return null; + } + + return parent::get_profile_value($field_value, $field_data); + } } diff --git a/phpBB/phpbb/report/controller/report.php b/phpBB/phpbb/report/controller/report.php index e1c14afde0..0aa6833dfa 100644 --- a/phpBB/phpbb/report/controller/report.php +++ b/phpBB/phpbb/report/controller/report.php @@ -141,7 +141,7 @@ class report // Handle request try { - if (!empty($submit) && sizeof($error) === 0) + if (!empty($submit) && count($error) === 0) { $this->report_handler->add_report( (int) $id, @@ -273,7 +273,7 @@ class report } $this->template->assign_vars(array( - 'ERROR' => (sizeof($error) > 0) ? implode('<br />', $error) : '', + 'ERROR' => (count($error) > 0) ? implode('<br />', $error) : '', 'S_REPORT_POST' => ($mode === 'pm') ? false : true, 'REPORT_TEXT' => $report_text, 'S_HIDDEN_FIELDS' => (!empty($s_hidden_fields)) ? $s_hidden_fields : null, @@ -302,7 +302,7 @@ class report $error[] = $visual_confirmation_response; } - if (sizeof($error) === 0) + if (count($error) === 0) { $captcha->reset(); } diff --git a/phpBB/phpbb/report/report_handler_pm.php b/phpBB/phpbb/report/report_handler_pm.php index 2f2a697efc..774ca329ad 100644 --- a/phpBB/phpbb/report/report_handler_pm.php +++ b/phpBB/phpbb/report/report_handler_pm.php @@ -53,8 +53,8 @@ class report_handler_pm extends report_handler 'user_notify' => $user_notify, 'report_text' => $report_text, 'reported_post_text' => $this->report_data['message_text'], - 'reported_post_uid' => $this->report_data['bbcode_bitfield'], - 'reported_post_bitfield' => $this->report_data['bbcode_uid'], + 'reported_post_uid' => $this->report_data['bbcode_uid'], + 'reported_post_bitfield' => $this->report_data['bbcode_bitfield'], 'reported_post_enable_bbcode' => $this->report_data['enable_bbcode'], 'reported_post_enable_smilies' => $this->report_data['enable_smilies'], 'reported_post_enable_magic_url' => $this->report_data['enable_magic_url'], diff --git a/phpBB/phpbb/report/report_handler_post.php b/phpBB/phpbb/report/report_handler_post.php index 5574a16dc0..52f09683ce 100644 --- a/phpBB/phpbb/report/report_handler_post.php +++ b/phpBB/phpbb/report/report_handler_post.php @@ -59,8 +59,8 @@ class report_handler_post extends report_handler 'user_notify' => $user_notify, 'report_text' => $report_text, 'reported_post_text' => $this->report_data['post_text'], - 'reported_post_uid' => $this->report_data['bbcode_bitfield'], - 'reported_post_bitfield' => $this->report_data['bbcode_uid'], + 'reported_post_uid' => $this->report_data['bbcode_uid'], + 'reported_post_bitfield' => $this->report_data['bbcode_bitfield'], 'reported_post_enable_bbcode' => $this->report_data['enable_bbcode'], 'reported_post_enable_smilies' => $this->report_data['enable_smilies'], 'reported_post_enable_magic_url' => $this->report_data['enable_magic_url'], diff --git a/phpBB/phpbb/request/request.php b/phpBB/phpbb/request/request.php index 00be8fd381..a0267d1370 100644 --- a/phpBB/phpbb/request/request.php +++ b/phpBB/phpbb/request/request.php @@ -150,8 +150,6 @@ class request implements \phpbb\request\request_interface return; } - $this->type_cast_helper->add_magic_quotes($value); - // setting to null means unsetting if ($value === null) { diff --git a/phpBB/phpbb/request/type_cast_helper.php b/phpBB/phpbb/request/type_cast_helper.php index 96e66950ca..912494998d 100644 --- a/phpBB/phpbb/request/type_cast_helper.php +++ b/phpBB/phpbb/request/type_cast_helper.php @@ -18,69 +18,6 @@ namespace phpbb\request; */ class type_cast_helper implements \phpbb\request\type_cast_helper_interface { - - /** - * @var string Whether slashes need to be stripped from input - */ - protected $strip; - - /** - * Initialises the type cast helper class. - * All it does is find out whether magic quotes are turned on. - */ - public function __construct() - { - if (version_compare(PHP_VERSION, '5.4.0-dev', '>=')) - { - $this->strip = false; - } - else - { - $this->strip = (@get_magic_quotes_gpc()) ? true : false; - } - } - - /** - * Recursively applies addslashes to a variable. - * - * @param mixed &$var Variable passed by reference to which slashes will be added. - */ - public function addslashes_recursively(&$var) - { - if (is_string($var)) - { - $var = addslashes($var); - } - else if (is_array($var)) - { - $var_copy = $var; - $var = array(); - foreach ($var_copy as $key => $value) - { - if (is_string($key)) - { - $key = addslashes($key); - } - $var[$key] = $value; - - $this->addslashes_recursively($var[$key]); - } - } - } - - /** - * Recursively applies addslashes to a variable if magic quotes are turned on. - * - * @param mixed &$var Variable passed by reference to which slashes will be added. - */ - public function add_magic_quotes(&$var) - { - if ($this->strip) - { - $this->addslashes_recursively($var); - } - } - /** * Set variable $result to a particular type. * @@ -129,8 +66,6 @@ class type_cast_helper implements \phpbb\request\type_cast_helper_interface $result = preg_replace('/[\x80-\xFF]/', '?', $result); } } - - $result = ($this->strip) ? stripslashes($result) : $result; } } diff --git a/phpBB/phpbb/request/type_cast_helper_interface.php b/phpBB/phpbb/request/type_cast_helper_interface.php index 2cb28d021f..9671573bf1 100644 --- a/phpBB/phpbb/request/type_cast_helper_interface.php +++ b/phpBB/phpbb/request/type_cast_helper_interface.php @@ -19,20 +19,6 @@ namespace phpbb\request; interface type_cast_helper_interface { /** - * Recursively applies addslashes to a variable. - * - * @param mixed &$var Variable passed by reference to which slashes will be added. - */ - public function addslashes_recursively(&$var); - - /** - * Recursively applies addslashes to a variable if magic quotes are turned on. - * - * @param mixed &$var Variable passed by reference to which slashes will be added. - */ - public function add_magic_quotes(&$var); - - /** * Set variable $result to a particular type. * * @param mixed &$result The variable to fill diff --git a/phpBB/phpbb/search/base.php b/phpBB/phpbb/search/base.php index 56de973b65..e7d0774b6c 100644 --- a/phpBB/phpbb/search/base.php +++ b/phpBB/phpbb/search/base.php @@ -133,7 +133,7 @@ class base { global $cache, $config, $db, $user; - $length = min(sizeof($id_ary), $config['search_block_size']); + $length = min(count($id_ary), $config['search_block_size']); // nothing to cache so exit if (!$length) @@ -148,7 +148,7 @@ class base if (!($store = $cache->get('_search_results_' . $search_key))) { // add the current keywords to the recent searches in the cache which are listed on the search page - if (!empty($keywords) || sizeof($author_ary)) + if (!empty($keywords) || count($author_ary)) { $sql = 'SELECT search_time FROM ' . SEARCH_RESULTS_TABLE . ' @@ -201,7 +201,7 @@ class base $store += $store_ids; // if the cache is too big - if (sizeof($store) - 2 > 20 * $config['search_block_size']) + if (count($store) - 2 > 20 * $config['search_block_size']) { // remove everything in front of two blocks in front of the current start index for ($i = 0, $n = $id_range[0] - 2 * $config['search_block_size']; $i < $n; $i++) @@ -243,7 +243,7 @@ class base global $db, $cache, $config; // clear all searches that searched for the specified words - if (sizeof($words)) + if (count($words)) { $sql_where = ''; foreach ($words as $word) @@ -264,7 +264,7 @@ class base } // clear all searches that searched for the specified authors - if (is_array($authors) && sizeof($authors)) + if (is_array($authors) && count($authors)) { $sql_where = ''; foreach ($authors as $author) diff --git a/phpBB/phpbb/search/fulltext_mysql.php b/phpBB/phpbb/search/fulltext_mysql.php index da1aad1c3a..1105d0892f 100644 --- a/phpBB/phpbb/search/fulltext_mysql.php +++ b/phpBB/phpbb/search/fulltext_mysql.php @@ -188,7 +188,7 @@ class fulltext_mysql extends \phpbb\search\base } $sql = 'SHOW VARIABLES - LIKE \'ft\_%\''; + LIKE \'%ft\_%\''; $result = $this->db->sql_query($sql); $mysql_info = array(); @@ -198,8 +198,16 @@ class fulltext_mysql extends \phpbb\search\base } $this->db->sql_freeresult($result); - $this->config->set('fulltext_mysql_max_word_len', $mysql_info['ft_max_word_len']); - $this->config->set('fulltext_mysql_min_word_len', $mysql_info['ft_min_word_len']); + if ($engine === 'MyISAM') + { + $this->config->set('fulltext_mysql_max_word_len', $mysql_info['ft_max_word_len']); + $this->config->set('fulltext_mysql_min_word_len', $mysql_info['ft_min_word_len']); + } + else if ($engine === 'InnoDB') + { + $this->config->set('fulltext_mysql_max_word_len', $mysql_info['innodb_ft_max_token_size']); + $this->config->set('fulltext_mysql_min_word_len', $mysql_info['innodb_ft_min_token_size']); + } return false; } @@ -232,9 +240,9 @@ class fulltext_mysql extends \phpbb\search\base $this->split_words = $matches[1]; // We limit the number of allowed keywords to minimize load on the database - if ($this->config['max_num_search_keywords'] && sizeof($this->split_words) > $this->config['max_num_search_keywords']) + if ($this->config['max_num_search_keywords'] && count($this->split_words) > $this->config['max_num_search_keywords']) { - trigger_error($this->user->lang('MAX_NUM_SEARCH_KEYWORDS_REFINE', (int) $this->config['max_num_search_keywords'], sizeof($this->split_words))); + trigger_error($this->user->lang('MAX_NUM_SEARCH_KEYWORDS_REFINE', (int) $this->config['max_num_search_keywords'], count($this->split_words))); } // to allow phrase search, we need to concatenate quoted words @@ -361,7 +369,7 @@ class fulltext_mysql extends \phpbb\search\base // remove too short or too long words $text = array_values($text); - for ($i = 0, $n = sizeof($text); $i < $n; $i++) + for ($i = 0, $n = count($text); $i < $n; $i++) { $text[$i] = trim($text[$i]); if (utf8_strlen($text[$i]) < $this->config['fulltext_mysql_min_word_len'] || utf8_strlen($text[$i]) > $this->config['fulltext_mysql_max_word_len']) @@ -563,12 +571,12 @@ class fulltext_mysql extends \phpbb\search\base $sql_select = ($type == 'posts') ? $sql_select . 'p.post_id' : 'DISTINCT ' . $sql_select . 't.topic_id'; $sql_from = ($join_topic) ? TOPICS_TABLE . ' t, ' : ''; $field = ($type == 'posts') ? 'post_id' : 'topic_id'; - if (sizeof($author_ary) && $author_name) + if (count($author_ary) && $author_name) { // first one matches post of registered users, second one guests and deleted users $sql_author = ' AND (' . $this->db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')'; } - else if (sizeof($author_ary)) + else if (count($author_ary)) { $sql_author = ' AND ' . $this->db->sql_in_set('p.poster_id', $author_ary); } @@ -580,7 +588,7 @@ class fulltext_mysql extends \phpbb\search\base $sql_where_options = $sql_sort_join; $sql_where_options .= ($topic_id) ? ' AND p.topic_id = ' . $topic_id : ''; $sql_where_options .= ($join_topic) ? ' AND t.topic_id = p.topic_id' : ''; - $sql_where_options .= (sizeof($ex_fid_ary)) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : ''; + $sql_where_options .= (count($ex_fid_ary)) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : ''; $sql_where_options .= ' AND ' . $post_visibility; $sql_where_options .= $sql_author; $sql_where_options .= ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : ''; @@ -591,6 +599,7 @@ class fulltext_mysql extends \phpbb\search\base WHERE MATCH ($sql_match) AGAINST ('" . $this->db->sql_escape(htmlspecialchars_decode($this->search_query)) . "' IN BOOLEAN MODE) $sql_where_options ORDER BY $sql_sort"; + $this->db->sql_return_on_error(true); $result = $this->db->sql_query_limit($sql, $this->config['search_block_size'], $start); while ($row = $this->db->sql_fetchrow($result)) @@ -602,7 +611,7 @@ class fulltext_mysql extends \phpbb\search\base $id_ary = array_unique($id_ary); // if the total result count is not cached yet, retrieve it from the db - if (!$result_count) + if (!$result_count && count($id_ary)) { $sql_found_rows = 'SELECT FOUND_ROWS() as result_count'; $result = $this->db->sql_query($sql_found_rows); @@ -659,7 +668,7 @@ class fulltext_mysql extends \phpbb\search\base public function author_search($type, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $post_visibility, $topic_id, $author_ary, $author_name, &$id_ary, &$start, $per_page) { // No author? No posts - if (!sizeof($author_ary)) + if (!count($author_ary)) { return 0; } @@ -736,7 +745,7 @@ class fulltext_mysql extends \phpbb\search\base { $sql_author = $this->db->sql_in_set('p.poster_id', $author_ary); } - $sql_fora = (sizeof($ex_fid_ary)) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : ''; + $sql_fora = (count($ex_fid_ary)) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : ''; $sql_topic_id = ($topic_id) ? ' AND p.topic_id = ' . (int) $topic_id : ''; $sql_time = ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : ''; $sql_firstpost = ($firstpost_only) ? ' AND p.post_id = t.topic_first_post_id' : ''; @@ -889,7 +898,7 @@ class fulltext_mysql extends \phpbb\search\base $id_ary = array_unique($id_ary); } - if (sizeof($id_ary)) + if (count($id_ary)) { $this->save_ids($search_key, '', $author_ary, $result_count, $id_ary, $start, $sort_dir); $id_ary = array_slice($id_ary, 0, $per_page); @@ -917,6 +926,34 @@ class fulltext_mysql extends \phpbb\search\base $words = array_unique(array_merge($split_text, $split_title)); + /** + * Event to modify method arguments and words before the MySQL search index is updated + * + * @event core.search_mysql_index_before + * @var string mode Contains the post mode: edit, post, reply, quote + * @var int post_id The id of the post which is modified/created + * @var string message New or updated post content + * @var string subject New or updated post subject + * @var int poster_id Post author's user id + * @var int forum_id The id of the forum in which the post is located + * @var array words List of words added to the index + * @var array split_text Array of words from the message + * @var array split_title Array of words from the title + * @since 3.2.3-RC1 + */ + $vars = array( + 'mode', + 'post_id', + 'message', + 'subject', + 'poster_id', + 'forum_id', + 'words', + 'split_text', + 'split_title', + ); + extract($this->phpbb_dispatcher->trigger_event('core.search_mysql_index_before', compact($vars))); + unset($split_text); unset($split_title); @@ -996,12 +1033,37 @@ class fulltext_mysql extends \phpbb\search\base $alter_list[] = $alter_entry; } - if (sizeof($alter_list)) + $sql_queries = []; + + foreach ($alter_list as $alter) { - foreach ($alter_list as $alter) - { - $this->db->sql_query('ALTER TABLE ' . POSTS_TABLE . ' ' . implode(', ', $alter)); - } + $sql_queries[] = 'ALTER TABLE ' . POSTS_TABLE . ' ' . implode(', ', $alter); + } + + if (!isset($this->stats['post_text'])) + { + $sql_queries[] = 'ALTER TABLE ' . POSTS_TABLE . ' ADD FULLTEXT post_text (post_text)'; + } + + $stats = $this->stats; + + /** + * Event to modify SQL queries before the MySQL search index is created + * + * @event core.search_mysql_create_index_before + * @var array sql_queries Array with queries for creating the search index + * @var array stats Array with statistics of the current index (read only) + * @since 3.2.3-RC1 + */ + $vars = array( + 'sql_queries', + 'stats', + ); + extract($this->phpbb_dispatcher->trigger_event('core.search_mysql_create_index_before', compact($vars))); + + foreach ($sql_queries as $sql_query) + { + $this->db->sql_query($sql_query); } $this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE); @@ -1039,9 +1101,37 @@ class fulltext_mysql extends \phpbb\search\base $alter[] = 'DROP INDEX post_content'; } - if (sizeof($alter)) + if (isset($this->stats['post_text'])) { - $this->db->sql_query('ALTER TABLE ' . POSTS_TABLE . ' ' . implode(', ', $alter)); + $alter[] = 'DROP INDEX post_text'; + } + + $sql_queries = []; + + if (count($alter)) + { + $sql_queries[] = 'ALTER TABLE ' . POSTS_TABLE . ' ' . implode(', ', $alter); + } + + $stats = $this->stats; + + /** + * Event to modify SQL queries before the MySQL search index is deleted + * + * @event core.search_mysql_delete_index_before + * @var array sql_queries Array with queries for deleting the search index + * @var array stats Array with statistics of the current index (read only) + * @since 3.2.3-RC1 + */ + $vars = array( + 'sql_queries', + 'stats', + ); + extract($this->phpbb_dispatcher->trigger_event('core.search_mysql_delete_index_before', compact($vars))); + + foreach ($sql_queries as $sql_query) + { + $this->db->sql_query($sql_query); } $this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE); @@ -1059,7 +1149,7 @@ class fulltext_mysql extends \phpbb\search\base $this->get_stats(); } - return isset($this->stats['post_subject']) && isset($this->stats['post_content']); + return isset($this->stats['post_subject']) && isset($this->stats['post_content']) && isset($this->stats['post_text']); } /** @@ -1103,6 +1193,10 @@ class fulltext_mysql extends \phpbb\search\base { $this->stats['post_subject'] = $row; } + else if ($row['Key_name'] == 'post_text') + { + $this->stats['post_text'] = $row; + } else if ($row['Key_name'] == 'post_content') { $this->stats['post_content'] = $row; diff --git a/phpBB/phpbb/search/fulltext_native.php b/phpBB/phpbb/search/fulltext_native.php index 73dcfce9a5..c83de75eed 100644 --- a/phpBB/phpbb/search/fulltext_native.php +++ b/phpBB/phpbb/search/fulltext_native.php @@ -190,7 +190,7 @@ class fulltext_native extends \phpbb\search\base */ public function split_keywords($keywords, $terms) { - $tokens = '+-|()*'; + $tokens = '+-|()* '; $keywords = trim($this->cleanup($keywords, $tokens)); @@ -224,12 +224,10 @@ class fulltext_native extends \phpbb\search\base $keywords[$i] = '|'; break; case '*': - if ($i === 0 || ($keywords[$i - 1] !== '*' && strcspn($keywords[$i - 1], $tokens) === 0)) + // $i can never be 0 here since $open_bracket is initialised to false + if (strpos($tokens, $keywords[$i - 1]) !== false && ($i + 1 === $n || strpos($tokens, $keywords[$i + 1]) !== false)) { - if ($i === $n - 1 || ($keywords[$i + 1] !== '*' && strcspn($keywords[$i + 1], $tokens) === 0)) - { - $keywords = substr($keywords, 0, $i) . substr($keywords, $i + 1); - } + $keywords[$i] = '|'; } break; } @@ -264,7 +262,7 @@ class fulltext_native extends \phpbb\search\base } } - if ($open_bracket) + if ($open_bracket !== false) { $keywords .= ')'; } @@ -285,7 +283,7 @@ class fulltext_native extends \phpbb\search\base ); $keywords = preg_replace($match, $replace, $keywords); - $num_keywords = sizeof(explode(' ', $keywords)); + $num_keywords = count(explode(' ', $keywords)); // We limit the number of allowed keywords to minimize load on the database if ($this->config['max_num_search_keywords'] && $num_keywords > $this->config['max_num_search_keywords']) @@ -301,12 +299,26 @@ class fulltext_native extends \phpbb\search\base $words = array(); preg_match_all('#([^\\s+\\-|()]+)(?:$|[\\s+\\-|()])#u', $keywords, $words); - if (sizeof($words[1])) + if (count($words[1])) { $keywords = '(' . implode('|', $words[1]) . ')'; } } + // Remove non trailing wildcards from each word to prevent a full table scan (it's now using the database index) + $match = '#\*(?!$|\s)#'; + $replace = '$1'; + $keywords = preg_replace($match, $replace, $keywords); + + // Only allow one wildcard in the search query to limit the database load + $match = '#\*#'; + $replace = '$1'; + $count_wildcards = substr_count($keywords, '*'); + + // Reverse the string to remove all wildcards except the first one + $keywords = strrev(preg_replace($match, $replace, strrev($keywords), $count_wildcards - 1)); + unset($count_wildcards); + // set the search_query which is shown to the user $this->search_query = $keywords; @@ -316,7 +328,7 @@ class fulltext_native extends \phpbb\search\base $common_ids = $words = array(); - if (sizeof($exact_words)) + if (count($exact_words)) { $sql = 'SELECT word_id, word_text, word_common FROM ' . SEARCH_WORDLIST_TABLE . ' @@ -409,8 +421,16 @@ class fulltext_native extends \phpbb\search\base { if (strpos($word_part, '*') !== false) { - $id_words[] = '\'' . $this->db->sql_escape(str_replace('*', '%', $word_part)) . '\''; - $non_common_words[] = $word_part; + $len = utf8_strlen(str_replace('*', '', $word_part)); + if ($len >= $this->word_length['min'] && $len <= $this->word_length['max']) + { + $id_words[] = '\'' . $this->db->sql_escape(str_replace('*', '%', $word_part)) . '\''; + $non_common_words[] = $word_part; + } + else + { + $this->common_words[] = $word_part; + } } else if (isset($words[$word_part])) { @@ -426,10 +446,10 @@ class fulltext_native extends \phpbb\search\base } } } - if (sizeof($id_words)) + if (count($id_words)) { sort($id_words); - if (sizeof($id_words) > 1) + if (count($id_words) > 1) { $this->{$mode . '_ids'}[] = $id_words; } @@ -440,7 +460,7 @@ class fulltext_native extends \phpbb\search\base } } // throw an error if we shall not ignore unexistant words - else if (!$ignore_no_id && sizeof($non_common_words)) + else if (!$ignore_no_id && count($non_common_words)) { trigger_error(sprintf($this->user->lang['WORDS_IN_NO_POST'], implode($this->user->lang['COMMA_SEPARATOR'], $non_common_words))); } @@ -480,7 +500,7 @@ class fulltext_native extends \phpbb\search\base } // Return true if all words are not common words - if (sizeof($exact_words) - sizeof($this->common_words) > 0) + if (count($exact_words) - count($this->common_words) > 0) { return true; } @@ -716,7 +736,7 @@ class fulltext_native extends \phpbb\search\base } } - if (sizeof($this->must_not_contain_ids)) + if (count($this->must_not_contain_ids)) { $sql_array['LEFT_JOIN'][] = array( 'FROM' => array(SEARCH_WORDMATCH_TABLE => 'm' . $m_num), @@ -826,7 +846,7 @@ class fulltext_native extends \phpbb\search\base $sql_where[] = 'p.topic_id = ' . $topic_id; } - if (sizeof($author_ary)) + if (count($author_ary)) { if ($author_name) { @@ -840,7 +860,7 @@ class fulltext_native extends \phpbb\search\base $sql_where[] = $sql_author; } - if (sizeof($ex_fid_ary)) + if (count($ex_fid_ary)) { $sql_where[] = $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true); } @@ -1010,7 +1030,7 @@ class fulltext_native extends \phpbb\search\base public function author_search($type, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $post_visibility, $topic_id, $author_ary, $author_name, &$id_ary, &$start, $per_page) { // No author? No posts - if (!sizeof($author_ary)) + if (!count($author_ary)) { return 0; } @@ -1082,7 +1102,7 @@ class fulltext_native extends \phpbb\search\base { $sql_author = $this->db->sql_in_set('p.poster_id', $author_ary); } - $sql_fora = (sizeof($ex_fid_ary)) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : ''; + $sql_fora = (count($ex_fid_ary)) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : ''; $sql_time = ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : ''; $sql_topic_id = ($topic_id) ? ' AND p.topic_id = ' . (int) $topic_id : ''; $sql_firstpost = ($firstpost_only) ? ' AND p.post_id = t.topic_first_post_id' : ''; @@ -1289,7 +1309,7 @@ class fulltext_native extends \phpbb\search\base $this->db->sql_freeresult($result); } - if (sizeof($id_ary)) + if (count($id_ary)) { $this->save_ids($search_key, '', $author_ary, $total_results, $id_ary, $start, $sort_dir); $id_ary = array_slice($id_ary, 0, $per_page); @@ -1433,6 +1453,38 @@ class fulltext_native extends \phpbb\search\base $words['del']['post'] = array(); $words['del']['title'] = array(); } + + /** + * Event to modify method arguments and words before the native search index is updated + * + * @event core.search_native_index_before + * @var string mode Contains the post mode: edit, post, reply, quote + * @var int post_id The id of the post which is modified/created + * @var string message New or updated post content + * @var string subject New or updated post subject + * @var int poster_id Post author's user id + * @var int forum_id The id of the forum in which the post is located + * @var array words Grouped lists of words added to or remove from the index + * @var array split_text Array of words from the message + * @var array split_title Array of words from the title + * @var array cur_words Array of words currently in the index for comparing to new words + * when mode is edit. Empty for other modes. + * @since 3.2.3-RC1 + */ + $vars = array( + 'mode', + 'post_id', + 'message', + 'subject', + 'poster_id', + 'forum_id', + 'words', + 'split_text', + 'split_title', + 'cur_words', + ); + extract($this->phpbb_dispatcher->trigger_event('core.search_native_index_before', compact($vars))); + unset($split_text); unset($split_title); @@ -1443,7 +1495,7 @@ class fulltext_native extends \phpbb\search\base // individual arrays of added and removed words for text and title. What // we need to do now is add the new words (if they don't already exist) // and then add (or remove) matches between the words and this post - if (sizeof($unique_add_words)) + if (count($unique_add_words)) { $sql = 'SELECT word_id, word_text FROM ' . SEARCH_WORDLIST_TABLE . ' @@ -1459,7 +1511,7 @@ class fulltext_native extends \phpbb\search\base $new_words = array_diff($unique_add_words, array_keys($word_ids)); $this->db->sql_transaction('begin'); - if (sizeof($new_words)) + if (count($new_words)) { $sql_ary = array(); @@ -1483,7 +1535,7 @@ class fulltext_native extends \phpbb\search\base { $title_match = ($word_in == 'title') ? 1 : 0; - if (sizeof($word_ary)) + if (count($word_ary)) { $sql_in = array(); foreach ($word_ary as $word) @@ -1512,7 +1564,7 @@ class fulltext_native extends \phpbb\search\base { $title_match = ($word_in == 'title') ? 1 : 0; - if (sizeof($word_ary)) + if (count($word_ary)) { $sql = 'INSERT INTO ' . SEARCH_WORDMATCH_TABLE . ' (post_id, word_id, title_match) SELECT ' . (int) $post_id . ', word_id, ' . (int) $title_match . ' @@ -1543,7 +1595,7 @@ class fulltext_native extends \phpbb\search\base */ public function index_remove($post_ids, $author_ids, $forum_ids) { - if (sizeof($post_ids)) + if (count($post_ids)) { $sql = 'SELECT w.word_id, w.word_text, m.title_match FROM ' . SEARCH_WORDMATCH_TABLE . ' m, ' . SEARCH_WORDLIST_TABLE . ' w @@ -1566,7 +1618,7 @@ class fulltext_native extends \phpbb\search\base } $this->db->sql_freeresult($result); - if (sizeof($title_word_ids)) + if (count($title_word_ids)) { $sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . ' SET word_count = word_count - 1 @@ -1575,7 +1627,7 @@ class fulltext_native extends \phpbb\search\base $this->db->sql_query($sql); } - if (sizeof($message_word_ids)) + if (count($message_word_ids)) { $sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . ' SET word_count = word_count - 1 @@ -1630,7 +1682,7 @@ class fulltext_native extends \phpbb\search\base } $this->db->sql_freeresult($result); - if (sizeof($sql_in)) + if (count($sql_in)) { // Flag the words $sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . ' @@ -1650,7 +1702,7 @@ class fulltext_native extends \phpbb\search\base unset($sql_in); } - if (sizeof($destroy_cache_words)) + if (count($destroy_cache_words)) { // destroy cached search results containing any of the words that are now common or were removed $this->destroy_cache(array_unique($destroy_cache_words)); @@ -1664,20 +1716,43 @@ class fulltext_native extends \phpbb\search\base */ public function delete_index($acp_module, $u_action) { + $sql_queries = []; + switch ($this->db->get_sql_layer()) { case 'sqlite3': - $this->db->sql_query('DELETE FROM ' . SEARCH_WORDLIST_TABLE); - $this->db->sql_query('DELETE FROM ' . SEARCH_WORDMATCH_TABLE); - $this->db->sql_query('DELETE FROM ' . SEARCH_RESULTS_TABLE); + $sql_queries[] = 'DELETE FROM ' . SEARCH_WORDLIST_TABLE; + $sql_queries[] = 'DELETE FROM ' . SEARCH_WORDMATCH_TABLE; + $sql_queries[] = 'DELETE FROM ' . SEARCH_RESULTS_TABLE; break; default: - $this->db->sql_query('TRUNCATE TABLE ' . SEARCH_WORDLIST_TABLE); - $this->db->sql_query('TRUNCATE TABLE ' . SEARCH_WORDMATCH_TABLE); - $this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE); + $sql_queries[] = 'TRUNCATE TABLE ' . SEARCH_WORDLIST_TABLE; + $sql_queries[] = 'TRUNCATE TABLE ' . SEARCH_WORDMATCH_TABLE; + $sql_queries[] = 'TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE; break; } + + $stats = $this->stats; + + /** + * Event to modify SQL queries before the native search index is deleted + * + * @event core.search_native_delete_index_before + * @var array sql_queries Array with queries for deleting the search index + * @var array stats Array with statistics of the current index (read only) + * @since 3.2.3-RC1 + */ + $vars = array( + 'sql_queries', + 'stats', + ); + extract($this->phpbb_dispatcher->trigger_event('core.search_native_delete_index_before', compact($vars))); + + foreach ($sql_queries as $sql_query) + { + $this->db->sql_query($sql_query); + } } /** @@ -1685,7 +1760,7 @@ class fulltext_native extends \phpbb\search\base */ public function index_created() { - if (!sizeof($this->stats)) + if (!count($this->stats)) { $this->get_stats(); } @@ -1698,7 +1773,7 @@ class fulltext_native extends \phpbb\search\base */ public function index_stats() { - if (!sizeof($this->stats)) + if (!count($this->stats)) { $this->get_stats(); } diff --git a/phpBB/phpbb/search/fulltext_postgres.php b/phpBB/phpbb/search/fulltext_postgres.php index 8dbc7212a1..2f387e791e 100644 --- a/phpBB/phpbb/search/fulltext_postgres.php +++ b/phpBB/phpbb/search/fulltext_postgres.php @@ -294,7 +294,7 @@ class fulltext_postgres extends \phpbb\search\base // remove too short or too long words $text = array_values($text); - for ($i = 0, $n = sizeof($text); $i < $n; $i++) + for ($i = 0, $n = count($text); $i < $n; $i++) { $text[$i] = trim($text[$i]); if (utf8_strlen($text[$i]) < $this->config['fulltext_postgres_min_word_len'] || utf8_strlen($text[$i]) > $this->config['fulltext_postgres_max_word_len']) @@ -498,16 +498,16 @@ class fulltext_postgres extends \phpbb\search\base ); extract($this->phpbb_dispatcher->trigger_event('core.search_postgres_keywords_main_query_before', compact($vars))); - $sql_select = ($type == 'posts') ? 'p.post_id' : 'DISTINCT t.topic_id'; + $sql_select = ($type == 'posts') ? 'p.post_id' : 'DISTINCT t.topic_id, ' . $sort_by_sql[$sort_key]; $sql_from = ($join_topic) ? TOPICS_TABLE . ' t, ' : ''; $field = ($type == 'posts') ? 'post_id' : 'topic_id'; - if (sizeof($author_ary) && $author_name) + if (count($author_ary) && $author_name) { // first one matches post of registered users, second one guests and deleted users $sql_author = '(' . $this->db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')'; } - else if (sizeof($author_ary)) + else if (count($author_ary)) { $sql_author = ' AND ' . $this->db->sql_in_set('p.poster_id', $author_ary); } @@ -519,7 +519,7 @@ class fulltext_postgres extends \phpbb\search\base $sql_where_options = $sql_sort_join; $sql_where_options .= ($topic_id) ? ' AND p.topic_id = ' . $topic_id : ''; $sql_where_options .= ($join_topic) ? ' AND t.topic_id = p.topic_id' : ''; - $sql_where_options .= (sizeof($ex_fid_ary)) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : ''; + $sql_where_options .= (count($ex_fid_ary)) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : ''; $sql_where_options .= ' AND ' . $post_visibility; $sql_where_options .= $sql_author; $sql_where_options .= ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : ''; @@ -609,7 +609,7 @@ class fulltext_postgres extends \phpbb\search\base public function author_search($type, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $post_visibility, $topic_id, $author_ary, $author_name, &$id_ary, &$start, $per_page) { // No author? No posts - if (!sizeof($author_ary)) + if (!count($author_ary)) { return 0; } @@ -686,7 +686,7 @@ class fulltext_postgres extends \phpbb\search\base { $sql_author = $this->db->sql_in_set('p.poster_id', $author_ary); } - $sql_fora = (sizeof($ex_fid_ary)) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : ''; + $sql_fora = (count($ex_fid_ary)) ? ' AND ' . $this->db->sql_in_set('p.forum_id', $ex_fid_ary, true) : ''; $sql_topic_id = ($topic_id) ? ' AND p.topic_id = ' . (int) $topic_id : ''; $sql_time = ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : ''; $sql_firstpost = ($firstpost_only) ? ' AND p.post_id = t.topic_first_post_id' : ''; @@ -861,7 +861,7 @@ class fulltext_postgres extends \phpbb\search\base $id_ary = array_unique($id_ary); } - if (sizeof($id_ary)) + if (count($id_ary)) { $this->save_ids($search_key, '', $author_ary, $result_count, $id_ary, $start, $sort_dir); $id_ary = array_slice($id_ary, 0, $per_page); @@ -889,6 +889,34 @@ class fulltext_postgres extends \phpbb\search\base $words = array_unique(array_merge($split_text, $split_title)); + /** + * Event to modify method arguments and words before the PostgreSQL search index is updated + * + * @event core.search_postgres_index_before + * @var string mode Contains the post mode: edit, post, reply, quote + * @var int post_id The id of the post which is modified/created + * @var string message New or updated post content + * @var string subject New or updated post subject + * @var int poster_id Post author's user id + * @var int forum_id The id of the forum in which the post is located + * @var array words Array of words added to the index + * @var array split_text Array of words from the message + * @var array split_title Array of words from the title + * @since 3.2.3-RC1 + */ + $vars = array( + 'mode', + 'post_id', + 'message', + 'subject', + 'poster_id', + 'forum_id', + 'words', + 'split_text', + 'split_title', + ); + extract($this->phpbb_dispatcher->trigger_event('core.search_postgres_index_before', compact($vars))); + unset($split_text); unset($split_title); @@ -935,14 +963,37 @@ class fulltext_postgres extends \phpbb\search\base $this->get_stats(); } + $sql_queries = []; + if (!isset($this->stats['post_subject'])) { - $this->db->sql_query("CREATE INDEX " . POSTS_TABLE . "_" . $this->config['fulltext_postgres_ts_name'] . "_post_subject ON " . POSTS_TABLE . " USING gin (to_tsvector ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', post_subject))"); + $sql_queries[] = "CREATE INDEX " . POSTS_TABLE . "_" . $this->config['fulltext_postgres_ts_name'] . "_post_subject ON " . POSTS_TABLE . " USING gin (to_tsvector ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', post_subject))"; } if (!isset($this->stats['post_content'])) { - $this->db->sql_query("CREATE INDEX " . POSTS_TABLE . "_" . $this->config['fulltext_postgres_ts_name'] . "_post_content ON " . POSTS_TABLE . " USING gin (to_tsvector ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', post_text || ' ' || post_subject))"); + $sql_queries[] = "CREATE INDEX " . POSTS_TABLE . "_" . $this->config['fulltext_postgres_ts_name'] . "_post_content ON " . POSTS_TABLE . " USING gin (to_tsvector ('" . $this->db->sql_escape($this->config['fulltext_postgres_ts_name']) . "', post_text || ' ' || post_subject))"; + } + + $stats = $this->stats; + + /** + * Event to modify SQL queries before the Postgres search index is created + * + * @event core.search_postgres_create_index_before + * @var array sql_queries Array with queries for creating the search index + * @var array stats Array with statistics of the current index (read only) + * @since 3.2.3-RC1 + */ + $vars = array( + 'sql_queries', + 'stats', + ); + extract($this->phpbb_dispatcher->trigger_event('core.search_postgres_create_index_before', compact($vars))); + + foreach ($sql_queries as $sql_query) + { + $this->db->sql_query($sql_query); } $this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE); @@ -968,14 +1019,37 @@ class fulltext_postgres extends \phpbb\search\base $this->get_stats(); } + $sql_queries = []; + if (isset($this->stats['post_subject'])) { - $this->db->sql_query('DROP INDEX ' . $this->stats['post_subject']['relname']); + $sql_queries[] = 'DROP INDEX ' . $this->stats['post_subject']['relname']; } if (isset($this->stats['post_content'])) { - $this->db->sql_query('DROP INDEX ' . $this->stats['post_content']['relname']); + $sql_queries[] = 'DROP INDEX ' . $this->stats['post_content']['relname']; + } + + $stats = $this->stats; + + /** + * Event to modify SQL queries before the Postgres search index is created + * + * @event core.search_postgres_delete_index_before + * @var array sql_queries Array with queries for deleting the search index + * @var array stats Array with statistics of the current index (read only) + * @since 3.2.3-RC1 + */ + $vars = array( + 'sql_queries', + 'stats', + ); + extract($this->phpbb_dispatcher->trigger_event('core.search_postgres_delete_index_before', compact($vars))); + + foreach ($sql_queries as $sql_query) + { + $this->db->sql_query($sql_query); } $this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE); diff --git a/phpBB/phpbb/search/fulltext_sphinx.php b/phpBB/phpbb/search/fulltext_sphinx.php index 59c3d55076..2c2eb84dc7 100644 --- a/phpBB/phpbb/search/fulltext_sphinx.php +++ b/phpBB/phpbb/search/fulltext_sphinx.php @@ -292,7 +292,6 @@ class fulltext_sphinx AND p.post_id >= $start AND p.post_id <= $end'), array('sql_query_post', ''), array('sql_query_post_index', 'UPDATE ' . SPHINX_TABLE . ' SET max_doc_id = $maxid WHERE counter_id = 1'), - array('sql_query_info', 'SELECT * FROM ' . POSTS_TABLE . ' WHERE post_id = $id'), array('sql_attr_uint', 'forum_id'), array('sql_attr_uint', 'topic_id'), array('sql_attr_uint', 'poster_id'), @@ -304,7 +303,7 @@ class fulltext_sphinx array('sql_attr_string', 'post_subject'), ), 'source source_phpbb_' . $this->id . '_delta : source_phpbb_' . $this->id . '_main' => array( - array('sql_query_pre', ''), + array('sql_query_pre', 'SET NAMES \'utf8\''), array('sql_query_range', ''), array('sql_range_step', ''), array('sql_query', 'SELECT @@ -324,6 +323,7 @@ class fulltext_sphinx WHERE p.topic_id = t.topic_id AND p.post_id >= ( SELECT max_doc_id FROM ' . SPHINX_TABLE . ' WHERE counter_id=1 )'), + array('sql_query_post_index', ''), ), 'index index_phpbb_' . $this->id . '_main' => array( array('path', $this->config['fulltext_sphinx_data_path'] . 'index_phpbb_' . $this->id . '_main'), @@ -332,7 +332,6 @@ class fulltext_sphinx array('morphology', 'none'), array('stopwords', ''), array('min_word_len', '2'), - array('charset_type', 'utf-8'), array('charset_table', 'U+FF10..U+FF19->0..9, 0..9, U+FF41..U+FF5A->a..z, U+FF21..U+FF3A->a..z, A..Z->a..z, a..z, U+0149, U+017F, U+0138, U+00DF, U+00FF, U+00C0..U+00D6->U+00E0..U+00F6, U+00E0..U+00F6, U+00D8..U+00DE->U+00F8..U+00FE, U+00F8..U+00FE, U+0100->U+0101, U+0101, U+0102->U+0103, U+0103, U+0104->U+0105, U+0105, U+0106->U+0107, U+0107, U+0108->U+0109, U+0109, U+010A->U+010B, U+010B, U+010C->U+010D, U+010D, U+010E->U+010F, U+010F, U+0110->U+0111, U+0111, U+0112->U+0113, U+0113, U+0114->U+0115, U+0115, U+0116->U+0117, U+0117, U+0118->U+0119, U+0119, U+011A->U+011B, U+011B, U+011C->U+011D, U+011D, U+011E->U+011F, U+011F, U+0130->U+0131, U+0131, U+0132->U+0133, U+0133, U+0134->U+0135, U+0135, U+0136->U+0137, U+0137, U+0139->U+013A, U+013A, U+013B->U+013C, U+013C, U+013D->U+013E, U+013E, U+013F->U+0140, U+0140, U+0141->U+0142, U+0142, U+0143->U+0144, U+0144, U+0145->U+0146, U+0146, U+0147->U+0148, U+0148, U+014A->U+014B, U+014B, U+014C->U+014D, U+014D, U+014E->U+014F, U+014F, U+0150->U+0151, U+0151, U+0152->U+0153, U+0153, U+0154->U+0155, U+0155, U+0156->U+0157, U+0157, U+0158->U+0159, U+0159, U+015A->U+015B, U+015B, U+015C->U+015D, U+015D, U+015E->U+015F, U+015F, U+0160->U+0161, U+0161, U+0162->U+0163, U+0163, U+0164->U+0165, U+0165, U+0166->U+0167, U+0167, U+0168->U+0169, U+0169, U+016A->U+016B, U+016B, U+016C->U+016D, U+016D, U+016E->U+016F, U+016F, U+0170->U+0171, U+0171, U+0172->U+0173, U+0173, U+0174->U+0175, U+0175, U+0176->U+0177, U+0177, U+0178->U+00FF, U+00FF, U+0179->U+017A, U+017A, U+017B->U+017C, U+017C, U+017D->U+017E, U+017E, U+0410..U+042F->U+0430..U+044F, U+0430..U+044F, U+4E00..U+9FFF'), array('min_prefix_len', '0'), array('min_infix_len', '0'), @@ -345,14 +344,12 @@ class fulltext_sphinx array('mem_limit', $this->config['fulltext_sphinx_indexer_mem_limit'] . 'M'), ), 'searchd' => array( - array('compat_sphinxql_magics' , '0'), array('listen' , ($this->config['fulltext_sphinx_host'] ? $this->config['fulltext_sphinx_host'] : 'localhost') . ':' . ($this->config['fulltext_sphinx_port'] ? $this->config['fulltext_sphinx_port'] : '9312')), array('log', $this->config['fulltext_sphinx_data_path'] . 'log/searchd.log'), array('query_log', $this->config['fulltext_sphinx_data_path'] . 'log/sphinx-query.log'), array('read_timeout', '5'), array('max_children', '30'), array('pid_file', $this->config['fulltext_sphinx_data_path'] . 'searchd.pid'), - array('max_matches', (string) SPHINX_MAX_MATCHES), array('binlog_path', $this->config['fulltext_sphinx_data_path']), ), ); @@ -482,7 +479,7 @@ class fulltext_sphinx global $user, $phpbb_log; // No keywords? No posts. - if (!strlen($this->search_query) && !sizeof($author_ary)) + if (!strlen($this->search_query) && !count($author_ary)) { return false; } @@ -622,7 +619,7 @@ class fulltext_sphinx break; } - if (sizeof($author_ary)) + if (count($author_ary)) { $this->sphinx->SetFilter('poster_id', $author_ary); } @@ -632,14 +629,14 @@ class fulltext_sphinx // but at least it will also cause the same for normal users. $this->sphinx->SetFilter('post_visibility', array(ITEM_APPROVED)); - if (sizeof($ex_fid_ary)) + if (count($ex_fid_ary)) { // All forums that a user is allowed to access $fid_ary = array_unique(array_intersect(array_keys($this->auth->acl_getf('f_read', true)), array_keys($this->auth->acl_getf('f_search', true)))); // All forums that the user wants to and can search in $search_forums = array_diff($fid_ary, $ex_fid_ary); - if (sizeof($search_forums)) + if (count($search_forums)) { $this->sphinx->SetFilter('forum_id', $search_forums); } @@ -647,7 +644,7 @@ class fulltext_sphinx $this->sphinx->SetFilter('deleted', array(0)); - $this->sphinx->SetLimits($start, (int) $per_page, SPHINX_MAX_MATCHES); + $this->sphinx->SetLimits((int) $start, (int) $per_page, SPHINX_MAX_MATCHES); $result = $this->sphinx->Query($search_query_prefix . $this->sphinx->EscapeString(str_replace('"', '"', $this->search_query)), $this->indexes); // Could be connection to localhost:9312 failed (errno=111, @@ -757,6 +754,28 @@ class fulltext_sphinx */ public function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id) { + /** + * Event to modify method arguments before the Sphinx search index is updated + * + * @event core.search_sphinx_index_before + * @var string mode Contains the post mode: edit, post, reply, quote + * @var int post_id The id of the post which is modified/created + * @var string message New or updated post content + * @var string subject New or updated post subject + * @var int poster_id Post author's user id + * @var int forum_id The id of the forum in which the post is located + * @since 3.2.3-RC1 + */ + $vars = array( + 'mode', + 'post_id', + 'message', + 'subject', + 'poster_id', + 'forum_id', + ); + extract($this->phpbb_dispatcher->trigger_event('core.search_sphinx_index_before', compact($vars))); + if ($mode == 'edit') { $this->sphinx->UpdateAttributes($this->indexes, array('forum_id', 'poster_id'), array((int) $post_id => array((int) $forum_id, (int) $poster_id))); @@ -789,7 +808,7 @@ class fulltext_sphinx } $this->db->sql_freeresult($result); - if (sizeof($post_updates)) + if (count($post_updates)) { $this->sphinx->UpdateAttributes($this->indexes, array('topic_last_post_time'), $post_updates); } diff --git a/phpBB/phpbb/search/sphinx/config.php b/phpBB/phpbb/search/sphinx/config.php index 675649b460..3205574b45 100644 --- a/phpBB/phpbb/search/sphinx/config.php +++ b/phpBB/phpbb/search/sphinx/config.php @@ -46,7 +46,7 @@ class config */ function get_section_by_name($name) { - for ($i = 0, $size = sizeof($this->sections); $i < $size; $i++) + for ($i = 0, $size = count($this->sections); $i < $size; $i++) { // Make sure this is really a section object and not a comment if (($this->sections[$i] instanceof \phpbb\search\sphinx\config_section) && $this->sections[$i]->get_name() == $name) @@ -67,7 +67,7 @@ class config function add_section($name) { $this->sections[] = new \phpbb\search\sphinx\config_section($name, ''); - return $this->sections[sizeof($this->sections) - 1]; + return $this->sections[count($this->sections) - 1]; } /** diff --git a/phpBB/phpbb/search/sphinx/config_section.php b/phpBB/phpbb/search/sphinx/config_section.php index 14ab3a752c..2fc8b2da17 100644 --- a/phpBB/phpbb/search/sphinx/config_section.php +++ b/phpBB/phpbb/search/sphinx/config_section.php @@ -87,7 +87,7 @@ class config_section */ function get_variable_by_name($name) { - for ($i = 0, $size = sizeof($this->variables); $i < $size; $i++) + for ($i = 0, $size = count($this->variables); $i < $size; $i++) { // Make sure this is a variable object and not a comment if (($this->variables[$i] instanceof \phpbb\search\sphinx\config_variable) && $this->variables[$i]->get_name() == $name) @@ -106,7 +106,7 @@ class config_section */ function delete_variables_by_name($name) { - for ($i = 0, $size = sizeof($this->variables); $i < $size; $i++) + for ($i = 0, $size = count($this->variables); $i < $size; $i++) { // Make sure this is a variable object and not a comment if (($this->variables[$i] instanceof \phpbb\search\sphinx\config_variable) && $this->variables[$i]->get_name() == $name) @@ -129,7 +129,7 @@ class config_section function create_variable($name, $value) { $this->variables[] = new \phpbb\search\sphinx\config_variable($name, $value, ''); - return $this->variables[sizeof($this->variables) - 1]; + return $this->variables[count($this->variables) - 1]; } /** diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php index 6b5b8f2625..31f32af7c4 100644 --- a/phpBB/phpbb/session.php +++ b/phpBB/phpbb/session.php @@ -108,7 +108,7 @@ class session $root_dirs = array_diff_assoc($root_dirs, $intersection); $page_dirs = array_diff_assoc($page_dirs, $intersection); - $page_dir = str_repeat('../', sizeof($root_dirs)) . implode('/', $page_dirs); + $page_dir = str_repeat('../', count($root_dirs)) . implode('/', $page_dirs); if ($page_dir && substr($page_dir, -1, 1) == '/') { @@ -127,8 +127,8 @@ class session // The script path from the webroot to the phpBB root (for example: /phpBB3/) $script_dirs = explode('/', $script_path); - array_splice($script_dirs, -sizeof($page_dirs)); - $root_script_path = implode('/', $script_dirs) . (sizeof($root_dirs) ? '/' . implode('/', $root_dirs) : ''); + array_splice($script_dirs, -count($page_dirs)); + $root_script_path = implode('/', $script_dirs) . (count($root_dirs) ? '/' . implode('/', $root_dirs) : ''); // We are on the base level (phpBB root == webroot), lets adjust the variables a bit... if (!$root_script_path) @@ -584,12 +584,12 @@ class session $provider = $provider_collection->get_provider(); $this->data = $provider->autologin(); - if ($user_id !== false && sizeof($this->data) && $this->data['user_id'] != $user_id) + if ($user_id !== false && isset($this->data['user_id']) && $this->data['user_id'] != $user_id) { $this->data = array(); } - if (sizeof($this->data)) + if (isset($this->data['user_id'])) { $this->cookie_data['k'] = ''; $this->cookie_data['u'] = $this->data['user_id']; @@ -597,7 +597,7 @@ class session // If we're presented with an autologin key we'll join against it. // Else if we've been passed a user_id we'll grab data based on that - if (isset($this->cookie_data['k']) && $this->cookie_data['k'] && $this->cookie_data['u'] && !sizeof($this->data)) + if (isset($this->cookie_data['k']) && $this->cookie_data['k'] && $this->cookie_data['u'] && empty($this->data)) { $sql = 'SELECT u.* FROM ' . USERS_TABLE . ' u, ' . SESSIONS_KEYS_TABLE . ' k @@ -617,7 +617,7 @@ class session $db->sql_freeresult($result); } - if ($user_id !== false && !sizeof($this->data)) + if ($user_id !== false && empty($this->data)) { $this->cookie_data['k'] = ''; $this->cookie_data['u'] = $user_id; @@ -645,7 +645,7 @@ class session // User does not exist // User is inactive // User is bot - if (!sizeof($this->data) || !is_array($this->data)) + if (!is_array($this->data) || !count($this->data)) { $this->cookie_data['k'] = ''; $this->cookie_data['u'] = ($bot) ? $bot : ANONYMOUS; @@ -1022,7 +1022,7 @@ class session } $db->sql_freeresult($result); - if (sizeof($del_user_id)) + if (count($del_user_id)) { // Delete expired sessions $sql = 'DELETE FROM ' . SESSIONS_TABLE . ' @@ -1156,7 +1156,7 @@ class session $where_sql[] = $_sql; } - $sql .= (sizeof($where_sql)) ? implode(' AND ', $where_sql) : ''; + $sql .= (count($where_sql)) ? implode(' AND ', $where_sql) : ''; $result = $db->sql_query($sql, $cache_ttl); $ban_triggered_by = 'user'; @@ -1299,7 +1299,12 @@ class session trigger_error($message); } - return ($banned && $ban_row['ban_give_reason']) ? $ban_row['ban_give_reason'] : $banned; + if (!empty($ban_row)) + { + $ban_row['ban_triggered_by'] = $ban_triggered_by; + } + + return ($banned && $ban_row) ? $ban_row : $banned; } /** @@ -1614,13 +1619,15 @@ class session return; } + // Do not update the session page for ajax requests, so the view online still works as intended + $page_changed = $this->update_session_page && $this->data['session_page'] != $this->page['page'] && !$request->is_ajax(); + // Only update session DB a minute or so after last update or if page changes - if ($this->time_now - ((isset($this->data['session_time'])) ? $this->data['session_time'] : 0) > 60 || ($this->update_session_page && $this->data['session_page'] != $this->page['page'])) + if ($this->time_now - (isset($this->data['session_time']) ? $this->data['session_time'] : 0) > 60 || $page_changed) { $sql_ary = array('session_time' => $this->time_now); - // Do not update the session page for ajax requests, so the view online still works as intended - if ($this->update_session_page && !$request->is_ajax()) + if ($page_changed) { $sql_ary['session_page'] = substr($this->page['page'], 0, 199); $sql_ary['session_forum_id'] = $this->page['forum']; diff --git a/phpBB/phpbb/template/assets_bag.php b/phpBB/phpbb/template/assets_bag.php index 9013061b96..067b0eb8f1 100644 --- a/phpBB/phpbb/template/assets_bag.php +++ b/phpBB/phpbb/template/assets_bag.php @@ -71,7 +71,7 @@ class assets_bag $output = ''; foreach ($this->stylesheets as $stylesheet) { - $output .= "<link href=\"{$stylesheet->get_url()}\" rel=\"stylesheet\" type=\"text/css\" media=\"screen\" />\n"; + $output .= "<link href=\"{$stylesheet->get_url()}\" rel=\"stylesheet\" media=\"screen\" />\n"; } return $output; @@ -87,7 +87,7 @@ class assets_bag $output = ''; foreach ($this->scripts as $script) { - $output .= "<script type=\"text/javascript\" src=\"{$script->get_url()}\"></script>\n"; + $output .= "<script src=\"{$script->get_url()}\"></script>\n"; } return $output; diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index 392efd5933..202e29ce00 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -142,7 +142,7 @@ class context */ protected function set_num_rows(&$loop_data) { - $s_num_rows = sizeof($loop_data); + $s_num_rows = count($loop_data); foreach ($loop_data as &$mod_block) { foreach ($mod_block as $sub_block_name => &$sub_block) @@ -190,70 +190,51 @@ class context public function assign_block_vars($blockname, array $vararray) { $this->num_rows_is_set = false; - if (strpos($blockname, '.') !== false) - { - // Nested block. - $blocks = explode('.', $blockname); - $blockcount = sizeof($blocks) - 1; - - $str = &$this->tpldata; - for ($i = 0; $i < $blockcount; $i++) - { - $str = &$str[$blocks[$i]]; - $str = &$str[sizeof($str) - 1]; - } - $s_row_count = isset($str[$blocks[$blockcount]]) ? sizeof($str[$blocks[$blockcount]]) : 0; - $vararray['S_ROW_COUNT'] = $vararray['S_ROW_NUM'] = $s_row_count; + // For nested block, $blockcount > 0, for top-level block, $blockcount == 0 + $blocks = explode('.', $blockname); + $blockcount = count($blocks) - 1; - // Assign S_FIRST_ROW - if (!$s_row_count) - { - $vararray['S_FIRST_ROW'] = true; - } + $block = &$this->tpldata; + for ($i = 0; $i < $blockcount; $i++) + { + $pos = strpos($blocks[$i], '['); + $name = ($pos !== false) ? substr($blocks[$i], 0, $pos) : $blocks[$i]; + $block = &$block[$name]; + $block_count = empty($block) ? 0 : count($block) - 1; + $index = (!$pos || strpos($blocks[$i], '[]') === $pos) ? $block_count : (min((int) substr($blocks[$i], $pos + 1, -1), $block_count)); + $block = &$block[$index]; + } - // Assign S_BLOCK_NAME - $vararray['S_BLOCK_NAME'] = $blocks[$blockcount]; + // $block = &$block[$blocks[$i]]; // Do not traverse the last block as it might be empty + $name = $blocks[$i]; - // Now the tricky part, we always assign S_LAST_ROW and remove the entry before - // This is much more clever than going through the complete template data on display (phew) - $vararray['S_LAST_ROW'] = true; - if ($s_row_count > 0) - { - unset($str[$blocks[$blockcount]][($s_row_count - 1)]['S_LAST_ROW']); - } + // Assign S_ROW_COUNT and S_ROW_NUM + $s_row_count = isset($block[$name]) ? count($block[$name]) : 0; + $vararray['S_ROW_COUNT'] = $vararray['S_ROW_NUM'] = $s_row_count; - // Now we add the block that we're actually assigning to. - // We're adding a new iteration to this block with the given - // variable assignments. - $str[$blocks[$blockcount]][] = $vararray; - } - else + // Assign S_FIRST_ROW + if (!$s_row_count) { - // Top-level block. - $s_row_count = (isset($this->tpldata[$blockname])) ? sizeof($this->tpldata[$blockname]) : 0; - $vararray['S_ROW_COUNT'] = $vararray['S_ROW_NUM'] = $s_row_count; - - // Assign S_FIRST_ROW - if (!$s_row_count) - { - $vararray['S_FIRST_ROW'] = true; - } - - // Assign S_BLOCK_NAME - $vararray['S_BLOCK_NAME'] = $blockname; + $vararray['S_FIRST_ROW'] = true; + } - // We always assign S_LAST_ROW and remove the entry before - $vararray['S_LAST_ROW'] = true; - if ($s_row_count > 0) - { - unset($this->tpldata[$blockname][($s_row_count - 1)]['S_LAST_ROW']); - } + // Assign S_BLOCK_NAME + $vararray['S_BLOCK_NAME'] = $name; - // Add a new iteration to this block with the variable assignments we were given. - $this->tpldata[$blockname][] = $vararray; + // Now the tricky part, we always assign S_LAST_ROW and remove the entry before + // This is much more clever than going through the complete template data on display (phew) + $vararray['S_LAST_ROW'] = true; + if ($s_row_count > 0) + { + unset($block[$name][($s_row_count - 1)]['S_LAST_ROW']); } + // Now we add the block that we're actually assigning to. + // We're adding a new iteration to this block with the given + // variable assignments. + $block[$name][] = $vararray; + return true; } @@ -285,7 +266,7 @@ class context { // For nested block, $blockcount > 0, for top-level block, $blockcount == 0 $blocks = explode('.', $blockname); - $blockcount = sizeof($blocks) - 1; + $blockcount = count($blocks) - 1; $block = $this->tpldata; for ($i = 0; $i <= $blockcount; $i++) @@ -294,19 +275,29 @@ class context { $name = substr($blocks[$i], 0, $pos); + if (empty($block[$name])) + { + return array(); + } + if (strpos($blocks[$i], '[]') === $pos) { - $index = sizeof($block[$name]) - 1; + $index = count($block[$name]) - 1; } else { - $index = min((int) substr($blocks[$i], $pos + 1, -1), sizeof($block[$name]) - 1); + $index = min((int) substr($blocks[$i], $pos + 1, -1), count($block[$name]) - 1); } } else { $name = $blocks[$i]; - $index = sizeof($block[$name]) - 1; + if (empty($block[$name])) + { + return array(); + } + + $index = count($block[$name]) - 1; } $block = $block[$name]; $block = $block[$index]; @@ -355,39 +346,26 @@ class context { // For nested block, $blockcount > 0, for top-level block, $blockcount == 0 $blocks = explode('.', $blockname); - $blockcount = sizeof($blocks) - 1; + $blockcount = count($blocks) - 1; $block = $this->tpldata; for ($i = 0; $i < $blockcount; $i++) { - if (($pos = strpos($blocks[$i], '[')) !== false) - { - $name = substr($blocks[$i], 0, $pos); + $pos = strpos($blocks[$i], '['); + $name = ($pos !== false) ? substr($blocks[$i], 0, $pos) : $blocks[$i]; - if (strpos($blocks[$i], '[]') === $pos) - { - $index = sizeof($block[$name]) - 1; - } - else - { - $index = min((int) substr($blocks[$i], $pos + 1, -1), sizeof($block[$name]) - 1); - } - } - else - { - $name = $blocks[$i]; - $index = sizeof($block[$name]) - 1; - } if (!isset($block[$name])) { return false; } - $block = $block[$name]; - if (!isset($block[$index])) + + $index = (!$pos || strpos($blocks[$i], '[]') === $pos) ? (count($block[$name]) - 1) : (min((int) substr($blocks[$i], $pos + 1, -1), count($block[$name]) - 1)); + + if (!isset($block[$name][$index])) { return false; } - $block = $block[$index]; + $block = $block[$name][$index]; } if (!isset($block[$blocks[$i]])) @@ -397,9 +375,9 @@ class context $block = $block[$blocks[$i]]; // Traverse the last block // Change key to zero (change first position) if false and to last position if true - if ($key === false || $key === true) + if (is_bool($key)) { - return ($key === false) ? 0 : sizeof($block) - 1; + return (!$key) ? 0 : count($block) - 1; } // Get correct position if array given @@ -416,7 +394,7 @@ class context } } - return (is_int($key) && ((0 <= $key) && ($key < sizeof($block)))) ? $key : false; + return (is_int($key) && ((0 <= $key) && ($key < count($block)))) ? $key : false; } /** @@ -453,7 +431,7 @@ class context // For nested block, $blockcount > 0, for top-level block, $blockcount == 0 $blocks = explode('.', $blockname); - $blockcount = sizeof($blocks) - 1; + $blockcount = count($blocks) - 1; $block = &$this->tpldata; for ($i = 0; $i < $blockcount; $i++) @@ -464,17 +442,17 @@ class context if (strpos($blocks[$i], '[]') === $pos) { - $index = sizeof($block[$name]) - 1; + $index = count($block[$name]) - 1; } else { - $index = min((int) substr($blocks[$i], $pos + 1, -1), sizeof($block[$name]) - 1); + $index = min((int) substr($blocks[$i], $pos + 1, -1), count($block[$name]) - 1); } } else { $name = $blocks[$i]; - $index = sizeof($block[$name]) - 1; + $index = count($block[$name]) - 1; } $block = &$block[$name]; $block = &$block[$index]; @@ -496,7 +474,7 @@ class context // Change key to zero (change first position) if false and to last position if true if ($key === false || $key === true) { - $key = ($key === false) ? 0 : sizeof($block); + $key = ($key === false) ? 0 : count($block); } // Get correct position if array given @@ -526,9 +504,9 @@ class context if ($mode == 'insert') { // Make sure we are not exceeding the last iteration - if ($key >= sizeof($block)) + if ($key >= count($block)) { - $key = sizeof($block); + $key = count($block); unset($block[($key - 1)]['S_LAST_ROW']); $vararray['S_LAST_ROW'] = true; } @@ -543,7 +521,7 @@ class context $vararray['S_BLOCK_NAME'] = $name; // Re-position template blocks - for ($i = sizeof($block); $i > $key; $i--) + for ($i = count($block); $i > $key; $i--) { $block[$i] = $block[$i-1]; @@ -561,12 +539,12 @@ class context if ($mode == 'change') { // If key is out of bounds, do not change anything - if ($key > sizeof($block) || $key < 0) + if ($key > count($block) || $key < 0) { return false; } - if ($key == sizeof($block)) + if ($key == count($block)) { $key--; } @@ -580,26 +558,26 @@ class context if ($mode == 'delete') { // If we are exceeding last iteration, do not delete anything - if ($key > sizeof($block) || $key < 0) + if ($key > count($block) || $key < 0) { return false; } // If we are positioned at the end, we remove the last element - if ($key == sizeof($block)) + if ($key == count($block)) { $key--; } // We are deleting the last element in the block, so remove the block - if (sizeof($block) === 1) + if (count($block) === 1) { $block = null; // unset($block); does not work on references return true; } // Re-position template blocks - for ($i = $key; $i < sizeof($block)-1; $i++) + for ($i = $key; $i < count($block)-1; $i++) { $block[$i] = $block[$i+1]; $block[$i]['S_ROW_COUNT'] = $block[$i]['S_ROW_NUM'] = $i; @@ -610,7 +588,7 @@ class context // Set first and last elements again, in case they were removed $block[0]['S_FIRST_ROW'] = true; - $block[sizeof($block)-1]['S_LAST_ROW'] = true; + $block[count($block)-1]['S_LAST_ROW'] = true; return true; } @@ -631,13 +609,13 @@ class context { // Nested block. $blocks = explode('.', $blockname); - $blockcount = sizeof($blocks) - 1; + $blockcount = count($blocks) - 1; $str = &$this->tpldata; for ($i = 0; $i < $blockcount; $i++) { $str = &$str[$blocks[$i]]; - $str = &$str[sizeof($str) - 1]; + $str = &$str[count($str) - 1]; } unset($str[$blocks[$blockcount]]); diff --git a/phpBB/phpbb/template/twig/extension.php b/phpBB/phpbb/template/twig/extension.php index f0e716d697..f6f8e03ca2 100644 --- a/phpBB/phpbb/template/twig/extension.php +++ b/phpBB/phpbb/template/twig/extension.php @@ -146,7 +146,7 @@ class extension extends \Twig_Extension // of items to grab (length) // Start must always be the actual starting number for this calculation (not negative) - $start = ($start < 0) ? sizeof($item) + $start : $start; + $start = ($start < 0) ? count($item) + $start : $start; $end = $end - $start; } @@ -172,7 +172,7 @@ class extension extends \Twig_Extension $context_vars = $this->context->get_root_ref(); - if (isset($context_vars['L_' . $key])) + if (is_string($key) && isset($context_vars['L_' . $key])) { return $context_vars['L_' . $key]; } diff --git a/phpBB/phpbb/template/twig/node/includeasset.php b/phpBB/phpbb/template/twig/node/includeasset.php index 6d50eafc9d..12034b7820 100644 --- a/phpBB/phpbb/template/twig/node/includeasset.php +++ b/phpBB/phpbb/template/twig/node/includeasset.php @@ -50,7 +50,12 @@ abstract class includeasset extends \Twig_Node ->write("\$asset->set_path(\$local_file, true);\n") ->outdent() ->write("}\n") - ->write("\$asset->add_assets_version('{$config['assets_version']}');\n") + ->outdent() + ->write("}\n") + ->write("\n") + ->write("if (\$asset->is_relative()) {\n") + ->indent() + ->write("\$asset->add_assets_version('{$config['assets_version']}');\n") ->outdent() ->write("}\n") ->write("\$this->getEnvironment()->get_assets_bag()->add_{$this->get_setters_name()}(\$asset);") diff --git a/phpBB/phpbb/textformatter/s9e/bbcode_merger.php b/phpBB/phpbb/textformatter/s9e/bbcode_merger.php new file mode 100644 index 0000000000..a05ca3c2b8 --- /dev/null +++ b/phpBB/phpbb/textformatter/s9e/bbcode_merger.php @@ -0,0 +1,183 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\textformatter\s9e; + +use phpbb\textformatter\s9e\factory; +use s9e\TextFormatter\Configurator\Helpers\TemplateHelper; +use s9e\TextFormatter\Configurator\Items\UnsafeTemplate; + +class bbcode_merger +{ + /** + * @var \s9e\TextFormatter\Configurator $configurator Configurator instance used to inspect BBCodes + */ + protected $configurator; + + /** + * @param \phpbb\textformatter\s9e\factory $factory + */ + public function __construct(factory $factory) + { + $this->configurator = $factory->get_configurator(); + } + + /** + * Merge two BBCode definitions + * + * All of the arrays contain a "usage" element and a "template" element + * + * @throws InvalidArgumentException if a definition cannot be interpreted + * @throws RuntimeException if something unexpected occurs + * + * @param array $without BBCode definition without an attribute + * @param array $with BBCode definition with an attribute + * @return array Merged definition + */ + public function merge_bbcodes(array $without, array $with) + { + $without = $this->create_bbcode($without); + $with = $this->create_bbcode($with); + + // Select the appropriate strategy for merging this BBCode + if ($this->is_content_bbcode($without, $with)) + { + $merged = $this->merge_content_bbcode($without, $with); + } + else + { + $merged = $this->merge_optional_bbcode($without, $with); + } + + $merged['template'] = $this->normalize_template($merged['template']); + + return $merged; + } + + /** + * Create a custom BBCode for inspection + * + * @param array $definition Original BBCode definition + * @return array Updated definition containing a BBCode object and a Tag + */ + protected function create_bbcode(array $definition) + { + $bbcode = $this->configurator->BBCodes->addCustom( + $definition['usage'], + new UnsafeTemplate($definition['template']) + ); + + $definition['bbcode'] = $bbcode; + $definition['tag'] = $this->configurator->tags[$bbcode->tagName]; + + return $definition; + } + + /** + * Indent given template for readability + * + * @param string $template + * @return string + */ + protected function indent_template($template) + { + $dom = TemplateHelper::loadTemplate($template); + $dom->formatOutput = true; + $template = TemplateHelper::saveTemplate($dom); + + // Remove the first level of indentation if the template starts with whitespace + if (preg_match('(^\\n +)', $template, $m)) + { + $template = str_replace($m[0], "\n", $template); + } + + return trim($template); + } + + /** + * Test whether the two definitions form a "content"-style BBCode + * + * Such BBCodes include the [URL] BBCode, which uses its text content as + * attribute if none is provided + * + * @param array $without BBCode definition without an attribute + * @param array $with BBCode definition with an attribute + * @return array Merged definition + */ + protected function is_content_bbcode(array $without, array $with) + { + // Test whether we find the same non-TEXT token between "]" and "[" in the usage + // as between ">" and "<" in the template + return (preg_match('(\\]\\s*(\\{(?!TEXT)[^}]+\\})\\s*\\[)', $without['usage'], $m) + && preg_match('(>[^<]*?' . preg_quote($m[1]) . '[^>]*?<)s', $without['template'])); + } + + /** + * Merge the two BBCode definitions of a "content"-style BBCode + * + * @param array $without BBCode definition without an attribute + * @param array $with BBCode definition with an attribute + * @return array Merged definition + */ + protected function merge_content_bbcode(array $without, array $with) + { + // Convert [X={X}] into [X={X;useContent}] + $usage = preg_replace('(\\})', ';useContent}', $with['usage'], 1); + + // Use the template from the definition that uses an attribute + $template = $with['tag']->template; + + return ['usage' => $usage, 'template' => $template]; + } + + /** + * Merge the two BBCode definitions of a BBCode with an optional argument + * + * Such BBCodes include the [QUOTE] BBCode, which takes an optional argument + * but otherwise does not behave differently + * + * @param array $without BBCode definition without an attribute + * @param array $with BBCode definition with an attribute + * @return array Merged definition + */ + protected function merge_optional_bbcode(array $without, array $with) + { + // Convert [X={X}] into [X={X?}] + $usage = preg_replace('(\\})', '?}', $with['usage'], 1); + + // Build a template for both versions + $template = '<xsl:choose><xsl:when test="@' . $with['bbcode']->defaultAttribute . '">' . $with['tag']->template . '</xsl:when><xsl:otherwise>' . $without['tag']->template . '</xsl:otherwise></xsl:choose>'; + + return ['usage' => $usage, 'template' => $template]; + } + + /** + * Normalize a template + * + * @param string $template + * @return string + */ + protected function normalize_template($template) + { + // Normalize the template to simplify it + $template = $this->configurator->templateNormalizer->normalizeTemplate($template); + + // Convert xsl:value-of elements back to {L_} tokens where applicable + $template = preg_replace('(<xsl:value-of select="\\$(L_\\w+)"/>)', '{$1}', $template); + + // Beautify the template + $template = $this->indent_template($template); + + return $template; + } +} diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index d5ad8283d9..6191b9a315 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -78,7 +78,7 @@ class factory implements \phpbb\textformatter\cache_interface 'b' => '[B]{TEXT}[/B]', 'code' => '[CODE lang={IDENTIFIER;optional}]{TEXT}[/CODE]', 'color' => '[COLOR={COLOR}]{TEXT}[/COLOR]', - 'email' => '[EMAIL={EMAIL;useContent} subject={TEXT;optional;postFilter=rawurlencode} body={TEXT;optional;postFilter=rawurlencode}]{TEXT}[/EMAIL]', + 'email' => '[EMAIL={EMAIL;useContent} subject={TEXT1;optional;postFilter=rawurlencode} body={TEXT2;optional;postFilter=rawurlencode}]{TEXT}[/EMAIL]', 'flash' => '[FLASH={NUMBER1},{NUMBER2} width={NUMBER1;postFilter=#flashwidth} height={NUMBER2;postFilter=#flashheight} url={URL;useContent} /]', 'i' => '[I]{TEXT}[/I]', 'img' => '[IMG src={IMAGEURL;useContent}]', @@ -132,6 +132,11 @@ class factory implements \phpbb\textformatter\cache_interface protected $dispatcher; /** + * @var \phpbb\log\log_interface + */ + protected $log; + + /** * Constructor * * @param \phpbb\textformatter\data_access $data_access @@ -139,11 +144,12 @@ class factory implements \phpbb\textformatter\cache_interface * @param \phpbb\event\dispatcher_interface $dispatcher * @param \phpbb\config\config $config * @param \phpbb\textformatter\s9e\link_helper $link_helper + * @param \phpbb\log\log_interface $log * @param string $cache_dir Path to the cache dir * @param string $cache_key_parser Cache key used for the parser * @param string $cache_key_renderer Cache key used for the renderer */ - public function __construct(\phpbb\textformatter\data_access $data_access, \phpbb\cache\driver\driver_interface $cache, \phpbb\event\dispatcher_interface $dispatcher, \phpbb\config\config $config, \phpbb\textformatter\s9e\link_helper $link_helper, $cache_dir, $cache_key_parser, $cache_key_renderer) + public function __construct(\phpbb\textformatter\data_access $data_access, \phpbb\cache\driver\driver_interface $cache, \phpbb\event\dispatcher_interface $dispatcher, \phpbb\config\config $config, \phpbb\textformatter\s9e\link_helper $link_helper, \phpbb\log\log_interface $log, $cache_dir, $cache_key_parser, $cache_key_renderer) { $this->link_helper = $link_helper; $this->cache = $cache; @@ -153,6 +159,7 @@ class factory implements \phpbb\textformatter\cache_interface $this->config = $config; $this->data_access = $data_access; $this->dispatcher = $dispatcher; + $this->log = $log; } /** @@ -266,12 +273,13 @@ class factory implements \phpbb\textformatter\cache_interface ->addParameterByName('logger') ->addParameterByName('max_img_height') ->addParameterByName('max_img_width') - ->markAsSafeAsURL(); + ->markAsSafeAsURL() + ->setJS('UrlFilter.filter'); // Add default BBCodes foreach ($this->get_default_bbcodes($configurator) as $bbcode) { - $configurator->BBCodes->addCustom($bbcode['usage'], $bbcode['template']); + $this->add_bbcode($configurator, $bbcode['usage'], $bbcode['template']); } if (isset($configurator->tags['QUOTE'])) { @@ -298,17 +306,7 @@ class factory implements \phpbb\textformatter\cache_interface }, $row['bbcode_tpl'] ); - - try - { - $configurator->BBCodes->addCustom($row['bbcode_match'], new UnsafeTemplate($tpl)); - } - catch (\Exception $e) - { - /** - * @todo log an error? - */ - } + $this->add_bbcode($configurator, $row['bbcode_match'], $tpl); } // Load smilies @@ -355,9 +353,15 @@ class factory implements \phpbb\textformatter\cache_interface $configurator->registeredVars['max_img_width'] = 0; // Load the Emoji plugin and modify its tag's template to obey viewsmilies - $configurator->Emoji->omitImageSize(); - $configurator->Emoji->useSVG(); $tag = $configurator->Emoji->getTag(); + $tag->template = '<xsl:choose> + <xsl:when test="@tseq"> + <img alt="{.}" class="emoji" draggable="false" src="//twemoji.maxcdn.com/2/svg/{@tseq}.svg"/> + </xsl:when> + <xsl:otherwise> + <img alt="{.}" class="emoji" draggable="false" src="https://cdn.jsdelivr.net/gh/s9e/emoji-assets-twemoji@11.2/dist/svgz/{@seq}.svgz"/> + </xsl:otherwise> + </xsl:choose>'; $tag->template = '<xsl:choose><xsl:when test="$S_VIEWSMILIES">' . str_replace('class="emoji"', 'class="emoji smilies"', $tag->template) . '</xsl:when><xsl:otherwise><xsl:value-of select="."/></xsl:otherwise></xsl:choose>'; /** @@ -420,6 +424,26 @@ class factory implements \phpbb\textformatter\cache_interface } /** + * Add a BBCode to given configurator + * + * @param Configurator $configurator + * @param string $usage + * @param string $template + * @return void + */ + protected function add_bbcode(Configurator $configurator, $usage, $template) + { + try + { + $configurator->BBCodes->addCustom($usage, new UnsafeTemplate($template)); + } + catch (\Exception $e) + { + $this->log->add('critical', null, null, 'LOG_BBCODE_CONFIGURATION_ERROR', false, [$usage, $e->getMessage()]); + } + } + + /** * Configure the Autolink / Autoemail plugins used to linkify text * * @param \s9e\TextFormatter\Configurator $configurator diff --git a/phpBB/phpbb/textformatter/s9e/link_helper.php b/phpBB/phpbb/textformatter/s9e/link_helper.php index 0f44603dec..483794a83e 100644 --- a/phpBB/phpbb/textformatter/s9e/link_helper.php +++ b/phpBB/phpbb/textformatter/s9e/link_helper.php @@ -23,14 +23,16 @@ class link_helper * * @param \s9e\TextFormatter\Parser\Tag $tag LINK_TEXT tag * @param \s9e\TextFormatter\Parser $parser Parser - * @return bool Whether the tag is valid + * @return void */ public function cleanup_tag(\s9e\TextFormatter\Parser\Tag $tag, \s9e\TextFormatter\Parser $parser) { // Invalidate if the content of the tag matches the text attribute $text = substr($parser->getText(), $tag->getPos(), $tag->getLen()); - - return ($text !== $tag->getAttribute('text')); + if ($text === $tag->getAttribute('text')) + { + $tag->invalidate(); + } } /** @@ -40,7 +42,7 @@ class link_helper * * @param \s9e\TextFormatter\Parser\Tag $tag URL tag (start tag) * @param \s9e\TextFormatter\Parser $parser Parser - * @return bool Always true to indicate that the tag is valid + * @return void */ public function generate_link_text_tag(\s9e\TextFormatter\Parser\Tag $tag, \s9e\TextFormatter\Parser $parser) { @@ -49,7 +51,7 @@ class link_helper // the [url] BBCode when its content is used for the URL if (!$tag->getEndTag() || !$this->should_shorten($tag, $parser->getText())) { - return true; + return; } // Capture the text between the start tag and its end tag @@ -58,10 +60,10 @@ class link_helper $length = $end - $start; $text = substr($parser->getText(), $start, $length); - // Create a tag that consumes the link's text - $parser->addSelfClosingTag('LINK_TEXT', $start, $length)->setAttribute('text', $text); - - return true; + // Create a tag that consumes the link's text and make it depends on this tag + $link_text_tag = $parser->addSelfClosingTag('LINK_TEXT', $start, $length); + $link_text_tag->setAttribute('text', $text); + $tag->cascadeInvalidationTo($link_text_tag); } /** @@ -84,7 +86,7 @@ class link_helper * * @param \s9e\TextFormatter\Parser\Tag $tag LINK_TEXT tag * @param string $board_url Forum's root URL (with trailing slash) - * @return bool Always true to indicate that the tag is valid + * @return void */ public function truncate_local_url(\s9e\TextFormatter\Parser\Tag $tag, $board_url) { @@ -93,15 +95,13 @@ class link_helper { $tag->setAttribute('text', substr($text, strlen($board_url))); } - - return true; } /** * Truncate the replacement text set in a LINK_TEXT tag * * @param \s9e\TextFormatter\Parser\Tag $tag LINK_TEXT tag - * @return bool Always true to indicate that the tag is valid + * @return void */ public function truncate_text(\s9e\TextFormatter\Parser\Tag $tag) { @@ -109,10 +109,7 @@ class link_helper if (utf8_strlen($text) > 55) { $text = utf8_substr($text, 0, 39) . ' ... ' . utf8_substr($text, -10); + $tag->setAttribute('text', $text); } - - $tag->setAttribute('text', $text); - - return true; } } diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index 05ddfffa11..3698dca224 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -13,7 +13,7 @@ namespace phpbb\textformatter\s9e; -use s9e\TextFormatter\Parser\BuiltInFilters; +use s9e\TextFormatter\Parser\AttributeFilters\UrlFilter; use s9e\TextFormatter\Parser\Logger; /** @@ -196,7 +196,7 @@ class parser implements \phpbb\textformatter\parser_interface public function get_errors() { $errors = array(); - foreach ($this->parser->getLogger()->get() as $entry) + foreach ($this->parser->getLogger()->getLogs() as $entry) { list(, $msg, $context) = $entry; @@ -365,7 +365,7 @@ class parser implements \phpbb\textformatter\parser_interface static public function filter_img_url($url, array $url_config, Logger $logger, $max_height, $max_width) { // Validate the URL - $url = BuiltInFilters::filterUrl($url, $url_config, $logger); + $url = UrlFilter::filter($url, $url_config, $logger); if ($url === false) { return false; diff --git a/phpBB/phpbb/textreparser/base.php b/phpBB/phpbb/textreparser/base.php index 27d7bc1f27..2ee6ea2cb3 100644 --- a/phpBB/phpbb/textreparser/base.php +++ b/phpBB/phpbb/textreparser/base.php @@ -153,8 +153,8 @@ abstract class base implements reparser_interface { // Look for the closing tag inside of a e element, in an element of the same name, e.g. // <e>[/url]</e></URL> - $match = '<e>[/' . $bbcode . ']</e></' . strtoupper($bbcode) . '>'; - if (strpos($record['text'], $match) !== false) + $match = '<e>[/' . $bbcode . ']</e></' . $bbcode . '>'; + if (stripos($record['text'], $match) !== false) { return true; } diff --git a/phpBB/phpbb/textreparser/plugins/poll_title.php b/phpBB/phpbb/textreparser/plugins/poll_title.php index 76d30655c9..5ca8bb063b 100644 --- a/phpBB/phpbb/textreparser/plugins/poll_title.php +++ b/phpBB/phpbb/textreparser/plugins/poll_title.php @@ -34,7 +34,7 @@ class poll_title extends \phpbb\textreparser\row_based_plugin $sql = 'SELECT t.topic_id AS id, t.poll_title AS text, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, p.bbcode_uid FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p WHERE t.topic_id BETWEEN ' . $min_id . ' AND ' . $max_id .' - AND t.poll_max_options > 0 + AND t.poll_start > 0 AND p.post_id = t.topic_first_post_id'; return $sql; diff --git a/phpBB/phpbb/tree/nestedset.php b/phpBB/phpbb/tree/nestedset.php index 7149513fd9..eadd2b3273 100644 --- a/phpBB/phpbb/tree/nestedset.php +++ b/phpBB/phpbb/tree/nestedset.php @@ -533,7 +533,7 @@ abstract class nestedset implements \phpbb\tree\tree_interface $row = $this->db->sql_fetchrow($result); $this->db->sql_freeresult($result); - $diff = ' + ' . ($row[$this->column_right_id] - (int) $item[$this->column_left_id] + 1); + $diff = ' + ' . ((int) $row[$this->column_right_id] - (int) $item[$this->column_left_id] + 1); } $sql = 'UPDATE ' . $this->table_name . ' @@ -706,7 +706,7 @@ abstract class nestedset implements \phpbb\tree\tree_interface { $acquired_new_lock = $this->acquire_lock(); - $diff = sizeof($subset_items) * 2; + $diff = count($subset_items) * 2; $sql_subset_items = $this->db->sql_in_set($this->column_item_id, $subset_items); $sql_not_subset_items = $this->db->sql_in_set($this->column_item_id, $subset_items, true); @@ -746,7 +746,7 @@ abstract class nestedset implements \phpbb\tree\tree_interface */ protected function prepare_adding_subset(array $subset_items, array $new_parent) { - $diff = sizeof($subset_items) * 2; + $diff = count($subset_items) * 2; $sql_not_subset_items = $this->db->sql_in_set($this->column_item_id, $subset_items, true); $set_left_id = $this->db->sql_case($this->column_left_id . ' > ' . (int) $new_parent[$this->column_right_id], $this->column_left_id . ' + ' . $diff, $this->column_left_id); diff --git a/phpBB/phpbb/user.php b/phpBB/phpbb/user.php index d4097f53ee..7363290e11 100644 --- a/phpBB/phpbb/user.php +++ b/phpBB/phpbb/user.php @@ -189,6 +189,9 @@ class user extends \phpbb\session /** * Event to load language files and modify user data on every page * + * Note: To load language file with this event, see description + * of lang_set_ext variable. + * * @event core.user_setup * @var array user_data Array with user's data row * @var string user_lang_name Basename of the user's langauge @@ -278,24 +281,6 @@ class user extends \phpbb\session $db->sql_freeresult($result); } - // User has wrong style - if (!$this->style && $style_id == $this->data['user_style']) - { - $style_id = $this->data['user_style'] = $config['default_style']; - - $sql = 'UPDATE ' . USERS_TABLE . " - SET user_style = $style_id - WHERE user_id = {$this->data['user_id']}"; - $db->sql_query($sql); - - $sql = 'SELECT * - FROM ' . STYLES_TABLE . " s - WHERE s.style_id = $style_id"; - $result = $db->sql_query($sql, 3600); - $this->style = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - } - if (!$this->style) { trigger_error('NO_STYLE_DATA', E_USER_ERROR); @@ -358,7 +343,7 @@ class user extends \phpbb\session } // Is board disabled and user not an admin or moderator? - if ($config['board_disable'] && !defined('IN_LOGIN') && !defined('SKIP_CHECK_DISABLED') && !$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_')) + if ($config['board_disable'] && !defined('IN_INSTALL') && !defined('IN_LOGIN') && !defined('SKIP_CHECK_DISABLED') && !$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_')) { if ($this->data['is_bot']) { diff --git a/phpBB/phpbb/user_loader.php b/phpBB/phpbb/user_loader.php index cdd28329db..9297450f3e 100644 --- a/phpBB/phpbb/user_loader.php +++ b/phpBB/phpbb/user_loader.php @@ -64,8 +64,9 @@ class user_loader * Load user helper * * @param array $user_ids + * @param array $ignore_types user types to ignore */ - public function load_users(array $user_ids) + public function load_users(array $user_ids, array $ignore_types = array()) { $user_ids[] = ANONYMOUS; @@ -75,11 +76,12 @@ class user_loader // Do not load users we already have in $this->users $user_ids = array_diff($user_ids, array_keys($this->users)); - if (sizeof($user_ids)) + if (count($user_ids)) { $sql = 'SELECT * FROM ' . $this->users_table . ' - WHERE ' . $this->db->sql_in_set('user_id', $user_ids); + WHERE ' . $this->db->sql_in_set('user_id', $user_ids) . ' + AND ' . $this->db->sql_in_set('user_type', $ignore_types, true, true); $result = $this->db->sql_query($sql); while ($row = $this->db->sql_fetchrow($result)) diff --git a/phpBB/posting.php b/phpBB/posting.php index 02bf1c1d07..5089448483 100644 --- a/phpBB/posting.php +++ b/phpBB/posting.php @@ -33,7 +33,6 @@ $post_id = $request->variable('p', 0); $topic_id = $request->variable('t', 0); $forum_id = $request->variable('f', 0); $draft_id = $request->variable('d', 0); -$lastclick = $request->variable('lastclick', 0); $preview = (isset($_POST['preview'])) ? true : false; $save = (isset($_POST['save'])) ? true : false; @@ -68,7 +67,6 @@ $current_time = time(); * @var int topic_id ID of the topic * @var int forum_id ID of the forum * @var int draft_id ID of the draft -* @var int lastclick Timestamp of when the form was last loaded * @var bool submit Whether or not the form has been submitted * @var bool preview Whether or not the post is being previewed * @var bool save Whether or not a draft is being saved @@ -85,13 +83,13 @@ $current_time = time(); * language keys. * @since 3.1.0-a1 * @changed 3.1.2-RC1 Removed 'delete' var as it does not exist +* @changed 3.2.4-RC1 Remove unused 'lastclick' var */ $vars = array( 'post_id', 'topic_id', 'forum_id', 'draft_id', - 'lastclick', 'submit', 'preview', 'save', @@ -224,6 +222,25 @@ if (!$post_data) trigger_error(($mode == 'post' || $mode == 'bump' || $mode == 'reply') ? 'NO_TOPIC' : 'NO_POST'); } +/** +* This event allows you to bypass reply/quote test of an unapproved post. +* +* @event core.posting_modify_row_data +* @var array post_data All post data from database +* @var string mode What action to take if the form has been submitted +* post|reply|quote|edit|delete|bump|smilies|popup +* @var int topic_id ID of the topic +* @var int forum_id ID of the forum +* @since 3.2.8-RC1 +*/ +$vars = array( + 'post_data', + 'mode', + 'topic_id', + 'forum_id', +); +extract($phpbb_dispatcher->trigger_event('core.posting_modify_row_data', compact($vars))); + // Not able to reply to unapproved posts/topics // TODO: add more descriptive language key if ($auth->acl_get('m_approve', $forum_id) && ((($mode == 'reply' || $mode == 'bump') && $post_data['topic_visibility'] != ITEM_APPROVED) || ($mode == 'quote' && $post_data['post_visibility'] != ITEM_APPROVED))) @@ -354,7 +371,6 @@ switch ($mode) * @var int topic_id ID of the topic * @var int forum_id ID of the forum * @var int draft_id ID of the draft -* @var int lastclick Timestamp of when the form was last loaded * @var bool submit Whether or not the form has been submitted * @var bool preview Whether or not the post is being previewed * @var bool save Whether or not a draft is being saved @@ -370,13 +386,13 @@ switch ($mode) * @var array post_data All post data from database * @since 3.1.3-RC1 * @changed 3.1.10-RC1 Added post_data +* @changed 3.2.4-RC1 Remove unused 'lastclick' var */ $vars = array( 'post_id', 'topic_id', 'forum_id', 'draft_id', - 'lastclick', 'submit', 'preview', 'save', @@ -581,7 +597,7 @@ if ($mode == 'edit') ); } -$orig_poll_options_size = sizeof($post_data['poll_options']); +$orig_poll_options_size = count($post_data['poll_options']); $message_parser = new parse_message(); /* @var $plupload \phpbb\plupload\plupload */ @@ -600,6 +616,20 @@ if (isset($post_data['post_text'])) // Set some default variables $uninit = array('post_attachment' => 0, 'poster_id' => $user->data['user_id'], 'enable_magic_url' => 0, 'topic_status' => 0, 'topic_type' => POST_NORMAL, 'post_subject' => '', 'topic_title' => '', 'post_time' => 0, 'post_edit_reason' => '', 'notify_set' => 0); +/** +* This event allows you to modify the default variables for post_data, and unset them in post_data if needed +* +* @event core.posting_modify_default_variables +* @var array post_data Array with post data +* @var array uninit Array with default vars to put into post_data, if they aren't there +* @since 3.2.5-RC1 +*/ +$vars = array( + 'post_data', + 'uninit', +); +extract($phpbb_dispatcher->trigger_event('core.posting_modify_default_variables', compact($vars))); + foreach ($uninit as $var_name => $default_value) { if (!isset($post_data[$var_name])) @@ -835,6 +865,7 @@ if ($load && ($mode == 'reply' || $mode == 'quote' || $mode == 'post') && $post_ load_drafts($topic_id, $forum_id); } +/** @var \phpbb\textformatter\utils_interface $bbcode_utils */ $bbcode_utils = $phpbb_container->get('text_formatter.utils'); if ($submit || $preview || $refresh) @@ -884,7 +915,7 @@ if ($submit || $preview || $refresh) } // Delete Poll - if ($poll_delete && $mode == 'edit' && sizeof($post_data['poll_options']) && + if ($poll_delete && $mode == 'edit' && count($post_data['poll_options']) && ((!$post_data['poll_last_vote'] && $post_data['poster_id'] == $user->data['user_id'] && $auth->acl_get('f_delete', $forum_id)) || $auth->acl_get('m_delete', $forum_id))) { if ($submit && check_form_key('posting')) @@ -1034,7 +1065,7 @@ if ($submit || $preview || $refresh) // Parse message if ($update_message) { - if (sizeof($message_parser->warn_msg)) + if (count($message_parser->warn_msg)) { $error[] = implode('<br />', $message_parser->warn_msg); $message_parser->warn_msg = array(); @@ -1046,7 +1077,7 @@ if ($submit || $preview || $refresh) } // On a refresh we do not care about message parsing errors - if (sizeof($message_parser->warn_msg) && $refresh && !$preview) + if (count($message_parser->warn_msg) && $refresh && !$preview) { $message_parser->warn_msg = array(); } @@ -1268,7 +1299,7 @@ if ($submit || $preview || $refresh) } } - if (sizeof($message_parser->warn_msg)) + if (count($message_parser->warn_msg)) { $error[] = implode('<br />', $message_parser->warn_msg); } @@ -1313,7 +1344,7 @@ if ($submit || $preview || $refresh) extract($phpbb_dispatcher->trigger_event('core.posting_modify_submission_errors', compact($vars))); // Store message, sync counters - if (!sizeof($error) && $submit) + if (!count($error) && $submit) { if ($submit) { @@ -1510,7 +1541,7 @@ if ($submit || $preview || $refresh) } // Preview -if (!sizeof($error) && $preview) +if (!count($error) && $preview) { $post_data['post_time'] = ($mode == 'edit') ? $post_data['post_time'] : $current_time; @@ -1552,7 +1583,7 @@ if (!sizeof($error) && $preview) } $template->assign_vars(array( - 'S_HAS_POLL_OPTIONS' => (sizeof($post_data['poll_options'])), + 'S_HAS_POLL_OPTIONS' => (count($post_data['poll_options'])), 'S_IS_MULTI_CHOICE' => ($post_data['poll_max_options'] > 1) ? true : false, 'POLL_QUESTION' => $parse_poll->message, @@ -1581,7 +1612,7 @@ if (!sizeof($error) && $preview) } // Attachment Preview - if (sizeof($message_parser->attachment_data)) + if (count($message_parser->attachment_data)) { $template->assign_var('S_HAS_ATTACHMENTS', true); @@ -1599,7 +1630,7 @@ if (!sizeof($error) && $preview) unset($attachment_data); } - if (!sizeof($error)) + if (!count($error)) { $template->assign_vars(array( 'PREVIEW_SUBJECT' => $preview_subject, @@ -1622,7 +1653,7 @@ if ($generate_quote && $config['max_quote_depth'] > 0) } // Decode text for message display -$post_data['bbcode_uid'] = ($mode == 'quote' && !$preview && !$refresh && !sizeof($error)) ? $post_data['bbcode_uid'] : $message_parser->bbcode_uid; +$post_data['bbcode_uid'] = ($mode == 'quote' && !$preview && !$refresh && !count($error)) ? $post_data['bbcode_uid'] : $message_parser->bbcode_uid; $message_parser->decode_message($post_data['bbcode_uid']); if ($generate_quote) @@ -1630,47 +1661,56 @@ if ($generate_quote) // Remove attachment bbcode tags from the quoted message to avoid mixing with the new post attachments if any $message_parser->message = preg_replace('#\[attachment=([0-9]+)\](.*?)\[\/attachment\]#uis', '\\2', $message_parser->message); - if ($config['allow_bbcode']) - { - $message_parser->message = $bbcode_utils->generate_quote( - censor_text($message_parser->message), - array( - 'author' => $post_data['quote_username'], - 'post_id' => $post_data['post_id'], - 'time' => $post_data['post_time'], - 'user_id' => $post_data['poster_id'], - ) - ); - $message_parser->message .= "\n\n"; - } - else - { - $offset = 0; - $quote_string = "> "; - $message = censor_text(trim($message_parser->message)); - // see if we are nesting. It's easily tricked but should work for one level of nesting - if (strpos($message, ">") !== false) - { - $offset = 10; - } - $message = utf8_wordwrap($message, 75 + $offset, "\n"); + $quote_attributes = array( + 'author' => $post_data['quote_username'], + 'post_id' => $post_data['post_id'], + 'time' => $post_data['post_time'], + 'user_id' => $post_data['poster_id'], + ); - $message = $quote_string . $message; - $message = str_replace("\n", "\n" . $quote_string, $message); - $message_parser->message = $post_data['quote_username'] . " " . $user->lang['WROTE'] . ":\n" . $message . "\n"; - } + /** + * This event allows you to modify the quote attributes of the post being quoted + * + * @event core.posting_modify_quote_attributes + * @var array quote_attributes Array with quote attributes + * @var array post_data Array with post data + * @since 3.2.6-RC1 + */ + $vars = array( + 'quote_attributes', + 'post_data', + ); + extract($phpbb_dispatcher->trigger_event('core.posting_modify_quote_attributes', compact($vars))); + + /** @var \phpbb\language\language $language */ + $language = $phpbb_container->get('language'); + phpbb_format_quote($language, $message_parser, $bbcode_utils, $bbcode_status, $quote_attributes); } if (($mode == 'reply' || $mode == 'quote') && !$submit && !$preview && !$refresh) { $post_data['post_subject'] = ((strpos($post_data['post_subject'], 'Re: ') !== 0) ? 'Re: ' : '') . censor_text($post_data['post_subject']); + + $post_subject = $post_data['post_subject']; + + /** + * This event allows you to modify the post subject of the post being quoted + * + * @event core.posting_modify_post_subject + * @var string post_subject String with the post subject already censored. + * @since 3.2.8-RC1 + */ + $vars = array('post_subject'); + extract($phpbb_dispatcher->trigger_event('core.posting_modify_post_subject', compact($vars))); + + $post_data['post_subject'] = $post_subject; } $attachment_data = $message_parser->attachment_data; $filename_data = $message_parser->filename_data; $post_data['post_text'] = $message_parser->message; -if (sizeof($post_data['poll_options']) || (isset($post_data['poll_title']) && !$bbcode_utils->is_empty($post_data['poll_title']))) +if (count($post_data['poll_options']) || (isset($post_data['poll_title']) && !$bbcode_utils->is_empty($post_data['poll_title']))) { $message_parser->message = $post_data['poll_title']; $message_parser->bbcode_uid = $post_data['bbcode_uid']; @@ -1762,7 +1802,6 @@ if ($config['enable_post_confirm'] && !$user->data['is_registered'] && (isset($c } $s_hidden_fields = ($mode == 'reply' || $mode == 'quote') ? '<input type="hidden" name="topic_cur_post_id" value="' . $post_data['topic_last_post_id'] . '" />' : ''; -$s_hidden_fields .= '<input type="hidden" name="lastclick" value="' . $current_time . '" />'; $s_hidden_fields .= ($draft_id || isset($_REQUEST['draft_loaded'])) ? '<input type="hidden" name="draft_loaded" value="' . $request->variable('draft_loaded', $draft_id) . '" />' : ''; if ($mode == 'edit') @@ -1795,7 +1834,7 @@ $page_data = array( 'FORUM_NAME' => $post_data['forum_name'], 'FORUM_DESC' => ($post_data['forum_desc']) ? generate_text_for_display($post_data['forum_desc'], $post_data['forum_desc_uid'], $post_data['forum_desc_bitfield'], $post_data['forum_desc_options']) : '', 'TOPIC_TITLE' => censor_text($post_data['topic_title']), - 'MODERATORS' => (sizeof($moderators)) ? implode($user->lang['COMMA_SEPARATOR'], $moderators[$forum_id]) : '', + 'MODERATORS' => (count($moderators)) ? implode($user->lang['COMMA_SEPARATOR'], $moderators[$forum_id]) : '', 'USERNAME' => ((!$preview && $mode != 'quote') || $preview) ? $post_data['username'] : '', 'SUBJECT' => $post_data['post_subject'], 'MESSAGE' => $post_data['post_text'], @@ -1807,7 +1846,7 @@ $page_data = array( 'MAX_FONT_SIZE' => (int) $config['max_post_font_size'], 'MINI_POST_IMG' => $user->img('icon_post_target', $user->lang['POST']), 'POST_DATE' => ($post_data['post_time']) ? $user->format_date($post_data['post_time']) : '', - 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + 'ERROR' => (count($error)) ? implode('<br />', $error) : '', 'TOPIC_TIME_LIMIT' => (int) $post_data['topic_time_limit'], 'EDIT_REASON' => $request->variable('edit_reason', '', true), 'SHOW_PANEL' => $request->variable('show_panel', ''), @@ -1867,7 +1906,7 @@ if (($mode == 'post' || ($mode == 'edit' && $post_id == $post_data['topic_first_ $page_data = array_merge($page_data, array( 'S_SHOW_POLL_BOX' => true, 'S_POLL_VOTE_CHANGE' => ($auth->acl_get('f_votechg', $forum_id) && $auth->acl_get('f_vote', $forum_id)), - 'S_POLL_DELETE' => ($mode == 'edit' && sizeof($post_data['poll_options']) && ((!$post_data['poll_last_vote'] && $post_data['poster_id'] == $user->data['user_id'] && $auth->acl_get('f_delete', $forum_id)) || $auth->acl_get('m_delete', $forum_id))), + 'S_POLL_DELETE' => ($mode == 'edit' && count($post_data['poll_options']) && ((!$post_data['poll_last_vote'] && $post_data['poster_id'] == $user->data['user_id'] && $auth->acl_get('f_delete', $forum_id)) || $auth->acl_get('m_delete', $forum_id))), 'S_POLL_DELETE_CHECKED' => (!empty($poll_delete)) ? true : false, 'L_POLL_OPTIONS_EXPLAIN' => $user->lang('POLL_OPTIONS_' . (($mode == 'edit') ? 'EDIT_' : '') . 'EXPLAIN', (int) $config['max_poll_options']), diff --git a/phpBB/search.php b/phpBB/search.php index f3988d7d04..791e5cc448 100644 --- a/phpBB/search.php +++ b/phpBB/search.php @@ -198,7 +198,7 @@ if ($keywords || $author || $author_id || $search_id || $submit) $sql_author_match = (strpos($author, '*') !== false) ? ' ' . $db->sql_like_expression(str_replace('*', $db->get_any_char(), utf8_clean_string($author))) : " = '" . $db->sql_escape(utf8_clean_string($author)) . "'"; } - if (!sizeof($author_id_ary)) + if (!count($author_id_ary)) { trigger_error('NO_SEARCH_RESULTS'); } @@ -220,7 +220,7 @@ if ($keywords || $author || $author_id || $search_id || $submit) } // Which forums should not be searched? Author searches are also carried out in unindexed forums - if (empty($keywords) && sizeof($author_id_ary)) + if (empty($keywords) && count($author_id_ary)) { $ex_fid_ary = array_keys($auth->acl_getf('!f_read', true)); } @@ -229,7 +229,7 @@ if ($keywords || $author || $author_id || $search_id || $submit) $ex_fid_ary = array_unique(array_merge(array_keys($auth->acl_getf('!f_read', true)), array_keys($auth->acl_getf('!f_search', true)))); } - $not_in_fid = (sizeof($ex_fid_ary)) ? 'WHERE ' . $db->sql_in_set('f.forum_id', $ex_fid_ary, true) . " OR (f.forum_password <> '' AND fa.user_id <> " . (int) $user->data['user_id'] . ')' : ""; + $not_in_fid = (count($ex_fid_ary)) ? 'WHERE ' . $db->sql_in_set('f.forum_id', $ex_fid_ary, true) . " OR (f.forum_password <> '' AND fa.user_id <> " . (int) $user->data['user_id'] . ')' : ""; $sql = 'SELECT f.forum_id, f.forum_name, f.parent_id, f.forum_type, f.right_id, f.forum_password, f.forum_flags, fa.user_id FROM ' . FORUMS_TABLE . ' f @@ -256,7 +256,7 @@ if ($keywords || $author || $author_id || $search_id || $submit) continue; } - if (sizeof($search_forum)) + if (count($search_forum)) { if ($search_child) { @@ -309,9 +309,9 @@ if ($keywords || $author || $author_id || $search_id || $submit) { $correct_query = $search->split_keywords($keywords, $search_terms); $common_words = $search->get_common_words(); - if (!$correct_query || (!$search->get_search_query() && !sizeof($author_id_ary) && !$search_id)) + if (!$correct_query || (!$search->get_search_query() && !count($author_id_ary) && !$search_id)) { - $ignored = (sizeof($common_words)) ? sprintf($user->lang['IGNORED_TERMS_EXPLAIN'], implode(' ', $common_words)) . '<br />' : ''; + $ignored = (count($common_words)) ? sprintf($user->lang['IGNORED_TERMS_EXPLAIN'], implode(' ', $common_words)) . '<br />' : ''; $word_length = $search->get_word_length(); if ($word_length) { @@ -324,7 +324,7 @@ if ($keywords || $author || $author_id || $search_id || $submit) } } - if (!$keywords && sizeof($author_id_ary)) + if (!$keywords && count($author_id_ary)) { // if it is an author search we want to show topics by default $show_results = ($topic_id) ? 'posts' : $request->variable('sr', ($search_id == 'egosearch') ? 'topics' : 'posts'); @@ -384,7 +384,7 @@ if ($keywords || $author || $author_id || $search_id || $submit) WHERE t.topic_moved_id = 0 $last_post_time_sql AND " . $m_approve_topics_fid_sql . ' - ' . ((sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('t.forum_id', $ex_fid_ary, true) : '') . ' + ' . ((count($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('t.forum_id', $ex_fid_ary, true) : '') . ' ORDER BY t.topic_last_post_time DESC'; $field = 'topic_id'; break; @@ -422,7 +422,7 @@ if ($keywords || $author || $author_id || $search_id || $submit) AND p.topic_id = t.topic_id $last_post_time AND $m_approve_posts_fid_sql - " . ((sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '') . " + " . ((count($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '') . " $sql_sort"; $field = 'post_id'; } @@ -435,7 +435,7 @@ if ($keywords || $author || $author_id || $search_id || $submit) AND p.topic_id = t.topic_id $last_post_time AND $m_approve_topics_fid_sql - " . ((sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '') . " + " . ((count($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '') . " $sql_sort"; $field = 'topic_id'; } @@ -451,7 +451,7 @@ if ($keywords || $author || $author_id || $search_id || $submit) $sql_where = 'AND t.topic_moved_id = 0 AND ' . $m_approve_topics_fid_sql . ' - ' . ((sizeof($ex_fid_ary)) ? 'AND ' . $db->sql_in_set('t.forum_id', $ex_fid_ary, true) : ''); + ' . ((count($ex_fid_ary)) ? 'AND ' . $db->sql_in_set('t.forum_id', $ex_fid_ary, true) : ''); gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param); $s_sort_key = $s_sort_dir = $u_sort_param = $s_limit_days = ''; @@ -477,7 +477,7 @@ if ($keywords || $author || $author_id || $search_id || $submit) FROM ' . POSTS_TABLE . ' p WHERE p.post_time > ' . $user->data['user_lastvisit'] . ' AND ' . $m_approve_posts_fid_sql . ' - ' . ((sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '') . " + ' . ((count($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '') . " $sql_sort"; $field = 'post_id'; } @@ -488,7 +488,7 @@ if ($keywords || $author || $author_id || $search_id || $submit) WHERE t.topic_last_post_time > ' . $user->data['user_lastvisit'] . ' AND t.topic_moved_id = 0 AND ' . $m_approve_topics_fid_sql . ' - ' . ((sizeof($ex_fid_ary)) ? 'AND ' . $db->sql_in_set('t.forum_id', $ex_fid_ary, true) : '') . " + ' . ((count($ex_fid_ary)) ? 'AND ' . $db->sql_in_set('t.forum_id', $ex_fid_ary, true) : '') . " $sql_sort"; /* [Fix] queued replies missing from "view new posts" (Bug #42705 - Patch by Paul) @@ -562,7 +562,7 @@ if ($keywords || $author || $author_id || $search_id || $submit) $search_id = ''; } - $total_match_count = sizeof($id_ary); + $total_match_count = count($id_ary); if ($total_match_count) { // Limit the number to $total_matches_limit for pre-made searches @@ -592,7 +592,7 @@ if ($keywords || $author || $author_id || $search_id || $submit) { $total_match_count = $search->keyword_search($show_results, $search_fields, $search_terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_posts_fid_sql, $topic_id, $author_id_ary, $sql_author_match, $id_ary, $start, $per_page); } - else if (sizeof($author_id_ary)) + else if (count($author_id_ary)) { $firstpost_only = ($search_fields === 'firstpost' || $search_fields == 'titleonly') ? true : false; $total_match_count = $search->author_search($show_results, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_posts_fid_sql, $topic_id, $author_id_ary, $sql_author_match, $id_ary, $start, $per_page); @@ -642,10 +642,10 @@ if ($keywords || $author || $author_id || $search_id || $submit) $sql_where = ''; - if (sizeof($id_ary)) + if (count($id_ary)) { $sql_where .= $db->sql_in_set(($show_results == 'posts') ? 'p.post_id' : 't.topic_id', $id_ary); - $sql_where .= (sizeof($ex_fid_ary)) ? ' AND (' . $db->sql_in_set('f.forum_id', $ex_fid_ary, true) . ' OR f.forum_id IS NULL)' : ''; + $sql_where .= (count($ex_fid_ary)) ? ' AND (' . $db->sql_in_set('f.forum_id', $ex_fid_ary, true) . ' OR f.forum_id IS NULL)' : ''; $sql_where .= ' AND ' . (($show_results == 'posts') ? $m_approve_posts_fid_sql : $m_approve_topics_fid_sql); } @@ -883,7 +883,7 @@ if ($keywords || $author || $author_id || $search_id || $submit) $db->sql_freeresult($result); // If we have some shadow topics, update the rowset to reflect their topic information - if (sizeof($shadow_topic_list)) + if (count($shadow_topic_list)) { $sql = 'SELECT * FROM ' . TOPICS_TABLE . ' @@ -932,6 +932,26 @@ if ($keywords || $author || $author_id || $search_id || $submit) while ($row = $db->sql_fetchrow($result)) { + /** + * Modify the row of a post result before the post_text is trimmed + * + * @event core.search_modify_post_row + * @var string hilit String to highlight + * @var array row Array with the post data + * @var string u_hilit Highlight string to be injected into URL + * @var string view Search results view mode + * @var array zebra Array with zebra data for the current user + * @since 3.2.2-RC1 + */ + $vars = array( + 'hilit', + 'row', + 'u_hilit', + 'view', + 'zebra', + ); + extract($phpbb_dispatcher->trigger_event('core.search_modify_post_row', compact($vars))); + // We pre-process some variables here for later usage $row['post_text'] = censor_text($row['post_text']); @@ -967,7 +987,7 @@ if ($keywords || $author || $author_id || $search_id || $submit) unset($text_only_message); // Pull attachment data - if (sizeof($attach_list)) + if (count($attach_list)) { $use_attach_list = $attach_list; $attach_list = array(); @@ -981,7 +1001,7 @@ if ($keywords || $author || $author_id || $search_id || $submit) } } - if (sizeof($attach_list)) + if (count($attach_list)) { $sql = 'SELECT * FROM ' . ATTACHMENTS_TABLE . ' diff --git a/phpBB/styles/prosilver/style.cfg b/phpBB/styles/prosilver/style.cfg index 2deceef788..8e3ba24aaa 100644 --- a/phpBB/styles/prosilver/style.cfg +++ b/phpBB/styles/prosilver/style.cfg @@ -21,11 +21,11 @@ # General Information about this style name = prosilver copyright = © phpBB Limited, 2007 -style_version = 3.2.1 -phpbb_version = 3.2.1 +style_version = 3.2.8 +phpbb_version = 3.2.8 # Defining a different template bitfield -# template_bitfield = lNg= +# template_bitfield = //g= # Parent style # Set value to empty or to this style's name if this style does not have a parent style diff --git a/phpBB/styles/prosilver/template/ajax.js b/phpBB/styles/prosilver/template/ajax.js index 6903ad2261..5e66e5cda1 100644 --- a/phpBB/styles/prosilver/template/ajax.js +++ b/phpBB/styles/prosilver/template/ajax.js @@ -199,7 +199,7 @@ phpbb.addAjaxCallback('zebra', function(res) { */ phpbb.addAjaxCallback('vote_poll', function(res) { if (typeof res.success !== 'undefined') { - var poll = $('.topic_poll'); + var poll = $(this).closest('.topic_poll'); var panel = poll.find('.panel'); var resultsVisible = poll.find('dl:first-child .resultbar').is(':visible'); var mostVotes = 0; diff --git a/phpBB/styles/prosilver/template/attachment.html b/phpBB/styles/prosilver/template/attachment.html index 0978d9189e..615717e026 100644 --- a/phpBB/styles/prosilver/template/attachment.html +++ b/phpBB/styles/prosilver/template/attachment.html @@ -8,14 +8,14 @@ <!-- IF _file.S_THUMBNAIL --> <dl class="thumbnail"> - <dt><a href="{_file.U_DOWNLOAD_LINK}"><img src="{_file.THUMB_IMAGE}" class="postimage" alt="{_file.DOWNLOAD_NAME}" title="{_file.DOWNLOAD_NAME} ({_file.FILESIZE} {_file.SIZE_LANG}) {_file.L_DOWNLOAD_COUNT}" /></a></dt> + <dt><a href="{_file.U_DOWNLOAD_LINK}"><img src="{_file.THUMB_IMAGE}" class="postimage" alt="{% if _file.COMMENT %}{{ _file.COMMENT|e('html') }}{% else %}{{ _file.DOWNLOAD_NAME }}{% endif %}" title="{_file.DOWNLOAD_NAME} ({_file.FILESIZE} {_file.SIZE_LANG}) {_file.L_DOWNLOAD_COUNT}" /></a></dt> <!-- IF _file.COMMENT --><dd> {_file.COMMENT}</dd><!-- ENDIF --> </dl> <!-- ENDIF --> <!-- IF _file.S_IMAGE --> <dl class="file"> - <dt class="attach-image"><img src="{_file.U_INLINE_LINK}" class="postimage" alt="{_file.DOWNLOAD_NAME}" onclick="viewableArea(this);" /></dt> + <dt class="attach-image"><img src="{_file.U_INLINE_LINK}" class="postimage" alt="{% if _file.COMMENT %}{{ _file.COMMENT|e('html') }}{% else %}{{ _file.DOWNLOAD_NAME }}{% endif %}" onclick="viewableArea(this);" /></dt> <!-- IF _file.COMMENT --><dd><em>{_file.COMMENT}</em></dd><!-- ENDIF --> <dd>{_file.DOWNLOAD_NAME} ({_file.FILESIZE} {_file.SIZE_LANG}) {_file.L_DOWNLOAD_COUNT}</dd> </dl> diff --git a/phpBB/styles/prosilver/template/confirm_delete_body.html b/phpBB/styles/prosilver/template/confirm_delete_body.html index 98974963c0..637830a5bc 100644 --- a/phpBB/styles/prosilver/template/confirm_delete_body.html +++ b/phpBB/styles/prosilver/template/confirm_delete_body.html @@ -49,6 +49,8 @@ </dl> <!-- ENDIF --> + {% EVENT confirm_delete_body_delete_reason_before %} + <dl> <dt><label for="delete_reason">{L_DELETE_REASON}{L_COLON}</label><br /><span>{L_DELETE_REASON_EXPLAIN}</span></dt> <dd><input type="text" name="delete_reason" id="delete_reason" value="" class="inputbox autowidth" maxlength="120" size="45" /></dd> diff --git a/phpBB/styles/prosilver/template/forum_fn.js b/phpBB/styles/prosilver/template/forum_fn.js index 3f59709ac6..3f28f8a326 100644 --- a/phpBB/styles/prosilver/template/forum_fn.js +++ b/phpBB/styles/prosilver/template/forum_fn.js @@ -273,11 +273,9 @@ function insertUser(formId, value) { function insert_marked_users(formId, users) { 'use strict'; - for (var i = 0; i < users.length; i++) { - if (users[i].checked) { - insertUser(formId, users[i].value); - } - } + $(users).filter(':checked').each(function() { + insertUser(formId, this.value); + }); window.close(); } @@ -612,7 +610,7 @@ function parseDocument($container) { // If there are any images in the links list, run the check again after they have loaded $linksAll.find('img').each(function() { - $(this).load(function() { + $(this).on('load', function() { check(); }); }); diff --git a/phpBB/styles/prosilver/template/forumlist_body.html b/phpBB/styles/prosilver/template/forumlist_body.html index c1a1445483..4932860f8c 100644 --- a/phpBB/styles/prosilver/template/forumlist_body.html +++ b/phpBB/styles/prosilver/template/forumlist_body.html @@ -42,7 +42,11 @@ </a> --> <!-- ENDIF --> - <!-- IF forumrow.FORUM_IMAGE --><span class="forum-image">{forumrow.FORUM_IMAGE}</span><!-- ENDIF --> + <!-- IF forumrow.FORUM_IMAGE --> + <!-- EVENT forumlist_body_forum_image_before --> + <span class="forum-image"><!-- EVENT forumlist_body_forum_image_prepend -->{forumrow.FORUM_IMAGE}<!-- EVENT forumlist_body_forum_image_append --></span> + <!-- EVENT forumlist_body_forum_image_after --> + <!-- ENDIF --> <a href="{forumrow.U_VIEWFORUM}" class="forumtitle">{forumrow.FORUM_NAME}</a> <!-- IF forumrow.FORUM_DESC --><br />{forumrow.FORUM_DESC}<!-- ENDIF --> <!-- IF forumrow.MODERATORS --> @@ -91,7 +95,7 @@ <!-- 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} + {L_POST_BY_AUTHOR} <!-- EVENT forumlist_body_last_poster_username_prepend -->{forumrow.LAST_POSTER_FULL}<!-- EVENT forumlist_body_last_poster_username_append --> <!-- IF not S_IS_BOT --> <a href="{forumrow.U_LAST_POST}" title="{L_VIEW_LATEST_POST}"> <i class="icon fa-external-link-square fa-fw icon-lightgray icon-md" aria-hidden="true"></i><span class="sr-only">{L_VIEW_LATEST_POST}</span> @@ -99,7 +103,11 @@ <!-- ENDIF --> <br /><time datetime="{forumrow.LAST_POST_TIME_RFC3339}">{forumrow.LAST_POST_TIME}</time> <!-- ELSE --> - {L_NO_POSTS}<br /> + {% if forumrow.U_UNAPPROVED_TOPICS %} + {{ lang('TOPIC_UNAPPROVED_FORUM', forumrow.TOPICS) }} + {% else %} + {{ lang('NO_POSTS') }} + {% endif %} <!-- ENDIF --> </span> </dd> diff --git a/phpBB/styles/prosilver/template/index_body.html b/phpBB/styles/prosilver/template/index_body.html index b292c40eb2..239a91c580 100644 --- a/phpBB/styles/prosilver/template/index_body.html +++ b/phpBB/styles/prosilver/template/index_body.html @@ -29,6 +29,7 @@ <!-- ENDIF --> <input type="submit" tabindex="5" name="login" value="{L_LOGIN}" class="button2" /> {S_LOGIN_REDIRECT} + {S_FORM_TOKEN_LOGIN} </fieldset> </form> <!-- ENDIF --> diff --git a/phpBB/styles/prosilver/template/login_body.html b/phpBB/styles/prosilver/template/login_body.html index ef08035717..dc597af51d 100644 --- a/phpBB/styles/prosilver/template/login_body.html +++ b/phpBB/styles/prosilver/template/login_body.html @@ -33,6 +33,7 @@ <!-- ENDIF --> {S_LOGIN_REDIRECT} + {S_FORM_TOKEN_LOGIN} <dl> <dt> </dt> <dd>{S_HIDDEN_FIELDS}<input type="submit" name="login" tabindex="6" value="{L_LOGIN}" class="button1" /></dd> diff --git a/phpBB/styles/prosilver/template/login_body_oauth.html b/phpBB/styles/prosilver/template/login_body_oauth.html index 156485d211..1364d01ccb 100644 --- a/phpBB/styles/prosilver/template/login_body_oauth.html +++ b/phpBB/styles/prosilver/template/login_body_oauth.html @@ -1,8 +1,6 @@ +<br> <div class="content"> - <!-- BEGIN oauth --> - <dl> - <dt> </dt> - <dd><a href="{oauth.REDIRECT_URL}" class="button2">{oauth.SERVICE_NAME}</a></dd> - </dl> - <!-- END oauth --> + {% for oauth in oauth %} + <a href="{{ oauth.REDIRECT_URL }}" class="button2">{{ oauth.SERVICE_NAME }}</a> + {% endfor %} </div> diff --git a/phpBB/styles/prosilver/template/login_forum.html b/phpBB/styles/prosilver/template/login_forum.html index 7fa9736a96..c5c36d4564 100644 --- a/phpBB/styles/prosilver/template/login_forum.html +++ b/phpBB/styles/prosilver/template/login_forum.html @@ -25,6 +25,7 @@ <dd><input type="password" tabindex="1" id="password" name="password" size="25" class="inputbox narrow" autocomplete="off" /></dd> </dl> {S_LOGIN_REDIRECT} + {S_FORM_TOKEN_LOGIN} <dl> <dt> </dt> <dd>{S_HIDDEN_FIELDS}<input type="submit" name="login" id="login" class="button1" value="{L_LOGIN}" tabindex="2" /></dd> diff --git a/phpBB/styles/prosilver/template/mcp_ban.html b/phpBB/styles/prosilver/template/mcp_ban.html index 5b798d9b6c..86a322435d 100644 --- a/phpBB/styles/prosilver/template/mcp_ban.html +++ b/phpBB/styles/prosilver/template/mcp_ban.html @@ -1,8 +1,6 @@ <!-- INCLUDE mcp_header.html --> -<script type="text/javascript"> -// <![CDATA[ - +<script> var ban_length = new Array(); ban_length[-1] = ''; var ban_reason = new Array(); @@ -11,12 +9,12 @@ ban_give_reason[-1] = ''; <!-- BEGIN bans --> - ban_length['{bans.BAN_ID}'] = '{bans.A_LENGTH}'; + ban_length['{bans.BAN_ID}'] = '{{ bans.A_LENGTH }}'; <!-- IF bans.A_REASON --> - ban_reason['{bans.BAN_ID}'] = '{bans.A_REASON}'; + ban_reason['{bans.BAN_ID}'] = '{{ bans.REASON | e('js') }}'; <!-- ENDIF --> <!-- IF bans.A_GIVE_REASON --> - ban_give_reason['{bans.BAN_ID}'] = '{bans.A_GIVE_REASON}'; + ban_give_reason['{bans.BAN_ID}'] = '{{ bans.GIVE_REASON | e('js') }}'; <!-- ENDIF --> <!-- END bans --> @@ -34,8 +32,6 @@ document.getElementById('unbangivereason').innerHTML = ''; } } - -// ]]> </script> <form id="mcp_ban" method="post" action="{U_ACTION}"> diff --git a/phpBB/styles/prosilver/template/mcp_forum.html b/phpBB/styles/prosilver/template/mcp_forum.html index f6c518e1df..82df5d5dbe 100644 --- a/phpBB/styles/prosilver/template/mcp_forum.html +++ b/phpBB/styles/prosilver/template/mcp_forum.html @@ -86,7 +86,9 @@ <div class="responsive-hide"> <!-- IF topicrow.ATTACH_ICON_IMG --><i class="icon fa-paperclip fa-fw" aria-hidden="true"></i> <!-- ENDIF --> + {% EVENT topiclist_row_topic_by_author_before %} {L_POST_BY_AUTHOR} {topicrow.TOPIC_AUTHOR_FULL} » {topicrow.FIRST_POST_TIME} + {% EVENT topiclist_row_topic_by_author_after %} </div> <!-- EVENT topiclist_row_append --> </div> diff --git a/phpBB/styles/prosilver/template/mcp_move.html b/phpBB/styles/prosilver/template/mcp_move.html index 45a9ae83bc..63197ef274 100644 --- a/phpBB/styles/prosilver/template/mcp_move.html +++ b/phpBB/styles/prosilver/template/mcp_move.html @@ -43,12 +43,14 @@ <!-- IF ADDITIONAL_MSG --><p>{ADDITIONAL_MSG}</p><!-- ENDIF --> <fieldset> + {% EVENT mcp_move_destination_forum_before %} <dl class="fields2"> <dt><label>{L_SELECT_DESTINATION_FORUM}{L_COLON}</label></dt> <dd><select name="to_forum_id">{S_FORUM_SELECT}</select></dd> <!-- IF S_CAN_LEAVE_SHADOW --><dd><label for="move_leave_shadow"><input type="checkbox" name="move_leave_shadow" id="move_leave_shadow" />{L_LEAVE_SHADOW}</label></dd><!-- ENDIF --> <!-- IF S_CAN_LOCK_TOPIC --><dd><label for="move_lock_topics"><input type="checkbox" name="move_lock_topics" id="move_lock_topics" />{L_LOCK_TOPIC}</label></dd><!-- ENDIF --> </dl> + {% EVENT mcp_move_destination_forum_after %} <dl class="fields2"> <dt> </dt> <dd><strong>{MESSAGE_TEXT}</strong></dd> diff --git a/phpBB/styles/prosilver/template/mcp_post.html b/phpBB/styles/prosilver/template/mcp_post.html index af16c8ab84..c2297a8053 100644 --- a/phpBB/styles/prosilver/template/mcp_post.html +++ b/phpBB/styles/prosilver/template/mcp_post.html @@ -31,10 +31,12 @@ <form method="post" id="mcp_report" action="{S_CLOSE_ACTION}"> <fieldset class="submit-buttons"> + {% EVENT mcp_post_report_buttons_top_before %} <!-- IF not S_REPORT_CLOSED --> <input class="button1" type="submit" value="{L_CLOSE_REPORT}" name="action[close]" /> <!-- ENDIF --> <input class="button2" type="submit" value="{L_DELETE_REPORT}" name="action[delete]" /> + {% EVENT mcp_post_report_buttons_top_after %} <input type="hidden" name="report_id_list[]" value="{REPORT_ID}" /> {S_FORM_TOKEN} </fieldset> @@ -69,8 +71,8 @@ <p class="author"> <strong>{L_SENT_AT}{L_COLON}</strong> {POST_DATE} <br /><strong>{L_PM_FROM}{L_COLON}</strong> {POST_AUTHOR_FULL} - <!-- IF S_TO_RECIPIENT --><br /><strong>{L_TO}{L_COLON}</strong> <!-- BEGIN to_recipient --><!-- IF to_recipient.NAME_FULL -->{to_recipient.NAME_FULL}<!-- ELSE --><a href="{to_recipient.U_VIEW}" style="color:<!-- IF to_recipient.COLOUR -->{to_recipient.COLOUR}<!-- ELSEIF to_recipient.IS_GROUP -->#0000FF<!-- ENDIF -->;">{to_recipient.NAME}</a><!-- ENDIF --> <!-- END to_recipient --><!-- ENDIF --> - <!-- IF S_BCC_RECIPIENT --><br /><strong>{L_BCC}{L_COLON}</strong> <!-- BEGIN bcc_recipient --><!-- IF bcc_recipient.NAME_FULL -->{bcc_recipient.NAME_FULL}<!-- ELSE --><a href="{bcc_recipient.U_VIEW}" style="color:<!-- IF bcc_recipient.COLOUR -->{bcc_recipient.COLOUR}<!-- ELSEIF bcc_recipient.IS_GROUP -->#0000FF<!-- ENDIF -->;">{bcc_recipient.NAME}</a><!-- ENDIF --> <!-- END bcc_recipient --><!-- ENDIF --> + <!-- IF S_TO_RECIPIENT --><br /><strong>{L_TO}{L_COLON}</strong> <!-- BEGIN to_recipient --><!-- IF to_recipient.NAME_FULL -->{to_recipient.NAME_FULL}<!-- ELSE --><a href="{to_recipient.U_VIEW}"<!-- IF to_recipient.COLOUR --> style="color:{to_recipient.COLOUR};"<!-- ENDIF -->><strong>{to_recipient.NAME}</strong></a><!-- ENDIF --> <!-- END to_recipient --><!-- ENDIF --> + <!-- IF S_BCC_RECIPIENT --><br /><strong>{L_BCC}{L_COLON}</strong> <!-- BEGIN bcc_recipient --><!-- IF bcc_recipient.NAME_FULL -->{bcc_recipient.NAME_FULL}<!-- ELSE --><a href="{bcc_recipient.U_VIEW}"<!-- IF bcc_recipient.COLOUR --> style="color:{bcc_recipient.COLOUR};"<!-- ENDIF -->><strong>{bcc_recipient.NAME}</strong></a><!-- ENDIF --> <!-- END bcc_recipient --><!-- ENDIF --> </p> <!-- ELSE --> <p class="author"><span><i class="icon fa-file fa-fw icon-lightgray icon-md" aria-hidden="true"></i><span class="sr-only">{MINI_POST_IMG}</span></span> {L_POSTED} {L_POST_BY_AUTHOR} {POST_AUTHOR_FULL} » {POST_DATE}</p> @@ -106,10 +108,14 @@ </p> <!-- ENDIF --> + {% EVENT mcp_post_text_before %} + <div id="post_details" class="content post_details"> {POST_PREVIEW} </div> + {% EVENT mcp_post_text_after %} + <!-- IF S_HAS_ATTACHMENTS --> <dl class="attachbox"> <dt>{L_ATTACHMENTS}</dt> diff --git a/phpBB/styles/prosilver/template/mcp_topic.html b/phpBB/styles/prosilver/template/mcp_topic.html index 35b1ecca0a..090e24041e 100644 --- a/phpBB/styles/prosilver/template/mcp_topic.html +++ b/phpBB/styles/prosilver/template/mcp_topic.html @@ -94,6 +94,7 @@ <div id="topicreview" class="topicreview"> <!-- BEGIN postrow --> + <!-- EVENT mcp_topic_postrow_post_before --> <div class="post <!-- IF postrow.S_ROW_COUNT is odd -->bg1<!-- ELSE -->bg2<!-- ENDIF -->"> <div class="inner"> @@ -119,7 +120,7 @@ <p class="author"> <a href="#pr{postrow.POST_ID}" title="{postrow.MINI_POST}"> <i class="icon fa-file fa-fw icon-lightgray icon-tiny" aria-hidden="true"></i><span class="sr-only">{postrow.MINI_POST}</span> - </a> {L_POSTED} {postrow.POST_DATE} {L_POST_BY_AUTHOR} <strong>{postrow.POST_AUTHOR_FULL}</strong><!-- IF postrow.U_MCP_DETAILS --> [ <a href="{postrow.U_MCP_DETAILS}">{L_POST_DETAILS}</a> ]<!-- ENDIF --> + </a> {L_POSTED} {postrow.POST_DATE} {L_POST_BY_AUTHOR} {% EVENT mcp_topic_post_author_full_prepend %}<strong>{postrow.POST_AUTHOR_FULL}</strong>{% EVENT mcp_topic_post_author_full_append %}<!-- IF postrow.U_MCP_DETAILS --> [ <a href="{postrow.U_MCP_DETAILS}">{L_POST_DETAILS}</a> ]<!-- ENDIF --> </p> <!-- EVENT mcp_topic_postrow_post_details_after --> @@ -143,6 +144,8 @@ <div class="content" id="message_{postrow.POST_ID}">{postrow.MESSAGE}</div> + <!-- EVENT mcp_topic_postrow_attachments_before --> + <!-- IF postrow.S_HAS_ATTACHMENTS --> <dl class="attachbox"> <dt>{L_ATTACHMENTS}</dt> @@ -152,6 +155,8 @@ </dl> <!-- ENDIF --> + <!-- EVENT mcp_topic_postrow_attachments_after --> + </div> </div> diff --git a/phpBB/styles/prosilver/template/memberlist_body.html b/phpBB/styles/prosilver/template/memberlist_body.html index 255e6746e1..5f03ad99cc 100644 --- a/phpBB/styles/prosilver/template/memberlist_body.html +++ b/phpBB/styles/prosilver/template/memberlist_body.html @@ -12,19 +12,28 @@ <!-- ENDIF --> +{% EVENT memberlist_body_page_header_after %} + <!-- IF S_SHOW_GROUP --> + {% EVENT memberlist_body_group_name_before %} <h2 class="group-title"<!-- IF GROUP_COLOR --> style="color:#{GROUP_COLOR};"<!-- ENDIF -->>{GROUP_NAME}</h2> + {% EVENT memberlist_body_group_name_after %} <!-- IF U_MANAGE --> <p class="right responsive-center manage rightside"><a href="{U_MANAGE}">{L_MANAGE_GROUP}</a></p> <!-- ENDIF --> <p>{GROUP_DESC} {GROUP_TYPE}</p> + {% EVENT memberlist_body_group_desc_after %} + <p> <!-- IF AVATAR_IMG -->{AVATAR_IMG}<!-- ENDIF --> + {% EVENT memberlist_body_group_rank_before %} <!-- IF RANK_IMG -->{RANK_IMG}<!-- ENDIF --> <!-- IF GROUP_RANK -->{GROUP_RANK}<!-- ENDIF --> + {% EVENT memberlist_body_group_rank_after %} </p> <!-- ELSE --> + {% EVENT memberlist_body_page_title_before %} <h2 class="solo">{PAGE_TITLE}<!-- IF SEARCH_WORDS -->{L_COLON} <a href="{U_SEARCH_WORDS}">{SEARCH_WORDS}</a><!-- ENDIF --></h2> <div class="action-bar bar-top"> @@ -60,6 +69,7 @@ <th class="info"><!-- BEGIN custom_fields --><!-- IF not custom_fields.S_FIRST_ROW -->{L_COMMA_SEPARATOR} <!-- ENDIF -->{custom_fields.PROFILE_FIELD_NAME}<!-- END custom_fields --></th> <th class="joined"><a href="{U_SORT_JOINED}#memberlist">{L_JOINED}</a></th> <!-- IF U_SORT_ACTIVE --><th class="active"><a href="{U_SORT_ACTIVE}#memberlist">{L_LAST_ACTIVE}</a></th><!-- ENDIF --> + {% EVENT memberlist_body_memberlist_after %} </tr> </thead> <tbody> @@ -88,15 +98,17 @@ <!-- IF not S_LEADERS_SET --> <th class="name" data-dfn="{L_RANK}{L_COMMA_SEPARATOR}{L_USERNAME}"><span class="rank-img"><a href="{U_SORT_RANK}">{L_RANK}</a></span><a href="{U_SORT_USERNAME}"><!-- IF S_SHOW_GROUP -->{L_GROUP_MEMBERS}<!-- ELSE -->{L_USERNAME}<!-- ENDIF --></a></th> <th class="posts"><a href="{U_SORT_POSTS}#memberlist">{L_POSTS}</a></th> - <th class="info"><!-- BEGIN custom_fields --><!-- IF not custom_fields.S_FIRST_ROW -->{L_COMMA_SEPARATOR} <!-- ENDIF -->{custom_fields.PROFILE_FIELD_NAME}<!-- END custom_fields --></th> + <th class="info">{% for field in custom_fields %}{% if not loop.first %}{L_COMMA_SEPARATOR} {% endif %}{{ field.PROFILE_FIELD_NAME }}{% endfor %}</th> <th class="joined"><a href="{U_SORT_JOINED}#memberlist">{L_JOINED}</a></th> <!-- IF U_SORT_ACTIVE --><th class="active"><a href="{U_SORT_ACTIVE}#memberlist">{L_LAST_ACTIVE}</a></th><!-- ENDIF --> + {% EVENT memberlist_body_leaders_set_after %} <!-- ELSEIF S_SHOW_GROUP --> <th class="name">{L_GROUP_MEMBERS}</th> <th class="posts">{L_POSTS}</th> <th class="info"><!-- BEGIN custom_fields --><!-- IF not custom_fields.S_FIRST_ROW -->{L_COMMA_SEPARATOR} <!-- ENDIF -->{custom_fields.PROFILE_FIELD_NAME}<!-- END custom_fields --></th> <th class="joined">{L_JOINED}</th> <!-- IF U_SORT_ACTIVE --><th class="active">{L_LAST_ACTIVE}</th><!-- ENDIF --> + {% EVENT memberlist_body_show_group_after %} <!-- ENDIF --> </tr> </thead> @@ -111,6 +123,7 @@ <td class="info"><!-- BEGIN custom_fields --><div>{memberrow.custom_fields.PROFILE_FIELD_VALUE}</div><!-- BEGINELSE --> <!-- END custom_fields --></td> <td>{memberrow.JOINED}</td> <!-- IF S_VIEWONLINE --><td>{memberrow.LAST_ACTIVE} </td><!-- ENDIF --> + {% EVENT memberlist_body_memberrow_after %} </tr> <!-- BEGINELSE --> <tr class="bg1"> @@ -156,6 +169,8 @@ </div> </div> +{% EVENT memberlist_body_page_footer_before %} + <!-- IF S_IN_SEARCH_POPUP --> <!-- INCLUDE simple_footer.html --> <!-- ELSE --> diff --git a/phpBB/styles/prosilver/template/memberlist_email.html b/phpBB/styles/prosilver/template/memberlist_email.html index d9752bed00..eea699da08 100644 --- a/phpBB/styles/prosilver/template/memberlist_email.html +++ b/phpBB/styles/prosilver/template/memberlist_email.html @@ -77,7 +77,7 @@ <dl> <dt><label for="message">{L_MESSAGE_BODY}{L_COLON}</label><br /> <span>{L_EMAIL_BODY_EXPLAIN}</span></dt> - <dd><textarea name="message" id="message" rows="15" cols="76" tabindex="4">{MESSAGE}</textarea></dd> + <dd><textarea class="inputbox" name="message" id="message" rows="15" cols="76" tabindex="4">{MESSAGE}</textarea></dd> </dl> <!-- IF S_REGISTERED_USER --> <dl> diff --git a/phpBB/styles/prosilver/template/memberlist_view.html b/phpBB/styles/prosilver/template/memberlist_view.html index a7439bc759..debf64cba2 100644 --- a/phpBB/styles/prosilver/template/memberlist_view.html +++ b/phpBB/styles/prosilver/template/memberlist_view.html @@ -21,7 +21,7 @@ <dl class="left-box details profile-details"> <dt>{L_USERNAME}{L_COLON}</dt> <dd> - <!-- IF USER_COLOR --><span style="color: {USER_COLOR}; font-weight: bold;"><!-- ELSE --><span><!-- ENDIF -->{USERNAME}</span> + <!-- EVENT memberlist_view_username_prepend --><!-- IF USER_COLOR --><span style="color: {USER_COLOR}; font-weight: bold;"><!-- ELSE --><span><!-- ENDIF -->{USERNAME}</span><!-- EVENT memberlist_view_username_append --> <!-- IF U_EDIT_SELF --> [ <a href="{U_EDIT_SELF}">{L_EDIT_PROFILE}</a> ]<!-- ENDIF --> <!-- IF U_USER_ADMIN --> [ <a href="{U_USER_ADMIN}">{L_USER_ADMIN}</a> ]<!-- ENDIF --> <!-- IF U_USER_BAN --> [ <a href="{U_USER_BAN}">{L_USER_BAN}</a> ]<!-- ENDIF --> diff --git a/phpBB/styles/prosilver/template/navbar_header.html b/phpBB/styles/prosilver/template/navbar_header.html index b8080a6be3..dc29285922 100644 --- a/phpBB/styles/prosilver/template/navbar_header.html +++ b/phpBB/styles/prosilver/template/navbar_header.html @@ -123,11 +123,13 @@ <i class="icon fa-sliders fa-fw" aria-hidden="true"></i><span>{L_PROFILE}</span> </a> </li> - <li> - <a href="{U_USER_PROFILE}" title="{L_READ_PROFILE}" role="menuitem"> - <i class="icon fa-user fa-fw" aria-hidden="true"></i><span>{L_READ_PROFILE}</span> - </a> - </li> + <!-- IF U_USER_PROFILE --> + <li> + <a href="{U_USER_PROFILE}" title="{L_READ_PROFILE}" role="menuitem"> + <i class="icon fa-user fa-fw" aria-hidden="true"></i><span>{L_READ_PROFILE}</span> + </a> + </li> + <!-- ENDIF --> <!-- EVENT navbar_header_profile_list_after --> @@ -176,18 +178,19 @@ </ul> <ul id="nav-breadcrumbs" class="nav-breadcrumbs linklist navlinks" role="menubar"> - <!-- DEFINE $MICRODATA = ' itemtype="http://data-vocabulary.org/Breadcrumb" itemscope=""' --> + <!-- DEFINE $MICRODATA = ' itemtype="http://schema.org/ListItem" itemprop="itemListElement" itemscope' --> + {% set navlink_position = 1 %} <!-- EVENT overall_header_breadcrumbs_before --> - <li class="breadcrumbs"> + <li class="breadcrumbs" itemscope itemtype="http://schema.org/BreadcrumbList"> <!-- IF U_SITE_HOME --> - <span class="crumb" {$MICRODATA}><a href="{U_SITE_HOME}" itemprop="url" data-navbar-reference="home"><i class="icon fa-home fa-fw" aria-hidden="true"></i><span itemprop="title">{L_SITE_HOME}</span></a></span> + <span class="crumb" {$MICRODATA}><a href="{U_SITE_HOME}" itemtype="https://schema.org/Thing" itemprop="item" data-navbar-reference="home"><i class="icon fa-home fa-fw" aria-hidden="true"></i><span itemprop="name">{L_SITE_HOME}</span></a><meta itemprop="position" content="{{ navlink_position }}{% set navlink_position = navlink_position + 1 %}" /></span> <!-- ENDIF --> <!-- EVENT overall_header_breadcrumb_prepend --> - <span class="crumb" {$MICRODATA}><a href="{U_INDEX}" itemprop="url" accesskey="h" data-navbar-reference="index"><!-- IF not U_SITE_HOME --><i class="icon fa-home fa-fw"></i><!-- ENDIF --><span itemprop="title">{L_INDEX}</span></a></span> + <span class="crumb" {$MICRODATA}><a href="{U_INDEX}" itemtype="https://schema.org/Thing" itemprop="item" accesskey="h" data-navbar-reference="index"><!-- IF not U_SITE_HOME --><i class="icon fa-home fa-fw"></i><!-- ENDIF --><span itemprop="name">{L_INDEX}</span></a><meta itemprop="position" content="{{ navlink_position }}{% set navlink_position = navlink_position + 1 %}" /></span> <!-- BEGIN navlinks --> <!-- EVENT overall_header_navlink_prepend --> - <span class="crumb" {$MICRODATA}<!-- IF navlinks.MICRODATA --> {navlinks.MICRODATA}<!-- ENDIF -->><a href="{navlinks.U_VIEW_FORUM}" itemprop="url"><span itemprop="title">{navlinks.FORUM_NAME}</span></a></span> + <span class="crumb" {$MICRODATA}<!-- IF navlinks.MICRODATA --> {navlinks.MICRODATA}<!-- ENDIF -->><a href="{navlinks.U_VIEW_FORUM}" itemtype="https://schema.org/Thing" itemprop="item"><span itemprop="name">{navlinks.FORUM_NAME}</span></a><meta itemprop="position" content="{{ navlink_position }}{% set navlink_position = navlink_position + 1 %}" /></span> <!-- EVENT overall_header_navlink_append --> <!-- END navlinks --> <!-- EVENT overall_header_breadcrumb_append --> diff --git a/phpBB/styles/prosilver/template/overall_footer.html b/phpBB/styles/prosilver/template/overall_footer.html index 97a21f9a6e..bdff1a0c05 100644 --- a/phpBB/styles/prosilver/template/overall_footer.html +++ b/phpBB/styles/prosilver/template/overall_footer.html @@ -8,11 +8,34 @@ <div class="copyright"> <!-- EVENT overall_footer_copyright_prepend --> - {CREDIT_LINE} - <!-- IF TRANSLATION_INFO --><br />{TRANSLATION_INFO}<!-- ENDIF --> + <p class="footer-row"> + <span class="footer-copyright">{{ CREDIT_LINE }}</span> + </p> + <!-- IF TRANSLATION_INFO --> + <p class="footer-row"> + <span class="footer-copyright">{{ TRANSLATION_INFO }}</span> + </p> + <!-- 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 --> + <p class="footer-row"> + <a class="footer-link" href="{{ U_PRIVACY }}" title="{{ lang('PRIVACY_LINK') }}" role="menuitem"> + <span class="footer-link-text">{{ lang('PRIVACY_LINK') }}</span> + </a> + | + <a class="footer-link" href="{{ U_TERMS_USE }}" title="{{ lang('TERMS_LINK') }}" role="menuitem"> + <span class="footer-link-text">{{ lang('TERMS_LINK') }}</span> + </a> + </p> + <!-- IF DEBUG_OUTPUT --> + <p class="footer-row"> + <span class="footer-info">{{ DEBUG_OUTPUT }}</span> + </p> + <!-- ENDIF --> + <!-- IF U_ACP --> + <p class="footer-row"> + <a class="footer-link text-strong" href="{{ U_ACP }}">{{ lang('ACP') }}</a> + </p> + <!-- ENDIF --> </div> <div id="darkenwrapper" class="darkenwrapper" data-ajax-error-title="{L_AJAX_ERROR_TITLE}" data-ajax-error-text="{L_AJAX_ERROR_TEXT}" data-ajax-error-text-abort="{L_AJAX_ERROR_TEXT_ABORT}" data-ajax-error-text-timeout="{L_AJAX_ERROR_TEXT_TIMEOUT}" data-ajax-error-text-parsererror="{L_AJAX_ERROR_TEXT_PARSERERROR}"> @@ -40,13 +63,13 @@ <!-- IF not S_IS_BOT -->{RUN_CRON_TASK}<!-- ENDIF --> </div> -<script type="text/javascript" src="{T_JQUERY_LINK}"></script> -<!-- IF S_ALLOW_CDN --><script type="text/javascript">window.jQuery || document.write('\x3Cscript src="{T_ASSETS_PATH}/javascript/jquery.min.js?assets_version={T_ASSETS_VERSION}">\x3C/script>');</script><!-- ENDIF --> -<script type="text/javascript" src="{T_ASSETS_PATH}/javascript/core.js?assets_version={T_ASSETS_VERSION}"></script> +<script src="{T_JQUERY_LINK}"></script> +<!-- IF S_ALLOW_CDN --><script>window.jQuery || document.write('\x3Cscript src="{T_ASSETS_PATH}/javascript/jquery.min.js?assets_version={T_ASSETS_VERSION}">\x3C/script>');</script><!-- ENDIF --> +<script src="{T_ASSETS_PATH}/javascript/core.js?assets_version={T_ASSETS_VERSION}"></script> <!-- INCLUDEJS forum_fn.js --> <!-- INCLUDEJS ajax.js --> <!-- IF S_ALLOW_CDN --> - <script type="text/javascript"> + <script> (function($){ var $fa_cdn = $('head').find('link[rel="stylesheet"]').first(), $span = $('<span class="fa" style="display:none"></span>').appendTo('body'); @@ -62,24 +85,27 @@ <!-- IF S_COOKIE_NOTICE --> <script src="{T_ASSETS_PATH}/cookieconsent/cookieconsent.min.js?assets_version={T_ASSETS_VERSION}"></script> <script> - window.addEventListener("load", function(){ - window.cookieconsent.initialise({ - "palette": { - "popup": { - "background": "#0F538A" + if (typeof window.cookieconsent === "object") { + window.addEventListener("load", function(){ + window.cookieconsent.initialise({ + "palette": { + "popup": { + "background": "#0F538A" + }, + "button": { + "background": "#E5E5E5" + } }, - "button": { - "background": "#E5E5E5" + "theme": "classic", + "content": { + "message": "{LA_COOKIE_CONSENT_MSG}", + "dismiss": "{LA_COOKIE_CONSENT_OK}", + "link": "{LA_COOKIE_CONSENT_INFO}", + "href": "{UA_PRIVACY}" } - }, - "theme": "classic", - "content": { - "message": "{LA_COOKIE_CONSENT_MSG}", - "dismiss": "{LA_COOKIE_CONSENT_OK}", - "link": "{LA_COOKIE_CONSENT_INFO}", - "href": "{LA_COOKIE_CONSENT_HREF}" - } - })}); + }); + }); + } </script> <!-- ENDIF --> diff --git a/phpBB/styles/prosilver/template/plupload.html b/phpBB/styles/prosilver/template/plupload.html index fc663118c1..1eb84372e8 100644 --- a/phpBB/styles/prosilver/template/plupload.html +++ b/phpBB/styles/prosilver/template/plupload.html @@ -1,5 +1,4 @@ -<script type="text/javascript"> -//<![CDATA[ +<script> phpbb.plupload = { i18n: { 'b': '{LA_BYTES_SHORT}', @@ -63,7 +62,6 @@ phpbb.plupload = { maxFiles: {MAX_ATTACHMENTS}, data: {S_ATTACH_DATA}, } -//]]> </script> <!-- INCLUDEJS {T_ASSETS_PATH}/plupload/plupload.full.min.js --> <!-- INCLUDEJS {T_ASSETS_PATH}/javascript/plupload.js --> diff --git a/phpBB/styles/prosilver/template/posting_attach_body.html b/phpBB/styles/prosilver/template/posting_attach_body.html index 444713d6e0..ff5bfe1b55 100644 --- a/phpBB/styles/prosilver/template/posting_attach_body.html +++ b/phpBB/styles/prosilver/template/posting_attach_body.html @@ -21,6 +21,7 @@ <input type="button" class="button2" value="{L_PLUPLOAD_ADD_FILES}" id="add_files" /> </div> + {% EVENT posting_attach_body_file_list_before %} <div class="panel<!-- IF not .attach_row --> hidden<!-- ENDIF --> file-list-container" id="file-list-container"> <div class="inner"> <table class="table1 zebra-list fixed-width-table"> @@ -33,7 +34,7 @@ </tr> </thead> <tbody class="responsive-skip-empty file-list" id="file-list"> - <tr class="attach-row" id="attach-row-tpl"> + <tr class="attach-row attach-row-tpl" id="attach-row-tpl"> <td class="attach-name"> <span class="file-name ellipsis-text"></span> <span class="attach-controls"> @@ -55,16 +56,18 @@ <span class="file-status"></span> </td> </tr> + {% EVENT posting_attach_body_attach_row_before %} <!-- BEGIN attach_row --> + {% EVENT posting_attach_body_attach_row_prepend %} <tr class="attach-row" data-attach-id="{attach_row.ATTACH_ID}"> <td class="attach-name"> <span class="file-name ellipsis-text"><a href="{attach_row.U_VIEW_ATTACHMENT}">{attach_row.FILENAME}</a></span> - <!-- EVENT posting_attach_body_attach_row_controls_prepend --> + {% EVENT posting_attach_body_attach_row_controls_prepend %} <span class="attach-controls"> <!-- IF S_INLINE_ATTACHMENT_OPTIONS --><input type="button" value="{L_PLACE_INLINE}" class="button2 file-inline-bbcode" /> <!-- ENDIF --> <input type="submit" name="delete_file[{attach_row.ASSOC_INDEX}]" value="{L_DELETE_FILE}" class="button2 file-delete" /> </span> - <!-- EVENT posting_attach_body_attach_row_controls_append --> + {% EVENT posting_attach_body_attach_row_controls_append %} <span class="clear"></span> </td> <td class="attach-comment"> @@ -78,10 +81,13 @@ <span class="file-status file-uploaded"></span> </td> </tr> + {% EVENT posting_attach_body_attach_row_append %} <!-- END attach_row --> + {% EVENT posting_attach_body_attach_row_after %} </tbody> </table> </div> </div> + {% EVENT posting_attach_body_file_list_after %} </div> </div> diff --git a/phpBB/styles/prosilver/template/posting_buttons.html b/phpBB/styles/prosilver/template/posting_buttons.html index 14185ed66b..122afdf978 100644 --- a/phpBB/styles/prosilver/template/posting_buttons.html +++ b/phpBB/styles/prosilver/template/posting_buttons.html @@ -1,6 +1,5 @@ -<script type="text/javascript"> -// <![CDATA[ +<script> var form_name = 'postform'; var text_name = <!-- IF $SIG_EDIT -->'signature'<!-- ELSE -->'message'<!-- ENDIF -->; var load_draft = false; @@ -46,8 +45,6 @@ document.getElementById('bbpalette').value = '{LA_FONT_COLOR}'; } } - -// ]]> </script> <!-- INCLUDEJS {T_ASSETS_PATH}/javascript/editor.js --> diff --git a/phpBB/styles/prosilver/template/posting_pm_header.html b/phpBB/styles/prosilver/template/posting_pm_header.html index 032d8c6a6f..7fee914525 100644 --- a/phpBB/styles/prosilver/template/posting_pm_header.html +++ b/phpBB/styles/prosilver/template/posting_pm_header.html @@ -32,7 +32,7 @@ <!-- BEGIN to_recipient --> <li> <!-- IF not S_EDIT_POST --><input type="submit" name="remove_{to_recipient.TYPE}[{to_recipient.UG_ID}]" value="x" class="button2" /><!-- ENDIF --> - <!-- IF to_recipient.IS_GROUP --><a href="{to_recipient.U_VIEW}"><strong>{to_recipient.NAME}</strong></a><!-- ELSE -->{to_recipient.NAME_FULL}<!-- ENDIF --> + <!-- IF to_recipient.IS_GROUP --><a href="{to_recipient.U_VIEW}" style="color: {{ to_recipient.COLOUR }}"><strong>{to_recipient.NAME}</strong></a><!-- ELSE -->{to_recipient.NAME_FULL}<!-- ENDIF --> </li> <!-- END to_recipient --> </ul> @@ -49,7 +49,7 @@ <!-- BEGIN bcc_recipient --> <li> <!-- IF not S_EDIT_POST --><input type="submit" name="remove_{bcc_recipient.TYPE}[{bcc_recipient.UG_ID}]" value="x" class="button2" /><!-- ENDIF --> - <!-- IF bcc_recipient.IS_GROUP --><a href="{bcc_recipient.U_VIEW}"><strong>{bcc_recipient.NAME}</strong></a><!-- ELSE -->{bcc_recipient.NAME_FULL}<!-- ENDIF --> + <!-- IF bcc_recipient.IS_GROUP --><a href="{bcc_recipient.U_VIEW}" style="color: {{ bcc_recipient.COLOUR }}"><strong>{bcc_recipient.NAME}</strong></a><!-- ELSE -->{bcc_recipient.NAME_FULL}<!-- ENDIF --> </li> <!-- END bcc_recipient --> </ul> diff --git a/phpBB/styles/prosilver/template/posting_poll_body.html b/phpBB/styles/prosilver/template/posting_poll_body.html index ee7100aded..795649650d 100644 --- a/phpBB/styles/prosilver/template/posting_poll_body.html +++ b/phpBB/styles/prosilver/template/posting_poll_body.html @@ -15,8 +15,8 @@ <!-- IF S_SHOW_POLL_BOX --> <dl> - <dt><label for="poll_title">{L_POLL_QUESTION}{L_COLON}</label></dt> - <dd><input type="text" name="poll_title" id="poll_title" maxlength="255" value="{POLL_TITLE}" class="inputbox" /></dd> + <dt><label for="poll_title">{{ lang('POLL_QUESTION') ~ lang('COLON') }}</label></dt> + <dd><input type="text" name="poll_title" id="poll_title" maxlength="100" value="{{ POLL_TITLE }}" class="inputbox" /></dd> </dl> <dl> <dt><label for="poll_option_text">{L_POLL_OPTIONS}{L_COLON}</label><br /><span>{L_POLL_OPTIONS_EXPLAIN}</span></dt> diff --git a/phpBB/styles/prosilver/template/posting_preview.html b/phpBB/styles/prosilver/template/posting_preview.html index aac117c090..781d0de06b 100644 --- a/phpBB/styles/prosilver/template/posting_preview.html +++ b/phpBB/styles/prosilver/template/posting_preview.html @@ -31,6 +31,8 @@ <div class="content">{PREVIEW_MESSAGE}</div> + <!-- EVENT posting_preview_content_after --> + <!-- IF .attachment --> <dl class="attachbox"> <dt>{L_ATTACHMENTS}</dt> diff --git a/phpBB/styles/prosilver/template/posting_review.html b/phpBB/styles/prosilver/template/posting_review.html index 1304046b23..033a88485e 100644 --- a/phpBB/styles/prosilver/template/posting_review.html +++ b/phpBB/styles/prosilver/template/posting_review.html @@ -22,7 +22,7 @@ <i class="icon fa-file fa-fw icon-lightgray icon-md" aria-hidden="true"></i><span class="sr-only">{post_review_row.MINI_POST}</span> </a> <!-- ENDIF --> - {L_POST_BY_AUTHOR}<strong> {post_review_row.POST_AUTHOR_FULL}</strong> » {post_review_row.POST_DATE} + {L_POST_BY_AUTHOR} <!-- EVENT posting_review_row_post_author_username_prepend --><strong>{post_review_row.POST_AUTHOR_FULL}</strong><!-- EVENT posting_review_row_post_author_username_append --> » {post_review_row.POST_DATE} </p> <div class="content">{post_review_row.MESSAGE}</div> diff --git a/phpBB/styles/prosilver/template/posting_smilies.html b/phpBB/styles/prosilver/template/posting_smilies.html index 54e82a58bc..b5794d5aff 100644 --- a/phpBB/styles/prosilver/template/posting_smilies.html +++ b/phpBB/styles/prosilver/template/posting_smilies.html @@ -1,10 +1,8 @@ <!-- INCLUDE simple_header.html --> -<script type="text/javascript"> -// <![CDATA[ +<script> var form_name = opener.form_name; var text_name = opener.text_name; -// ]]> </script> <!-- INCLUDEJS {T_ASSETS_PATH}/javascript/editor.js --> diff --git a/phpBB/styles/prosilver/template/posting_topic_review.html b/phpBB/styles/prosilver/template/posting_topic_review.html index 857c686774..8faece3447 100644 --- a/phpBB/styles/prosilver/template/posting_topic_review.html +++ b/phpBB/styles/prosilver/template/posting_topic_review.html @@ -5,10 +5,8 @@ </h3> <div id="topicreview" class="topicreview"> -<script type="text/javascript"> -// <![CDATA[ +<script> bbcodeEnabled = {S_BBCODE_ALLOWED}; -// ]]> </script> <!-- BEGIN topic_review_row --> @@ -56,12 +54,14 @@ <i class="icon fa-file fa-fw icon-lightgray icon-md" aria-hidden="true"></i><span class="sr-only">{topic_review_row.MINI_POST}</span> </a> <!-- ENDIF --> - {L_POST_BY_AUTHOR} <strong>{topic_review_row.POST_AUTHOR_FULL}</strong> » {topic_review_row.POST_DATE} + {L_POST_BY_AUTHOR} <!-- EVENT posting_topic_review_row_post_author_username_prepend --><strong>{topic_review_row.POST_AUTHOR_FULL}</strong><!-- EVENT posting_topic_review_row_post_author_username_append --> » {topic_review_row.POST_DATE} </p> <!-- EVENT posting_topic_review_row_post_details_after --> <div class="content">{topic_review_row.MESSAGE}</div> + <!-- EVENT posting_topic_review_row_content_after --> + <!-- IF topic_review_row.S_HAS_ATTACHMENTS --> <dl class="attachbox"> <dt>{L_ATTACHMENTS}</dt> diff --git a/phpBB/styles/prosilver/template/search_results.html b/phpBB/styles/prosilver/template/search_results.html index 3e1be4d4cb..9ee13a4224 100644 --- a/phpBB/styles/prosilver/template/search_results.html +++ b/phpBB/styles/prosilver/template/search_results.html @@ -108,7 +108,7 @@ <!-- IF not S_IS_BOT --> <div class="responsive-show" style="display: none;"> - {L_LAST_POST} {L_POST_BY_AUTHOR} {searchresults.LAST_POST_AUTHOR_FULL} « <a href="{searchresults.U_LAST_POST}" title="{L_GOTO_LAST_POST}"><time datetime="{searchresults.LAST_POST_TIME_RFC3339}">{searchresults.LAST_POST_TIME}</time></a> + {L_LAST_POST} {L_POST_BY_AUTHOR} <!-- EVENT search_results_last_post_author_username_prepend -->{searchresults.LAST_POST_AUTHOR_FULL}<!-- EVENT search_results_last_post_author_username_append --> « <a href="{searchresults.U_LAST_POST}" title="{L_GOTO_LAST_POST}"><time datetime="{searchresults.LAST_POST_TIME_RFC3339}">{searchresults.LAST_POST_TIME}</time></a> <br />{L_POSTED} {L_IN} <a href="{searchresults.U_VIEW_FORUM}">{searchresults.FORUM_TITLE}</a> </div> <!-- IF searchresults.TOPIC_REPLIES --><span class="responsive-show left-box" style="display: none;">{L_REPLIES}{L_COLON} <strong>{searchresults.TOPIC_REPLIES}</strong></span><!-- ENDIF --> @@ -117,7 +117,9 @@ <div class="responsive-hide left-box"> <!-- IF searchresults.S_HAS_POLL --><i class="icon fa-bar-chart fa-fw" aria-hidden="true"></i><!-- ENDIF --> <!-- IF searchresults.ATTACH_ICON_IMG --><i class="icon fa-paperclip fa-fw" aria-hidden="true"></i><!-- ENDIF --> - {L_POST_BY_AUTHOR} {searchresults.TOPIC_AUTHOR_FULL} » <time datetime="{searchresults.FIRST_POST_TIME_RFC3339}">{searchresults.FIRST_POST_TIME}</time> » {L_IN} <a href="{searchresults.U_VIEW_FORUM}">{searchresults.FORUM_TITLE}</a> + {% EVENT topiclist_row_topic_by_author_before %} + {L_POST_BY_AUTHOR} <!-- EVENT search_results_topic_author_username_prepend -->{searchresults.TOPIC_AUTHOR_FULL}<!-- EVENT search_results_topic_author_username_append --> » <time datetime="{searchresults.FIRST_POST_TIME_RFC3339}">{searchresults.FIRST_POST_TIME}</time> » {L_IN} <a href="{searchresults.U_VIEW_FORUM}">{searchresults.FORUM_TITLE}</a> + {% EVENT topiclist_row_topic_by_author_after %} </div> <!-- IF .searchresults.pagination --> @@ -142,7 +144,7 @@ <dd class="posts">{searchresults.TOPIC_REPLIES} <dfn>{L_REPLIES}</dfn></dd> <dd class="views">{searchresults.TOPIC_VIEWS} <dfn>{L_VIEWS}</dfn></dd> <dd class="lastpost"> - <span><dfn>{L_LAST_POST} </dfn>{L_POST_BY_AUTHOR} {searchresults.LAST_POST_AUTHOR_FULL} + <span><dfn>{L_LAST_POST} </dfn>{L_POST_BY_AUTHOR} <!-- EVENT search_results_last_post_author_username_prepend -->{searchresults.LAST_POST_AUTHOR_FULL}<!-- EVENT search_results_last_post_author_username_append --> <!-- IF not S_IS_BOT --> <a href="{searchresults.U_LAST_POST}" title="{L_GOTO_LAST_POST}"> <i class="icon fa-external-link-square fa-fw icon-lightgray icon-md" aria-hidden="true"></i><span class="sr-only">{VIEW_LATEST_POST}</span> @@ -181,7 +183,7 @@ <!-- ELSE --> <dl class="postprofile"> <!-- EVENT search_results_postprofile_before --> - <dt class="author">{L_POST_BY_AUTHOR} {searchresults.POST_AUTHOR_FULL}</dt> + <dt class="author">{L_POST_BY_AUTHOR} <!-- EVENT search_results_post_author_username_prepend -->{searchresults.POST_AUTHOR_FULL}<!-- EVENT search_results_post_author_username_append --></dt> <dd class="search-result-date">{searchresults.POST_DATE}</dd> <dd>{L_FORUM}{L_COLON} <a href="{searchresults.U_VIEW_FORUM}">{searchresults.FORUM_TITLE}</a></dd> <dd>{L_TOPIC}{L_COLON} <a href="{searchresults.U_VIEW_TOPIC}">{searchresults.TOPIC_TITLE}</a></dd> @@ -194,6 +196,7 @@ <div class="postbody"> <h3><a href="{searchresults.U_VIEW_POST}">{searchresults.POST_SUBJECT}</a></h3> <div class="content">{searchresults.MESSAGE}</div> + <!-- EVENT search_results_content_after --> </div> <!-- ENDIF --> diff --git a/phpBB/styles/prosilver/template/simple_footer.html b/phpBB/styles/prosilver/template/simple_footer.html index 614c137835..1ef44d1688 100644 --- a/phpBB/styles/prosilver/template/simple_footer.html +++ b/phpBB/styles/prosilver/template/simple_footer.html @@ -24,9 +24,9 @@ </div> </div> -<script type="text/javascript" src="{T_JQUERY_LINK}"></script> -<!-- IF S_ALLOW_CDN --><script type="text/javascript">window.jQuery || document.write('\x3Cscript src="{T_ASSETS_PATH}/javascript/jquery.min.js?assets_version={T_ASSETS_VERSION}">\x3C/script>');</script><!-- ENDIF --> -<script type="text/javascript" src="{T_ASSETS_PATH}/javascript/core.js?assets_version={T_ASSETS_VERSION}"></script> +<script src="{T_JQUERY_LINK}"></script> +<!-- IF S_ALLOW_CDN --><script>window.jQuery || document.write('\x3Cscript src="{T_ASSETS_PATH}/javascript/jquery.min.js?assets_version={T_ASSETS_VERSION}">\x3C/script>');</script><!-- ENDIF --> +<script src="{T_ASSETS_PATH}/javascript/core.js?assets_version={T_ASSETS_VERSION}"></script> <!-- INCLUDEJS forum_fn.js --> <!-- INCLUDEJS ajax.js --> @@ -34,5 +34,7 @@ {$SCRIPTS} +{% EVENT simple_footer_body_after %} + </body> </html> diff --git a/phpBB/styles/prosilver/template/ucp_agreement.html b/phpBB/styles/prosilver/template/ucp_agreement.html index 943774c6ec..d4fef9f0a5 100644 --- a/phpBB/styles/prosilver/template/ucp_agreement.html +++ b/phpBB/styles/prosilver/template/ucp_agreement.html @@ -3,8 +3,7 @@ <!-- IF S_SHOW_COPPA or S_REGISTRATION --> <!-- IF S_LANG_OPTIONS --> -<script type="text/javascript"> -// <![CDATA[ +<script> /** * Change language */ @@ -14,8 +13,6 @@ document.forms['register'].change_lang.value = lang_iso; document.forms['register'].submit(); } - -// ]]> </script> <form method="post" action="{S_UCP_ACTION}" id="register"> @@ -65,8 +62,6 @@ <div class="content"> <h2 class="sitename-title">{SITENAME} - {AGREEMENT_TITLE}</h2> <p>{AGREEMENT_TEXT}</p> - <hr class="dashed" /> - <p><a href="{U_BACK}" class="button2">{L_BACK}</a></p> </div> </div> </div> diff --git a/phpBB/styles/prosilver/template/ucp_attachments.html b/phpBB/styles/prosilver/template/ucp_attachments.html index 696f621116..cfdbf9c7ea 100644 --- a/phpBB/styles/prosilver/template/ucp_attachments.html +++ b/phpBB/styles/prosilver/template/ucp_attachments.html @@ -44,7 +44,7 @@ </dt> <dd class="extra">{attachrow.DOWNLOAD_COUNT}</dd> <dd class="time"><span>{attachrow.POST_TIME}</span></dd> - <dd class="mark"><input type="checkbox" name="attachment[{attachrow.ATTACH_ID}]" value="1" /></dd> + <dd class="mark"><input type="checkbox" name="attachment[{attachrow.ATTACH_ID}]" value="1"{% if attachrow.S_LOCKED %} disabled title="{{ lang('ATTACHMENT_LOCKED') }}"{% endif %} /></dd> </dl> </li> <!-- END attachrow --> diff --git a/phpBB/styles/prosilver/template/ucp_auth_link_oauth.html b/phpBB/styles/prosilver/template/ucp_auth_link_oauth.html index 18316613b0..60061a3139 100644 --- a/phpBB/styles/prosilver/template/ucp_auth_link_oauth.html +++ b/phpBB/styles/prosilver/template/ucp_auth_link_oauth.html @@ -1,5 +1,5 @@ <!-- BEGIN oauth --> - <form id="ucp" method="post" action="{S_UCP_ACTION}"> + <form id="ucp_oauth_{oauth.SERVICE_ID}" method="post" action="{S_UCP_ACTION}"> <h3>{oauth.SERVICE_NAME}</h3> <fieldset class="fields2"> diff --git a/phpBB/styles/prosilver/template/ucp_footer.html b/phpBB/styles/prosilver/template/ucp_footer.html index f2f1a68db3..eb07f52e05 100644 --- a/phpBB/styles/prosilver/template/ucp_footer.html +++ b/phpBB/styles/prosilver/template/ucp_footer.html @@ -9,6 +9,4 @@ </form> <!-- ENDIF --> -<!-- INCLUDE jumpbox.html --> - <!-- INCLUDE overall_footer.html --> diff --git a/phpBB/styles/prosilver/template/ucp_pm_history.html b/phpBB/styles/prosilver/template/ucp_pm_history.html index e97befc552..b53eb0c7ec 100644 --- a/phpBB/styles/prosilver/template/ucp_pm_history.html +++ b/phpBB/styles/prosilver/template/ucp_pm_history.html @@ -6,10 +6,8 @@ <!-- EVENT ucp_pm_history_review_before --> <div id="topicreview" class="topicreview"> - <script type="text/javascript"> - // <![CDATA[ + <script> bbcodeEnabled = {S_BBCODE_ALLOWED}; - // ]]> </script> <!-- BEGIN history_row --> <div class="post <!-- IF history_row.S_ROW_COUNT is even -->bg1<!-- ELSE -->bg2<!-- ENDIF -->"> @@ -38,7 +36,7 @@ <p class="author"> <span><i class="icon fa-file fa-fw icon-lightgray icon-md" aria-hidden="true"></i><span class="sr-only">{history_row.MINI_POST}</span></span> {L_SENT_AT}{L_COLON} <strong>{history_row.SENT_DATE}</strong> <br /> - {L_MESSAGE_BY_AUTHOR} {history_row.MESSAGE_AUTHOR_FULL} + {L_MESSAGE_BY_AUTHOR} <!-- EVENT ucp_pm_history_row_message_author_username_prepend -->{history_row.MESSAGE_AUTHOR_FULL}<!-- EVENT ucp_pm_history_row_message_author_username_append --> </p> <div class="content"><!-- IF history_row.MESSAGE -->{history_row.MESSAGE}<!-- ELSE --><span class="error">{L_MESSAGE_REMOVED_FROM_OUTBOX}</span><!-- ENDIF --></div> <div id="message_{history_row.MSG_ID}" style="display: none;">{history_row.DECODED_MESSAGE}</div> @@ -56,4 +54,3 @@ <i class="icon fa-chevron-circle-up fa-fw icon-gray" aria-hidden="true"></i><span>{L_BACK_TO_TOP}</span> </a> </p> - diff --git a/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html b/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html index 4295867c05..7cb44a0189 100644 --- a/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html +++ b/phpBB/styles/prosilver/template/ucp_pm_viewmessage.html @@ -91,28 +91,28 @@ <!-- IF U_EDIT --> <li> <a href="{U_EDIT}" title="{L_POST_EDIT_PM}" class="button button-icon-only"> - <i class="icon fa-pencil fa-fw" aria-hidden="true"></i><span class="sr-only">{L_POST_EDIT_PM}</span> + <i class="icon fa-pencil fa-fw" aria-hidden="true"></i><span class="sr-only">{L_BUTTON_EDIT}</span> </a> </li> <!-- ENDIF --> <!-- IF U_DELETE --> <li> <a href="{U_DELETE}" title="{L_DELETE_MESSAGE}" class="button button-icon-only"> - <i class="icon fa-times fa-fw" aria-hidden="true"></i><span class="sr-only">{L_DELETE_MESSAGE}</span> + <i class="icon fa-times fa-fw" aria-hidden="true"></i><span class="sr-only">{L_BUTTON_DELETE}</span> </a> </li> <!-- ENDIF --> <!-- IF U_REPORT --> <li> <a href="{U_REPORT}" title="{L_REPORT_PM}" class="button button-icon-only"> - <i class="icon fa-exclamation fa-fw" aria-hidden="true"></i><span class="sr-only">{L_REPORT_PM}</span> + <i class="icon fa-exclamation fa-fw" aria-hidden="true"></i><span class="sr-only">{L_BUTTON_REPORT}</span> </a> </li> <!-- ENDIF --> <!-- IF U_QUOTE --> <li> <a href="{U_QUOTE}" title="{L_POST_QUOTE_PM}" class="button button-icon-only"> - <i class="icon fa-quote-left fa-fw" aria-hidden="true"></i><span class="sr-only">{L_POST_QUOTE_PM}</span> + <i class="icon fa-quote-left fa-fw" aria-hidden="true"></i><span class="sr-only">{L_BUTTON_QUOTE}</span> </a> </li> <!-- ENDIF --> @@ -124,8 +124,8 @@ <p class="author"> <strong>{L_SENT_AT}{L_COLON}</strong> {SENT_DATE} <br /><strong>{L_PM_FROM}{L_COLON}</strong> {MESSAGE_AUTHOR_FULL} - <!-- IF S_TO_RECIPIENT --><br /><strong>{L_TO}{L_COLON}</strong> <!-- BEGIN to_recipient --><!-- IF to_recipient.NAME_FULL -->{to_recipient.NAME_FULL}<!-- ELSE --><a href="{to_recipient.U_VIEW}" style="color:<!-- IF to_recipient.COLOUR -->{to_recipient.COLOUR}<!-- ELSEIF to_recipient.IS_GROUP -->#0000FF<!-- ENDIF -->;">{to_recipient.NAME}</a><!-- ENDIF --> <!-- END to_recipient --><!-- ENDIF --> - <!-- IF S_BCC_RECIPIENT --><br /><strong>{L_BCC}{L_COLON}</strong> <!-- BEGIN bcc_recipient --><!-- IF bcc_recipient.NAME_FULL -->{bcc_recipient.NAME_FULL}<!-- ELSE --><a href="{bcc_recipient.U_VIEW}" style="color:<!-- IF bcc_recipient.COLOUR -->{bcc_recipient.COLOUR}<!-- ELSEIF bcc_recipient.IS_GROUP -->#0000FF<!-- ENDIF -->;">{bcc_recipient.NAME}</a><!-- ENDIF --> <!-- END bcc_recipient --><!-- ENDIF --> + <!-- IF S_TO_RECIPIENT --><br /><strong>{L_TO}{L_COLON}</strong> <!-- BEGIN to_recipient --><!-- IF to_recipient.NAME_FULL -->{to_recipient.NAME_FULL}<!-- ELSE --><a href="{to_recipient.U_VIEW}"<!-- IF to_recipient.COLOUR --> style="color:{to_recipient.COLOUR};"<!-- ENDIF -->><strong>{to_recipient.NAME}</strong></a><!-- ENDIF --> <!-- END to_recipient --><!-- ENDIF --> + <!-- IF S_BCC_RECIPIENT --><br /><strong>{L_BCC}{L_COLON}</strong> <!-- BEGIN bcc_recipient --><!-- IF bcc_recipient.NAME_FULL -->{bcc_recipient.NAME_FULL}<!-- ELSE --><a href="{bcc_recipient.U_VIEW}"<!-- IF bcc_recipient.COLOUR --> style="color:{bcc_recipient.COLOUR};"<!-- ENDIF -->><strong>{bcc_recipient.NAME}</strong></a><!-- ENDIF --> <!-- END bcc_recipient --><!-- ENDIF --> </p> diff --git a/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html b/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html index 9377eeb9f5..41ff5b898a 100644 --- a/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html +++ b/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html @@ -8,6 +8,7 @@ <title>{SITENAME} • {PAGE_TITLE}</title> <link href="{T_THEME_PATH}/print.css" rel="stylesheet"> +<link href="{T_THEME_PATH}/bidi.css" rel="stylesheet"> <!-- EVENT ucp_pm_viewmessage_print_head_append --> </head> <body id="phpbb"> @@ -41,7 +42,14 @@ <div id="page-footer" class="page-footer"> <div class="page-number">{S_TIMEZONE}<br />{PAGE_NUMBER}</div> - <div class="copyright">Powered by phpBB® Forum Software © phpBB Limited<br />https://www.phpbb.com/</div> + <div class="copyright"> + <p>{{ CREDIT_LINE }} + </p> + {% if TRANSLATION_INFO %} + <p>{{ TRANSLATION_INFO }} + </p> + {% endif %} + </div> </div> </div> diff --git a/phpBB/styles/prosilver/template/ucp_prefs_personal.html b/phpBB/styles/prosilver/template/ucp_prefs_personal.html index 4cd9f6655b..1650705d4b 100644 --- a/phpBB/styles/prosilver/template/ucp_prefs_personal.html +++ b/phpBB/styles/prosilver/template/ucp_prefs_personal.html @@ -85,8 +85,7 @@ </fieldset> </form> -<script type="text/javascript"> -// <![CDATA[ +<script> var date_format = '{A_DATE_FORMAT}'; var default_dateformat = '{A_DEFAULT_DATEFORMAT}'; @@ -118,7 +117,6 @@ } window.onload = customDates; -// ]]> </script> <!-- INCLUDE ucp_footer.html --> diff --git a/phpBB/styles/prosilver/template/ucp_profile_signature.html b/phpBB/styles/prosilver/template/ucp_profile_signature.html index 614f6f440d..ed28b7ab02 100644 --- a/phpBB/styles/prosilver/template/ucp_profile_signature.html +++ b/phpBB/styles/prosilver/template/ucp_profile_signature.html @@ -24,6 +24,7 @@ <!-- INCLUDE posting_editor.html --> <h3>{L_OPTIONS}</h3> <fieldset> + {% EVENT ucp_profile_signature_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/ucp_register.html b/phpBB/styles/prosilver/template/ucp_register.html index 38413addba..bf39990c35 100644 --- a/phpBB/styles/prosilver/template/ucp_register.html +++ b/phpBB/styles/prosilver/template/ucp_register.html @@ -1,7 +1,6 @@ <!-- INCLUDE overall_header.html --> -<script type="text/javascript"> -// <![CDATA[ +<script> /** * Change language */ @@ -11,7 +10,6 @@ document.forms['register'].change_lang.value = lang_iso; document.forms['register'].submit.click(); } -// ]]> </script> <form id="register" method="post" action="{S_UCP_ACTION}"{S_FORM_ENCTYPE}> diff --git a/phpBB/styles/prosilver/template/ucp_remind.html b/phpBB/styles/prosilver/template/ucp_remind.html index 0ab1251d9e..8b700de430 100644 --- a/phpBB/styles/prosilver/template/ucp_remind.html +++ b/phpBB/styles/prosilver/template/ucp_remind.html @@ -9,14 +9,19 @@ <h2>{L_SEND_PASSWORD}</h2> <fieldset> + {% if USERNAME_REQUIRED %} + <p class="error">{{ lang('EMAIL_NOT_UNIQUE') }}</p> + {% endif %} <dl> - <dt><label for="username">{L_USERNAME}{L_COLON}</label></dt> - <dd><input class="inputbox narrow" type="text" name="username" id="username" size="25" /></dd> + <dt><label for="email">{L_EMAIL_ADDRESS}{L_COLON}</label><br /><span>{L_EMAIL_REMIND}</span></dt> + <dd><input class="inputbox narrow" type="email" name="email" id="email" size="25" maxlength="100" value="{{ EMAIL }}" autofocus /></dd> </dl> + {% if USERNAME_REQUIRED %} <dl> - <dt><label for="email">{L_EMAIL_ADDRESS}{L_COLON}</label><br /><span>{L_EMAIL_REMIND}</span></dt> - <dd><input class="inputbox narrow" type="email" name="email" id="email" size="25" maxlength="100" /></dd> + <dt><label for="username">{L_USERNAME}{L_COLON}</label></dt> + <dd><input class="inputbox narrow" type="text" name="username" id="username" size="25" /></dd> </dl> + {% endif %} <dl> <dt> </dt> <dd>{S_HIDDEN_FIELDS}<input type="submit" name="submit" id="submit" class="button1" value="{L_SUBMIT}" tabindex="2" /> <input type="reset" value="{L_RESET}" name="reset" class="button2" /></dd> diff --git a/phpBB/styles/prosilver/template/viewforum_body.html b/phpBB/styles/prosilver/template/viewforum_body.html index b7093cbac5..40beb784d7 100644 --- a/phpBB/styles/prosilver/template/viewforum_body.html +++ b/phpBB/styles/prosilver/template/viewforum_body.html @@ -114,6 +114,7 @@ <dd><input type="submit" name="login" tabindex="5" value="{L_LOGIN}" class="button1" /></dd> </dl> {S_LOGIN_REDIRECT} + {S_FORM_TOKEN_LOGIN} </fieldset> </div> @@ -156,7 +157,7 @@ <li class="row<!-- IF topicrow.S_ROW_COUNT is even --> bg1<!-- ELSE --> bg2<!-- ENDIF --><!-- IF topicrow.S_POST_GLOBAL --> global-announce<!-- ENDIF --><!-- IF topicrow.S_POST_ANNOUNCE --> announce<!-- ENDIF --><!-- IF topicrow.S_POST_STICKY --> sticky<!-- ENDIF --><!-- IF topicrow.S_TOPIC_REPORTED --> reported<!-- ENDIF -->"> <!-- EVENT viewforum_body_topic_row_prepend --> <dl class="row-item {topicrow.TOPIC_IMG_STYLE}"> - <dt<!-- IF topicrow.TOPIC_ICON_IMG and S_TOPIC_ICONS --> style="background-image: url({T_ICONS_PATH}{topicrow.TOPIC_ICON_IMG}); background-repeat: no-repeat;"<!-- ENDIF --> title="{topicrow.TOPIC_FOLDER_IMG_ALT}"> + <dt<!-- IF topicrow.TOPIC_ICON_IMG and S_TOPIC_ICONS --> style="background-image: url('{T_ICONS_PATH}{topicrow.TOPIC_ICON_IMG}'); background-repeat: no-repeat;"<!-- ENDIF --> title="{topicrow.TOPIC_FOLDER_IMG_ALT}"> <!-- IF topicrow.S_UNREAD_TOPIC and not S_IS_BOT --><a href="{topicrow.U_NEWEST_POST}" class="row-item-link"></a><!-- ENDIF --> <div class="list-inner"> <!-- EVENT topiclist_row_prepend --> @@ -165,10 +166,10 @@ <i class="icon fa-file fa-fw icon-red icon-md" aria-hidden="true"></i><span class="sr-only">{NEW_POST}</span> </a> <!-- ENDIF --> - <a href="{topicrow.U_VIEW_TOPIC}" class="topictitle">{topicrow.TOPIC_TITLE}</a> + <!-- IF topicrow.U_VIEW_TOPIC --><a href="{topicrow.U_VIEW_TOPIC}" class="topictitle">{topicrow.TOPIC_TITLE}</a><!-- ELSE -->{topicrow.TOPIC_TITLE}<!-- ENDIF --> <!-- IF topicrow.S_TOPIC_UNAPPROVED or topicrow.S_POSTS_UNAPPROVED --> - <a href="{topicrow.U_MCP_QUEUE}" title="{L_TOPIC_UNAPPROVED}"> - <i class="icon fa-question fa-fw icon-blue" aria-hidden="true"></i><span class="sr-only">{L_TOPIC_UNAPPROVED}</span> + <a href="{topicrow.U_MCP_QUEUE}" title="<!-- IF topicrow.S_TOPIC_UNAPPROVED -->{L_TOPIC_UNAPPROVED}<!-- ELSE -->{L_POSTS_UNAPPROVED}<!-- ENDIF -->"> + <i class="icon fa-question fa-fw icon-blue" aria-hidden="true"></i><span class="sr-only"><!-- IF topicrow.S_TOPIC_UNAPPROVED -->{L_TOPIC_UNAPPROVED}<!-- ELSE -->{L_POSTS_UNAPPROVED}<!-- ENDIF --></span> </a> <!-- ENDIF --> <!-- IF topicrow.S_TOPIC_DELETED --> @@ -186,7 +187,7 @@ <!-- IF not S_IS_BOT --> <div class="responsive-show" style="display: none;"> - {L_LAST_POST} {L_POST_BY_AUTHOR} {topicrow.LAST_POST_AUTHOR_FULL} « <a href="{topicrow.U_LAST_POST}" title="{L_GOTO_LAST_POST}"><time datetime="{topicrow.LAST_POST_TIME_RFC3339}">{topicrow.LAST_POST_TIME}</time></a> + {L_LAST_POST} {L_POST_BY_AUTHOR} <!-- EVENT viewforum_body_last_post_author_username_prepend -->{topicrow.LAST_POST_AUTHOR_FULL}<!-- EVENT viewforum_body_last_post_author_username_append --> « <a href="{topicrow.U_LAST_POST}" title="{L_GOTO_LAST_POST}"><time datetime="{topicrow.LAST_POST_TIME_RFC3339}">{topicrow.LAST_POST_TIME}</time></a> <!-- IF topicrow.S_POST_GLOBAL and FORUM_ID != topicrow.FORUM_ID --><br />{L_POSTED} {L_IN} <a href="{topicrow.U_VIEW_FORUM}">{topicrow.FORUM_NAME}</a><!-- ENDIF --> </div> <!-- IF topicrow.REPLIES --> @@ -197,7 +198,9 @@ <div class="topic-poster responsive-hide left-box"> <!-- IF topicrow.S_HAS_POLL --><i class="icon fa-bar-chart fa-fw" aria-hidden="true"></i><!-- ENDIF --> <!-- IF topicrow.ATTACH_ICON_IMG --><i class="icon fa-paperclip fa-fw" aria-hidden="true"></i><!-- ENDIF --> - {L_POST_BY_AUTHOR} {topicrow.TOPIC_AUTHOR_FULL} » <time datetime="{topicrow.FIRST_POST_TIME_RFC3339}">{topicrow.FIRST_POST_TIME}</time> + {% EVENT topiclist_row_topic_by_author_before %} + {L_POST_BY_AUTHOR} <!-- EVENT viewforum_body_topic_author_username_prepend -->{topicrow.TOPIC_AUTHOR_FULL}<!-- EVENT viewforum_body_topic_author_username_append --> » <time datetime="{topicrow.FIRST_POST_TIME_RFC3339}">{topicrow.FIRST_POST_TIME}</time> + {% EVENT topiclist_row_topic_by_author_after %} <!-- IF topicrow.S_POST_GLOBAL and FORUM_ID != topicrow.FORUM_ID --> » {L_IN} <a href="{topicrow.U_VIEW_FORUM}">{topicrow.FORUM_NAME}</a><!-- ENDIF --> </div> @@ -223,8 +226,8 @@ <dd class="posts">{topicrow.REPLIES} <dfn>{L_REPLIES}</dfn></dd> <dd class="views">{topicrow.VIEWS} <dfn>{L_VIEWS}</dfn></dd> <dd class="lastpost"> - <span><dfn>{L_LAST_POST} </dfn>{L_POST_BY_AUTHOR} {topicrow.LAST_POST_AUTHOR_FULL} - <!-- IF not S_IS_BOT --> + <span><dfn>{L_LAST_POST} </dfn>{L_POST_BY_AUTHOR} <!-- EVENT viewforum_body_last_post_author_username_prepend -->{topicrow.LAST_POST_AUTHOR_FULL}<!-- EVENT viewforum_body_last_post_author_username_append --> + <!-- IF not S_IS_BOT and topicrow.U_LAST_POST --> <a href="{topicrow.U_LAST_POST}" title="{L_GOTO_LAST_POST}"> <i class="icon fa-external-link-square fa-fw icon-lightgray icon-md" aria-hidden="true"></i><span class="sr-only">{VIEW_LATEST_POST}</span> </a> @@ -250,10 +253,10 @@ <strong>{L_NO_TOPICS}</strong> </div> </div> - <!-- ELSE IF not S_USER_CAN_POST --> + <!-- ELSE IF not S_HAS_SUBFORUM --> <div class="panel"> <div class="inner"> - <strong>{L_NO_FORUMS}</strong> + <strong>{L_NO_FORUMS_IN_CATEGORY}</strong> </div> </div> <!-- ENDIF --> diff --git a/phpBB/styles/prosilver/template/viewonline_body.html b/phpBB/styles/prosilver/template/viewonline_body.html index dd0ca72502..c019977179 100644 --- a/phpBB/styles/prosilver/template/viewonline_body.html +++ b/phpBB/styles/prosilver/template/viewonline_body.html @@ -29,7 +29,7 @@ <tbody> <!-- BEGIN user_row --> <tr class="<!-- IF user_row.S_ROW_COUNT is odd -->bg1<!-- ELSE -->bg2<!-- ENDIF -->"> - <td>{user_row.USERNAME_FULL}<!-- IF user_row.USER_IP --> <span style="float: {S_CONTENT_FLOW_END};">{L_IP}{L_COLON} <a href="{user_row.U_USER_IP}">{user_row.USER_IP}</a> » <a href="{user_row.U_WHOIS}" onclick="popup(this.href, 750, 500); return false;">{L_WHOIS}</a></span><!-- ENDIF --> + <td><!-- EVENT viewonline_body_username_prepend -->{user_row.USERNAME_FULL}<!-- EVENT viewonline_body_username_append --><!-- IF user_row.USER_IP --> <span style="float: {S_CONTENT_FLOW_END};">{L_IP}{L_COLON} <a href="{user_row.U_USER_IP}">{user_row.USER_IP}</a> » <a href="{user_row.U_WHOIS}" onclick="popup(this.href, 750, 500); return false;">{L_WHOIS}</a></span><!-- ENDIF --> <!-- IF user_row.USER_BROWSER --><br />{user_row.USER_BROWSER}<!-- ENDIF --></td> <td class="info"><a href="{user_row.U_FORUM_LOCATION}">{user_row.FORUM_LOCATION}</a></td> <td class="active">{user_row.LASTUPDATE}</td> diff --git a/phpBB/styles/prosilver/template/viewtopic_body.html b/phpBB/styles/prosilver/template/viewtopic_body.html index 0de641c985..f77b99dc29 100644 --- a/phpBB/styles/prosilver/template/viewtopic_body.html +++ b/phpBB/styles/prosilver/template/viewtopic_body.html @@ -242,35 +242,35 @@ <!-- IF postrow.U_DELETE --> <li> <a href="{postrow.U_DELETE}" title="{L_DELETE_POST}" class="button button-icon-only"> - <i class="icon fa-times fa-fw" aria-hidden="true"></i><span class="sr-only">{L_DELETE_POST}</span> + <i class="icon fa-times fa-fw" aria-hidden="true"></i><span class="sr-only">{L_BUTTON_DELETE}</span> </a> </li> <!-- ENDIF --> <!-- IF postrow.U_REPORT --> <li> <a href="{postrow.U_REPORT}" title="{L_REPORT_POST}" class="button button-icon-only"> - <i class="icon fa-exclamation fa-fw" aria-hidden="true"></i><span class="sr-only">{L_REPORT_POST}</span> + <i class="icon fa-exclamation fa-fw" aria-hidden="true"></i><span class="sr-only">{L_BUTTON_REPORT}</span> </a> </li> <!-- ENDIF --> <!-- IF postrow.U_WARN --> <li> <a href="{postrow.U_WARN}" title="{L_WARN_USER}" class="button button-icon-only"> - <i class="icon fa-exclamation-triangle fa-fw" aria-hidden="true"></i><span class="sr-only">{L_WARN_USER}</span> + <i class="icon fa-exclamation-triangle fa-fw" aria-hidden="true"></i><span class="sr-only">{L_BUTTON_WARN}</span> </a> </li> <!-- ENDIF --> <!-- IF postrow.U_INFO --> <li> <a href="{postrow.U_INFO}" title="{L_INFORMATION}" class="button button-icon-only"> - <i class="icon fa-info fa-fw" aria-hidden="true"></i><span class="sr-only">{L_INFORMATION}</span> + <i class="icon fa-info fa-fw" aria-hidden="true"></i><span class="sr-only">{L_BUTTON_INFORMATION}</span> </a> </li> <!-- ENDIF --> <!-- IF postrow.U_QUOTE --> <li> <a href="{postrow.U_QUOTE}" title="{L_REPLY_WITH_QUOTE}" class="button button-icon-only"> - <i class="icon fa-quote-left fa-fw" aria-hidden="true"></i><span class="sr-only">{L_QUOTE}</span> + <i class="icon fa-quote-left fa-fw" aria-hidden="true"></i><span class="sr-only">{L_BUTTON_QUOTE}</span> </a> </li> <!-- ENDIF --> @@ -326,6 +326,8 @@ <div class="content">{postrow.MESSAGE}</div> + <!-- EVENT viewtopic_body_postrow_content_after --> + <!-- IF postrow.S_HAS_ATTACHMENTS --> <dl class="attachbox"> <dt> diff --git a/phpBB/styles/prosilver/template/viewtopic_print.html b/phpBB/styles/prosilver/template/viewtopic_print.html index 3c1ed4c3f1..658062f9fd 100644 --- a/phpBB/styles/prosilver/template/viewtopic_print.html +++ b/phpBB/styles/prosilver/template/viewtopic_print.html @@ -8,9 +8,10 @@ <title>{SITENAME} • {PAGE_TITLE}</title> <link href="{T_THEME_PATH}/print.css" rel="stylesheet"> +<link href="{T_THEME_PATH}/bidi.css" rel="stylesheet"> <!-- EVENT viewtopic_print_head_append --> </head> -<body id="phpbb"> +<body id="phpbb" class="{S_CONTENT_DIRECTION}"> <div id="wrap" class="wrap"> <a id="top" class="top-anchor" accesskey="t"></a> @@ -37,7 +38,14 @@ <div id="page-footer" class="page-footer"> <div class="page-number">{S_TIMEZONE}<br />{PAGE_NUMBER}</div> - <div class="copyright">Powered by phpBB® Forum Software © phpBB Limited<br />https://www.phpbb.com/</div> + <div class="copyright"> + <p>{{ CREDIT_LINE }} + </p> + {% if TRANSLATION_INFO %} + <p>{{ TRANSLATION_INFO }} + </p> + {% endif %} + </div> </div> </div> diff --git a/phpBB/styles/prosilver/template/viewtopic_topic_tools.html b/phpBB/styles/prosilver/template/viewtopic_topic_tools.html index 397c807bb3..272a434f6a 100644 --- a/phpBB/styles/prosilver/template/viewtopic_topic_tools.html +++ b/phpBB/styles/prosilver/template/viewtopic_topic_tools.html @@ -11,7 +11,7 @@ <!-- IF U_WATCH_TOPIC --> <li> <a href="{U_WATCH_TOPIC}" class="watch-topic-link" title="{S_WATCH_TOPIC_TITLE}" data-ajax="toggle_link" data-toggle-class="icon <!-- IF S_WATCHING_TOPIC -->fa-check-square-o<!-- ELSE -->fa-square-o<!-- ENDIF --> fa-fw" data-toggle-text="{S_WATCH_TOPIC_TOGGLE}" data-toggle-url="{U_WATCH_TOPIC_TOGGLE}" data-update-all=".watch-topic-link"> - <i class="icon <!-- IF S_WATCHING_FORUM -->fa-square-o<!-- ELSE -->fa-check-square-o<!-- ENDIF --> fa-fw" aria-hidden="true"></i><span>{S_WATCH_TOPIC_TITLE}</span> + <i class="icon <!-- IF S_WATCHING_TOPIC -->fa-square-o<!-- ELSE -->fa-check-square-o<!-- ENDIF --> fa-fw" aria-hidden="true"></i><span>{S_WATCH_TOPIC_TITLE}</span> </a> </li> <!-- ENDIF --> diff --git a/phpBB/styles/prosilver/theme/bidi.css b/phpBB/styles/prosilver/theme/bidi.css index 923ff3e792..79b769b1e7 100644 --- a/phpBB/styles/prosilver/theme/bidi.css +++ b/phpBB/styles/prosilver/theme/bidi.css @@ -239,6 +239,10 @@ /* Pagination ---------------------------------------- */ +.rtl .page-number { + float: left; +} + .rtl .pagination { text-align: left; float: left; @@ -451,6 +455,10 @@ li.breadcrumbs span:first-child > a { /* Post body styles ----------------------------------------*/ +.rtl .date { + float: left; +} + .rtl .postbody, .rtl .postbody h3 { float: right; } diff --git a/phpBB/styles/prosilver/theme/common.css b/phpBB/styles/prosilver/theme/common.css index 348355e8c4..a0dc5e043b 100644 --- a/phpBB/styles/prosilver/theme/common.css +++ b/phpBB/styles/prosilver/theme/common.css @@ -981,8 +981,15 @@ fieldset.fields1 dl.pmlist dd.recipients { /* Miscellaneous styles ---------------------------------------- */ .copyright { - padding: 5px; + font-size: 10px; text-align: center; + padding: 10px; +} + +.footer-row { + font-size: 10px; + line-height: 1.8; + margin: 0; } .small { @@ -1267,6 +1274,10 @@ ul.linklist:after, width: 50px; } +.dropdown .clone.hidden { + display: none; +} + .dropdown .clone.hidden + li.separator { display: none; } diff --git a/phpBB/styles/prosilver/theme/content.css b/phpBB/styles/prosilver/theme/content.css index a071e63c69..807633864c 100644 --- a/phpBB/styles/prosilver/theme/content.css +++ b/phpBB/styles/prosilver/theme/content.css @@ -18,7 +18,7 @@ ul.topiclist dl { } ul.topiclist li.row dl { - padding: 2px 0; + margin: 2px 0; } ul.topiclist dt, ul.topiclist dd { @@ -70,6 +70,11 @@ ul.topiclist dd { box-sizing: border-box; } +ul.topiclist li.row dd { + padding: 4px 0 999px 0; + margin-bottom: -995px; +} + ul.topiclist dfn { /* Labels for post/view counts */ position: absolute; @@ -524,6 +529,7 @@ blockquote .codebox { /* Attachments ----------------------------------------*/ .attachbox { + font-size: 13px; float: left; width: auto; max-width: 100%; diff --git a/phpBB/styles/prosilver/theme/cp.css b/phpBB/styles/prosilver/theme/cp.css index d54c948343..0041417022 100644 --- a/phpBB/styles/prosilver/theme/cp.css +++ b/phpBB/styles/prosilver/theme/cp.css @@ -300,11 +300,14 @@ ol.def-rules li { padding: 0 3px; } +/* DEPRECATED 3.2.6 .pmlist li.pm_message_reported_colour, .pm_message_reported_colour { border-left-color: transparent; border-right-color: transparent; } +*/ +.pmlist li.pm_message_reported_colour, .pm_message_reported_colour, .pmlist li.pm_marked_colour, .pm_marked_colour, .pmlist li.pm_replied_colour, .pm_replied_colour, .pmlist li.pm_friend_colour, .pm_friend_colour, diff --git a/phpBB/styles/prosilver/theme/plupload.css b/phpBB/styles/prosilver/theme/plupload.css index f466803964..b1f3ae2da8 100644 --- a/phpBB/styles/prosilver/theme/plupload.css +++ b/phpBB/styles/prosilver/theme/plupload.css @@ -3,6 +3,10 @@ margin-bottom: 1em; } +.attach-row-tpl { + display: none; +} + .file-list td { vertical-align: middle; } diff --git a/phpBB/styles/prosilver/theme/print.css b/phpBB/styles/prosilver/theme/print.css index a83270b742..9445279773 100644 --- a/phpBB/styles/prosilver/theme/print.css +++ b/phpBB/styles/prosilver/theme/print.css @@ -133,6 +133,8 @@ ol, ul { /* Misc page elements */ div.spacer { clear: both; } +code { display: block; } + /* Accessibility tweaks: Mozilla.org */ .skip_link { display: none; } diff --git a/phpBB/styles/prosilver/theme/responsive.css b/phpBB/styles/prosilver/theme/responsive.css index fcc11f1fc2..ca4054c27f 100644 --- a/phpBB/styles/prosilver/theme/responsive.css +++ b/phpBB/styles/prosilver/theme/responsive.css @@ -421,6 +421,7 @@ .column1, .column2, .left-box.profile-details { float: none; width: auto; + clear: both; } /* Polls diff --git a/phpBB/ucp.php b/phpBB/ucp.php index 7eca5ede62..96a3efea97 100644 --- a/phpBB/ucp.php +++ b/phpBB/ucp.php @@ -30,6 +30,12 @@ if (in_array($mode, array('login', 'login_link', 'logout', 'confirm', 'sendpassw define('IN_LOGIN', true); } +if ($mode === 'delete_cookies') +{ + define('SKIP_CHECK_BAN', true); + define('SKIP_CHECK_DISABLED', true); +} + // Start session management $user->session_begin(); $auth->acl($user->data); @@ -138,7 +144,7 @@ switch ($mode) 'AGREEMENT_TITLE' => $user->lang[$title], 'AGREEMENT_TEXT' => sprintf($user->lang[$message], $config['sitename'], generate_board_url()), 'U_BACK' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login'), - 'L_BACK' => $user->lang['BACK_TO_LOGIN'], + 'L_BACK' => $user->lang['BACK_TO_PREV'], )); page_footer(); diff --git a/phpBB/viewforum.php b/phpBB/viewforum.php index 94309afc5a..a77c08cdd0 100644 --- a/phpBB/viewforum.php +++ b/phpBB/viewforum.php @@ -87,7 +87,7 @@ if (isset($_GET['e']) && !$user->data['is_registered']) } // Permissions check -if (!$auth->acl_gets('f_list', 'f_read', $forum_id) || ($forum_data['forum_type'] == FORUM_LINK && $forum_data['forum_link'] && !$auth->acl_get('f_read', $forum_id))) +if (!$auth->acl_gets('f_list', 'f_list_topics', 'f_read', $forum_id) || ($forum_data['forum_type'] == FORUM_LINK && $forum_data['forum_link'] && !$auth->acl_get('f_read', $forum_id))) { if ($user->data['user_id'] != ANONYMOUS) { @@ -161,7 +161,22 @@ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); $topics_count = $phpbb_content_visibility->get_count('forum_topics', $forum_data, $forum_id); $start = $pagination->validate_start($start, $config['topics_per_page'], $topics_count); -page_header($forum_data['forum_name'] . ($start ? ' - ' . $user->lang('PAGE_TITLE_NUMBER', $pagination->get_on_page($config['topics_per_page'], $start)) : ''), true, $forum_id); +$page_title = $forum_data['forum_name'] . ($start ? ' - ' . $user->lang('PAGE_TITLE_NUMBER', $pagination->get_on_page($config['topics_per_page'], $start)) : ''); + +/** +* You can use this event to modify the page title of the viewforum page +* +* @event core.viewforum_modify_page_title +* @var string page_title Title of the viewforum page +* @var array forum_data Array with forum data +* @var int forum_id The forum ID +* @var int start Start offset used to calculate the page +* @since 3.2.2-RC1 +*/ +$vars = array('page_title', 'forum_data', 'forum_id', 'start'); +extract($phpbb_dispatcher->trigger_event('core.viewforum_modify_page_title', compact($vars))); + +page_header($page_title, true, $forum_id); $template->set_filenames(array( 'body' => 'viewforum_body.html') @@ -181,7 +196,7 @@ if (!($forum_data['forum_type'] == FORUM_POST || (($forum_data['forum_flags'] & // Ok, if someone has only list-access, we only display the forum list. // We also make this circumstance available to the template in case we want to display a notice. ;) -if (!$auth->acl_get('f_read', $forum_id)) +if (!$auth->acl_gets('f_read', 'f_list_topics', $forum_id)) { $template->assign_vars(array( 'S_NO_READ_ACCESS' => true, @@ -270,6 +285,20 @@ $limit_days = array(0 => $user->lang['ALL_TOPICS'], 1 => $user->lang['1_DAY'], 7 $sort_by_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIME'], 'r' => $user->lang['REPLIES'], 's' => $user->lang['SUBJECT'], 'v' => $user->lang['VIEWS']); $sort_by_sql = array('a' => 't.topic_first_poster_name', 't' => array('t.topic_last_post_time', 't.topic_last_post_id'), 'r' => (($auth->acl_get('m_approve', $forum_id)) ? 't.topic_posts_approved + t.topic_posts_unapproved + t.topic_posts_softdeleted' : 't.topic_posts_approved'), 's' => 'LOWER(t.topic_title)', 'v' => 't.topic_views'); +/** + * Modify the topic ordering if needed + * + * @event core.viewforum_modify_topic_ordering + * @var array sort_by_text Topic ordering options + * @var array sort_by_sql Topic orderings options SQL equivalent + * @since 3.2.5-RC1 + */ +$vars = array( + 'sort_by_text', + 'sort_by_sql', +); +extract($phpbb_dispatcher->trigger_event('core.viewforum_modify_topic_ordering', compact($vars))); + $s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = ''; gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param, $default_sort_days, $default_sort_key, $default_sort_dir); @@ -385,7 +414,7 @@ $template->assign_vars(array( 'S_SELECT_SORT_DIR' => $s_sort_dir, 'S_SELECT_SORT_KEY' => $s_sort_key, 'S_SELECT_SORT_DAYS' => $s_limit_days, - 'S_TOPIC_ICONS' => ($s_display_active && sizeof($active_forum_ary)) ? max($active_forum_ary['enable_icons']) : (($forum_data['enable_icons']) ? true : false), + 'S_TOPIC_ICONS' => ($s_display_active && count($active_forum_ary)) ? max($active_forum_ary['enable_icons']) : (($forum_data['enable_icons']) ? true : false), 'U_WATCH_FORUM_LINK' => $s_watching_forum['link'], 'U_WATCH_FORUM_TOGGLE' => $s_watching_forum['link_toggle'], 'S_WATCH_FORUM_TITLE' => $s_watching_forum['title'], @@ -395,7 +424,7 @@ $template->assign_vars(array( 'S_DISPLAY_SEARCHBOX' => ($auth->acl_get('u_search') && $auth->acl_get('f_search', $forum_id) && $config['load_search']) ? true : false, 'S_SEARCHBOX_ACTION' => append_sid("{$phpbb_root_path}search.$phpEx"), 'S_SEARCH_LOCAL_HIDDEN_FIELDS' => build_hidden_fields($s_search_hidden_fields), - 'S_SINGLE_MODERATOR' => (!empty($moderators[$forum_id]) && sizeof($moderators[$forum_id]) > 1) ? false : true, + 'S_SINGLE_MODERATOR' => (!empty($moderators[$forum_id]) && count($moderators[$forum_id]) > 1) ? false : true, 'S_IS_LOCKED' => ($forum_data['forum_status'] == ITEM_LOCKED) ? true : false, 'S_VIEWFORUM' => true, @@ -465,7 +494,7 @@ if ($user->data['is_registered']) $sql_array['LEFT_JOIN'][] = array('FROM' => array(TOPICS_TRACK_TABLE => 'tt'), 'ON' => 'tt.topic_id = t.topic_id AND tt.user_id = ' . $user->data['user_id']); $sql_array['SELECT'] .= ', tt.mark_time'; - if ($s_display_active && sizeof($active_forum_ary)) + if ($s_display_active && count($active_forum_ary)) { $sql_array['LEFT_JOIN'][] = array('FROM' => array(FORUMS_TRACK_TABLE => 'ft'), 'ON' => 'ft.forum_id = t.forum_id AND ft.user_id = ' . $user->data['user_id']); $sql_array['SELECT'] .= ', ft.mark_time AS forum_mark_time'; @@ -491,7 +520,7 @@ if ($forum_data['forum_type'] == FORUM_POST) 'WHERE' => '(t.forum_id = ' . $forum_id . ' AND t.topic_type = ' . POST_ANNOUNCE . ') OR - (' . $db->sql_in_set('t.forum_id', $g_forum_ary) . ' + (' . $db->sql_in_set('t.forum_id', $g_forum_ary, false, true) . ' AND t.topic_type = ' . POST_GLOBAL . ')', 'ORDER_BY' => 't.topic_time DESC', @@ -523,7 +552,7 @@ if ($forum_data['forum_type'] == FORUM_POST) while ($row = $db->sql_fetchrow($result)) { - if ($row['topic_visibility'] != ITEM_APPROVED && !$auth->acl_get('m_approve', $row['forum_id'])) + if (!$phpbb_content_visibility->is_visible('topic', $row['forum_id'], $row)) { // Do not display announcements that are waiting for approval or soft deleted. continue; @@ -573,8 +602,8 @@ if ($start > $topics_count / 2) // Select the sort order $direction = (($sort_dir == 'd') ? 'ASC' : 'DESC'); - $sql_limit = $pagination->reverse_limit($start, $sql_limit, $topics_count - sizeof($announcement_list)); - $sql_start = $pagination->reverse_start($start, $sql_limit, $topics_count - sizeof($announcement_list)); + $sql_limit = $pagination->reverse_limit($start, $sql_limit, $topics_count - count($announcement_list)); + $sql_start = $pagination->reverse_start($start, $sql_limit, $topics_count - count($announcement_list)); } else { @@ -583,6 +612,18 @@ else $sql_start = $start; } +/** + * Modify the topics sort ordering if needed + * + * @event core.viewforum_modify_sort_direction + * @var string direction Topics sort order + * @since 3.2.5-RC1 + */ +$vars = array( + 'direction', +); +extract($phpbb_dispatcher->trigger_event('core.viewforum_modify_sort_direction', compact($vars))); + if (is_array($sort_by_sql[$sort_key])) { $sql_sort_order = implode(' ' . $direction . ', ', $sort_by_sql[$sort_key]) . ' ' . $direction; @@ -592,7 +633,7 @@ else $sql_sort_order = $sort_by_sql[$sort_key] . ' ' . $direction; } -if ($forum_data['forum_type'] == FORUM_POST || !sizeof($active_forum_ary)) +if ($forum_data['forum_type'] == FORUM_POST || !count($active_forum_ary)) { $sql_where = 't.forum_id = ' . $forum_id; } @@ -603,7 +644,7 @@ else if (empty($active_forum_ary['exclude_forum_id'])) else { $get_forum_ids = array_diff($active_forum_ary['forum_id'], $active_forum_ary['exclude_forum_id']); - $sql_where = (sizeof($get_forum_ids)) ? $db->sql_in_set('t.forum_id', $get_forum_ids) : 't.forum_id = ' . $forum_id; + $sql_where = (count($get_forum_ids)) ? $db->sql_in_set('t.forum_id', $get_forum_ids) : 't.forum_id = ' . $forum_id; } // Grab just the sorted topic ids @@ -662,7 +703,7 @@ $db->sql_freeresult($result); // For storing shadow topics $shadow_topic_list = array(); -if (sizeof($topic_list)) +if (count($topic_list)) { // SQL array for obtaining topics/stickies $sql_array = array( @@ -692,7 +733,7 @@ if (sizeof($topic_list)) } // If we have some shadow topics, update the rowset to reflect their topic information -if (sizeof($shadow_topic_list)) +if (count($shadow_topic_list)) { // SQL array for obtaining shadow topics $sql_array = array( @@ -732,7 +773,7 @@ if (sizeof($shadow_topic_list)) } // Do not include those topics the user has no permission to access - if (!$auth->acl_get('f_read', $row['forum_id'])) + if (!$auth->acl_gets('f_read', 'f_list_topics', $row['forum_id'])) { // We need to remove any trace regarding this topic. :) unset($rowset[$orig_topic_id]); @@ -767,7 +808,7 @@ if ($s_display_active) // We need to remove the global announcements from the forums total topic count, // otherwise the number is different from the one on the forum list -$total_topic_count = $topics_count - sizeof($announcement_list); +$total_topic_count = $topics_count - count($announcement_list); $base_url = append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$forum_id" . ((strlen($u_sort_param)) ? "&$u_sort_param" : '')); $pagination->generate_template_pagination($base_url, 'pagination', 'start', $total_topic_count, $config['topics_per_page'], $start); @@ -794,7 +835,7 @@ $vars = array('topic_list', 'rowset', 'total_topic_count', 'forum_id'); extract($phpbb_dispatcher->trigger_event('core.viewforum_modify_topics_data', compact($vars))); // Okay, lets dump out the page ... -if (sizeof($topic_list)) +if (count($topic_list)) { $mark_forum_read = true; $mark_time_forum = 0; @@ -875,7 +916,7 @@ if (sizeof($topic_list)) // Generate all the URIs ... $view_topic_url_params = 'f=' . $row['forum_id'] . '&t=' . $topic_id; - $view_topic_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params); + $view_topic_url = $auth->acl_get('f_read', $forum_id) ? append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params) : false; $topic_unapproved = (($row['topic_visibility'] == ITEM_UNAPPROVED || $row['topic_visibility'] == ITEM_REAPPROVE) && $auth->acl_get('m_approve', $row['forum_id'])); $posts_unapproved = ($row['topic_visibility'] == ITEM_APPROVED && $row['topic_posts_unapproved'] && $auth->acl_get('m_approve', $row['forum_id'])); @@ -932,8 +973,8 @@ if (sizeof($topic_list)) 'S_TOPIC_LOCKED' => ($row['topic_status'] == ITEM_LOCKED) ? true : false, 'S_TOPIC_MOVED' => ($row['topic_status'] == ITEM_MOVED) ? true : false, - 'U_NEWEST_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params . '&view=unread') . '#unread', - 'U_LAST_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params . '&p=' . $row['topic_last_post_id']) . '#p' . $row['topic_last_post_id'], + 'U_NEWEST_POST' => $auth->acl_get('f_read', $forum_id) ? append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params . '&view=unread') . '#unread' : false, + 'U_LAST_POST' => $auth->acl_get('f_read', $forum_id) ? append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params . '&p=' . $row['topic_last_post_id']) . '#p' . $row['topic_last_post_id'] : false, 'U_LAST_POST_AUTHOR' => get_username_string('profile', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), 'U_TOPIC_AUTHOR' => get_username_string('profile', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), 'U_VIEW_TOPIC' => $view_topic_url, @@ -1010,7 +1051,7 @@ extract($phpbb_dispatcher->trigger_event('core.viewforum_generate_page_after', c // on all topics (as we do in 2.0.x). It looks for unread or new topics, if it doesn't find // any it updates the forum last read cookie. This requires that the user visit the forum // after reading a topic -if ($forum_data['forum_type'] == FORUM_POST && sizeof($topic_list) && $mark_forum_read) +if ($forum_data['forum_type'] == FORUM_POST && count($topic_list) && $mark_forum_read) { update_forum_tracking_info($forum_id, $forum_data['forum_last_post_time'], false, $mark_time_forum); } diff --git a/phpBB/viewtopic.php b/phpBB/viewtopic.php index a1dc60955c..e49959b3b5 100644 --- a/phpBB/viewtopic.php +++ b/phpBB/viewtopic.php @@ -32,7 +32,7 @@ $topic_id = $request->variable('t', 0); $post_id = $request->variable('p', 0); $voted_id = $request->variable('vote_id', array('' => 0)); -$voted_id = (sizeof($voted_id) > 1) ? array_unique($voted_id) : $voted_id; +$voted_id = (count($voted_id) > 1) ? array_unique($voted_id) : $voted_id; $start = $request->variable('start', 0); @@ -263,8 +263,26 @@ if (!$topic_data) $forum_id = (int) $topic_data['forum_id']; +/** + * Modify the forum ID to handle the correct display of viewtopic if needed + * + * @event core.viewtopic_modify_forum_id + * @var string forum_id forum ID + * @var array topic_data array of topic's data + * @since 3.2.5-RC1 + */ +$vars = array( + 'forum_id', + 'topic_data', +); +extract($phpbb_dispatcher->trigger_event('core.viewtopic_modify_forum_id', compact($vars))); + +// If the request is missing the f parameter, the forum id in the user session data is 0 at the moment. +// Let's fix that now so that the user can't hide from the forum's Who Is Online list. +$user->page['forum'] = $forum_id; + // Now we know the forum_id and can check the permissions -if ($topic_data['topic_visibility'] != ITEM_APPROVED && !$auth->acl_get('m_approve', $forum_id)) +if (!$phpbb_content_visibility->is_visible('topic', $forum_id, $topic_data)) { trigger_error('NO_TOPIC'); } @@ -338,6 +356,12 @@ if (($topic_data['topic_type'] != POST_NORMAL) && $topic_data['topic_time_limit' // Setup look and feel $user->setup('viewtopic', $topic_data['forum_style']); +if ($view == 'print' && !$auth->acl_get('f_print', $forum_id)) +{ + send_status_line(403, 'Forbidden'); + trigger_error('NO_AUTH_PRINT_TOPIC'); +} + $overrides_f_read_check = false; $overrides_forum_password_check = false; $topic_tracking_info = isset($topic_tracking_info) ? $topic_tracking_info : null; @@ -429,6 +453,38 @@ $join_user_sql = array('a' => true, 't' => false, 's' => false); $s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = ''; +/** +* Event to add new sorting options +* +* @event core.viewtopic_gen_sort_selects_before +* @var array limit_days Limit results by time +* @var array sort_by_text Language strings for sorting options +* @var array sort_by_sql SQL conditions for sorting options +* @var array join_user_sql SQL joins required for sorting options +* @var int sort_days User selected sort days +* @var string sort_key User selected sort key +* @var string sort_dir User selected sort direction +* @var string s_limit_days Initial value of limit days selectbox +* @var string s_sort_key Initial value of sort key selectbox +* @var string s_sort_dir Initial value of sort direction selectbox +* @var string u_sort_param Initial value of sorting form action +* @since 3.2.8-RC1 +*/ +$vars = array( + 'limit_days', + 'sort_by_text', + 'sort_by_sql', + 'join_user_sql', + 'sort_days', + 'sort_key', + 'sort_dir', + 's_limit_days', + 's_sort_key', + 's_sort_dir', + 'u_sort_param', +); +extract($phpbb_dispatcher->trigger_event('core.viewtopic_gen_sort_selects_before', compact($vars))); + gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param, $default_sort_days, $default_sort_key, $default_sort_dir); // Obtain correct post count and ordering SQL if user has @@ -736,7 +792,7 @@ $template->assign_vars(array( 'TOTAL_POSTS' => $user->lang('VIEW_TOPIC_POSTS', (int) $total_posts), 'U_MCP' => ($auth->acl_get('m_', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", "i=main&mode=topic_view&f=$forum_id&t=$topic_id" . (($start == 0) ? '' : "&start=$start") . ((strlen($u_sort_param)) ? "&$u_sort_param" : ''), true, $user->session_id) : '', - 'MODERATORS' => (isset($forum_moderators[$forum_id]) && sizeof($forum_moderators[$forum_id])) ? implode($user->lang['COMMA_SEPARATOR'], $forum_moderators[$forum_id]) : '', + 'MODERATORS' => (isset($forum_moderators[$forum_id]) && count($forum_moderators[$forum_id])) ? implode($user->lang['COMMA_SEPARATOR'], $forum_moderators[$forum_id]) : '', 'POST_IMG' => ($topic_data['forum_status'] == ITEM_LOCKED) ? $user->img('button_topic_locked', 'FORUM_LOCKED') : $user->img('button_topic_new', 'POST_NEW_TOPIC'), 'QUOTE_IMG' => $user->img('icon_post_quote', 'REPLY_WITH_QUOTE'), @@ -759,7 +815,7 @@ $template->assign_vars(array( 'S_SELECT_SORT_DIR' => $s_sort_dir, 'S_SELECT_SORT_KEY' => $s_sort_key, 'S_SELECT_SORT_DAYS' => $s_limit_days, - 'S_SINGLE_MODERATOR' => (!empty($forum_moderators[$forum_id]) && sizeof($forum_moderators[$forum_id]) > 1) ? false : true, + 'S_SINGLE_MODERATOR' => (!empty($forum_moderators[$forum_id]) && count($forum_moderators[$forum_id]) > 1) ? false : true, 'S_TOPIC_ACTION' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=$topic_id" . (($start == 0) ? '' : "&start=$start")), 'S_MOD_ACTION' => $s_quickmod_action, @@ -776,7 +832,7 @@ $template->assign_vars(array( 'U_TOPIC' => "{$server_path}viewtopic.$phpEx?f=$forum_id&t=$topic_id", 'U_FORUM' => $server_path, - 'U_VIEW_TOPIC' => $viewtopic_url, + 'U_VIEW_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=$topic_id" . (($start == 0) ? '' : "&start=$start") . (strlen($u_sort_param) ? "&$u_sort_param" : '')), 'U_CANONICAL' => generate_board_url() . '/' . append_sid("viewtopic.$phpEx", "t=$topic_id" . (($start) ? "&start=$start" : ''), true, ''), 'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id), 'U_VIEW_OLDER_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=$topic_id&view=previous"), @@ -852,9 +908,9 @@ if (!empty($topic_data['poll_start'])) (($topic_data['poll_length'] != 0 && $topic_data['poll_start'] + $topic_data['poll_length'] > time()) || $topic_data['poll_length'] == 0) && $topic_data['topic_status'] != ITEM_LOCKED && $topic_data['forum_status'] != ITEM_LOCKED && - (!sizeof($cur_voted_id) || + (!count($cur_voted_id) || ($auth->acl_get('f_votechg', $forum_id) && $topic_data['poll_vote_change']))) ? true : false; - $s_display_results = (!$s_can_vote || ($s_can_vote && sizeof($cur_voted_id)) || $view == 'viewpoll') ? true : false; + $s_display_results = (!$s_can_vote || ($s_can_vote && count($cur_voted_id)) || $view == 'viewpoll') ? true : false; /** * Event to manipulate the poll data @@ -889,16 +945,16 @@ if (!empty($topic_data['poll_start'])) if ($update && $s_can_vote) { - if (!sizeof($voted_id) || sizeof($voted_id) > $topic_data['poll_max_options'] || in_array(VOTE_CONVERTED, $cur_voted_id) || !check_form_key('posting')) + if (!count($voted_id) || count($voted_id) > $topic_data['poll_max_options'] || in_array(VOTE_CONVERTED, $cur_voted_id) || !check_form_key('posting')) { $redirect_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=$topic_id" . (($start == 0) ? '' : "&start=$start")); meta_refresh(5, $redirect_url); - if (!sizeof($voted_id)) + if (!count($voted_id)) { $message = 'NO_VOTE_OPTION'; } - else if (sizeof($voted_id) > $topic_data['poll_max_options']) + else if (count($voted_id) > $topic_data['poll_max_options']) { $message = 'TOO_MANY_VOTE_OPTIONS'; } @@ -992,8 +1048,31 @@ if (!empty($topic_data['poll_start'])) 'user_votes' => array_flip($valid_user_votes), 'vote_counts' => $vote_counts, 'total_votes' => array_sum($vote_counts), - 'can_vote' => !sizeof($valid_user_votes) || ($auth->acl_get('f_votechg', $forum_id) && $topic_data['poll_vote_change']), + 'can_vote' => !count($valid_user_votes) || ($auth->acl_get('f_votechg', $forum_id) && $topic_data['poll_vote_change']), + ); + + /** + * Event to manipulate the poll data sent by AJAX response + * + * @event core.viewtopic_modify_poll_ajax_data + * @var array data JSON response data + * @var array valid_user_votes Valid user votes + * @var array vote_counts Vote counts + * @var int forum_id Forum ID + * @var array topic_data Topic data + * @var array poll_info Array with the poll information + * @since 3.2.4-RC1 + */ + $vars = array( + 'data', + 'valid_user_votes', + 'vote_counts', + 'forum_id', + 'topic_data', + 'poll_info', ); + extract($phpbb_dispatcher->trigger_event('core.viewtopic_modify_poll_ajax_data', compact($vars))); + $json_response = new \phpbb\json_response(); $json_response->send($data); } @@ -1012,7 +1091,7 @@ if (!empty($topic_data['poll_start'])) $parse_flags = ($poll_info[0]['bbcode_bitfield'] ? OPTION_FLAG_BBCODE : 0) | OPTION_FLAG_SMILIES; - for ($i = 0, $size = sizeof($poll_info); $i < $size; $i++) + for ($i = 0, $size = count($poll_info); $i < $size; $i++) { $poll_info[$i]['poll_option_text'] = generate_text_for_display($poll_info[$i]['poll_option_text'], $poll_info[$i]['bbcode_uid'], $poll_option['bbcode_bitfield'], $parse_flags, true); } @@ -1144,6 +1223,29 @@ $sql = 'SELECT p.post_id " . (($join_user_sql[$sort_key]) ? 'AND u.user_id = p.poster_id': '') . " $limit_posts_time ORDER BY $sql_sort_order"; + +/** +* Event to modify the SQL query that gets post_list +* +* @event core.viewtopic_modify_post_list_sql +* @var string sql The SQL query to generate the post_list +* @var int sql_limit The number of posts the query fetches +* @var int sql_start The index the query starts to fetch from +* @var string sort_key Key the posts are sorted by +* @var string sort_days Display posts of previous x days +* @var int forum_id Forum ID +* @since 3.2.4-RC1 +*/ +$vars = array( + 'sql', + 'sql_limit', + 'sql_start', + 'sort_key', + 'sort_days', + 'forum_id', +); +extract($phpbb_dispatcher->trigger_event('core.viewtopic_modify_post_list_sql', compact($vars))); + $result = $db->sql_query_limit($sql, $sql_limit, $sql_start); $i = ($store_reverse) ? $sql_limit - 1 : 0; @@ -1154,7 +1256,7 @@ while ($row = $db->sql_fetchrow($result)) } $db->sql_freeresult($result); -if (!sizeof($post_list)) +if (!count($post_list)) { if ($sort_days) { @@ -1478,7 +1580,7 @@ if ($config['load_cpf_viewtopic']) } // Generate online information for user -if ($config['load_onlinetrack'] && sizeof($id_cache)) +if ($config['load_onlinetrack'] && count($id_cache)) { $sql = 'SELECT session_user_id, MAX(session_time) as online_time, MIN(session_viewonline) AS viewonline FROM ' . SESSIONS_TABLE . ' @@ -1496,7 +1598,7 @@ if ($config['load_onlinetrack'] && sizeof($id_cache)) unset($id_cache); // Pull attachment data -if (sizeof($attach_list)) +if (count($attach_list)) { if ($auth->acl_get('u_download') && $auth->acl_get('f_download', $forum_id)) { @@ -1514,7 +1616,7 @@ if (sizeof($attach_list)) $db->sql_freeresult($result); // No attachments exist, but post table thinks they do so go ahead and reset post_attach flags - if (!sizeof($attachments)) + if (!count($attachments)) { $sql = 'UPDATE ' . POSTS_TABLE . ' SET post_attachment = 0 @@ -1522,7 +1624,7 @@ if (sizeof($attach_list)) $db->sql_query($sql); // We need to update the topic indicator too if the complete topic is now without an attachment - if (sizeof($rowset) != $total_posts) + if (count($rowset) != $total_posts) { // Not all posts are displayed so we query the db to find if there's any attachment for this topic $sql = 'SELECT a.post_msg_id as post_id @@ -1572,19 +1674,27 @@ if (sizeof($attach_list)) } } -// Get the list of users who can receive private messages -$can_receive_pm_list = $auth->acl_get_list(array_keys($user_cache), 'u_readpm'); -$can_receive_pm_list = (empty($can_receive_pm_list) || !isset($can_receive_pm_list[0]['u_readpm'])) ? array() : $can_receive_pm_list[0]['u_readpm']; +if ($config['enable_accurate_pm_button']) +{ + // Get the list of users who can receive private messages + $can_receive_pm_list = $auth->acl_get_list(array_keys($user_cache), 'u_readpm'); + $can_receive_pm_list = (empty($can_receive_pm_list) || !isset($can_receive_pm_list[0]['u_readpm'])) ? array() : $can_receive_pm_list[0]['u_readpm']; -// Get the list of permanently banned users -$permanently_banned_users = phpbb_get_banned_user_ids(array_keys($user_cache), false); + // Get the list of permanently banned users + $permanently_banned_users = phpbb_get_banned_user_ids(array_keys($user_cache), false); +} +else +{ + $can_receive_pm_list = array_keys($user_cache); + $permanently_banned_users = []; +} -$i_total = sizeof($rowset) - 1; +$i_total = count($rowset) - 1; $prev_post_id = ''; $template->assign_vars(array( 'S_HAS_ATTACHMENTS' => $topic_data['topic_attachment'], - 'S_NUM_POSTS' => sizeof($post_list)) + 'S_NUM_POSTS' => count($post_list)) ); /** @@ -1629,7 +1739,7 @@ extract($phpbb_dispatcher->trigger_event('core.viewtopic_modify_post_data', comp // Output the posts $first_unread = $post_unread = false; -for ($i = 0, $end = sizeof($post_list); $i < $end; ++$i) +for ($i = 0, $end = count($post_list); $i < $end; ++$i) { // A non-existing rowset only happens if there was no user present for the entered poster_id // This could be a broken posts table. @@ -1672,7 +1782,7 @@ for ($i = 0, $end = sizeof($post_list); $i < $end; ++$i) if (($row['post_edit_count'] && $config['display_last_edited']) || $row['post_edit_reason']) { // Get usernames for all following posts if not already stored - if (!sizeof($post_edit_list) && ($row['post_edit_reason'] || ($row['post_edit_user'] && !isset($user_cache[$row['post_edit_user']])))) + if (!count($post_edit_list) && ($row['post_edit_reason'] || ($row['post_edit_user'] && !isset($user_cache[$row['post_edit_user']])))) { // Remove all post_ids already parsed (we do not have to check them) $post_storage_list = (!$store_reverse) ? array_slice($post_list, $i) : array_slice(array_reverse($post_list), $i); @@ -1736,7 +1846,7 @@ for ($i = 0, $end = sizeof($post_list); $i < $end; ++$i) if ($row['post_visibility'] == ITEM_DELETED && $row['post_delete_user']) { // Get usernames for all following posts if not already stored - if (!sizeof($post_delete_list) && ($row['post_delete_reason'] || ($row['post_delete_user'] && !isset($user_cache[$row['post_delete_user']])))) + if (!count($post_delete_list) && ($row['post_delete_reason'] || ($row['post_delete_user'] && !isset($user_cache[$row['post_delete_user']])))) { // Remove all post_ids already parsed (we do not have to check them) $post_storage_list = (!$store_reverse) ? array_slice($post_list, $i) : array_slice(array_reverse($post_list), $i); @@ -1980,7 +2090,7 @@ for ($i = 0, $end = sizeof($post_list); $i < $end; ++$i) 'S_HAS_ATTACHMENTS' => (!empty($attachments[$row['post_id']])) ? true : false, - 'S_MULTIPLE_ATTACHMENTS' => !empty($attachments[$row['post_id']]) && sizeof($attachments[$row['post_id']]) > 1, + 'S_MULTIPLE_ATTACHMENTS' => !empty($attachments[$row['post_id']]) && count($attachments[$row['post_id']]) > 1, 'S_POST_UNAPPROVED' => ($row['post_visibility'] == ITEM_UNAPPROVED || $row['post_visibility'] == ITEM_REAPPROVE) ? true : false, 'S_POST_DELETED' => ($row['post_visibility'] == ITEM_DELETED) ? true : false, 'L_POST_DELETED_MESSAGE' => $l_deleted_message, @@ -1989,8 +2099,9 @@ for ($i = 0, $end = sizeof($post_list); $i < $end; ++$i) 'S_FRIEND' => ($row['friend']) ? true : false, 'S_UNREAD_POST' => $post_unread, 'S_FIRST_UNREAD' => $s_first_unread, - 'S_CUSTOM_FIELDS' => (isset($cp_row['row']) && sizeof($cp_row['row'])) ? true : false, + 'S_CUSTOM_FIELDS' => (isset($cp_row['row']) && count($cp_row['row'])) ? true : false, 'S_TOPIC_POSTER' => ($topic_data['topic_poster'] == $poster_id) ? true : false, + 'S_FIRST_POST' => ($topic_data['topic_first_post_id'] == $row['post_id']) ? true : false, 'S_IGNORE_POST' => ($row['foe']) ? true : false, 'L_IGNORE_POST' => ($row['foe']) ? sprintf($user->lang['POST_BY_FOE'], get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username'])) : '', @@ -2045,7 +2156,7 @@ for ($i = 0, $end = sizeof($post_list); $i < $end; ++$i) $i = $current_row_number; - if (isset($cp_row['row']) && sizeof($cp_row['row'])) + if (isset($cp_row['row']) && count($cp_row['row'])) { $post_row = array_merge($post_row, $cp_row['row']); } @@ -2057,7 +2168,7 @@ for ($i = 0, $end = sizeof($post_list); $i < $end; ++$i) array( 'ID' => 'pm', 'NAME' => $user->lang['SEND_PRIVATE_MESSAGE'], - 'U_CONTACT' => $u_pm, + 'U_CONTACT' => $post_row['U_PM'], ), array( 'ID' => 'email', @@ -2158,7 +2269,7 @@ if (isset($user->data['session_page']) && !$user->data['is_bot'] && (strpos($use $db->sql_query($sql); // Update the attachment download counts - if (sizeof($update_count)) + if (count($update_count)) { $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET download_count = download_count + 1 @@ -2237,7 +2348,6 @@ if ($s_can_vote || $s_quick_reply) $qr_hidden_fields = array( 'topic_cur_post_id' => (int) $topic_data['topic_last_post_id'], - 'lastclick' => (int) time(), 'topic_id' => (int) $topic_data['topic_id'], 'forum_id' => (int) $forum_id, ); |